Migration Guides
Upgrading to v19.0.0
Configuration changes
- The
gqlModuleconfiguration property has been renamed togqmModuleto maintain consistency with the project naming. Please update your.gqmrc.jsonfile accordingly:
{
"modelsPath": "path/to/models.ts",
"generatedFolderPath": "path/to/generated",
"graphqlQueriesPath": "path/to/queries",
- "gqlModule": "../path/to/module",
+ "gqmModule": "../path/to/module",
"knexfilePath": "knexfile.ts",
"dateLibrary": "luxon"
}
Enhanced delete functionality
New onDelete option: restrict
You can now use restrict as an onDelete option for relations, in addition to the existing cascade and set-null options:
{
name: 'author',
type: 'User',
kind: 'relation',
onDelete: 'restrict', // New option
}
When using restrict, deletion of a parent entity will be prevented if it has related child entities, ensuring referential integrity.
Database schema changes
New fields have been added to deletable entities to track deletion context:
deleteRootType: Stores the type of the root entity that initiated the deletiondeleteRootId: Stores the ID of the root entity that initiated the deletion
Generate a migration to add these fields:
npx gqm generate-migration
Mutation hook signature changes
The MutationHook function signature has been updated to use object destructuring for better maintainability and extensibility. Update your mutation hook implementations:
- export const mutationHook: MutationHook = (model, action, when, data, ctx) => {
+ export const mutationHook: MutationHook = ({ model, action, trigger, when, data, ctx }) => {
// Your implementation
}
The new signature includes a trigger parameter that indicates how the mutation was initiated:
'mutation': Direct GraphQL mutation'cascade': Triggered by cascading delete'set-null': Triggered by setting foreign key to null
Upgrading to v18.0.0
This was a dummy release, nothing to do here.
Upgrading to v17.2.0
From now on, foreign keys will be indexed by default. For existing projects, you'll need to add indices manually to your existing foreign keys.
Here's a sample script to generate the migration:
import { execSync } from 'child_process';
import { writeFileSync } from 'fs';
import { models } from '../../../src/config/models';
const start = async () => {
const instructions: string[] = [];
instructions.push(`import { Knex } from 'knex';
export const up = async (knex: Knex) => {`);
for (const model of models.entities) {
if (model.fields.some((field) => field.kind === 'relation')) {
instructions.push(`await knex.schema.alterTable('${model.name}', (table) => {`);
for (const field of model.fields) {
if (field.kind === 'relation') {
instructions.push(`table.index('${field.foreignKey || field.name + 'Id'}');`);
}
}
instructions.push(`});`);
}
}
instructions.push(`};`);
instructions.push(`export const down = async (knex: Knex) => {`);
for (const model of models.entities) {
if (model.fields.some((field) => field.kind === 'relation')) {
instructions.push(`await knex.schema.alterTable('${model.name}', (table) => {`);
for (const field of model.fields) {
if (field.kind === 'relation') {
instructions.push(`table.dropIndex('${field.foreignKey || field.name + 'Id'}');`);
}
}
instructions.push(`});`);
}
}
instructions.push(`};`);
writeFileSync('migrations/20250305130109_create-foreign-key-indices.ts', instructions.join('\n'));
execSync('npx eslint --fix migrations/20250305130109_create-foreign-key-indices.ts');
};
void start();