@smartive/graphql-magic 22.0.2 → 22.2.0-next.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 +9 -2
- package/dist/bin/gqm.cjs +212 -17
- package/dist/cjs/index.cjs +197 -17
- package/dist/esm/migrations/generate.d.ts +5 -0
- package/dist/esm/migrations/generate.js +187 -18
- package/dist/esm/migrations/generate.js.map +1 -1
- package/dist/esm/models/model-definitions.d.ts +1 -0
- package/package.json +6 -6
- package/src/bin/gqm/gqm.ts +21 -0
- package/src/migrations/generate.ts +228 -18
- package/src/models/model-definitions.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
##
|
|
1
|
+
## 22.2.0-next.1 (2025-12-02)
|
|
2
2
|
|
|
3
|
-
*
|
|
3
|
+
* feat: generated fields and migration check ([d0a275c](https://github.com/smartive/graphql-magic/commit/d0a275c))
|
|
4
|
+
* chore(deps): update dependency @types/lodash to v4.17.21 (#383) ([b0dd062](https://github.com/smartive/graphql-magic/commit/b0dd062)), closes [#383](https://github.com/smartive/graphql-magic/issues/383)
|
|
5
|
+
* chore(deps): update dependency esbuild to v0.26.0 (#380) ([c3065d6](https://github.com/smartive/graphql-magic/commit/c3065d6)), closes [#380](https://github.com/smartive/graphql-magic/issues/380)
|
|
6
|
+
* chore(deps): update dependency esbuild to v0.27.0 (#381) ([62cca2a](https://github.com/smartive/graphql-magic/commit/62cca2a)), closes [#381](https://github.com/smartive/graphql-magic/issues/381)
|
|
7
|
+
* chore(deps): update dependency prettier to v3.7.1 (#385) ([680ed83](https://github.com/smartive/graphql-magic/commit/680ed83)), closes [#385](https://github.com/smartive/graphql-magic/issues/385)
|
|
8
|
+
* chore(deps): update dependency prettier to v3.7.2 (#386) ([19e819d](https://github.com/smartive/graphql-magic/commit/19e819d)), closes [#386](https://github.com/smartive/graphql-magic/issues/386)
|
|
9
|
+
* chore(deps): update dependency prettier to v3.7.3 (#387) ([73f2af9](https://github.com/smartive/graphql-magic/commit/73f2af9)), closes [#387](https://github.com/smartive/graphql-magic/issues/387)
|
|
10
|
+
* chore(deps): update dependency ts-jest to v29.4.6 (#388) ([31776a8](https://github.com/smartive/graphql-magic/commit/31776a8)), closes [#388](https://github.com/smartive/graphql-magic/issues/388)
|
package/dist/bin/gqm.cjs
CHANGED
|
@@ -750,6 +750,7 @@ var MigrationGenerator = class {
|
|
|
750
750
|
columns = {};
|
|
751
751
|
uuidUsed;
|
|
752
752
|
nowUsed;
|
|
753
|
+
needsMigration = false;
|
|
753
754
|
async generate() {
|
|
754
755
|
const { writer, schema, models } = this;
|
|
755
756
|
const enums = (await schema.knex("pg_type").where({ typtype: "e" }).select("typname")).map(({ typname }) => typname);
|
|
@@ -848,13 +849,23 @@ var MigrationGenerator = class {
|
|
|
848
849
|
up,
|
|
849
850
|
down
|
|
850
851
|
);
|
|
851
|
-
const
|
|
852
|
-
|
|
852
|
+
const rawExistingFields = model.fields.filter((field) => {
|
|
853
|
+
if (!field.generateAs) {
|
|
854
|
+
return false;
|
|
855
|
+
}
|
|
856
|
+
const col = this.getColumn(model.name, field.kind === "relation" ? `${field.name}Id` : field.name);
|
|
853
857
|
if (!col) {
|
|
854
858
|
return false;
|
|
855
859
|
}
|
|
856
|
-
|
|
860
|
+
if (col.generation_expression !== field.generateAs) {
|
|
861
|
+
return true;
|
|
862
|
+
}
|
|
863
|
+
return this.hasChanged(model, field);
|
|
857
864
|
});
|
|
865
|
+
if (rawExistingFields.length) {
|
|
866
|
+
this.updateFieldsRaw(model, rawExistingFields, up, down);
|
|
867
|
+
}
|
|
868
|
+
const existingFields = model.fields.filter((field) => !field.generateAs && this.hasChanged(model, field));
|
|
858
869
|
this.updateFields(model, existingFields, up, down);
|
|
859
870
|
}
|
|
860
871
|
if (isUpdatableModel(model)) {
|
|
@@ -952,6 +963,9 @@ var MigrationGenerator = class {
|
|
|
952
963
|
if (this.nowUsed) {
|
|
953
964
|
writer.writeLine(`const now = date();`).blankLine();
|
|
954
965
|
}
|
|
966
|
+
if (up.length || down.length) {
|
|
967
|
+
this.needsMigration = true;
|
|
968
|
+
}
|
|
955
969
|
this.migration("up", up);
|
|
956
970
|
this.migration("down", down.reverse());
|
|
957
971
|
return writer.toString();
|
|
@@ -994,6 +1008,9 @@ var MigrationGenerator = class {
|
|
|
994
1008
|
const postAlter = [];
|
|
995
1009
|
for (const field of fields2) {
|
|
996
1010
|
alter.push(() => this.column(field, { setNonNull: field.defaultValue !== void 0 }));
|
|
1011
|
+
if (field.generateAs) {
|
|
1012
|
+
continue;
|
|
1013
|
+
}
|
|
997
1014
|
if (field.nonNull && field.defaultValue === void 0) {
|
|
998
1015
|
updates.push(() => this.writer.write(`${field.name}: 'TODO',`).newLine());
|
|
999
1016
|
postAlter.push(() => this.column(field, { alter: true, foreign: false }));
|
|
@@ -1017,12 +1034,56 @@ var MigrationGenerator = class {
|
|
|
1017
1034
|
});
|
|
1018
1035
|
down.push(() => {
|
|
1019
1036
|
this.alterTable(model.name, () => {
|
|
1020
|
-
for (const { kind, name: name2 } of fields2) {
|
|
1037
|
+
for (const { kind, name: name2 } of fields2.toReversed()) {
|
|
1021
1038
|
this.dropColumn(kind === "relation" ? `${name2}Id` : name2);
|
|
1022
1039
|
}
|
|
1023
1040
|
});
|
|
1024
1041
|
});
|
|
1025
1042
|
}
|
|
1043
|
+
updateFieldsRaw(model, fields2, up, down) {
|
|
1044
|
+
if (!fields2.length) {
|
|
1045
|
+
return;
|
|
1046
|
+
}
|
|
1047
|
+
up.push(() => {
|
|
1048
|
+
this.alterTableRaw(model.name, () => {
|
|
1049
|
+
for (const [index, field] of fields2.entries()) {
|
|
1050
|
+
this.columnRaw(field, { alter: true }, index);
|
|
1051
|
+
}
|
|
1052
|
+
});
|
|
1053
|
+
});
|
|
1054
|
+
down.push(() => {
|
|
1055
|
+
this.alterTableRaw(model.name, () => {
|
|
1056
|
+
for (const [index, field] of fields2.entries()) {
|
|
1057
|
+
this.columnRaw(field, { alter: true }, index);
|
|
1058
|
+
}
|
|
1059
|
+
});
|
|
1060
|
+
});
|
|
1061
|
+
if (isUpdatableModel(model)) {
|
|
1062
|
+
const updatableFields = fields2.filter(isUpdatableField);
|
|
1063
|
+
if (!updatableFields.length) {
|
|
1064
|
+
return;
|
|
1065
|
+
}
|
|
1066
|
+
up.push(() => {
|
|
1067
|
+
this.alterTable(`${model.name}Revision`, () => {
|
|
1068
|
+
for (const [index, field] of updatableFields.entries()) {
|
|
1069
|
+
this.columnRaw(field, { alter: true }, index);
|
|
1070
|
+
}
|
|
1071
|
+
});
|
|
1072
|
+
});
|
|
1073
|
+
down.push(() => {
|
|
1074
|
+
this.alterTable(`${model.name}Revision`, () => {
|
|
1075
|
+
for (const [index, field] of updatableFields.entries()) {
|
|
1076
|
+
this.columnRaw(
|
|
1077
|
+
field,
|
|
1078
|
+
{ alter: true },
|
|
1079
|
+
index,
|
|
1080
|
+
summonByName(this.columns[model.name], field.kind === "relation" ? `${field.name}Id` : field.name)
|
|
1081
|
+
);
|
|
1082
|
+
}
|
|
1083
|
+
});
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1026
1087
|
updateFields(model, fields2, up, down) {
|
|
1027
1088
|
if (!fields2.length) {
|
|
1028
1089
|
return;
|
|
@@ -1143,6 +1204,11 @@ var MigrationGenerator = class {
|
|
|
1143
1204
|
createTable(table, block) {
|
|
1144
1205
|
return this.writer.write(`await knex.schema.createTable('${table}', (table) => `).inlineBlock(block).write(");").newLine().blankLine();
|
|
1145
1206
|
}
|
|
1207
|
+
alterTableRaw(table, block) {
|
|
1208
|
+
this.writer.write(`await knex.raw('ALTER TABLE "${table}"`);
|
|
1209
|
+
block();
|
|
1210
|
+
this.writer.write(`');`).newLine().blankLine();
|
|
1211
|
+
}
|
|
1146
1212
|
alterTable(table, block) {
|
|
1147
1213
|
return this.writer.write(`await knex.schema.alterTable('${table}', (table) => `).inlineBlock(block).write(");").newLine().blankLine();
|
|
1148
1214
|
}
|
|
@@ -1164,25 +1230,107 @@ var MigrationGenerator = class {
|
|
|
1164
1230
|
}
|
|
1165
1231
|
return value2;
|
|
1166
1232
|
}
|
|
1167
|
-
|
|
1168
|
-
const
|
|
1169
|
-
if (what) {
|
|
1170
|
-
this.writer.write(what);
|
|
1171
|
-
}
|
|
1233
|
+
columnRaw({ name: name2, ...field }, { setNonNull = true, alter = false } = {}, index, toColumn) {
|
|
1234
|
+
const nonNull2 = () => {
|
|
1172
1235
|
if (setNonNull) {
|
|
1173
1236
|
if (toColumn) {
|
|
1174
1237
|
if (toColumn.is_nullable) {
|
|
1175
|
-
|
|
1176
|
-
} else {
|
|
1177
|
-
this.writer.write(".notNullable()");
|
|
1238
|
+
return false;
|
|
1178
1239
|
}
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1240
|
+
return true;
|
|
1241
|
+
}
|
|
1242
|
+
if (field.nonNull) {
|
|
1243
|
+
return true;
|
|
1244
|
+
}
|
|
1245
|
+
return false;
|
|
1246
|
+
}
|
|
1247
|
+
};
|
|
1248
|
+
const kind = field.kind;
|
|
1249
|
+
if (field.generateAs) {
|
|
1250
|
+
let type = "";
|
|
1251
|
+
switch (kind) {
|
|
1252
|
+
case void 0:
|
|
1253
|
+
case "primitive":
|
|
1254
|
+
switch (field.type) {
|
|
1255
|
+
case "Float":
|
|
1256
|
+
type = `decimal(${field.precision ?? "undefined"}, ${field.scale ?? "undefined"})`;
|
|
1257
|
+
break;
|
|
1258
|
+
default:
|
|
1259
|
+
throw new Error(`Generated columns of kind ${kind} and type ${field.type} are not supported yet.`);
|
|
1260
|
+
}
|
|
1261
|
+
break;
|
|
1262
|
+
default:
|
|
1263
|
+
throw new Error(`Generated columns of kind ${kind} are not supported yet.`);
|
|
1264
|
+
}
|
|
1265
|
+
if (index) {
|
|
1266
|
+
this.writer.write(`,`);
|
|
1267
|
+
}
|
|
1268
|
+
if (alter) {
|
|
1269
|
+
this.writer.write(` ALTER COLUMN "${name2}" TYPE ${type}`);
|
|
1270
|
+
if (setNonNull) {
|
|
1271
|
+
if (nonNull2()) {
|
|
1272
|
+
this.writer.write(`, ALTER COLUMN "${name2}" SET NOT NULL`);
|
|
1182
1273
|
} else {
|
|
1183
|
-
this.writer.write("
|
|
1274
|
+
this.writer.write(`, ALTER COLUMN "${name2}" DROP NOT NULL`);
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
this.writer.write(`, ALTER COLUMN "${name2}" SET EXPRESSION AS (${field.generateAs})`);
|
|
1278
|
+
} else {
|
|
1279
|
+
this.writer.write(
|
|
1280
|
+
`${alter ? "ALTER" : "ADD"} COLUMN "${name2}" ${type}${nonNull2() ? " not null" : ""} GENERATED ALWAYS AS (${field.generateAs}) STORED`
|
|
1281
|
+
);
|
|
1282
|
+
}
|
|
1283
|
+
return;
|
|
1284
|
+
}
|
|
1285
|
+
throw new Error(`Only generated columns can be created with columnRaw`);
|
|
1286
|
+
}
|
|
1287
|
+
column({ name: name2, primary, list: list2, ...field }, { setUnique = true, setNonNull = true, alter = false, foreign = true, setDefault = true } = {}, toColumn) {
|
|
1288
|
+
const nonNull2 = () => {
|
|
1289
|
+
if (setNonNull) {
|
|
1290
|
+
if (toColumn) {
|
|
1291
|
+
if (toColumn.is_nullable) {
|
|
1292
|
+
return false;
|
|
1184
1293
|
}
|
|
1294
|
+
return true;
|
|
1295
|
+
}
|
|
1296
|
+
if (field.nonNull) {
|
|
1297
|
+
return true;
|
|
1185
1298
|
}
|
|
1299
|
+
return false;
|
|
1300
|
+
}
|
|
1301
|
+
};
|
|
1302
|
+
const kind = field.kind;
|
|
1303
|
+
if (field.generateAs) {
|
|
1304
|
+
let type = "";
|
|
1305
|
+
switch (kind) {
|
|
1306
|
+
case void 0:
|
|
1307
|
+
case "primitive":
|
|
1308
|
+
switch (field.type) {
|
|
1309
|
+
case "Float":
|
|
1310
|
+
type = `decimal(${field.precision ?? "undefined"}, ${field.scale ?? "undefined"})`;
|
|
1311
|
+
break;
|
|
1312
|
+
default:
|
|
1313
|
+
throw new Error(`Generated columns of kind ${kind} and type ${field.type} are not supported yet.`);
|
|
1314
|
+
}
|
|
1315
|
+
break;
|
|
1316
|
+
default:
|
|
1317
|
+
throw new Error(`Generated columns of kind ${kind} are not supported yet.`);
|
|
1318
|
+
}
|
|
1319
|
+
this.writer.write(
|
|
1320
|
+
`table.specificType('${name2}', '${type}${nonNull2() ? " not null" : ""} GENERATED ALWAYS AS (${field.generateAs}) STORED')`
|
|
1321
|
+
);
|
|
1322
|
+
if (alter) {
|
|
1323
|
+
this.writer.write(".alter()");
|
|
1324
|
+
}
|
|
1325
|
+
this.writer.write(";").newLine();
|
|
1326
|
+
return;
|
|
1327
|
+
}
|
|
1328
|
+
const col = (what) => {
|
|
1329
|
+
if (what) {
|
|
1330
|
+
this.writer.write(what);
|
|
1331
|
+
}
|
|
1332
|
+
if (setNonNull) {
|
|
1333
|
+
this.writer.write(nonNull2() ? ".notNullable()" : ".nullable()");
|
|
1186
1334
|
}
|
|
1187
1335
|
if (setDefault && field.defaultValue !== void 0) {
|
|
1188
1336
|
this.writer.write(`.defaultTo(${this.value(field.defaultValue)})`);
|
|
@@ -1197,7 +1345,6 @@ var MigrationGenerator = class {
|
|
|
1197
1345
|
}
|
|
1198
1346
|
this.writer.write(";").newLine();
|
|
1199
1347
|
};
|
|
1200
|
-
const kind = field.kind;
|
|
1201
1348
|
switch (kind) {
|
|
1202
1349
|
case void 0:
|
|
1203
1350
|
case "primitive":
|
|
@@ -1267,6 +1414,39 @@ var MigrationGenerator = class {
|
|
|
1267
1414
|
getColumn(tableName, columnName) {
|
|
1268
1415
|
return this.columns[tableName].find((col) => col.name === columnName);
|
|
1269
1416
|
}
|
|
1417
|
+
hasChanged(model, field) {
|
|
1418
|
+
const col = this.getColumn(model.name, field.kind === "relation" ? `${field.name}Id` : field.name);
|
|
1419
|
+
if (!col) {
|
|
1420
|
+
return false;
|
|
1421
|
+
}
|
|
1422
|
+
if (field.generateAs) {
|
|
1423
|
+
if (col.generation_expression !== field.generateAs) {
|
|
1424
|
+
throw new Error(
|
|
1425
|
+
`Column ${col.name} has specific type ${col.generation_expression} but expected ${field.generateAs}`
|
|
1426
|
+
);
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
if (!field.nonNull && !col.is_nullable || field.nonNull && col.is_nullable) {
|
|
1430
|
+
return true;
|
|
1431
|
+
}
|
|
1432
|
+
if (!field.kind || field.kind === "primitive") {
|
|
1433
|
+
if (field.type === "Int") {
|
|
1434
|
+
if (col.data_type !== "integer") {
|
|
1435
|
+
return true;
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
if (field.type === "Float") {
|
|
1439
|
+
if (field.double) {
|
|
1440
|
+
if (col.data_type !== "double precision") {
|
|
1441
|
+
return true;
|
|
1442
|
+
}
|
|
1443
|
+
} else if (col.data_type !== "numeric") {
|
|
1444
|
+
return true;
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
return false;
|
|
1449
|
+
}
|
|
1270
1450
|
};
|
|
1271
1451
|
var getMigrationDate = () => {
|
|
1272
1452
|
const date = /* @__PURE__ */ new Date();
|
|
@@ -2478,6 +2658,21 @@ import_commander.program.command("generate-migration [<name>] [<date>]").descrip
|
|
|
2478
2658
|
await db.destroy();
|
|
2479
2659
|
}
|
|
2480
2660
|
});
|
|
2661
|
+
import_commander.program.command("check-needs-migration").description("Check if a migration is needed").action(async () => {
|
|
2662
|
+
const knexfile = await parseKnexfile();
|
|
2663
|
+
const db = (0, import_knex.default)(knexfile);
|
|
2664
|
+
try {
|
|
2665
|
+
const models = await parseModels();
|
|
2666
|
+
const mg = new MigrationGenerator(db, models);
|
|
2667
|
+
await mg.generate();
|
|
2668
|
+
if (mg.needsMigration) {
|
|
2669
|
+
console.error("Migration is needed.");
|
|
2670
|
+
process.exit(1);
|
|
2671
|
+
}
|
|
2672
|
+
} finally {
|
|
2673
|
+
await db.destroy();
|
|
2674
|
+
}
|
|
2675
|
+
});
|
|
2481
2676
|
import_commander.program.command("*", { noHelp: true }).description("Invalid command").action(() => {
|
|
2482
2677
|
console.error("Invalid command: %s\nSee --help for a list of available commands.", import_commander.program.args.join(" "));
|
|
2483
2678
|
process.exit(1);
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -1114,6 +1114,7 @@ var MigrationGenerator = class {
|
|
|
1114
1114
|
columns = {};
|
|
1115
1115
|
uuidUsed;
|
|
1116
1116
|
nowUsed;
|
|
1117
|
+
needsMigration = false;
|
|
1117
1118
|
async generate() {
|
|
1118
1119
|
const { writer, schema, models } = this;
|
|
1119
1120
|
const enums = (await schema.knex("pg_type").where({ typtype: "e" }).select("typname")).map(({ typname }) => typname);
|
|
@@ -1212,13 +1213,23 @@ var MigrationGenerator = class {
|
|
|
1212
1213
|
up,
|
|
1213
1214
|
down
|
|
1214
1215
|
);
|
|
1215
|
-
const
|
|
1216
|
-
|
|
1216
|
+
const rawExistingFields = model.fields.filter((field) => {
|
|
1217
|
+
if (!field.generateAs) {
|
|
1218
|
+
return false;
|
|
1219
|
+
}
|
|
1220
|
+
const col = this.getColumn(model.name, field.kind === "relation" ? `${field.name}Id` : field.name);
|
|
1217
1221
|
if (!col) {
|
|
1218
1222
|
return false;
|
|
1219
1223
|
}
|
|
1220
|
-
|
|
1224
|
+
if (col.generation_expression !== field.generateAs) {
|
|
1225
|
+
return true;
|
|
1226
|
+
}
|
|
1227
|
+
return this.hasChanged(model, field);
|
|
1221
1228
|
});
|
|
1229
|
+
if (rawExistingFields.length) {
|
|
1230
|
+
this.updateFieldsRaw(model, rawExistingFields, up, down);
|
|
1231
|
+
}
|
|
1232
|
+
const existingFields = model.fields.filter((field) => !field.generateAs && this.hasChanged(model, field));
|
|
1222
1233
|
this.updateFields(model, existingFields, up, down);
|
|
1223
1234
|
}
|
|
1224
1235
|
if (isUpdatableModel(model)) {
|
|
@@ -1316,6 +1327,9 @@ var MigrationGenerator = class {
|
|
|
1316
1327
|
if (this.nowUsed) {
|
|
1317
1328
|
writer.writeLine(`const now = date();`).blankLine();
|
|
1318
1329
|
}
|
|
1330
|
+
if (up.length || down.length) {
|
|
1331
|
+
this.needsMigration = true;
|
|
1332
|
+
}
|
|
1319
1333
|
this.migration("up", up);
|
|
1320
1334
|
this.migration("down", down.reverse());
|
|
1321
1335
|
return writer.toString();
|
|
@@ -1358,6 +1372,9 @@ var MigrationGenerator = class {
|
|
|
1358
1372
|
const postAlter = [];
|
|
1359
1373
|
for (const field of fields2) {
|
|
1360
1374
|
alter.push(() => this.column(field, { setNonNull: field.defaultValue !== void 0 }));
|
|
1375
|
+
if (field.generateAs) {
|
|
1376
|
+
continue;
|
|
1377
|
+
}
|
|
1361
1378
|
if (field.nonNull && field.defaultValue === void 0) {
|
|
1362
1379
|
updates.push(() => this.writer.write(`${field.name}: 'TODO',`).newLine());
|
|
1363
1380
|
postAlter.push(() => this.column(field, { alter: true, foreign: false }));
|
|
@@ -1381,12 +1398,56 @@ var MigrationGenerator = class {
|
|
|
1381
1398
|
});
|
|
1382
1399
|
down.push(() => {
|
|
1383
1400
|
this.alterTable(model.name, () => {
|
|
1384
|
-
for (const { kind, name: name2 } of fields2) {
|
|
1401
|
+
for (const { kind, name: name2 } of fields2.toReversed()) {
|
|
1385
1402
|
this.dropColumn(kind === "relation" ? `${name2}Id` : name2);
|
|
1386
1403
|
}
|
|
1387
1404
|
});
|
|
1388
1405
|
});
|
|
1389
1406
|
}
|
|
1407
|
+
updateFieldsRaw(model, fields2, up, down) {
|
|
1408
|
+
if (!fields2.length) {
|
|
1409
|
+
return;
|
|
1410
|
+
}
|
|
1411
|
+
up.push(() => {
|
|
1412
|
+
this.alterTableRaw(model.name, () => {
|
|
1413
|
+
for (const [index, field] of fields2.entries()) {
|
|
1414
|
+
this.columnRaw(field, { alter: true }, index);
|
|
1415
|
+
}
|
|
1416
|
+
});
|
|
1417
|
+
});
|
|
1418
|
+
down.push(() => {
|
|
1419
|
+
this.alterTableRaw(model.name, () => {
|
|
1420
|
+
for (const [index, field] of fields2.entries()) {
|
|
1421
|
+
this.columnRaw(field, { alter: true }, index);
|
|
1422
|
+
}
|
|
1423
|
+
});
|
|
1424
|
+
});
|
|
1425
|
+
if (isUpdatableModel(model)) {
|
|
1426
|
+
const updatableFields = fields2.filter(isUpdatableField);
|
|
1427
|
+
if (!updatableFields.length) {
|
|
1428
|
+
return;
|
|
1429
|
+
}
|
|
1430
|
+
up.push(() => {
|
|
1431
|
+
this.alterTable(`${model.name}Revision`, () => {
|
|
1432
|
+
for (const [index, field] of updatableFields.entries()) {
|
|
1433
|
+
this.columnRaw(field, { alter: true }, index);
|
|
1434
|
+
}
|
|
1435
|
+
});
|
|
1436
|
+
});
|
|
1437
|
+
down.push(() => {
|
|
1438
|
+
this.alterTable(`${model.name}Revision`, () => {
|
|
1439
|
+
for (const [index, field] of updatableFields.entries()) {
|
|
1440
|
+
this.columnRaw(
|
|
1441
|
+
field,
|
|
1442
|
+
{ alter: true },
|
|
1443
|
+
index,
|
|
1444
|
+
summonByName(this.columns[model.name], field.kind === "relation" ? `${field.name}Id` : field.name)
|
|
1445
|
+
);
|
|
1446
|
+
}
|
|
1447
|
+
});
|
|
1448
|
+
});
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1390
1451
|
updateFields(model, fields2, up, down) {
|
|
1391
1452
|
if (!fields2.length) {
|
|
1392
1453
|
return;
|
|
@@ -1507,6 +1568,11 @@ var MigrationGenerator = class {
|
|
|
1507
1568
|
createTable(table, block) {
|
|
1508
1569
|
return this.writer.write(`await knex.schema.createTable('${table}', (table) => `).inlineBlock(block).write(");").newLine().blankLine();
|
|
1509
1570
|
}
|
|
1571
|
+
alterTableRaw(table, block) {
|
|
1572
|
+
this.writer.write(`await knex.raw('ALTER TABLE "${table}"`);
|
|
1573
|
+
block();
|
|
1574
|
+
this.writer.write(`');`).newLine().blankLine();
|
|
1575
|
+
}
|
|
1510
1576
|
alterTable(table, block) {
|
|
1511
1577
|
return this.writer.write(`await knex.schema.alterTable('${table}', (table) => `).inlineBlock(block).write(");").newLine().blankLine();
|
|
1512
1578
|
}
|
|
@@ -1528,25 +1594,107 @@ var MigrationGenerator = class {
|
|
|
1528
1594
|
}
|
|
1529
1595
|
return value2;
|
|
1530
1596
|
}
|
|
1531
|
-
|
|
1532
|
-
const
|
|
1533
|
-
if (what) {
|
|
1534
|
-
this.writer.write(what);
|
|
1535
|
-
}
|
|
1597
|
+
columnRaw({ name: name2, ...field }, { setNonNull = true, alter = false } = {}, index, toColumn) {
|
|
1598
|
+
const nonNull2 = () => {
|
|
1536
1599
|
if (setNonNull) {
|
|
1537
1600
|
if (toColumn) {
|
|
1538
1601
|
if (toColumn.is_nullable) {
|
|
1539
|
-
|
|
1540
|
-
} else {
|
|
1541
|
-
this.writer.write(".notNullable()");
|
|
1602
|
+
return false;
|
|
1542
1603
|
}
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1604
|
+
return true;
|
|
1605
|
+
}
|
|
1606
|
+
if (field.nonNull) {
|
|
1607
|
+
return true;
|
|
1608
|
+
}
|
|
1609
|
+
return false;
|
|
1610
|
+
}
|
|
1611
|
+
};
|
|
1612
|
+
const kind = field.kind;
|
|
1613
|
+
if (field.generateAs) {
|
|
1614
|
+
let type = "";
|
|
1615
|
+
switch (kind) {
|
|
1616
|
+
case void 0:
|
|
1617
|
+
case "primitive":
|
|
1618
|
+
switch (field.type) {
|
|
1619
|
+
case "Float":
|
|
1620
|
+
type = `decimal(${field.precision ?? "undefined"}, ${field.scale ?? "undefined"})`;
|
|
1621
|
+
break;
|
|
1622
|
+
default:
|
|
1623
|
+
throw new Error(`Generated columns of kind ${kind} and type ${field.type} are not supported yet.`);
|
|
1624
|
+
}
|
|
1625
|
+
break;
|
|
1626
|
+
default:
|
|
1627
|
+
throw new Error(`Generated columns of kind ${kind} are not supported yet.`);
|
|
1628
|
+
}
|
|
1629
|
+
if (index) {
|
|
1630
|
+
this.writer.write(`,`);
|
|
1631
|
+
}
|
|
1632
|
+
if (alter) {
|
|
1633
|
+
this.writer.write(` ALTER COLUMN "${name2}" TYPE ${type}`);
|
|
1634
|
+
if (setNonNull) {
|
|
1635
|
+
if (nonNull2()) {
|
|
1636
|
+
this.writer.write(`, ALTER COLUMN "${name2}" SET NOT NULL`);
|
|
1546
1637
|
} else {
|
|
1547
|
-
this.writer.write("
|
|
1638
|
+
this.writer.write(`, ALTER COLUMN "${name2}" DROP NOT NULL`);
|
|
1548
1639
|
}
|
|
1549
1640
|
}
|
|
1641
|
+
this.writer.write(`, ALTER COLUMN "${name2}" SET EXPRESSION AS (${field.generateAs})`);
|
|
1642
|
+
} else {
|
|
1643
|
+
this.writer.write(
|
|
1644
|
+
`${alter ? "ALTER" : "ADD"} COLUMN "${name2}" ${type}${nonNull2() ? " not null" : ""} GENERATED ALWAYS AS (${field.generateAs}) STORED`
|
|
1645
|
+
);
|
|
1646
|
+
}
|
|
1647
|
+
return;
|
|
1648
|
+
}
|
|
1649
|
+
throw new Error(`Only generated columns can be created with columnRaw`);
|
|
1650
|
+
}
|
|
1651
|
+
column({ name: name2, primary, list: list2, ...field }, { setUnique = true, setNonNull = true, alter = false, foreign = true, setDefault = true } = {}, toColumn) {
|
|
1652
|
+
const nonNull2 = () => {
|
|
1653
|
+
if (setNonNull) {
|
|
1654
|
+
if (toColumn) {
|
|
1655
|
+
if (toColumn.is_nullable) {
|
|
1656
|
+
return false;
|
|
1657
|
+
}
|
|
1658
|
+
return true;
|
|
1659
|
+
}
|
|
1660
|
+
if (field.nonNull) {
|
|
1661
|
+
return true;
|
|
1662
|
+
}
|
|
1663
|
+
return false;
|
|
1664
|
+
}
|
|
1665
|
+
};
|
|
1666
|
+
const kind = field.kind;
|
|
1667
|
+
if (field.generateAs) {
|
|
1668
|
+
let type = "";
|
|
1669
|
+
switch (kind) {
|
|
1670
|
+
case void 0:
|
|
1671
|
+
case "primitive":
|
|
1672
|
+
switch (field.type) {
|
|
1673
|
+
case "Float":
|
|
1674
|
+
type = `decimal(${field.precision ?? "undefined"}, ${field.scale ?? "undefined"})`;
|
|
1675
|
+
break;
|
|
1676
|
+
default:
|
|
1677
|
+
throw new Error(`Generated columns of kind ${kind} and type ${field.type} are not supported yet.`);
|
|
1678
|
+
}
|
|
1679
|
+
break;
|
|
1680
|
+
default:
|
|
1681
|
+
throw new Error(`Generated columns of kind ${kind} are not supported yet.`);
|
|
1682
|
+
}
|
|
1683
|
+
this.writer.write(
|
|
1684
|
+
`table.specificType('${name2}', '${type}${nonNull2() ? " not null" : ""} GENERATED ALWAYS AS (${field.generateAs}) STORED')`
|
|
1685
|
+
);
|
|
1686
|
+
if (alter) {
|
|
1687
|
+
this.writer.write(".alter()");
|
|
1688
|
+
}
|
|
1689
|
+
this.writer.write(";").newLine();
|
|
1690
|
+
return;
|
|
1691
|
+
}
|
|
1692
|
+
const col = (what) => {
|
|
1693
|
+
if (what) {
|
|
1694
|
+
this.writer.write(what);
|
|
1695
|
+
}
|
|
1696
|
+
if (setNonNull) {
|
|
1697
|
+
this.writer.write(nonNull2() ? ".notNullable()" : ".nullable()");
|
|
1550
1698
|
}
|
|
1551
1699
|
if (setDefault && field.defaultValue !== void 0) {
|
|
1552
1700
|
this.writer.write(`.defaultTo(${this.value(field.defaultValue)})`);
|
|
@@ -1561,7 +1709,6 @@ var MigrationGenerator = class {
|
|
|
1561
1709
|
}
|
|
1562
1710
|
this.writer.write(";").newLine();
|
|
1563
1711
|
};
|
|
1564
|
-
const kind = field.kind;
|
|
1565
1712
|
switch (kind) {
|
|
1566
1713
|
case void 0:
|
|
1567
1714
|
case "primitive":
|
|
@@ -1631,6 +1778,39 @@ var MigrationGenerator = class {
|
|
|
1631
1778
|
getColumn(tableName, columnName) {
|
|
1632
1779
|
return this.columns[tableName].find((col) => col.name === columnName);
|
|
1633
1780
|
}
|
|
1781
|
+
hasChanged(model, field) {
|
|
1782
|
+
const col = this.getColumn(model.name, field.kind === "relation" ? `${field.name}Id` : field.name);
|
|
1783
|
+
if (!col) {
|
|
1784
|
+
return false;
|
|
1785
|
+
}
|
|
1786
|
+
if (field.generateAs) {
|
|
1787
|
+
if (col.generation_expression !== field.generateAs) {
|
|
1788
|
+
throw new Error(
|
|
1789
|
+
`Column ${col.name} has specific type ${col.generation_expression} but expected ${field.generateAs}`
|
|
1790
|
+
);
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
if (!field.nonNull && !col.is_nullable || field.nonNull && col.is_nullable) {
|
|
1794
|
+
return true;
|
|
1795
|
+
}
|
|
1796
|
+
if (!field.kind || field.kind === "primitive") {
|
|
1797
|
+
if (field.type === "Int") {
|
|
1798
|
+
if (col.data_type !== "integer") {
|
|
1799
|
+
return true;
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
if (field.type === "Float") {
|
|
1803
|
+
if (field.double) {
|
|
1804
|
+
if (col.data_type !== "double precision") {
|
|
1805
|
+
return true;
|
|
1806
|
+
}
|
|
1807
|
+
} else if (col.data_type !== "numeric") {
|
|
1808
|
+
return true;
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
return false;
|
|
1813
|
+
}
|
|
1634
1814
|
};
|
|
1635
1815
|
var getMigrationDate = () => {
|
|
1636
1816
|
const date = /* @__PURE__ */ new Date();
|
|
@@ -7,23 +7,28 @@ export declare class MigrationGenerator {
|
|
|
7
7
|
private columns;
|
|
8
8
|
private uuidUsed?;
|
|
9
9
|
private nowUsed?;
|
|
10
|
+
needsMigration: boolean;
|
|
10
11
|
constructor(knex: Knex, models: Models);
|
|
11
12
|
generate(): Promise<string>;
|
|
12
13
|
private renameFields;
|
|
13
14
|
private createFields;
|
|
15
|
+
private updateFieldsRaw;
|
|
14
16
|
private updateFields;
|
|
15
17
|
private createRevisionTable;
|
|
16
18
|
private createRevisionFields;
|
|
17
19
|
private createEnums;
|
|
18
20
|
private migration;
|
|
19
21
|
private createTable;
|
|
22
|
+
private alterTableRaw;
|
|
20
23
|
private alterTable;
|
|
21
24
|
private dropColumn;
|
|
22
25
|
private dropTable;
|
|
23
26
|
private renameTable;
|
|
24
27
|
private renameColumn;
|
|
25
28
|
private value;
|
|
29
|
+
private columnRaw;
|
|
26
30
|
private column;
|
|
27
31
|
private getColumn;
|
|
32
|
+
private hasChanged;
|
|
28
33
|
}
|
|
29
34
|
export declare const getMigrationDate: () => string;
|