Content Migrations in Contember
Introduction
Content migrations within Contember are designed to manage and transform the existing data in your database. This is achieved using GraphQL queries, which provide a powerful and versatile approach to data manipulation.
Setting Up Content Migration Files
Content migration files should be added to the api/migrations
directory in your Contember project. The naming convention for these files is YYYY-MM-DD-HHMMSS-label
, which ensures they are executed in the correct order and are easy to identify.
Example File Name: 2023-10-26-150000-add-english-locale.js
Using the CLI to create blank migration files
You can use the Contember CLI to create blank migration files. Simply run the following command and provide a label for your migration.
yarn contember migration:blank <label>
Depending on the complexity of your migration, you can choose to use a JSON, JavaScript (JS), or TypeScript (TS) file. By default, the CLI will create a TypeScript file.
Defining Migrations in JSON
Content migrations can be defined in JSON, using a single "query" or an array of "queries".
Single Query Example
{
"query": "mutation { createLocale(data: { code: \"en\" }) { ok errorMessage } }"
}
Multiple Queries Example
{
"queries": [
{
"query": "mutation { createLocale(data: { code: \"en\" }) { ok errorMessage } }"
},
{
"query": "mutation { createLocale(data: { code: \"fr\" }) { ok errorMessage } }"
}
]
}
Defining Migrations in JavaScript or TypeScript
For more advanced use cases, JS or TS can be used to define migrations.
Single Query with Variables
export default {
query: `
mutation CreateLocale($data: LocaleCreateInput) {
createLocale(data: $data) {
ok
errorMessage
}
}
`,
variables: {
data: {
code: "en"
}
}
};
Multiple Queries with Variables
export default {
queries: [
{
query: `
mutation CreateLocale($data: LocaleCreateInput) {
createLocale(data: $data) {
ok
errorMessage
}
}
`,
variables: {
data: {
code: "en"
}
}
},
{
// Second query
}
]
};
Instead of default export, you can use named exports "queries" and "query" to define migrations.
Utilizing Functions in Migrations
Functions in migration files provide a higher level of control and the ability to perform dynamic operations.
export default async function () {
// Fetch data, execute queries, and perform other asynchronous operations here.
// Return content migrations if needed
return {
queries: [
// Individual queries
]
};
};
Validating Mutation Results
It's crucial to fetch the "ok" and "errorMessage" fields for top-level mutations to ensure they have executed successfully. Contember CLI checks these fields by default, but you can bypass this check (not recommended) by including checkMutationResult: false
in your query object.
Applying Migrations
To run your content migrations, use the Contember CLI’s migration:execute
command.
npx contember migration:execute
Execution Model for Function Migrations
Function migrations introduce a unique execution model. The CLI orchestrates the migrations, grouping non-function migrations into a single transaction, while function migrations are executed separately, each in its own transaction.
Execution Flow Example:
-
Transaction 1:
- Schema Migration A
- Content Migration B
- Schema Migration C
-
Function Migration (Separate Transaction):
- Execute exported function and await result
- If the function returns content migrations, send them to the migration API
-
Subsequent Non-Function Migrations (New Transaction)
Note: Due to this model, it’s advisable to run function migrations independently to avoid complications, as some migrations might succeed even if others fail.