@smartive/graphql-magic 23.4.0-next.8 → 23.4.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +2 -2
  2. package/dist/bin/gqm.cjs +125 -656
  3. package/dist/cjs/index.cjs +2132 -2702
  4. package/dist/esm/migrations/generate.d.ts +1 -9
  5. package/dist/esm/migrations/generate.js +33 -269
  6. package/dist/esm/migrations/generate.js.map +1 -1
  7. package/dist/esm/migrations/index.d.ts +0 -2
  8. package/dist/esm/migrations/index.js +0 -2
  9. package/dist/esm/migrations/index.js.map +1 -1
  10. package/dist/esm/models/model-definitions.d.ts +1 -4
  11. package/dist/esm/resolvers/filters.js +14 -73
  12. package/dist/esm/resolvers/filters.js.map +1 -1
  13. package/dist/esm/resolvers/selects.js +2 -33
  14. package/dist/esm/resolvers/selects.js.map +1 -1
  15. package/dist/esm/resolvers/utils.d.ts +0 -1
  16. package/dist/esm/resolvers/utils.js +0 -22
  17. package/dist/esm/resolvers/utils.js.map +1 -1
  18. package/docs/docs/3-fields.md +0 -149
  19. package/docs/docs/5-migrations.md +1 -9
  20. package/package.json +2 -2
  21. package/src/bin/gqm/gqm.ts +5 -44
  22. package/src/bin/gqm/settings.ts +0 -7
  23. package/src/bin/gqm/static-eval.ts +102 -0
  24. package/src/bin/gqm/utils.ts +0 -1
  25. package/src/migrations/generate.ts +41 -334
  26. package/src/migrations/index.ts +0 -2
  27. package/src/models/model-definitions.ts +1 -4
  28. package/src/resolvers/filters.ts +25 -81
  29. package/src/resolvers/selects.ts +5 -38
  30. package/src/resolvers/utils.ts +0 -32
  31. package/dist/esm/migrations/generate-functions.d.ts +0 -2
  32. package/dist/esm/migrations/generate-functions.js +0 -60
  33. package/dist/esm/migrations/generate-functions.js.map +0 -1
  34. package/dist/esm/migrations/types.d.ts +0 -7
  35. package/dist/esm/migrations/types.js +0 -2
  36. package/dist/esm/migrations/types.js.map +0 -1
  37. package/dist/esm/migrations/update-functions.d.ts +0 -3
  38. package/dist/esm/migrations/update-functions.js +0 -177
  39. package/dist/esm/migrations/update-functions.js.map +0 -1
  40. package/src/bin/gqm/parse-functions.ts +0 -141
  41. package/src/migrations/generate-functions.ts +0 -74
  42. package/src/migrations/types.ts +0 -7
  43. package/src/migrations/update-functions.ts +0 -221
package/dist/bin/gqm.cjs CHANGED
@@ -750,25 +750,9 @@ var generateKnexTables = (models) => {
750
750
  var import_code_block_writer2 = __toESM(require("code-block-writer"), 1);
751
751
  var import_knex_schema_inspector = require("knex-schema-inspector");
752
752
  var import_lowerFirst = __toESM(require("lodash/lowerFirst"), 1);
753
-
754
- // src/resolvers/arguments.ts
755
- var import_graphql3 = require("graphql");
756
-
757
- // src/resolvers/utils.ts
758
- var import_graphql4 = require("graphql");
759
- var import_isEqual = __toESM(require("lodash/isEqual"), 1);
760
- var getColumnName = (field) => field.kind === "relation" ? field.foreignKey || `${field.name}Id` : field.name;
761
-
762
- // src/resolvers/resolver.ts
763
- var import_cloneDeep2 = __toESM(require("lodash/cloneDeep"), 1);
764
- var import_flatMap = __toESM(require("lodash/flatMap"), 1);
765
-
766
- // src/migrations/generate.ts
767
753
  var MigrationGenerator = class {
768
- constructor(knex2, models, parsedFunctions) {
754
+ constructor(knex2, models) {
769
755
  this.models = models;
770
- this.parsedFunctions = parsedFunctions;
771
- this.knex = knex2;
772
756
  this.schema = (0, import_knex_schema_inspector.SchemaInspector)(knex2);
773
757
  }
774
758
  // eslint-disable-next-line @typescript-eslint/dot-notation
@@ -781,7 +765,6 @@ var MigrationGenerator = class {
781
765
  uuidUsed;
782
766
  nowUsed;
783
767
  needsMigration = false;
784
- knex;
785
768
  async generate() {
786
769
  const { writer, schema, models } = this;
787
770
  const enums = (await schema.knex("pg_type").where({ typtype: "e" }).select("typname")).map(({ typname }) => typname);
@@ -796,7 +779,6 @@ var MigrationGenerator = class {
796
779
  up,
797
780
  down
798
781
  );
799
- await this.handleFunctions(up, down);
800
782
  for (const model of models.entities) {
801
783
  if (model.deleted) {
802
784
  up.push(() => {
@@ -858,7 +840,7 @@ var MigrationGenerator = class {
858
840
  foreignKey: "id"
859
841
  });
860
842
  }
861
- for (const field of model.fields.filter(not(isInherited)).filter((f) => !(f.generateAs?.type === "expression"))) {
843
+ for (const field of model.fields.filter(not(isInherited))) {
862
844
  this.column(field);
863
845
  }
864
846
  });
@@ -867,25 +849,29 @@ var MigrationGenerator = class {
867
849
  this.dropTable(model.name);
868
850
  });
869
851
  } else {
870
- const fieldsToRename = model.fields.filter(not(isInherited)).filter(({ oldName }) => oldName);
871
- this.renameFields(model.name, fieldsToRename, up, down);
852
+ this.renameFields(
853
+ model,
854
+ model.fields.filter(not(isInherited)).filter(({ oldName }) => oldName),
855
+ up,
856
+ down
857
+ );
872
858
  this.createFields(
873
859
  model,
874
860
  model.fields.filter(not(isInherited)).filter(
875
- ({ name: name2, ...field }) => field.kind !== "custom" && !(field.generateAs?.type === "expression") && !this.getColumn(model.name, field.kind === "relation" ? field.foreignKey || `${name2}Id` : name2)
861
+ ({ name: name2, ...field }) => field.kind !== "custom" && !this.getColumn(model.name, field.kind === "relation" ? field.foreignKey || `${name2}Id` : name2)
876
862
  ),
877
863
  up,
878
864
  down
879
865
  );
880
866
  const rawExistingFields = model.fields.filter((field) => {
881
- if (!field.generateAs || field.generateAs.type === "expression") {
867
+ if (!field.generateAs) {
882
868
  return false;
883
869
  }
884
870
  const col = this.getColumn(model.name, field.kind === "relation" ? `${field.name}Id` : field.name);
885
871
  if (!col) {
886
872
  return false;
887
873
  }
888
- if (col.generation_expression !== field.generateAs.expression) {
874
+ if (col.generation_expression !== field.generateAs) {
889
875
  return true;
890
876
  }
891
877
  return this.hasChanged(model, field);
@@ -893,9 +879,7 @@ var MigrationGenerator = class {
893
879
  if (rawExistingFields.length) {
894
880
  this.updateFieldsRaw(model, rawExistingFields, up, down);
895
881
  }
896
- const existingFields = model.fields.filter(
897
- (field) => (!field.generateAs || field.generateAs.type === "expression") && this.hasChanged(model, field)
898
- );
882
+ const existingFields = model.fields.filter((field) => !field.generateAs && this.hasChanged(model, field));
899
883
  this.updateFields(model, existingFields, up, down);
900
884
  }
901
885
  if (isUpdatableModel(model)) {
@@ -919,7 +903,7 @@ var MigrationGenerator = class {
919
903
  writer.writeLine(`deleteRootType: row.deleteRootType,`);
920
904
  writer.writeLine(`deleteRootId: row.deleteRootId,`);
921
905
  }
922
- for (const { name: name2, kind } of model.fields.filter(isUpdatableField).filter((f) => !(f.generateAs?.type === "expression"))) {
906
+ for (const { name: name2, kind } of model.fields.filter(isUpdatableField)) {
923
907
  const col = kind === "relation" ? `${name2}Id` : name2;
924
908
  writer.writeLine(`${col}: row.${col},`);
925
909
  }
@@ -933,14 +917,8 @@ var MigrationGenerator = class {
933
917
  });
934
918
  } else {
935
919
  const revisionTable = `${model.name}Revision`;
936
- this.renameFields(
937
- revisionTable,
938
- model.fields.filter(isUpdatableField).filter(not(isInherited)).filter(({ oldName }) => oldName),
939
- up,
940
- down
941
- );
942
920
  const missingRevisionFields = model.fields.filter(isUpdatableField).filter(
943
- ({ name: name2, ...field }) => field.kind !== "custom" && !(field.generateAs?.type === "expression") && !this.getColumn(revisionTable, field.kind === "relation" ? field.foreignKey || `${name2}Id` : name2)
921
+ ({ name: name2, ...field }) => field.kind !== "custom" && !this.getColumn(revisionTable, field.kind === "relation" ? field.foreignKey || `${name2}Id` : name2)
944
922
  );
945
923
  this.createRevisionFields(model, missingRevisionFields, up, down);
946
924
  const revisionFieldsToRemove = model.fields.filter(
@@ -1006,13 +984,13 @@ var MigrationGenerator = class {
1006
984
  this.migration("down", down.reverse());
1007
985
  return writer.toString();
1008
986
  }
1009
- renameFields(tableName, fields2, up, down) {
987
+ renameFields(model, fields2, up, down) {
1010
988
  if (!fields2.length) {
1011
989
  return;
1012
990
  }
1013
991
  up.push(() => {
1014
992
  for (const field of fields2) {
1015
- this.alterTable(tableName, () => {
993
+ this.alterTable(model.name, () => {
1016
994
  this.renameColumn(
1017
995
  field.kind === "relation" ? `${field.oldName}Id` : get(field, "oldName"),
1018
996
  field.kind === "relation" ? `${field.name}Id` : field.name
@@ -1022,7 +1000,7 @@ var MigrationGenerator = class {
1022
1000
  });
1023
1001
  down.push(() => {
1024
1002
  for (const field of fields2) {
1025
- this.alterTable(tableName, () => {
1003
+ this.alterTable(model.name, () => {
1026
1004
  this.renameColumn(
1027
1005
  field.kind === "relation" ? `${field.name}Id` : field.name,
1028
1006
  field.kind === "relation" ? `${field.oldName}Id` : get(field, "oldName")
@@ -1031,7 +1009,7 @@ var MigrationGenerator = class {
1031
1009
  }
1032
1010
  });
1033
1011
  for (const field of fields2) {
1034
- summonByName(this.columns[tableName], field.kind === "relation" ? `${field.oldName}Id` : field.oldName).name = field.kind === "relation" ? `${field.name}Id` : field.name;
1012
+ summonByName(this.columns[model.name], field.kind === "relation" ? `${field.oldName}Id` : field.oldName).name = field.kind === "relation" ? `${field.name}Id` : field.name;
1035
1013
  }
1036
1014
  }
1037
1015
  createFields(model, fields2, up, down) {
@@ -1043,9 +1021,6 @@ var MigrationGenerator = class {
1043
1021
  const updates = [];
1044
1022
  const postAlter = [];
1045
1023
  for (const field of fields2) {
1046
- if (field.generateAs?.type === "expression") {
1047
- continue;
1048
- }
1049
1024
  alter.push(() => this.column(field, { setNonNull: field.defaultValue !== void 0 }));
1050
1025
  if (field.generateAs) {
1051
1026
  continue;
@@ -1098,7 +1073,7 @@ var MigrationGenerator = class {
1098
1073
  });
1099
1074
  });
1100
1075
  if (isUpdatableModel(model)) {
1101
- const updatableFields = fields2.filter(isUpdatableField).filter((f) => !(f.generateAs?.type === "expression"));
1076
+ const updatableFields = fields2.filter(isUpdatableField);
1102
1077
  if (!updatableFields.length) {
1103
1078
  return;
1104
1079
  }
@@ -1146,7 +1121,7 @@ var MigrationGenerator = class {
1146
1121
  });
1147
1122
  });
1148
1123
  if (isUpdatableModel(model)) {
1149
- const updatableFields = fields2.filter(isUpdatableField).filter((f) => !(f.generateAs?.type === "expression"));
1124
+ const updatableFields = fields2.filter(isUpdatableField);
1150
1125
  if (!updatableFields.length) {
1151
1126
  return;
1152
1127
  }
@@ -1184,7 +1159,7 @@ var MigrationGenerator = class {
1184
1159
  writer.writeLine(`table.uuid('deleteRootId');`);
1185
1160
  }
1186
1161
  }
1187
- for (const field of model.fields.filter(and(isUpdatableField, not(isInherited))).filter((f) => !(f.generateAs?.type === "expression"))) {
1162
+ for (const field of model.fields.filter(and(isUpdatableField, not(isInherited)))) {
1188
1163
  this.column(field, { setUnique: false, setDefault: false });
1189
1164
  }
1190
1165
  });
@@ -1198,19 +1173,14 @@ var MigrationGenerator = class {
1198
1173
  this.column(field, { setUnique: false, setNonNull: false, setDefault: false });
1199
1174
  }
1200
1175
  });
1201
- const revisionFieldsWithDataToCopy = missingRevisionFields.filter(
1202
- (field) => this.columns[model.name].find((col) => col.name === getColumnName(field)) || field.defaultValue !== void 0 || field.nonNull
1203
- );
1204
- if (revisionFieldsWithDataToCopy.length) {
1205
- this.writer.write(`await knex('${model.name}Revision').update(`).inlineBlock(() => {
1206
- for (const { name: name2, kind: type } of revisionFieldsWithDataToCopy) {
1207
- const col = type === "relation" ? `${name2}Id` : name2;
1208
- this.writer.write(
1209
- `${col}: knex.raw('(select "${col}" from "${model.name}" where "${model.name}".id = "${model.name}Revision"."${typeToField(model.name)}Id")'),`
1210
- ).newLine();
1211
- }
1212
- }).write(");").newLine().blankLine();
1213
- }
1176
+ this.writer.write(`await knex('${model.name}Revision').update(`).inlineBlock(() => {
1177
+ for (const { name: name2, kind: type } of missingRevisionFields) {
1178
+ const col = type === "relation" ? `${name2}Id` : name2;
1179
+ this.writer.write(
1180
+ `${col}: knex.raw('(select "${col}" from "${model.name}" where "${model.name}".id = "${model.name}Revision"."${typeToField(model.name)}Id")'),`
1181
+ ).newLine();
1182
+ }
1183
+ }).write(");").newLine().blankLine();
1214
1184
  const nonNullableMissingRevisionFields = missingRevisionFields.filter(({ nonNull: nonNull2 }) => nonNull2);
1215
1185
  if (nonNullableMissingRevisionFields.length) {
1216
1186
  this.alterTable(revisionTable, () => {
@@ -1266,7 +1236,7 @@ var MigrationGenerator = class {
1266
1236
  return this.writer.writeLine(`await knex.schema.renameTable('${from}', '${to}');`).blankLine();
1267
1237
  }
1268
1238
  renameColumn(from, to) {
1269
- this.writer.writeLine(`table.renameColumn('${from}', '${to}');`);
1239
+ this.writer.writeLine(`table.renameColumn('${from}', '${to}')`);
1270
1240
  }
1271
1241
  value(value2) {
1272
1242
  if (typeof value2 === "string") {
@@ -1291,9 +1261,6 @@ var MigrationGenerator = class {
1291
1261
  };
1292
1262
  const kind = field.kind;
1293
1263
  if (field.generateAs) {
1294
- if (field.generateAs.type === "expression") {
1295
- throw new Error(`Expression fields cannot be created in SQL schema.`);
1296
- }
1297
1264
  let type = "";
1298
1265
  switch (kind) {
1299
1266
  case void 0:
@@ -1302,9 +1269,6 @@ var MigrationGenerator = class {
1302
1269
  case "Float":
1303
1270
  type = `decimal(${field.precision ?? "undefined"}, ${field.scale ?? "undefined"})`;
1304
1271
  break;
1305
- case "Boolean":
1306
- type = "boolean";
1307
- break;
1308
1272
  default:
1309
1273
  throw new Error(`Generated columns of kind ${kind} and type ${field.type} are not supported yet.`);
1310
1274
  }
@@ -1324,10 +1288,10 @@ var MigrationGenerator = class {
1324
1288
  this.writer.write(`, ALTER COLUMN "${name2}" DROP NOT NULL`);
1325
1289
  }
1326
1290
  }
1327
- this.writer.write(`, ALTER COLUMN "${name2}" SET EXPRESSION AS (${field.generateAs.expression})`);
1291
+ this.writer.write(`, ALTER COLUMN "${name2}" SET EXPRESSION AS (${field.generateAs})`);
1328
1292
  } else {
1329
1293
  this.writer.write(
1330
- `${alter ? "ALTER" : "ADD"} COLUMN "${name2}" ${type}${nonNull2() ? " not null" : ""} GENERATED ALWAYS AS (${field.generateAs.expression}) STORED`
1294
+ `${alter ? "ALTER" : "ADD"} COLUMN "${name2}" ${type}${nonNull2() ? " not null" : ""} GENERATED ALWAYS AS (${field.generateAs}) STORED`
1331
1295
  );
1332
1296
  }
1333
1297
  return;
@@ -1351,9 +1315,6 @@ var MigrationGenerator = class {
1351
1315
  };
1352
1316
  const kind = field.kind;
1353
1317
  if (field.generateAs) {
1354
- if (field.generateAs.type === "expression") {
1355
- throw new Error(`Expression fields cannot be created in SQL schema.`);
1356
- }
1357
1318
  let type = "";
1358
1319
  switch (kind) {
1359
1320
  case void 0:
@@ -1362,9 +1323,6 @@ var MigrationGenerator = class {
1362
1323
  case "Float":
1363
1324
  type = `decimal(${field.precision ?? "undefined"}, ${field.scale ?? "undefined"})`;
1364
1325
  break;
1365
- case "Boolean":
1366
- type = "boolean";
1367
- break;
1368
1326
  default:
1369
1327
  throw new Error(`Generated columns of kind ${kind} and type ${field.type} are not supported yet.`);
1370
1328
  }
@@ -1373,7 +1331,7 @@ var MigrationGenerator = class {
1373
1331
  throw new Error(`Generated columns of kind ${kind} are not supported yet.`);
1374
1332
  }
1375
1333
  this.writer.write(
1376
- `table.specificType('${name2}', '${type}${nonNull2() ? " not null" : ""} GENERATED ALWAYS AS (${field.generateAs.expression}) ${field.generateAs.type === "virtual" ? "VIRTUAL" : "STORED"}')`
1334
+ `table.specificType('${name2}', '${type}${nonNull2() ? " not null" : ""} GENERATED ALWAYS AS (${field.generateAs}) STORED')`
1377
1335
  );
1378
1336
  if (alter) {
1379
1337
  this.writer.write(".alter()");
@@ -1471,17 +1429,14 @@ var MigrationGenerator = class {
1471
1429
  return this.columns[tableName].find((col) => col.name === columnName);
1472
1430
  }
1473
1431
  hasChanged(model, field) {
1474
- if (field.generateAs?.type === "expression") {
1475
- return false;
1476
- }
1477
1432
  const col = this.getColumn(model.name, field.kind === "relation" ? `${field.name}Id` : field.name);
1478
1433
  if (!col) {
1479
1434
  return false;
1480
1435
  }
1481
1436
  if (field.generateAs) {
1482
- if (col.generation_expression !== field.generateAs.expression) {
1437
+ if (col.generation_expression !== field.generateAs) {
1483
1438
  throw new Error(
1484
- `Column ${col.name} has specific type ${col.generation_expression} but expected ${field.generateAs.expression}`
1439
+ `Column ${col.name} has specific type ${col.generation_expression} but expected ${field.generateAs}`
1485
1440
  );
1486
1441
  }
1487
1442
  }
@@ -1523,182 +1478,6 @@ var MigrationGenerator = class {
1523
1478
  }
1524
1479
  return false;
1525
1480
  }
1526
- normalizeFunctionBody(body) {
1527
- return body.replace(/\s+/g, " ").replace(/\s*\(\s*/g, "(").replace(/\s*\)\s*/g, ")").replace(/\s*,\s*/g, ",").trim();
1528
- }
1529
- normalizeAggregateDefinition(definition) {
1530
- let normalized = definition.replace(/\s+/g, " ").replace(/\s*\(\s*/g, "(").replace(/\s*\)\s*/g, ")").replace(/\s*,\s*/g, ",").trim();
1531
- const initCondMatch = normalized.match(/INITCOND\s*=\s*([^,)]+)/i);
1532
- if (initCondMatch) {
1533
- const initCondValue = initCondMatch[1].trim();
1534
- const unquoted = initCondValue.replace(/^['"]|['"]$/g, "");
1535
- if (/^\d+$/.test(unquoted)) {
1536
- normalized = normalized.replace(/INITCOND\s*=\s*[^,)]+/i, `INITCOND = '${unquoted}'`);
1537
- }
1538
- }
1539
- return normalized;
1540
- }
1541
- extractFunctionBody(definition) {
1542
- const dollarQuoteMatch = definition.match(/AS\s+\$([^$]*)\$([\s\S]*?)\$\1\$/i);
1543
- if (dollarQuoteMatch) {
1544
- return dollarQuoteMatch[2].trim();
1545
- }
1546
- const bodyMatch = definition.match(/AS\s+\$\$([\s\S]*?)\$\$/i) || definition.match(/AS\s+['"]([\s\S]*?)['"]/i);
1547
- if (bodyMatch) {
1548
- return bodyMatch[1].trim();
1549
- }
1550
- return definition;
1551
- }
1552
- async getDatabaseFunctions() {
1553
- const regularFunctions = await this.knex.raw(`
1554
- SELECT
1555
- p.proname as name,
1556
- pg_get_function_identity_arguments(p.oid) as arguments,
1557
- pg_get_functiondef(p.oid) as definition,
1558
- false as is_aggregate
1559
- FROM pg_proc p
1560
- JOIN pg_namespace n ON p.pronamespace = n.oid
1561
- WHERE n.nspname = 'public'
1562
- AND NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid)
1563
- ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
1564
- `);
1565
- const aggregateFunctions = await this.knex.raw(`
1566
- SELECT
1567
- p.proname as name,
1568
- pg_get_function_identity_arguments(p.oid) as arguments,
1569
- a.aggtransfn::regproc::text as trans_func,
1570
- a.aggfinalfn::regproc::text as final_func,
1571
- a.agginitval as init_val,
1572
- pg_catalog.format_type(a.aggtranstype, NULL) as state_type,
1573
- true as is_aggregate
1574
- FROM pg_proc p
1575
- JOIN pg_aggregate a ON p.oid = a.aggfnoid
1576
- JOIN pg_namespace n ON p.pronamespace = n.oid
1577
- WHERE n.nspname = 'public'
1578
- ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
1579
- `);
1580
- const result = [];
1581
- for (const row of regularFunctions.rows || []) {
1582
- const definition = row.definition || "";
1583
- const name2 = row.name || "";
1584
- const argumentsStr = row.arguments || "";
1585
- if (!definition) {
1586
- continue;
1587
- }
1588
- const signature = `${name2}(${argumentsStr})`;
1589
- const body = this.normalizeFunctionBody(this.extractFunctionBody(definition));
1590
- result.push({
1591
- name: name2,
1592
- signature,
1593
- body,
1594
- isAggregate: false,
1595
- definition
1596
- });
1597
- }
1598
- for (const row of aggregateFunctions.rows || []) {
1599
- const name2 = row.name || "";
1600
- const argumentsStr = row.arguments || "";
1601
- const transFunc = row.trans_func || "";
1602
- const finalFunc = row.final_func || "";
1603
- const initVal = row.init_val;
1604
- const stateType = row.state_type || "";
1605
- const signature = `${name2}(${argumentsStr})`;
1606
- let aggregateDef = `CREATE AGGREGATE ${name2}(${argumentsStr}) (`;
1607
- aggregateDef += `SFUNC = ${transFunc}, STYPE = ${stateType}`;
1608
- if (finalFunc) {
1609
- aggregateDef += `, FINALFUNC = ${finalFunc}`;
1610
- }
1611
- if (initVal !== null && initVal !== void 0) {
1612
- let initValStr;
1613
- if (typeof initVal === "string") {
1614
- initValStr = `'${initVal}'`;
1615
- } else {
1616
- const numStr = String(initVal);
1617
- initValStr = /^\d+$/.test(numStr) ? `'${numStr}'` : numStr;
1618
- }
1619
- aggregateDef += `, INITCOND = ${initValStr}`;
1620
- }
1621
- aggregateDef += ");";
1622
- result.push({
1623
- name: name2,
1624
- signature,
1625
- body: this.normalizeAggregateDefinition(aggregateDef),
1626
- isAggregate: true,
1627
- definition: aggregateDef
1628
- });
1629
- }
1630
- return result;
1631
- }
1632
- async handleFunctions(up, down) {
1633
- if (!this.parsedFunctions || this.parsedFunctions.length === 0) {
1634
- return;
1635
- }
1636
- const definedFunctions = this.parsedFunctions;
1637
- const dbFunctions = await this.getDatabaseFunctions();
1638
- const dbFunctionsBySignature = /* @__PURE__ */ new Map();
1639
- for (const func of dbFunctions) {
1640
- dbFunctionsBySignature.set(func.signature, func);
1641
- }
1642
- const definedFunctionsBySignature = /* @__PURE__ */ new Map();
1643
- for (const func of definedFunctions) {
1644
- definedFunctionsBySignature.set(func.signature, func);
1645
- }
1646
- const functionsToRestore = [];
1647
- for (const definedFunc of definedFunctions) {
1648
- const dbFunc = dbFunctionsBySignature.get(definedFunc.signature);
1649
- if (!dbFunc) {
1650
- up.push(() => {
1651
- this.writer.writeLine(`await knex.raw(\`${definedFunc.fullDefinition.replace(/`/g, "\\`")}\`);`).blankLine();
1652
- });
1653
- down.push(() => {
1654
- const isAggregate = definedFunc.isAggregate;
1655
- const dropMatch = definedFunc.fullDefinition.match(/CREATE\s+(OR\s+REPLACE\s+)?(FUNCTION|AGGREGATE)\s+([^(]+)\(/i);
1656
- if (dropMatch) {
1657
- const functionName = dropMatch[3].trim();
1658
- const argsMatch = definedFunc.fullDefinition.match(
1659
- /CREATE\s+(OR\s+REPLACE\s+)?(FUNCTION|AGGREGATE)\s+[^(]+\(([^)]*)\)/i
1660
- );
1661
- const args2 = argsMatch ? argsMatch[3].trim() : "";
1662
- const dropType = isAggregate ? "AGGREGATE" : "FUNCTION";
1663
- this.writer.writeLine(`await knex.raw(\`DROP ${dropType} IF EXISTS ${functionName}${args2 ? `(${args2})` : ""}\`);`).blankLine();
1664
- }
1665
- });
1666
- } else {
1667
- const dbBody = dbFunc.isAggregate ? this.normalizeAggregateDefinition(dbFunc.body) : this.normalizeFunctionBody(dbFunc.body);
1668
- const definedBody = definedFunc.isAggregate ? this.normalizeAggregateDefinition(definedFunc.body) : this.normalizeFunctionBody(definedFunc.body);
1669
- if (dbBody !== definedBody) {
1670
- const oldDefinition = dbFunc.definition || dbFunc.body;
1671
- up.push(() => {
1672
- this.writer.writeLine(`await knex.raw(\`${definedFunc.fullDefinition.replace(/`/g, "\\`")}\`);`).blankLine();
1673
- });
1674
- down.push(() => {
1675
- if (oldDefinition) {
1676
- this.writer.writeLine(`await knex.raw(\`${oldDefinition.replace(/`/g, "\\`")}\`);`).blankLine();
1677
- }
1678
- });
1679
- }
1680
- }
1681
- }
1682
- for (const dbFunc of dbFunctions) {
1683
- if (!definedFunctionsBySignature.has(dbFunc.signature)) {
1684
- const definition = dbFunc.definition || dbFunc.body;
1685
- if (definition) {
1686
- functionsToRestore.push({ func: dbFunc, definition });
1687
- down.push(() => {
1688
- const argsMatch = dbFunc.signature.match(/\(([^)]*)\)/);
1689
- const args2 = argsMatch ? argsMatch[1] : "";
1690
- const dropType = dbFunc.isAggregate ? "AGGREGATE" : "FUNCTION";
1691
- this.writer.writeLine(`await knex.raw(\`DROP ${dropType} IF EXISTS ${dbFunc.name}${args2 ? `(${args2})` : ""}\`);`).blankLine();
1692
- });
1693
- }
1694
- }
1695
- }
1696
- for (const { definition } of functionsToRestore) {
1697
- up.push(() => {
1698
- this.writer.writeLine(`await knex.raw(\`${definition.replace(/`/g, "\\`")}\`);`).blankLine();
1699
- });
1700
- }
1701
- }
1702
1481
  };
1703
1482
  var getMigrationDate = () => {
1704
1483
  const date = /* @__PURE__ */ new Date();
@@ -1711,258 +1490,21 @@ var getMigrationDate = () => {
1711
1490
  return `${year}${month}${day}${hours}${minutes}${seconds}`;
1712
1491
  };
1713
1492
 
1714
- // src/migrations/generate-functions.ts
1715
- var generateFunctionsFromDatabase = async (knex2) => {
1716
- const regularFunctions = await knex2.raw(`
1717
- SELECT
1718
- pg_get_functiondef(p.oid) as definition
1719
- FROM pg_proc p
1720
- JOIN pg_namespace n ON p.pronamespace = n.oid
1721
- WHERE n.nspname = 'public'
1722
- AND NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid)
1723
- ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
1724
- `);
1725
- const aggregateFunctions = await knex2.raw(`
1726
- SELECT
1727
- p.proname as name,
1728
- pg_get_function_identity_arguments(p.oid) as arguments,
1729
- a.aggtransfn::regproc::text as trans_func,
1730
- a.aggfinalfn::regproc::text as final_func,
1731
- a.agginitval as init_val,
1732
- pg_catalog.format_type(a.aggtranstype, NULL) as state_type
1733
- FROM pg_proc p
1734
- JOIN pg_aggregate a ON p.oid = a.aggfnoid
1735
- JOIN pg_namespace n ON p.pronamespace = n.oid
1736
- WHERE n.nspname = 'public'
1737
- ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
1738
- `);
1739
- const functions = [];
1740
- for (const row of regularFunctions.rows || []) {
1741
- if (row.definition) {
1742
- functions.push(row.definition.trim());
1743
- }
1744
- }
1745
- for (const row of aggregateFunctions.rows || []) {
1746
- const name2 = row.name || "";
1747
- const argumentsStr = row.arguments || "";
1748
- const transFunc = row.trans_func || "";
1749
- const finalFunc = row.final_func || "";
1750
- const initVal = row.init_val;
1751
- const stateType = row.state_type || "";
1752
- if (!name2 || !transFunc || !stateType) {
1753
- continue;
1754
- }
1755
- let aggregateDef = `CREATE AGGREGATE ${name2}(${argumentsStr}) (
1756
- `;
1757
- aggregateDef += ` SFUNC = ${transFunc},
1758
- `;
1759
- aggregateDef += ` STYPE = ${stateType}`;
1760
- if (finalFunc) {
1761
- aggregateDef += `,
1762
- FINALFUNC = ${finalFunc}`;
1763
- }
1764
- if (initVal !== null && initVal !== void 0) {
1765
- const initValStr = typeof initVal === "string" ? `'${initVal}'` : String(initVal);
1766
- aggregateDef += `,
1767
- INITCOND = ${initValStr}`;
1768
- }
1769
- aggregateDef += "\n);";
1770
- functions.push(aggregateDef);
1771
- }
1772
- if (functions.length === 0) {
1773
- return `export const functions: string[] = [];
1774
- `;
1775
- }
1776
- const functionsArrayString = functions.map((func) => ` ${JSON.stringify(func)}`).join(",\n");
1777
- return `export const functions: string[] = [
1778
- ${functionsArrayString},
1779
- ];
1780
- `;
1781
- };
1782
-
1783
- // src/migrations/update-functions.ts
1784
- var normalizeWhitespace = (str) => {
1785
- return str.replace(/\s+/g, " ").replace(/\s*\(\s*/g, "(").replace(/\s*\)\s*/g, ")").replace(/\s*,\s*/g, ",").replace(/\s*;\s*/g, ";").trim();
1786
- };
1787
- var normalizeFunctionBody = (body) => {
1788
- return normalizeWhitespace(body);
1789
- };
1790
- var extractFunctionBody = (definition) => {
1791
- const dollarQuoteMatch = definition.match(/AS\s+\$([^$]*)\$([\s\S]*?)\$\1\$/i);
1792
- if (dollarQuoteMatch) {
1793
- return dollarQuoteMatch[2].trim();
1794
- }
1795
- const bodyMatch = definition.match(/AS\s+\$\$([\s\S]*?)\$\$/i) || definition.match(/AS\s+['"]([\s\S]*?)['"]/i);
1796
- if (bodyMatch) {
1797
- return bodyMatch[1].trim();
1798
- }
1799
- return definition;
1800
- };
1801
- var getDatabaseFunctions = async (knex2) => {
1802
- const regularFunctions = await knex2.raw(`
1803
- SELECT
1804
- p.proname as name,
1805
- pg_get_function_identity_arguments(p.oid) as arguments,
1806
- pg_get_functiondef(p.oid) as definition,
1807
- false as is_aggregate
1808
- FROM pg_proc p
1809
- JOIN pg_namespace n ON p.pronamespace = n.oid
1810
- WHERE n.nspname = 'public'
1811
- AND NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid)
1812
- ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
1813
- `);
1814
- const aggregateFunctions = await knex2.raw(`
1815
- SELECT
1816
- p.proname as name,
1817
- pg_get_function_identity_arguments(p.oid) as arguments,
1818
- a.aggtransfn::regproc::text as trans_func,
1819
- a.aggfinalfn::regproc::text as final_func,
1820
- a.agginitval as init_val,
1821
- pg_catalog.format_type(a.aggtranstype, NULL) as state_type,
1822
- true as is_aggregate
1823
- FROM pg_proc p
1824
- JOIN pg_aggregate a ON p.oid = a.aggfnoid
1825
- JOIN pg_namespace n ON p.pronamespace = n.oid
1826
- WHERE n.nspname = 'public'
1827
- ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
1828
- `);
1829
- const result = [];
1830
- for (const row of regularFunctions.rows || []) {
1831
- const definition = row.definition || "";
1832
- const name2 = row.name || "";
1833
- const argumentsStr = row.arguments || "";
1834
- if (!definition) {
1835
- continue;
1836
- }
1837
- const signature = `${name2}(${argumentsStr})`;
1838
- const body = normalizeFunctionBody(extractFunctionBody(definition));
1839
- result.push({
1840
- name: name2,
1841
- signature,
1842
- body,
1843
- isAggregate: false,
1844
- definition
1845
- });
1846
- }
1847
- for (const row of aggregateFunctions.rows || []) {
1848
- const name2 = row.name || "";
1849
- const argumentsStr = row.arguments || "";
1850
- const transFunc = row.trans_func || "";
1851
- const finalFunc = row.final_func || "";
1852
- const initVal = row.init_val;
1853
- const stateType = row.state_type || "";
1854
- const signature = `${name2}(${argumentsStr})`;
1855
- let aggregateDef = `CREATE AGGREGATE ${name2}(${argumentsStr}) (`;
1856
- aggregateDef += `SFUNC = ${transFunc}, STYPE = ${stateType}`;
1857
- if (finalFunc) {
1858
- aggregateDef += `, FINALFUNC = ${finalFunc}`;
1859
- }
1860
- if (initVal !== null && initVal !== void 0) {
1861
- const initValStr = typeof initVal === "string" ? `'${initVal}'` : String(initVal);
1862
- aggregateDef += `, INITCOND = ${initValStr}`;
1863
- }
1864
- aggregateDef += ");";
1865
- result.push({
1866
- name: name2,
1867
- signature,
1868
- body: normalizeFunctionBody(aggregateDef),
1869
- isAggregate: true,
1870
- definition: aggregateDef
1871
- });
1872
- }
1873
- return result;
1874
- };
1875
- var compareFunctions = (defined, db) => {
1876
- const definedBody = normalizeFunctionBody(defined.body);
1877
- const dbBody = normalizeFunctionBody(db.body);
1878
- if (definedBody !== dbBody) {
1879
- const definedPreview = definedBody.length > 200 ? `${definedBody.substring(0, 200)}...` : definedBody;
1880
- const dbPreview = dbBody.length > 200 ? `${dbBody.substring(0, 200)}...` : dbBody;
1881
- return {
1882
- changed: true,
1883
- diff: `Definition changed:
1884
- File: ${definedPreview}
1885
- DB: ${dbPreview}`
1886
- };
1887
- }
1888
- return { changed: false };
1889
- };
1890
- var updateFunctions = async (knex2, parsedFunctions) => {
1891
- if (parsedFunctions.length === 0) {
1892
- return;
1893
- }
1894
- const definedFunctions = parsedFunctions;
1895
- const dbFunctions = await getDatabaseFunctions(knex2);
1896
- const dbFunctionsBySignature = /* @__PURE__ */ new Map();
1897
- for (const func of dbFunctions) {
1898
- dbFunctionsBySignature.set(func.signature, func);
1899
- }
1900
- console.info(`Found ${definedFunctions.length} function(s) in file, ${dbFunctions.length} function(s) in database.`);
1901
- let updatedCount = 0;
1902
- let skippedCount = 0;
1903
- for (const definedFunc of definedFunctions) {
1904
- const dbFunc = dbFunctionsBySignature.get(definedFunc.signature);
1905
- if (!dbFunc) {
1906
- try {
1907
- await knex2.raw(definedFunc.fullDefinition);
1908
- console.info(`\u2713 Created ${definedFunc.isAggregate ? "aggregate" : "function"}: ${definedFunc.signature}`);
1909
- updatedCount++;
1910
- } catch (error) {
1911
- console.error(
1912
- `\u2717 Failed to create ${definedFunc.isAggregate ? "aggregate" : "function"} ${definedFunc.signature}:`,
1913
- error.message
1914
- );
1915
- throw error;
1916
- }
1917
- } else {
1918
- const comparison = compareFunctions(definedFunc, dbFunc);
1919
- if (comparison.changed) {
1920
- console.info(`
1921
- \u26A0 ${definedFunc.isAggregate ? "Aggregate" : "Function"} ${definedFunc.signature} has changes:`);
1922
- if (comparison.diff) {
1923
- console.info(comparison.diff);
1924
- }
1925
- try {
1926
- if (definedFunc.isAggregate) {
1927
- const dropMatch = definedFunc.fullDefinition.match(/CREATE\s+(OR\s+REPLACE\s+)?AGGREGATE\s+([^(]+)\(/i);
1928
- if (dropMatch) {
1929
- const functionName = dropMatch[2].trim();
1930
- const argsMatch = definedFunc.fullDefinition.match(/CREATE\s+(OR\s+REPLACE\s+)?AGGREGATE\s+[^(]+\(([^)]*)\)/i);
1931
- const args2 = argsMatch ? argsMatch[2].trim() : "";
1932
- await knex2.raw(`DROP AGGREGATE IF EXISTS ${functionName}${args2 ? `(${args2})` : ""}`);
1933
- }
1934
- }
1935
- await knex2.raw(definedFunc.fullDefinition);
1936
- console.info(`\u2713 Updated ${definedFunc.isAggregate ? "aggregate" : "function"}: ${definedFunc.signature}
1937
- `);
1938
- updatedCount++;
1939
- } catch (error) {
1940
- console.error(
1941
- `\u2717 Failed to update ${definedFunc.isAggregate ? "aggregate" : "function"} ${definedFunc.signature}:`,
1942
- error.message
1943
- );
1944
- throw error;
1945
- }
1946
- } else {
1947
- console.info(
1948
- `\u25CB Skipped ${definedFunc.isAggregate ? "aggregate" : "function"} (unchanged): ${definedFunc.signature}`
1949
- );
1950
- skippedCount++;
1951
- }
1952
- }
1953
- }
1954
- console.info(`
1955
- Summary: ${updatedCount} updated, ${skippedCount} skipped`);
1956
- if (updatedCount > 0) {
1957
- console.info("Functions updated successfully.");
1958
- } else {
1959
- console.info("All functions are up to date.");
1960
- }
1961
- };
1493
+ // src/resolvers/utils.ts
1494
+ var import_graphql3 = require("graphql");
1495
+ var import_isEqual = __toESM(require("lodash/isEqual"), 1);
1496
+ var getColumnName = (field) => field.kind === "relation" ? field.foreignKey || `${field.name}Id` : field.name;
1962
1497
 
1963
1498
  // src/permissions/generate.ts
1964
1499
  var ACTIONS = ["READ", "CREATE", "UPDATE", "DELETE", "RESTORE", "LINK"];
1965
1500
 
1501
+ // src/resolvers/arguments.ts
1502
+ var import_graphql4 = require("graphql");
1503
+
1504
+ // src/resolvers/resolver.ts
1505
+ var import_cloneDeep2 = __toESM(require("lodash/cloneDeep"), 1);
1506
+ var import_flatMap = __toESM(require("lodash/flatMap"), 1);
1507
+
1966
1508
  // src/schema/generate.ts
1967
1509
  var import_graphql6 = require("graphql");
1968
1510
 
@@ -2540,14 +2082,6 @@ var DEFAULTS = {
2540
2082
  ensureFileExists(path, EMPTY_MODELS);
2541
2083
  }
2542
2084
  },
2543
- functionsPath: {
2544
- question: "What is the PostgreSQL functions file path?",
2545
- defaultValue: "src/config/functions.ts",
2546
- init: (path) => {
2547
- ensureFileExists(path, `export const functions: string[] = [];
2548
- `);
2549
- }
2550
- },
2551
2085
  generatedFolderPath: {
2552
2086
  question: "What is the path for generated stuff?",
2553
2087
  defaultValue: "src/generated",
@@ -2727,8 +2261,7 @@ var generateGraphqlClientTypes = async () => {
2727
2261
  });
2728
2262
  };
2729
2263
 
2730
- // src/bin/gqm/parse-functions.ts
2731
- var import_fs2 = require("fs");
2264
+ // src/bin/gqm/parse-knexfile.ts
2732
2265
  var import_ts_morph4 = require("ts-morph");
2733
2266
 
2734
2267
  // src/bin/gqm/static-eval.ts
@@ -2821,6 +2354,72 @@ var VISITOR = {
2821
2354
  }),
2822
2355
  [import_ts_morph2.SyntaxKind.SpreadElement]: (node, context) => staticEval(node.getExpression(), context),
2823
2356
  [import_ts_morph2.SyntaxKind.SpreadAssignment]: (node, context) => staticEval(node.getExpression(), context),
2357
+ [import_ts_morph2.SyntaxKind.ImportSpecifier]: (node, context) => {
2358
+ const nameNode = node.getNameNode();
2359
+ const name2 = nameNode.getText();
2360
+ if (name2 in KNOWN_IDENTIFIERS) {
2361
+ return KNOWN_IDENTIFIERS[name2];
2362
+ }
2363
+ if (nameNode instanceof import_ts_morph2.StringLiteral) {
2364
+ throw new Error(`Cannot handle computed import specifier: ${name2}. Only static imports are supported.`);
2365
+ }
2366
+ const definitions = nameNode.getDefinitionNodes();
2367
+ let externalDefinition = definitions.find((d) => d.compilerNode !== node.compilerNode);
2368
+ if (!externalDefinition) {
2369
+ const importDeclaration = node.getImportDeclaration();
2370
+ let sourceFile = importDeclaration.getModuleSpecifierSourceFile();
2371
+ if (!sourceFile) {
2372
+ const moduleSpecifier = importDeclaration.getModuleSpecifierValue();
2373
+ const project = node.getProject();
2374
+ if (moduleSpecifier.startsWith("@/")) {
2375
+ const suffix = moduleSpecifier.substring(2);
2376
+ sourceFile = project.getSourceFiles().find((sf) => {
2377
+ const filePath = sf.getFilePath();
2378
+ return filePath.endsWith(`/${suffix}.ts`) || filePath.endsWith(`/${suffix}.tsx`) || filePath.endsWith(`/${suffix}/index.ts`) || filePath.endsWith(`/${suffix}/index.tsx`);
2379
+ });
2380
+ if (!sourceFile) {
2381
+ const candidates = [
2382
+ `src/${suffix}.ts`,
2383
+ `src/${suffix}.tsx`,
2384
+ `src/${suffix}/index.ts`,
2385
+ `src/${suffix}/index.tsx`
2386
+ ];
2387
+ for (const candidate of candidates) {
2388
+ try {
2389
+ const added = project.addSourceFileAtPathIfExists(candidate);
2390
+ if (added) {
2391
+ sourceFile = added;
2392
+ break;
2393
+ }
2394
+ } catch {
2395
+ }
2396
+ }
2397
+ }
2398
+ }
2399
+ }
2400
+ if (sourceFile) {
2401
+ const localName = node.getName();
2402
+ const propertyName = node.compilerNode.propertyName?.getText();
2403
+ const exportedName = propertyName ?? localName;
2404
+ const exportedDeclarations = sourceFile.getExportedDeclarations();
2405
+ const declarations = exportedDeclarations.get(exportedName);
2406
+ const declaration = declarations?.[0];
2407
+ if (declaration) {
2408
+ externalDefinition = declaration;
2409
+ }
2410
+ }
2411
+ }
2412
+ if (externalDefinition && externalDefinition.getKind() === import_ts_morph2.SyntaxKind.ImportSpecifier) {
2413
+ return staticEval(externalDefinition, context);
2414
+ }
2415
+ if (!externalDefinition) {
2416
+ const importDeclaration = node.getImportDeclaration();
2417
+ throw new Error(
2418
+ `No definition node found for import specifier '${name2}' imported from '${importDeclaration.getModuleSpecifierValue()}'.`
2419
+ );
2420
+ }
2421
+ return staticEval(externalDefinition, context);
2422
+ },
2824
2423
  [import_ts_morph2.SyntaxKind.Identifier]: (node, context) => {
2825
2424
  const identifierName = node.getText();
2826
2425
  if (identifierName in KNOWN_IDENTIFIERS) {
@@ -3047,114 +2646,11 @@ var findDeclaration = (syntaxList, name2) => {
3047
2646
  }
3048
2647
  };
3049
2648
 
3050
- // src/bin/gqm/parse-functions.ts
3051
- var normalizeWhitespace2 = (str) => {
3052
- return str.replace(/\s+/g, " ").replace(/\s*\(\s*/g, "(").replace(/\s*\)\s*/g, ")").replace(/\s*,\s*/g, ",").replace(/\s*;\s*/g, ";").trim();
3053
- };
3054
- var normalizeFunctionBody2 = (body) => {
3055
- return normalizeWhitespace2(body);
3056
- };
3057
- var normalizeAggregateDefinition = (definition) => {
3058
- let normalized = normalizeWhitespace2(definition);
3059
- const initCondMatch = normalized.match(/INITCOND\s*=\s*([^,)]+)/i);
3060
- if (initCondMatch) {
3061
- const initCondValue = initCondMatch[1].trim();
3062
- const unquoted = initCondValue.replace(/^['"]|['"]$/g, "");
3063
- if (/^\d+$/.test(unquoted)) {
3064
- normalized = normalized.replace(/INITCOND\s*=\s*[^,)]+/i, `INITCOND = '${unquoted}'`);
3065
- }
3066
- }
3067
- return normalized;
3068
- };
3069
- var extractFunctionSignature = (definition, isAggregate) => {
3070
- if (isAggregate) {
3071
- const createMatch2 = definition.match(/CREATE\s+(OR\s+REPLACE\s+)?AGGREGATE\s+([^(]+)\(/i);
3072
- if (!createMatch2) {
3073
- return null;
3074
- }
3075
- const functionNamePart2 = createMatch2[2].trim().replace(/^[^.]+\./, "");
3076
- const argsMatch = definition.match(/CREATE\s+(OR\s+REPLACE\s+)?AGGREGATE\s+[^(]+\(([^)]*)\)/i);
3077
- const args3 = argsMatch ? argsMatch[2].trim() : "";
3078
- return `${functionNamePart2}(${args3})`;
3079
- }
3080
- const createMatch = definition.match(/CREATE\s+(OR\s+REPLACE\s+)?FUNCTION\s+([^(]+)\(/i);
3081
- if (!createMatch) {
3082
- return null;
3083
- }
3084
- const functionNamePart = createMatch[2].trim().replace(/^[^.]+\./, "");
3085
- const fullArgsMatch = definition.match(
3086
- /CREATE\s+(OR\s+REPLACE\s+)?FUNCTION\s+[^(]+\(([\s\S]*?)\)\s*(RETURNS|LANGUAGE|AS|STRICT|IMMUTABLE|STABLE|VOLATILE|SECURITY)/i
3087
- );
3088
- if (!fullArgsMatch) {
3089
- return null;
3090
- }
3091
- const argsSection = fullArgsMatch[2].trim();
3092
- const args2 = argsSection.split(/\s*,\s*/).map((arg) => {
3093
- return arg.trim().replace(/\s+/g, " ");
3094
- }).join(", ");
3095
- return `${functionNamePart}(${args2})`;
3096
- };
3097
- var extractFunctionBody2 = (definition) => {
3098
- const dollarQuoteMatch = definition.match(/AS\s+\$([^$]*)\$([\s\S]*?)\$\1\$/i);
3099
- if (dollarQuoteMatch) {
3100
- return dollarQuoteMatch[2].trim();
3101
- }
3102
- const bodyMatch = definition.match(/AS\s+\$\$([\s\S]*?)\$\$/i) || definition.match(/AS\s+['"]([\s\S]*?)['"]/i);
3103
- if (bodyMatch) {
3104
- return bodyMatch[1].trim();
3105
- }
3106
- return definition;
3107
- };
3108
- var parseFunctionsFile = (filePath) => {
3109
- if (!(0, import_fs2.existsSync)(filePath)) {
3110
- return [];
3111
- }
3112
- const project = new import_ts_morph4.Project({
3113
- manipulationSettings: {
3114
- indentationText: import_ts_morph4.IndentationText.TwoSpaces
3115
- }
3116
- });
3117
- const sourceFile = project.addSourceFileAtPath(filePath);
3118
- try {
3119
- const functionsDeclaration = findDeclarationInFile(sourceFile, "functions");
3120
- const functionsArray = staticEval(functionsDeclaration, {});
3121
- if (!Array.isArray(functionsArray)) {
3122
- return [];
3123
- }
3124
- const parsedFunctions = [];
3125
- for (const definition of functionsArray) {
3126
- if (!definition || typeof definition !== "string") {
3127
- continue;
3128
- }
3129
- const trimmedDefinition = definition.trim();
3130
- const isAggregate = /CREATE\s+(OR\s+REPLACE\s+)?AGGREGATE/i.test(trimmedDefinition);
3131
- const signature = extractFunctionSignature(trimmedDefinition, isAggregate);
3132
- if (!signature) {
3133
- continue;
3134
- }
3135
- const nameMatch = signature.match(/^([^(]+)\(/);
3136
- const name2 = nameMatch ? nameMatch[1].trim().split(".").pop() || "" : "";
3137
- const body = isAggregate ? trimmedDefinition : extractFunctionBody2(trimmedDefinition);
3138
- parsedFunctions.push({
3139
- name: name2,
3140
- signature,
3141
- body: isAggregate ? normalizeAggregateDefinition(body) : normalizeFunctionBody2(body),
3142
- fullDefinition: trimmedDefinition,
3143
- isAggregate
3144
- });
3145
- }
3146
- return parsedFunctions;
3147
- } catch (error) {
3148
- return [];
3149
- }
3150
- };
3151
-
3152
2649
  // src/bin/gqm/parse-knexfile.ts
3153
- var import_ts_morph5 = require("ts-morph");
3154
2650
  var parseKnexfile = async () => {
3155
- const project = new import_ts_morph5.Project({
2651
+ const project = new import_ts_morph4.Project({
3156
2652
  manipulationSettings: {
3157
- indentationText: import_ts_morph5.IndentationText.TwoSpaces
2653
+ indentationText: import_ts_morph4.IndentationText.TwoSpaces
3158
2654
  }
3159
2655
  });
3160
2656
  const knexfilePath = await getSetting("knexfilePath");
@@ -3166,11 +2662,11 @@ var parseKnexfile = async () => {
3166
2662
  };
3167
2663
 
3168
2664
  // src/bin/gqm/parse-models.ts
3169
- var import_ts_morph6 = require("ts-morph");
2665
+ var import_ts_morph5 = require("ts-morph");
3170
2666
  var parseModels = async () => {
3171
- const project = new import_ts_morph6.Project({
2667
+ const project = new import_ts_morph5.Project({
3172
2668
  manipulationSettings: {
3173
- indentationText: import_ts_morph6.IndentationText.TwoSpaces
2669
+ indentationText: import_ts_morph5.IndentationText.TwoSpaces
3174
2670
  }
3175
2671
  });
3176
2672
  const modelsPath = await getSetting("modelsPath");
@@ -3183,11 +2679,11 @@ var parseModels = async () => {
3183
2679
  };
3184
2680
 
3185
2681
  // src/bin/gqm/permissions.ts
3186
- var import_ts_morph7 = require("ts-morph");
2682
+ var import_ts_morph6 = require("ts-morph");
3187
2683
  var generatePermissionTypes = (models) => {
3188
- const project = new import_ts_morph7.Project({
2684
+ const project = new import_ts_morph6.Project({
3189
2685
  manipulationSettings: {
3190
- indentationText: import_ts_morph7.IndentationText.TwoSpaces
2686
+ indentationText: import_ts_morph6.IndentationText.TwoSpaces
3191
2687
  }
3192
2688
  });
3193
2689
  const sourceFile = project.createSourceFile("permissions.ts", "", {
@@ -3290,9 +2786,7 @@ import_commander.program.command("generate-migration [<name>] [<date>]").descrip
3290
2786
  const db = (0, import_knex.default)(knexfile);
3291
2787
  try {
3292
2788
  const models = await parseModels();
3293
- const functionsPath = await getSetting("functionsPath");
3294
- const parsedFunctions = parseFunctionsFile(functionsPath);
3295
- const migrations = await new MigrationGenerator(db, models, parsedFunctions).generate();
2789
+ const migrations = await new MigrationGenerator(db, models).generate();
3296
2790
  writeToFile(`migrations/${date || getMigrationDate()}_${name2}.ts`, migrations);
3297
2791
  } finally {
3298
2792
  await db.destroy();
@@ -3303,9 +2797,7 @@ import_commander.program.command("check-needs-migration").description("Check if
3303
2797
  const db = (0, import_knex.default)(knexfile);
3304
2798
  try {
3305
2799
  const models = await parseModels();
3306
- const functionsPath = await getSetting("functionsPath");
3307
- const parsedFunctions = parseFunctionsFile(functionsPath);
3308
- const mg = new MigrationGenerator(db, models, parsedFunctions);
2800
+ const mg = new MigrationGenerator(db, models);
3309
2801
  await mg.generate();
3310
2802
  if (mg.needsMigration) {
3311
2803
  console.error("Migration is needed.");
@@ -3315,31 +2807,8 @@ import_commander.program.command("check-needs-migration").description("Check if
3315
2807
  await db.destroy();
3316
2808
  }
3317
2809
  });
3318
- import_commander.program.command("generate-functions").description("Generate functions.ts file from database").action(async () => {
3319
- const knexfile = await parseKnexfile();
3320
- const db = (0, import_knex.default)(knexfile);
3321
- try {
3322
- const functionsPath = await getSetting("functionsPath");
3323
- const functions = await generateFunctionsFromDatabase(db);
3324
- writeToFile(functionsPath, functions);
3325
- } finally {
3326
- await db.destroy();
3327
- }
3328
- });
3329
- import_commander.program.command("update-functions").description("Update database functions from functions.ts file").action(async () => {
3330
- const knexfile = await parseKnexfile();
3331
- const db = (0, import_knex.default)(knexfile);
3332
- try {
3333
- const functionsPath = await getSetting("functionsPath");
3334
- const parsedFunctions = parseFunctionsFile(functionsPath);
3335
- await updateFunctions(db, parsedFunctions);
3336
- } finally {
3337
- await db.destroy();
3338
- }
3339
- });
3340
- import_commander.program.command("*").description("Invalid command").action((command) => {
3341
- console.error(`Invalid command: ${command}
3342
- See --help for a list of available commands.`);
2810
+ import_commander.program.command("*", { noHelp: true }).description("Invalid command").action(() => {
2811
+ console.error("Invalid command: %s\nSee --help for a list of available commands.", import_commander.program.args.join(" "));
3343
2812
  process.exit(1);
3344
2813
  });
3345
2814
  import_commander.program.parse(process.argv);