Learn how to create a Master Data v2 CRUD apps in VTEX IO.
This guide will teach you how to build a Master Data v2 CRUD (Create, Read, Update, Delete) application within VTEX IO using the masterdata
builder. Master Data is a native key-document database that allows you to efficiently store, search, expand, and personalize your data. While it is possible to integrate Master Data into any VTEX IO app by connecting to the Master Data API, this is not the most efficient approach.
To streamline your development experience, we recommend leveraging the masterdata
builder to create apps with Master Data v2 features, including data creation, editing, and deletion.
If you prefer to use Master Data v1, check Creating a VTEX IO service to interact with Master Data v1.
Before you begin
Before diving into coding your app, it's essential to grasp some fundamental concepts:
- Master Data
- VTEX IO service development
Instructions
To create a Master Data app, follow these steps:
Step 1 - Defining the data structure
Before diving into coding, take time to plan your data structure. Since you will be setting up a VTEX IO service app with a focus on Master Data's basic elements, ensure you have well-defined data entities and written schemas prepared for each entity your app will interact with.
For each data entity that your app will interact with, plan and prepare its corresponding JSON schema. See an example below:
Schema example
_24{_24 "$schema": "http://json-schema.org/schema#",_24 "title": "my_schema",_24 "type": "object",_24 "properties": {_24 "string_field_example": {_24 "type": "string"_24 },_24 "number_field_example": {_24 "type": "number"_24 },_24 "boolean_field_example": {_24 "type": "boolean"_24 }_24 },_24 "required": [_24 "number_field_example",_24 "string_field_example"_24 ],_24 "v-default-fields": [_24 "number_field_example",_24 "string_field_example"_24 ]_24}
Step 2 - Editing the manifest.json
file
- Use the VTEX IO CLI and run
vtex init
to copy the service-example boilerplate files to your computer. - Add the
masterdata
builder to your manifest file.
_10 "builders": {_10 ..._10+ "masterdata": "1.x",_10 }
- Add the following policies to your app’s
manifest.json
file:
_10[{_10 "name": "outbound-access",_10 "attrs": {_10 "host": "api.vtex.com",_10 "path": "/api/*"_10 }_10},_10{_10 "name": "ADMIN_DS"_10 }]
Step 3 - Using the masterdata
builder
- Create a folder named
masterdata
at the root of your app. This will be your Master Data configuration folder. - For each data entity your app interacts with, create a dedicated folder inside the
masterdata
directory. - Within each data entity folder, create a file named
schema.json
. The folder structure should resemble the following:
_10masterdata_10 | --myEntity_10 | --schema.json
- Populate the
schema.json
file with the JSON schema corresponding to the respective and save your changes. Notice that each data entity must have its ownschema.json
with a valid JSON schema. - In the terminal, run
vtex link
to test your code.
Note that your app creates regular Master Data entities accessible via the Master Data v2 endpoints. The naming convention for the entities follows this pattern: {vendor}_{appName}_{entityName}
.
Note that each time you install or link a different version of your app, the
masterdata
builder creates a new schema with the app’s name and version. Hence, since Master Data v2 data entities have a limit of 60 schemas per entity, ensure to delete unused schemas to prevent from running into issues.
Step - 4 - Generating TypeScript typings
Run vtex setup -i
at the root of your project. This command will generate all TypeScript typings for your data entity, making them available for import in your app. You can find them in your node/node_modules
folder.
Whenever you change a data entity schema, you must regenerate the TypeScript typings. Hence, if you run into issues related to the data entity typings, try regenerating the typings. Also, ensure to run
vtex setup -i
before releasing your app so that the typings will not be tied to your development workspace.
Step 5 - Using the node
builder
- In the terminal, change to the
node
folder of your app. - Run
yarn add @vtex/clients
to install theclients
package. - Open the file
node/clients/index.ts
and import the following modules:
_10import { masterDataFor } from '@vtex/clients'_10import { myEntity } from 'vendor.appName' // Replace with the names of your data entity, store, and app.
When importing your data entity typings from the app, follow the format
{vendor}.{appName}
, as specified in yourmanifest.json
. If the app does not recognize the generated typings import, try deleting thenode/node_modules
folder. Then runyarn
to reinstall dependencies andvtex setup
to regenerate the typings. Finally, runvtex link
to check if everything is functioning correctly.
- In the same
node/clients/index.ts
file, create a new property for theClients
class to create a client for your data entity. This represents the data entity you are working with. See this code example:
_10public get entity() {_10 return this.getOrSet('entity', masterDataFor<myEntity>('entity'))_10}
Step 6 - Configuring Master Data triggers
To configure Master Data triggers in your app, follow these steps:
- Create a folder named
triggers
inside yourmasterdata/{dataEntity}
folder. - Create a JSON file inside the
triggers
folder. - Declare your triggers in the JSON file, following the same format described for the
v-triggers
field when setting up Master Data v2 triggers.
Step 7 - Creating Master Data functions
Now that your app is set up, you can begin coding Master Data functions, such as saving, editing, retrieving, or deleting data. You can then use these functions in your app’s resolvers
and middlewares
.
Master Data functions are available via global context through ctx.clients.{entityName}.{function}()
. Below, you can see more details on each function. These functions are equivalent to those performed by Master Data v2 endpoints.
Get
The get()
function returns a document by its ID. You may specify what fields you want to be returned. If you do not, all fields in the document will be returned.
Argument | Required | Type | Description |
---|---|---|---|
id | Yes | String | ID of the document you wish to retrieve. |
fields | No | Array of strings | List of the names of the fields you wish to be returned. If not sent, all fields are returned. |
Example: Getting a complete document of the Book
entity.
_10ctx.client.Book.get(id: 'sdfg3543df5g4h3d5fh47d')
Example: Getting the name and release date of a given book from the Book
entity.
_10ctx.client.Book.get(id: 'sdfg3543df5g4h3d5fh47d’, fields:['name', 'releaseDate'])
Save
The save()
function saves a new document to your data entity and returns the generated ID for that new document.
This function’s arguments follow the format you described when setting up JSON schemas in your data structure.
Example: Saving a new document to the Book
data entity.
_10ctx.client.Book.save({_10 name: 'Dom Quixote',_10 releaseDate: 1605,_10 author: 'Miguel de Cervantes'_10})
Update
The update()
function an existing document by ID.
Argument | Required | Type | Description |
---|---|---|---|
id | Yes | String | ID of the document you wish to update. |
{document-data} | Yes | Corresponding to the types declared in the schema | This function’s arguments follow the format you described when setting up JSON schemas in your data structure. Required fields apply even for partial updates. |
Example: Updating a document’s rating
field in the Book
entity.
_10ctx.client.Book.udpate(_10 id: 'sdfg3543df5g4h3d5fh47d',_10 {_10 name 'Dom Quixote',_10 rating: 4,5_10 }_10)
Save or update
The saveOrUpdate()
function updates an existing document by ID or creates a new document if you do not send an ID.
Argument | Required | Type | Description |
---|---|---|---|
id | No | String | ID of the document you wish to update. If you send an ID, the document is updated. Otherwise, a new document is created. |
{document-data} | Yes | Corresponding to the types declared in the schema | This function’s arguments follow the format you described when setting up JSON schemas in your data structure. Required fields apply even for partial updates. |
Example: Updating a document’s rating
field in the Book
entity.
_10ctx.client.Book.saveOrUpdate(_10 id: ‘sdfg3543df5g4h3d5fh47d’,_10 {_10 name ‘Dom Quixote’,_10 rating: 4,5_10 }_10)
Example: Saving a new document to the Book
data entity.
_10ctx.client.Book.saveOrUpdate({_10 name: 'Dom Quixote',_10 releaseDate: 1605,_10 author: 'Miguel de Cervantes'_10})
Delete
The delete()
function deletes a document by ID.
Argument | Required | Type | Description |
---|---|---|---|
id | Yes | String | ID of the document you wish to delete. |
Example: Deleting a document of the Book
entity.
_10ctx.client.Book.delete(id: 'sdfg3543df5g4h3d5fh47d')
Search
The search()
function returns an array of documents that satisfy the criteria described in the arguments.
Argument | Required | Type | Description |
---|---|---|---|
page | Yes | Integer | Number of the page you wish to retrieve. |
pageSize | Yes | Integer | Number of documents that should be returned in each page. |
fields | No | Array of strings | Names of the fields you wish to be returned. If not sent, all fields are returned. |
where | No | String | Filtering condition. |
Example: Searching names and release dates of all books by the author Miguel de Cervantes.
_10ctx.client.Book.search(_10 pagination: {_10 page: 1,_10 pageSize: 10_10 },_10 fields: ['name', 'releaseDate'],_10 where: 'name=Miguel de Cervantes'_10)