Migration Guides
Upgrading to v19.0.0
Configuration changes
- The
gqlModule
configuration property has been renamed togqmModule
to maintain consistency with the project naming. Please update your.gqmrc.json
file 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();