@smartive/graphql-magic 23.6.1-next.1 → 23.6.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/.gqmrc.json CHANGED
@@ -4,5 +4,6 @@
4
4
  "graphqlQueriesPath": "tests",
5
5
  "gqmModule": "../../../src",
6
6
  "knexfilePath": "knexfile.ts",
7
- "dateLibrary": "luxon"
7
+ "dateLibrary": "luxon",
8
+ "functionsPath": "tests/functions.ts"
8
9
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,5 @@
1
- ## [23.6.1-next.1](https://github.com/smartive/graphql-magic/compare/v23.6.0...v23.6.1-next.1) (2026-02-24)
1
+ ## [23.6.1](https://github.com/smartive/graphql-magic/compare/v23.6.0...v23.6.1) (2026-02-24)
2
2
 
3
3
  ### Bug Fixes
4
4
 
5
- * exclude expression from DB types and all generateAs from upserts ([adfa7fc](https://github.com/smartive/graphql-magic/commit/adfa7fc10b2fd84ae951840d1dc553d50f78bc3e))
5
+ * correctly generate types for fields that are dynamic e.g. generateAs expression ([8a63cf1](https://github.com/smartive/graphql-magic/commit/8a63cf18a742b5b6530f582c20e8f802ef2cb354))
package/dist/bin/gqm.cjs CHANGED
@@ -558,8 +558,8 @@ var getLabel = (s) => (0, import_startCase.default)((0, import_camelCase.default
558
558
  var and = (...predicates) => (field) => predicates.every((predicate) => predicate(field));
559
559
  var not = (predicate) => (field) => !predicate(field);
560
560
  var isRootModel = (model) => !!model.root;
561
- var isCreatableModel = (model) => model.creatable && model.fields.some(isCreatableField);
562
- var isUpdatableModel = (model) => model.updatable && model.fields.some(isUpdatableField);
561
+ var isCreatableModel = (model) => !!model.creatable && model.fields.some(isCreatableField);
562
+ var isUpdatableModel = (model) => !!model.updatable && model.fields.some(isUpdatableField);
563
563
  var isCreatableField = (field) => !field.inherited && !!field.creatable;
564
564
  var isUpdatableField = (field) => !field.inherited && !!field.updatable;
565
565
  var modelNeedsTable = (model) => model.fields.some((field) => !field.inherited);
@@ -568,9 +568,11 @@ var isInherited = (field) => !!field.inherited;
568
568
  var isInTable = (field) => field.name === "id" || !field.inherited;
569
569
  var isQueriableField = ({ queriable }) => queriable !== false;
570
570
  var isCustomField = (field) => field.kind === "custom";
571
- var isGenerateAsField = (field) => !!field.generateAs;
572
- var isStoredInDatabase = (field) => field.generateAs?.type !== "expression";
571
+ var isDynamicField = (field) => !!field.generateAs || isCustomField(field);
572
+ var isStoredInDatabase = (field) => !isCustomField(field) && field.generateAs?.type !== "expression";
573
573
  var isSimpleField = and(not(isRelation), not(isCustomField));
574
+ var isUpdatable = ({ updatable }) => !!updatable;
575
+ var isCreatable = ({ creatable }) => !!creatable;
574
576
  var summonByName = (array, value2) => summonByKey(array, "name", value2);
575
577
  var summonByKey = (array, key, value2) => summon(array, (element) => (0, import_get.default)(element, key) === value2, `No element found with ${key} ${value2}`);
576
578
  var summon = (array, cb, errorMessage) => {
@@ -696,12 +698,12 @@ var generateDBModels = (models, dateLibrary) => {
696
698
  for (const model of models.entities) {
697
699
  const fields2 = model.relations.some((relation) => relation.field.foreignKey === "id") ? model.fields.filter((field) => field.name !== "id") : model.fields;
698
700
  writer.write(`export type ${model.name} = `).inlineBlock(() => {
699
- for (const field of fields2.filter(not(isCustomField)).filter(isStoredInDatabase)) {
701
+ for (const field of fields2.filter(isStoredInDatabase)) {
700
702
  writer.write(`'${getColumnName(field)}': ${getFieldType(field, dateLibrary)}${field.nonNull ? "" : " | null"};`).newLine();
701
703
  }
702
704
  }).blankLine();
703
705
  writer.write(`export type ${model.name}Initializer = `).inlineBlock(() => {
704
- for (const field of fields2.filter(not(isCustomField)).filter(isInTable).filter(not(isGenerateAsField))) {
706
+ for (const field of fields2.filter(and(isInTable, not(isDynamicField)))) {
705
707
  writer.write(
706
708
  `'${getColumnName(field)}'${field.nonNull && field.defaultValue === void 0 ? "" : "?"}: ${getFieldType(
707
709
  field,
@@ -712,7 +714,7 @@ var generateDBModels = (models, dateLibrary) => {
712
714
  }
713
715
  }).blankLine();
714
716
  writer.write(`export type ${model.name}Mutator = `).inlineBlock(() => {
715
- for (const field of fields2.filter(not(isCustomField)).filter(isInTable).filter(not(isGenerateAsField))) {
717
+ for (const field of fields2.filter(and(isInTable, not(isDynamicField)))) {
716
718
  writer.write(
717
719
  `'${getColumnName(field)}'?: ${getFieldType(field, dateLibrary, true)}${field.list ? " | string" : ""}${field.nonNull ? "" : " | null"};`
718
720
  ).newLine();
@@ -720,7 +722,7 @@ var generateDBModels = (models, dateLibrary) => {
720
722
  }).blankLine();
721
723
  if (!isRootModel(model)) {
722
724
  writer.write(`export type ${model.name}Seed = `).inlineBlock(() => {
723
- for (const field of fields2.filter(not(isCustomField)).filter(not(isGenerateAsField))) {
725
+ for (const field of fields2.filter(not(isDynamicField))) {
724
726
  if (model.parent && field.name === "type") {
725
727
  continue;
726
728
  }
@@ -781,6 +783,75 @@ var generateKnexTables = (models) => {
781
783
  return writer.toString();
782
784
  };
783
785
 
786
+ // src/migrations/generate-functions.ts
787
+ var generateFunctionsFromDatabase = async (knex2) => {
788
+ const regularFunctions = await knex2.raw(`
789
+ SELECT
790
+ pg_get_functiondef(p.oid) as definition
791
+ FROM pg_proc p
792
+ JOIN pg_namespace n ON p.pronamespace = n.oid
793
+ WHERE n.nspname = 'public'
794
+ AND NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid)
795
+ ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
796
+ `);
797
+ const aggregateFunctions = await knex2.raw(`
798
+ SELECT
799
+ p.proname as name,
800
+ pg_get_function_identity_arguments(p.oid) as arguments,
801
+ a.aggtransfn::regproc::text as trans_func,
802
+ a.aggfinalfn::regproc::text as final_func,
803
+ a.agginitval as init_val,
804
+ pg_catalog.format_type(a.aggtranstype, NULL) as state_type
805
+ FROM pg_proc p
806
+ JOIN pg_aggregate a ON p.oid = a.aggfnoid
807
+ JOIN pg_namespace n ON p.pronamespace = n.oid
808
+ WHERE n.nspname = 'public'
809
+ ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
810
+ `);
811
+ const functions = [];
812
+ for (const row of regularFunctions.rows || []) {
813
+ if (row.definition) {
814
+ functions.push(row.definition.trim());
815
+ }
816
+ }
817
+ for (const row of aggregateFunctions.rows || []) {
818
+ const name2 = row.name || "";
819
+ const argumentsStr = row.arguments || "";
820
+ const transFunc = row.trans_func || "";
821
+ const finalFunc = row.final_func || "";
822
+ const initVal = row.init_val;
823
+ const stateType = row.state_type || "";
824
+ if (!name2 || !transFunc || !stateType) {
825
+ continue;
826
+ }
827
+ let aggregateDef = `CREATE AGGREGATE ${name2}(${argumentsStr}) (
828
+ `;
829
+ aggregateDef += ` SFUNC = ${transFunc},
830
+ `;
831
+ aggregateDef += ` STYPE = ${stateType}`;
832
+ if (finalFunc) {
833
+ aggregateDef += `,
834
+ FINALFUNC = ${finalFunc}`;
835
+ }
836
+ if (initVal !== null && initVal !== void 0) {
837
+ const initValStr = typeof initVal === "string" ? `'${initVal}'` : String(initVal);
838
+ aggregateDef += `,
839
+ INITCOND = ${initValStr}`;
840
+ }
841
+ aggregateDef += "\n);";
842
+ functions.push(aggregateDef);
843
+ }
844
+ if (functions.length === 0) {
845
+ return `export const functions: string[] = [];
846
+ `;
847
+ }
848
+ const functionsArrayString = functions.map((func) => ` ${JSON.stringify(func)}`).join(",\n");
849
+ return `export const functions: string[] = [
850
+ ${functionsArrayString},
851
+ ];
852
+ `;
853
+ };
854
+
784
855
  // src/migrations/generate.ts
785
856
  var import_code_block_writer2 = __toESM(require("code-block-writer"), 1);
786
857
  var import_knex_schema_inspector = require("knex-schema-inspector");
@@ -1215,7 +1286,7 @@ var MigrationGenerator = class {
1215
1286
  writer.writeLine(`deleteRootType: row.deleteRootType,`);
1216
1287
  writer.writeLine(`deleteRootId: row.deleteRootId,`);
1217
1288
  }
1218
- for (const { name: name2, kind } of model.fields.filter(isUpdatableField).filter(not(isGenerateAsField))) {
1289
+ for (const { name: name2, kind } of model.fields.filter(and(isUpdatableField, isStoredInDatabase))) {
1219
1290
  const col = kind === "relation" ? `${name2}Id` : name2;
1220
1291
  writer.writeLine(`${col}: row.${col},`);
1221
1292
  }
@@ -1235,8 +1306,8 @@ var MigrationGenerator = class {
1235
1306
  up,
1236
1307
  down
1237
1308
  );
1238
- const missingRevisionFields = model.fields.filter(isUpdatableField).filter(not(isGenerateAsField)).filter(
1239
- ({ name: name2, ...field }) => field.kind !== "custom" && !this.getColumn(revisionTable, field.kind === "relation" ? field.foreignKey || `${name2}Id` : name2)
1309
+ const missingRevisionFields = model.fields.filter(and(isUpdatableField, isStoredInDatabase)).filter(
1310
+ ({ name: name2, ...field }) => !this.getColumn(revisionTable, field.kind === "relation" ? field.foreignKey || `${name2}Id` : name2)
1240
1311
  );
1241
1312
  this.createRevisionFields(model, missingRevisionFields, up, down);
1242
1313
  const revisionFieldsToRemove = model.fields.filter(
@@ -1394,7 +1465,7 @@ var MigrationGenerator = class {
1394
1465
  });
1395
1466
  });
1396
1467
  if (isUpdatableModel(model)) {
1397
- const updatableFields = fields2.filter(isUpdatableField).filter(not(isGenerateAsField));
1468
+ const updatableFields = fields2.filter(and(isUpdatableField, isStoredInDatabase));
1398
1469
  if (!updatableFields.length) {
1399
1470
  return;
1400
1471
  }
@@ -1442,7 +1513,7 @@ var MigrationGenerator = class {
1442
1513
  });
1443
1514
  });
1444
1515
  if (isUpdatableModel(model)) {
1445
- const updatableFields = fields2.filter(isUpdatableField).filter(not(isGenerateAsField));
1516
+ const updatableFields = fields2.filter(and(isUpdatableField, isStoredInDatabase));
1446
1517
  if (!updatableFields.length) {
1447
1518
  return;
1448
1519
  }
@@ -1480,7 +1551,7 @@ var MigrationGenerator = class {
1480
1551
  writer.writeLine(`table.uuid('deleteRootId');`);
1481
1552
  }
1482
1553
  }
1483
- for (const field of model.fields.filter(and(isUpdatableField, not(isInherited))).filter(not(isGenerateAsField))) {
1554
+ for (const field of model.fields.filter(and(isUpdatableField, not(isInherited), isStoredInDatabase))) {
1484
1555
  this.column(field, { setUnique: false, setDefault: false });
1485
1556
  }
1486
1557
  });
@@ -1922,75 +1993,6 @@ var getMigrationDate = () => {
1922
1993
  return `${year}${month}${day}${hours}${minutes}${seconds}`;
1923
1994
  };
1924
1995
 
1925
- // src/migrations/generate-functions.ts
1926
- var generateFunctionsFromDatabase = async (knex2) => {
1927
- const regularFunctions = await knex2.raw(`
1928
- SELECT
1929
- pg_get_functiondef(p.oid) as definition
1930
- FROM pg_proc p
1931
- JOIN pg_namespace n ON p.pronamespace = n.oid
1932
- WHERE n.nspname = 'public'
1933
- AND NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid)
1934
- ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
1935
- `);
1936
- const aggregateFunctions = await knex2.raw(`
1937
- SELECT
1938
- p.proname as name,
1939
- pg_get_function_identity_arguments(p.oid) as arguments,
1940
- a.aggtransfn::regproc::text as trans_func,
1941
- a.aggfinalfn::regproc::text as final_func,
1942
- a.agginitval as init_val,
1943
- pg_catalog.format_type(a.aggtranstype, NULL) as state_type
1944
- FROM pg_proc p
1945
- JOIN pg_aggregate a ON p.oid = a.aggfnoid
1946
- JOIN pg_namespace n ON p.pronamespace = n.oid
1947
- WHERE n.nspname = 'public'
1948
- ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
1949
- `);
1950
- const functions = [];
1951
- for (const row of regularFunctions.rows || []) {
1952
- if (row.definition) {
1953
- functions.push(row.definition.trim());
1954
- }
1955
- }
1956
- for (const row of aggregateFunctions.rows || []) {
1957
- const name2 = row.name || "";
1958
- const argumentsStr = row.arguments || "";
1959
- const transFunc = row.trans_func || "";
1960
- const finalFunc = row.final_func || "";
1961
- const initVal = row.init_val;
1962
- const stateType = row.state_type || "";
1963
- if (!name2 || !transFunc || !stateType) {
1964
- continue;
1965
- }
1966
- let aggregateDef = `CREATE AGGREGATE ${name2}(${argumentsStr}) (
1967
- `;
1968
- aggregateDef += ` SFUNC = ${transFunc},
1969
- `;
1970
- aggregateDef += ` STYPE = ${stateType}`;
1971
- if (finalFunc) {
1972
- aggregateDef += `,
1973
- FINALFUNC = ${finalFunc}`;
1974
- }
1975
- if (initVal !== null && initVal !== void 0) {
1976
- const initValStr = typeof initVal === "string" ? `'${initVal}'` : String(initVal);
1977
- aggregateDef += `,
1978
- INITCOND = ${initValStr}`;
1979
- }
1980
- aggregateDef += "\n);";
1981
- functions.push(aggregateDef);
1982
- }
1983
- if (functions.length === 0) {
1984
- return `export const functions: string[] = [];
1985
- `;
1986
- }
1987
- const functionsArrayString = functions.map((func) => ` ${JSON.stringify(func)}`).join(",\n");
1988
- return `export const functions: string[] = [
1989
- ${functionsArrayString},
1990
- ];
1991
- `;
1992
- };
1993
-
1994
1996
  // src/permissions/generate.ts
1995
1997
  var ACTIONS = ["READ", "CREATE", "UPDATE", "DELETE", "RESTORE", "LINK"];
1996
1998
 
@@ -2255,7 +2257,7 @@ var generateDefinitions = ({
2255
2257
  types.push(
2256
2258
  input(
2257
2259
  `Create${model.name}`,
2258
- model.fields.filter(({ creatable }) => creatable).filter(not(isGenerateAsField)).map(
2260
+ model.fields.filter(and(isCreatable, isStoredInDatabase)).map(
2259
2261
  (field) => field.kind === "relation" ? { name: `${field.name}Id`, type: "ID", nonNull: field.nonNull } : {
2260
2262
  name: field.name,
2261
2263
  type: field.kind === "json" ? `Create${field.type}` : field.type,
@@ -2270,7 +2272,7 @@ var generateDefinitions = ({
2270
2272
  types.push(
2271
2273
  input(
2272
2274
  `Update${model.name}`,
2273
- model.fields.filter(({ updatable }) => updatable).filter(not(isGenerateAsField)).map(
2275
+ model.fields.filter(and(isUpdatable, isStoredInDatabase)).map(
2274
2276
  (field) => field.kind === "relation" ? { name: `${field.name}Id`, type: "ID" } : {
2275
2277
  name: field.name,
2276
2278
  type: field.kind === "json" ? `Update${field.type}` : field.type,
@@ -133,12 +133,12 @@ __export(index_exports, {
133
133
  isCreatableField: () => isCreatableField,
134
134
  isCreatableModel: () => isCreatableModel,
135
135
  isCustomField: () => isCustomField,
136
+ isDynamicField: () => isDynamicField,
136
137
  isEntityModel: () => isEntityModel,
137
138
  isEnum: () => isEnum,
138
139
  isEnumModel: () => isEnumModel,
139
140
  isFieldNode: () => isFieldNode,
140
141
  isFragmentSpreadNode: () => isFragmentSpreadNode,
141
- isGenerateAsField: () => isGenerateAsField,
142
142
  isInTable: () => isInTable,
143
143
  isInherited: () => isInherited,
144
144
  isInlineFragmentNode: () => isInlineFragmentNode,
@@ -833,8 +833,8 @@ var isScalarModel = (model) => model instanceof ScalarModel;
833
833
  var isObjectModel = (model) => model instanceof ObjectModel;
834
834
  var isInputModel = (model) => model instanceof InputModel;
835
835
  var isInterfaceModel = (model) => model instanceof InterfaceModel;
836
- var isCreatableModel = (model) => model.creatable && model.fields.some(isCreatableField);
837
- var isUpdatableModel = (model) => model.updatable && model.fields.some(isUpdatableField);
836
+ var isCreatableModel = (model) => !!model.creatable && model.fields.some(isCreatableField);
837
+ var isUpdatableModel = (model) => !!model.updatable && model.fields.some(isUpdatableField);
838
838
  var isCreatableField = (field) => !field.inherited && !!field.creatable;
839
839
  var isUpdatableField = (field) => !field.inherited && !!field.updatable;
840
840
  var modelNeedsTable = (model) => model.fields.some((field) => !field.inherited);
@@ -847,8 +847,8 @@ var isInTable = (field) => field.name === "id" || !field.inherited;
847
847
  var isToOneRelation = (field) => isRelation(field) && !!field.toOne;
848
848
  var isQueriableField = ({ queriable }) => queriable !== false;
849
849
  var isCustomField = (field) => field.kind === "custom";
850
- var isGenerateAsField = (field) => !!field.generateAs;
851
- var isStoredInDatabase = (field) => field.generateAs?.type !== "expression";
850
+ var isDynamicField = (field) => !!field.generateAs || isCustomField(field);
851
+ var isStoredInDatabase = (field) => !isCustomField(field) && field.generateAs?.type !== "expression";
852
852
  var isVisible = ({ hidden }) => hidden !== true;
853
853
  var isSimpleField = and(not(isRelation), not(isCustomField));
854
854
  var isUpdatable = ({ updatable }) => !!updatable;
@@ -1072,12 +1072,12 @@ var generateDBModels = (models, dateLibrary) => {
1072
1072
  for (const model of models.entities) {
1073
1073
  const fields2 = model.relations.some((relation) => relation.field.foreignKey === "id") ? model.fields.filter((field) => field.name !== "id") : model.fields;
1074
1074
  writer.write(`export type ${model.name} = `).inlineBlock(() => {
1075
- for (const field of fields2.filter(not(isCustomField)).filter(isStoredInDatabase)) {
1075
+ for (const field of fields2.filter(isStoredInDatabase)) {
1076
1076
  writer.write(`'${getColumnName(field)}': ${getFieldType(field, dateLibrary)}${field.nonNull ? "" : " | null"};`).newLine();
1077
1077
  }
1078
1078
  }).blankLine();
1079
1079
  writer.write(`export type ${model.name}Initializer = `).inlineBlock(() => {
1080
- for (const field of fields2.filter(not(isCustomField)).filter(isInTable).filter(not(isGenerateAsField))) {
1080
+ for (const field of fields2.filter(and(isInTable, not(isDynamicField)))) {
1081
1081
  writer.write(
1082
1082
  `'${getColumnName(field)}'${field.nonNull && field.defaultValue === void 0 ? "" : "?"}: ${getFieldType(
1083
1083
  field,
@@ -1088,7 +1088,7 @@ var generateDBModels = (models, dateLibrary) => {
1088
1088
  }
1089
1089
  }).blankLine();
1090
1090
  writer.write(`export type ${model.name}Mutator = `).inlineBlock(() => {
1091
- for (const field of fields2.filter(not(isCustomField)).filter(isInTable).filter(not(isGenerateAsField))) {
1091
+ for (const field of fields2.filter(and(isInTable, not(isDynamicField)))) {
1092
1092
  writer.write(
1093
1093
  `'${getColumnName(field)}'?: ${getFieldType(field, dateLibrary, true)}${field.list ? " | string" : ""}${field.nonNull ? "" : " | null"};`
1094
1094
  ).newLine();
@@ -1096,7 +1096,7 @@ var generateDBModels = (models, dateLibrary) => {
1096
1096
  }).blankLine();
1097
1097
  if (!isRootModel(model)) {
1098
1098
  writer.write(`export type ${model.name}Seed = `).inlineBlock(() => {
1099
- for (const field of fields2.filter(not(isCustomField)).filter(not(isGenerateAsField))) {
1099
+ for (const field of fields2.filter(not(isDynamicField))) {
1100
1100
  if (model.parent && field.name === "type") {
1101
1101
  continue;
1102
1102
  }
@@ -1157,6 +1157,75 @@ var generateKnexTables = (models) => {
1157
1157
  return writer.toString();
1158
1158
  };
1159
1159
 
1160
+ // src/migrations/generate-functions.ts
1161
+ var generateFunctionsFromDatabase = async (knex) => {
1162
+ const regularFunctions = await knex.raw(`
1163
+ SELECT
1164
+ pg_get_functiondef(p.oid) as definition
1165
+ FROM pg_proc p
1166
+ JOIN pg_namespace n ON p.pronamespace = n.oid
1167
+ WHERE n.nspname = 'public'
1168
+ AND NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid)
1169
+ ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
1170
+ `);
1171
+ const aggregateFunctions = await knex.raw(`
1172
+ SELECT
1173
+ p.proname as name,
1174
+ pg_get_function_identity_arguments(p.oid) as arguments,
1175
+ a.aggtransfn::regproc::text as trans_func,
1176
+ a.aggfinalfn::regproc::text as final_func,
1177
+ a.agginitval as init_val,
1178
+ pg_catalog.format_type(a.aggtranstype, NULL) as state_type
1179
+ FROM pg_proc p
1180
+ JOIN pg_aggregate a ON p.oid = a.aggfnoid
1181
+ JOIN pg_namespace n ON p.pronamespace = n.oid
1182
+ WHERE n.nspname = 'public'
1183
+ ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
1184
+ `);
1185
+ const functions = [];
1186
+ for (const row of regularFunctions.rows || []) {
1187
+ if (row.definition) {
1188
+ functions.push(row.definition.trim());
1189
+ }
1190
+ }
1191
+ for (const row of aggregateFunctions.rows || []) {
1192
+ const name2 = row.name || "";
1193
+ const argumentsStr = row.arguments || "";
1194
+ const transFunc = row.trans_func || "";
1195
+ const finalFunc = row.final_func || "";
1196
+ const initVal = row.init_val;
1197
+ const stateType = row.state_type || "";
1198
+ if (!name2 || !transFunc || !stateType) {
1199
+ continue;
1200
+ }
1201
+ let aggregateDef = `CREATE AGGREGATE ${name2}(${argumentsStr}) (
1202
+ `;
1203
+ aggregateDef += ` SFUNC = ${transFunc},
1204
+ `;
1205
+ aggregateDef += ` STYPE = ${stateType}`;
1206
+ if (finalFunc) {
1207
+ aggregateDef += `,
1208
+ FINALFUNC = ${finalFunc}`;
1209
+ }
1210
+ if (initVal !== null && initVal !== void 0) {
1211
+ const initValStr = typeof initVal === "string" ? `'${initVal}'` : String(initVal);
1212
+ aggregateDef += `,
1213
+ INITCOND = ${initValStr}`;
1214
+ }
1215
+ aggregateDef += "\n);";
1216
+ functions.push(aggregateDef);
1217
+ }
1218
+ if (functions.length === 0) {
1219
+ return `export const functions: string[] = [];
1220
+ `;
1221
+ }
1222
+ const functionsArrayString = functions.map((func) => ` ${JSON.stringify(func)}`).join(",\n");
1223
+ return `export const functions: string[] = [
1224
+ ${functionsArrayString},
1225
+ ];
1226
+ `;
1227
+ };
1228
+
1160
1229
  // src/migrations/generate.ts
1161
1230
  var import_code_block_writer2 = __toESM(require("code-block-writer"), 1);
1162
1231
  var import_knex_schema_inspector = require("knex-schema-inspector");
@@ -1790,7 +1859,7 @@ var checkCanWrite = async (ctx, model, data, action) => {
1790
1859
  }
1791
1860
  const query = ctx.knex.first();
1792
1861
  let linked = false;
1793
- for (const field of model.fields.filter(not(isGenerateAsField)).filter((field2) => field2.generated || (action === "CREATE" ? field2.creatable : field2.updatable))) {
1862
+ for (const field of model.fields.filter(isStoredInDatabase).filter((field2) => field2.generated || (action === "CREATE" ? field2.creatable : field2.updatable))) {
1794
1863
  const fieldPermissions = field[action === "CREATE" ? "creatable" : "updatable"];
1795
1864
  const role2 = getRole(ctx);
1796
1865
  if (getColumnName(field) in data && fieldPermissions && typeof fieldPermissions === "object" && !fieldPermissions.roles?.includes(role2)) {
@@ -2302,7 +2371,7 @@ var createEntity = async (modelName, input2, ctx, trigger = "direct-call") => wi
2302
2371
  if (model.parent) {
2303
2372
  const rootInput = {};
2304
2373
  const childInput = { id };
2305
- for (const field of model.fields.filter(not(isGenerateAsField))) {
2374
+ for (const field of model.fields.filter(not(isDynamicField))) {
2306
2375
  const columnName = field.kind === "relation" ? `${field.name}Id` : field.name;
2307
2376
  if (columnName in normalizedInput) {
2308
2377
  if (field.inherited) {
@@ -2316,7 +2385,7 @@ var createEntity = async (modelName, input2, ctx, trigger = "direct-call") => wi
2316
2385
  await ctx2.knex(model.name).insert(childInput);
2317
2386
  } else {
2318
2387
  const insertData = { ...normalizedInput };
2319
- for (const field of model.fields.filter(isGenerateAsField)) {
2388
+ for (const field of model.fields.filter(isDynamicField)) {
2320
2389
  const columnName = field.kind === "relation" ? `${field.name}Id` : field.name;
2321
2390
  delete insertData[columnName];
2322
2391
  }
@@ -2682,7 +2751,7 @@ var createRevision = async (model, data, ctx) => {
2682
2751
  rootRevisionData.deleted = data.deleted || false;
2683
2752
  }
2684
2753
  const childRevisionData = { id: revisionId };
2685
- for (const field of model.fields.filter(({ updatable }) => updatable).filter(not(isGenerateAsField))) {
2754
+ for (const field of model.fields.filter(and(isUpdatableField, not(isDynamicField)))) {
2686
2755
  const col = field.kind === "relation" ? `${field.name}Id` : field.name;
2687
2756
  let value2;
2688
2757
  if (field.nonNull && (!(col in data) || col === void 0 || col === null)) {
@@ -2746,7 +2815,7 @@ var doUpdate = async (model, currentEntity, update, ctx) => {
2746
2815
  if (model.parent) {
2747
2816
  const rootInput = {};
2748
2817
  const childInput = {};
2749
- for (const field of model.fields.filter(not(isGenerateAsField))) {
2818
+ for (const field of model.fields.filter(not(isDynamicField))) {
2750
2819
  const columnName = field.kind === "relation" ? `${field.name}Id` : field.name;
2751
2820
  if (columnName in update) {
2752
2821
  if (field.inherited) {
@@ -2764,7 +2833,7 @@ var doUpdate = async (model, currentEntity, update, ctx) => {
2764
2833
  }
2765
2834
  } else {
2766
2835
  const updateData = { ...update };
2767
- for (const field of model.fields.filter(isGenerateAsField)) {
2836
+ for (const field of model.fields.filter(isDynamicField)) {
2768
2837
  const columnName = field.kind === "relation" ? `${field.name}Id` : field.name;
2769
2838
  delete updateData[columnName];
2770
2839
  }
@@ -2792,10 +2861,10 @@ var getResolvers = (models) => {
2792
2861
  ])
2793
2862
  };
2794
2863
  const mutations = [
2795
- ...models.entities.filter(not(isRootModel)).filter(({ creatable }) => creatable).map((model) => ({
2864
+ ...models.entities.filter(and(not(isRootModel), isCreatable)).map((model) => ({
2796
2865
  [`create${model.name}`]: mutationResolver
2797
2866
  })),
2798
- ...models.entities.filter(not(isRootModel)).filter(({ updatable }) => updatable).map((model) => ({
2867
+ ...models.entities.filter(and(not(isRootModel), isUpdatable)).map((model) => ({
2799
2868
  [`update${model.name}`]: mutationResolver
2800
2869
  })),
2801
2870
  ...models.entities.filter(not(isRootModel)).filter(({ deletable }) => deletable).map((model) => ({
@@ -3231,7 +3300,7 @@ var MigrationGenerator = class {
3231
3300
  writer.writeLine(`deleteRootType: row.deleteRootType,`);
3232
3301
  writer.writeLine(`deleteRootId: row.deleteRootId,`);
3233
3302
  }
3234
- for (const { name: name2, kind } of model.fields.filter(isUpdatableField).filter(not(isGenerateAsField))) {
3303
+ for (const { name: name2, kind } of model.fields.filter(and(isUpdatableField, isStoredInDatabase))) {
3235
3304
  const col = kind === "relation" ? `${name2}Id` : name2;
3236
3305
  writer.writeLine(`${col}: row.${col},`);
3237
3306
  }
@@ -3251,8 +3320,8 @@ var MigrationGenerator = class {
3251
3320
  up,
3252
3321
  down
3253
3322
  );
3254
- const missingRevisionFields = model.fields.filter(isUpdatableField).filter(not(isGenerateAsField)).filter(
3255
- ({ name: name2, ...field }) => field.kind !== "custom" && !this.getColumn(revisionTable, field.kind === "relation" ? field.foreignKey || `${name2}Id` : name2)
3323
+ const missingRevisionFields = model.fields.filter(and(isUpdatableField, isStoredInDatabase)).filter(
3324
+ ({ name: name2, ...field }) => !this.getColumn(revisionTable, field.kind === "relation" ? field.foreignKey || `${name2}Id` : name2)
3256
3325
  );
3257
3326
  this.createRevisionFields(model, missingRevisionFields, up, down);
3258
3327
  const revisionFieldsToRemove = model.fields.filter(
@@ -3410,7 +3479,7 @@ var MigrationGenerator = class {
3410
3479
  });
3411
3480
  });
3412
3481
  if (isUpdatableModel(model)) {
3413
- const updatableFields = fields2.filter(isUpdatableField).filter(not(isGenerateAsField));
3482
+ const updatableFields = fields2.filter(and(isUpdatableField, isStoredInDatabase));
3414
3483
  if (!updatableFields.length) {
3415
3484
  return;
3416
3485
  }
@@ -3458,7 +3527,7 @@ var MigrationGenerator = class {
3458
3527
  });
3459
3528
  });
3460
3529
  if (isUpdatableModel(model)) {
3461
- const updatableFields = fields2.filter(isUpdatableField).filter(not(isGenerateAsField));
3530
+ const updatableFields = fields2.filter(and(isUpdatableField, isStoredInDatabase));
3462
3531
  if (!updatableFields.length) {
3463
3532
  return;
3464
3533
  }
@@ -3496,7 +3565,7 @@ var MigrationGenerator = class {
3496
3565
  writer.writeLine(`table.uuid('deleteRootId');`);
3497
3566
  }
3498
3567
  }
3499
- for (const field of model.fields.filter(and(isUpdatableField, not(isInherited))).filter(not(isGenerateAsField))) {
3568
+ for (const field of model.fields.filter(and(isUpdatableField, not(isInherited), isStoredInDatabase))) {
3500
3569
  this.column(field, { setUnique: false, setDefault: false });
3501
3570
  }
3502
3571
  });
@@ -3938,75 +4007,6 @@ var getMigrationDate = () => {
3938
4007
  return `${year}${month}${day}${hours}${minutes}${seconds}`;
3939
4008
  };
3940
4009
 
3941
- // src/migrations/generate-functions.ts
3942
- var generateFunctionsFromDatabase = async (knex) => {
3943
- const regularFunctions = await knex.raw(`
3944
- SELECT
3945
- pg_get_functiondef(p.oid) as definition
3946
- FROM pg_proc p
3947
- JOIN pg_namespace n ON p.pronamespace = n.oid
3948
- WHERE n.nspname = 'public'
3949
- AND NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid)
3950
- ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
3951
- `);
3952
- const aggregateFunctions = await knex.raw(`
3953
- SELECT
3954
- p.proname as name,
3955
- pg_get_function_identity_arguments(p.oid) as arguments,
3956
- a.aggtransfn::regproc::text as trans_func,
3957
- a.aggfinalfn::regproc::text as final_func,
3958
- a.agginitval as init_val,
3959
- pg_catalog.format_type(a.aggtranstype, NULL) as state_type
3960
- FROM pg_proc p
3961
- JOIN pg_aggregate a ON p.oid = a.aggfnoid
3962
- JOIN pg_namespace n ON p.pronamespace = n.oid
3963
- WHERE n.nspname = 'public'
3964
- ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
3965
- `);
3966
- const functions = [];
3967
- for (const row of regularFunctions.rows || []) {
3968
- if (row.definition) {
3969
- functions.push(row.definition.trim());
3970
- }
3971
- }
3972
- for (const row of aggregateFunctions.rows || []) {
3973
- const name2 = row.name || "";
3974
- const argumentsStr = row.arguments || "";
3975
- const transFunc = row.trans_func || "";
3976
- const finalFunc = row.final_func || "";
3977
- const initVal = row.init_val;
3978
- const stateType = row.state_type || "";
3979
- if (!name2 || !transFunc || !stateType) {
3980
- continue;
3981
- }
3982
- let aggregateDef = `CREATE AGGREGATE ${name2}(${argumentsStr}) (
3983
- `;
3984
- aggregateDef += ` SFUNC = ${transFunc},
3985
- `;
3986
- aggregateDef += ` STYPE = ${stateType}`;
3987
- if (finalFunc) {
3988
- aggregateDef += `,
3989
- FINALFUNC = ${finalFunc}`;
3990
- }
3991
- if (initVal !== null && initVal !== void 0) {
3992
- const initValStr = typeof initVal === "string" ? `'${initVal}'` : String(initVal);
3993
- aggregateDef += `,
3994
- INITCOND = ${initValStr}`;
3995
- }
3996
- aggregateDef += "\n);";
3997
- functions.push(aggregateDef);
3998
- }
3999
- if (functions.length === 0) {
4000
- return `export const functions: string[] = [];
4001
- `;
4002
- }
4003
- const functionsArrayString = functions.map((func) => ` ${JSON.stringify(func)}`).join(",\n");
4004
- return `export const functions: string[] = [
4005
- ${functionsArrayString},
4006
- ];
4007
- `;
4008
- };
4009
-
4010
4010
  // src/permissions/generate.ts
4011
4011
  var ACTIONS = ["READ", "CREATE", "UPDATE", "DELETE", "RESTORE", "LINK"];
4012
4012
  var generatePermissions = (models, config) => {
@@ -4364,7 +4364,7 @@ var generateDefinitions = ({
4364
4364
  types.push(
4365
4365
  input(
4366
4366
  `Create${model.name}`,
4367
- model.fields.filter(({ creatable }) => creatable).filter(not(isGenerateAsField)).map(
4367
+ model.fields.filter(and(isCreatable, isStoredInDatabase)).map(
4368
4368
  (field) => field.kind === "relation" ? { name: `${field.name}Id`, type: "ID", nonNull: field.nonNull } : {
4369
4369
  name: field.name,
4370
4370
  type: field.kind === "json" ? `Create${field.type}` : field.type,
@@ -4379,7 +4379,7 @@ var generateDefinitions = ({
4379
4379
  types.push(
4380
4380
  input(
4381
4381
  `Update${model.name}`,
4382
- model.fields.filter(({ updatable }) => updatable).filter(not(isGenerateAsField)).map(
4382
+ model.fields.filter(and(isUpdatable, isStoredInDatabase)).map(
4383
4383
  (field) => field.kind === "relation" ? { name: `${field.name}Id`, type: "ID" } : {
4384
4384
  name: field.name,
4385
4385
  type: field.kind === "json" ? `Update${field.type}` : field.type,
@@ -4631,12 +4631,12 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql6.buildAST
4631
4631
  isCreatableField,
4632
4632
  isCreatableModel,
4633
4633
  isCustomField,
4634
+ isDynamicField,
4634
4635
  isEntityModel,
4635
4636
  isEnum,
4636
4637
  isEnumModel,
4637
4638
  isFieldNode,
4638
4639
  isFragmentSpreadNode,
4639
- isGenerateAsField,
4640
4640
  isInTable,
4641
4641
  isInherited,
4642
4642
  isInlineFragmentNode,