@smartive/graphql-magic 22.2.0-next.1 → 22.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -9
- package/dist/bin/gqm.cjs +33 -190
- package/dist/cjs/index.cjs +33 -190
- package/dist/esm/migrations/generate.d.ts +0 -4
- package/dist/esm/migrations/generate.js +35 -180
- package/dist/esm/migrations/generate.js.map +1 -1
- package/dist/esm/models/model-definitions.d.ts +0 -1
- package/package.json +2 -2
- package/src/migrations/generate.ts +35 -220
- package/src/models/model-definitions.ts +0 -1
|
@@ -160,27 +160,35 @@ export class MigrationGenerator {
|
|
|
160
160
|
);
|
|
161
161
|
|
|
162
162
|
// Update fields
|
|
163
|
-
const
|
|
164
|
-
if (!field.generateAs) {
|
|
165
|
-
return false;
|
|
166
|
-
}
|
|
167
|
-
|
|
163
|
+
const existingFields = model.fields.filter((field) => {
|
|
168
164
|
const col = this.getColumn(model.name, field.kind === 'relation' ? `${field.name}Id` : field.name);
|
|
169
165
|
if (!col) {
|
|
170
166
|
return false;
|
|
171
167
|
}
|
|
172
168
|
|
|
173
|
-
if (col.
|
|
169
|
+
if ((!field.nonNull && !col.is_nullable) || (field.nonNull && col.is_nullable)) {
|
|
174
170
|
return true;
|
|
175
171
|
}
|
|
176
172
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
173
|
+
if (!field.kind || field.kind === 'primitive') {
|
|
174
|
+
if (field.type === 'Int') {
|
|
175
|
+
if (col.data_type !== 'integer') {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (field.type === 'Float') {
|
|
180
|
+
if (field.double) {
|
|
181
|
+
if (col.data_type !== 'double precision') {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
} else if (col.data_type !== 'numeric') {
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
182
189
|
|
|
183
|
-
|
|
190
|
+
return false;
|
|
191
|
+
});
|
|
184
192
|
this.updateFields(model, existingFields, up, down);
|
|
185
193
|
}
|
|
186
194
|
|
|
@@ -367,10 +375,6 @@ export class MigrationGenerator {
|
|
|
367
375
|
for (const field of fields) {
|
|
368
376
|
alter.push(() => this.column(field, { setNonNull: field.defaultValue !== undefined }));
|
|
369
377
|
|
|
370
|
-
if (field.generateAs) {
|
|
371
|
-
continue;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
378
|
// If the field is not nullable but has no default, write placeholder code
|
|
375
379
|
if (field.nonNull && field.defaultValue === undefined) {
|
|
376
380
|
updates.push(() => this.writer.write(`${field.name}: 'TODO',`).newLine());
|
|
@@ -401,63 +405,13 @@ export class MigrationGenerator {
|
|
|
401
405
|
|
|
402
406
|
down.push(() => {
|
|
403
407
|
this.alterTable(model.name, () => {
|
|
404
|
-
for (const { kind, name } of fields
|
|
408
|
+
for (const { kind, name } of fields) {
|
|
405
409
|
this.dropColumn(kind === 'relation' ? `${name}Id` : name);
|
|
406
410
|
}
|
|
407
411
|
});
|
|
408
412
|
});
|
|
409
413
|
}
|
|
410
414
|
|
|
411
|
-
private updateFieldsRaw(model: EntityModel, fields: EntityField[], up: Callbacks, down: Callbacks) {
|
|
412
|
-
if (!fields.length) {
|
|
413
|
-
return;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
up.push(() => {
|
|
417
|
-
this.alterTableRaw(model.name, () => {
|
|
418
|
-
for (const [index, field] of fields.entries()) {
|
|
419
|
-
this.columnRaw(field, { alter: true }, index);
|
|
420
|
-
}
|
|
421
|
-
});
|
|
422
|
-
});
|
|
423
|
-
|
|
424
|
-
down.push(() => {
|
|
425
|
-
this.alterTableRaw(model.name, () => {
|
|
426
|
-
for (const [index, field] of fields.entries()) {
|
|
427
|
-
this.columnRaw(field, { alter: true }, index);
|
|
428
|
-
}
|
|
429
|
-
});
|
|
430
|
-
});
|
|
431
|
-
|
|
432
|
-
if (isUpdatableModel(model)) {
|
|
433
|
-
const updatableFields = fields.filter(isUpdatableField);
|
|
434
|
-
if (!updatableFields.length) {
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
up.push(() => {
|
|
439
|
-
this.alterTable(`${model.name}Revision`, () => {
|
|
440
|
-
for (const [index, field] of updatableFields.entries()) {
|
|
441
|
-
this.columnRaw(field, { alter: true }, index);
|
|
442
|
-
}
|
|
443
|
-
});
|
|
444
|
-
});
|
|
445
|
-
|
|
446
|
-
down.push(() => {
|
|
447
|
-
this.alterTable(`${model.name}Revision`, () => {
|
|
448
|
-
for (const [index, field] of updatableFields.entries()) {
|
|
449
|
-
this.columnRaw(
|
|
450
|
-
field,
|
|
451
|
-
{ alter: true },
|
|
452
|
-
index,
|
|
453
|
-
summonByName(this.columns[model.name], field.kind === 'relation' ? `${field.name}Id` : field.name),
|
|
454
|
-
);
|
|
455
|
-
}
|
|
456
|
-
});
|
|
457
|
-
});
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
|
|
461
415
|
private updateFields(model: EntityModel, fields: EntityField[], up: Callbacks, down: Callbacks) {
|
|
462
416
|
if (!fields.length) {
|
|
463
417
|
return;
|
|
@@ -618,12 +572,6 @@ export class MigrationGenerator {
|
|
|
618
572
|
.blankLine();
|
|
619
573
|
}
|
|
620
574
|
|
|
621
|
-
private alterTableRaw(table: string, block: () => void) {
|
|
622
|
-
this.writer.write(`await knex.raw('ALTER TABLE "${table}"`);
|
|
623
|
-
block();
|
|
624
|
-
this.writer.write(`');`).newLine().blankLine();
|
|
625
|
-
}
|
|
626
|
-
|
|
627
575
|
private alterTable(table: string, block: () => void) {
|
|
628
576
|
return this.writer
|
|
629
577
|
.write(`await knex.schema.alterTable('${table}', (table) => `)
|
|
@@ -657,125 +605,29 @@ export class MigrationGenerator {
|
|
|
657
605
|
return value;
|
|
658
606
|
}
|
|
659
607
|
|
|
660
|
-
private columnRaw(
|
|
661
|
-
{ name, ...field }: EntityField,
|
|
662
|
-
{ setNonNull = true, alter = false } = {},
|
|
663
|
-
index: number,
|
|
664
|
-
toColumn?: Column,
|
|
665
|
-
) {
|
|
666
|
-
const nonNull = () => {
|
|
667
|
-
if (setNonNull) {
|
|
668
|
-
if (toColumn) {
|
|
669
|
-
if (toColumn.is_nullable) {
|
|
670
|
-
return false;
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
return true;
|
|
674
|
-
}
|
|
675
|
-
if (field.nonNull) {
|
|
676
|
-
return true;
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
return false;
|
|
680
|
-
}
|
|
681
|
-
};
|
|
682
|
-
const kind = field.kind;
|
|
683
|
-
if (field.generateAs) {
|
|
684
|
-
let type = '';
|
|
685
|
-
switch (kind) {
|
|
686
|
-
case undefined:
|
|
687
|
-
case 'primitive':
|
|
688
|
-
switch (field.type) {
|
|
689
|
-
case 'Float':
|
|
690
|
-
type = `decimal(${field.precision ?? 'undefined'}, ${field.scale ?? 'undefined'})`;
|
|
691
|
-
break;
|
|
692
|
-
default:
|
|
693
|
-
throw new Error(`Generated columns of kind ${kind} and type ${field.type} are not supported yet.`);
|
|
694
|
-
}
|
|
695
|
-
break;
|
|
696
|
-
default:
|
|
697
|
-
throw new Error(`Generated columns of kind ${kind} are not supported yet.`);
|
|
698
|
-
}
|
|
699
|
-
if (index) {
|
|
700
|
-
this.writer.write(`,`);
|
|
701
|
-
}
|
|
702
|
-
if (alter) {
|
|
703
|
-
this.writer.write(` ALTER COLUMN "${name}" TYPE ${type}`);
|
|
704
|
-
if (setNonNull) {
|
|
705
|
-
if (nonNull()) {
|
|
706
|
-
this.writer.write(`, ALTER COLUMN "${name}" SET NOT NULL`);
|
|
707
|
-
} else {
|
|
708
|
-
this.writer.write(`, ALTER COLUMN "${name}" DROP NOT NULL`);
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
this.writer.write(`, ALTER COLUMN "${name}" SET EXPRESSION AS (${field.generateAs})`);
|
|
712
|
-
} else {
|
|
713
|
-
this.writer.write(
|
|
714
|
-
`${alter ? 'ALTER' : 'ADD'} COLUMN "${name}" ${type}${nonNull() ? ' not null' : ''} GENERATED ALWAYS AS (${field.generateAs}) STORED`,
|
|
715
|
-
);
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
return;
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
throw new Error(`Only generated columns can be created with columnRaw`);
|
|
722
|
-
}
|
|
723
|
-
|
|
724
608
|
private column(
|
|
725
609
|
{ name, primary, list, ...field }: EntityField,
|
|
726
610
|
{ setUnique = true, setNonNull = true, alter = false, foreign = true, setDefault = true } = {},
|
|
727
611
|
toColumn?: Column,
|
|
728
612
|
) {
|
|
729
|
-
const nonNull = () => {
|
|
730
|
-
if (setNonNull) {
|
|
731
|
-
if (toColumn) {
|
|
732
|
-
if (toColumn.is_nullable) {
|
|
733
|
-
return false;
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
return true;
|
|
737
|
-
}
|
|
738
|
-
if (field.nonNull) {
|
|
739
|
-
return true;
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
return false;
|
|
743
|
-
}
|
|
744
|
-
};
|
|
745
|
-
const kind = field.kind;
|
|
746
|
-
if (field.generateAs) {
|
|
747
|
-
let type = '';
|
|
748
|
-
switch (kind) {
|
|
749
|
-
case undefined:
|
|
750
|
-
case 'primitive':
|
|
751
|
-
switch (field.type) {
|
|
752
|
-
case 'Float':
|
|
753
|
-
type = `decimal(${field.precision ?? 'undefined'}, ${field.scale ?? 'undefined'})`;
|
|
754
|
-
break;
|
|
755
|
-
default:
|
|
756
|
-
throw new Error(`Generated columns of kind ${kind} and type ${field.type} are not supported yet.`);
|
|
757
|
-
}
|
|
758
|
-
break;
|
|
759
|
-
default:
|
|
760
|
-
throw new Error(`Generated columns of kind ${kind} are not supported yet.`);
|
|
761
|
-
}
|
|
762
|
-
this.writer.write(
|
|
763
|
-
`table.specificType('${name}', '${type}${nonNull() ? ' not null' : ''} GENERATED ALWAYS AS (${field.generateAs}) STORED')`,
|
|
764
|
-
);
|
|
765
|
-
if (alter) {
|
|
766
|
-
this.writer.write('.alter()');
|
|
767
|
-
}
|
|
768
|
-
this.writer.write(';').newLine();
|
|
769
|
-
|
|
770
|
-
return;
|
|
771
|
-
}
|
|
772
|
-
|
|
773
613
|
const col = (what?: string) => {
|
|
774
614
|
if (what) {
|
|
775
615
|
this.writer.write(what);
|
|
776
616
|
}
|
|
777
617
|
if (setNonNull) {
|
|
778
|
-
|
|
618
|
+
if (toColumn) {
|
|
619
|
+
if (toColumn.is_nullable) {
|
|
620
|
+
this.writer.write(`.nullable()`);
|
|
621
|
+
} else {
|
|
622
|
+
this.writer.write('.notNullable()');
|
|
623
|
+
}
|
|
624
|
+
} else {
|
|
625
|
+
if (field.nonNull) {
|
|
626
|
+
this.writer.write(`.notNullable()`);
|
|
627
|
+
} else {
|
|
628
|
+
this.writer.write('.nullable()');
|
|
629
|
+
}
|
|
630
|
+
}
|
|
779
631
|
}
|
|
780
632
|
if (setDefault && field.defaultValue !== undefined) {
|
|
781
633
|
this.writer.write(`.defaultTo(${this.value(field.defaultValue)})`);
|
|
@@ -790,6 +642,7 @@ export class MigrationGenerator {
|
|
|
790
642
|
}
|
|
791
643
|
this.writer.write(';').newLine();
|
|
792
644
|
};
|
|
645
|
+
const kind = field.kind;
|
|
793
646
|
switch (kind) {
|
|
794
647
|
case undefined:
|
|
795
648
|
case 'primitive':
|
|
@@ -863,44 +716,6 @@ export class MigrationGenerator {
|
|
|
863
716
|
private getColumn(tableName: string, columnName: string) {
|
|
864
717
|
return this.columns[tableName].find((col) => col.name === columnName);
|
|
865
718
|
}
|
|
866
|
-
|
|
867
|
-
private hasChanged(model: EntityModel, field: EntityField) {
|
|
868
|
-
const col = this.getColumn(model.name, field.kind === 'relation' ? `${field.name}Id` : field.name);
|
|
869
|
-
if (!col) {
|
|
870
|
-
return false;
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
if (field.generateAs) {
|
|
874
|
-
if (col.generation_expression !== field.generateAs) {
|
|
875
|
-
throw new Error(
|
|
876
|
-
`Column ${col.name} has specific type ${col.generation_expression} but expected ${field.generateAs}`,
|
|
877
|
-
);
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
|
|
881
|
-
if ((!field.nonNull && !col.is_nullable) || (field.nonNull && col.is_nullable)) {
|
|
882
|
-
return true;
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
if (!field.kind || field.kind === 'primitive') {
|
|
886
|
-
if (field.type === 'Int') {
|
|
887
|
-
if (col.data_type !== 'integer') {
|
|
888
|
-
return true;
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
if (field.type === 'Float') {
|
|
892
|
-
if (field.double) {
|
|
893
|
-
if (col.data_type !== 'double precision') {
|
|
894
|
-
return true;
|
|
895
|
-
}
|
|
896
|
-
} else if (col.data_type !== 'numeric') {
|
|
897
|
-
return true;
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
return false;
|
|
903
|
-
}
|
|
904
719
|
}
|
|
905
720
|
|
|
906
721
|
export const getMigrationDate = () => {
|