@smartive/graphql-magic 3.0.1 → 4.0.0

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 (50) hide show
  1. package/CHANGELOG.md +1 -6
  2. package/dist/cjs/index.cjs +205 -172
  3. package/dist/esm/client/queries.d.ts +4 -1
  4. package/dist/esm/client/queries.js +16 -6
  5. package/dist/esm/client/queries.js.map +1 -1
  6. package/dist/esm/db/generate.js +21 -13
  7. package/dist/esm/db/generate.js.map +1 -1
  8. package/dist/esm/generate/generate.js +17 -22
  9. package/dist/esm/generate/generate.js.map +1 -1
  10. package/dist/esm/generate/utils.d.ts +10 -1
  11. package/dist/esm/generate/utils.js.map +1 -1
  12. package/dist/esm/migrations/generate.js +82 -89
  13. package/dist/esm/migrations/generate.js.map +1 -1
  14. package/dist/esm/models.d.ts +115 -93
  15. package/dist/esm/models.js +1 -26
  16. package/dist/esm/models.js.map +1 -1
  17. package/dist/esm/permissions/check.js +2 -2
  18. package/dist/esm/permissions/check.js.map +1 -1
  19. package/dist/esm/permissions/generate.js +2 -2
  20. package/dist/esm/permissions/generate.js.map +1 -1
  21. package/dist/esm/resolvers/filters.js +1 -1
  22. package/dist/esm/resolvers/filters.js.map +1 -1
  23. package/dist/esm/resolvers/mutations.js +5 -6
  24. package/dist/esm/resolvers/mutations.js.map +1 -1
  25. package/dist/esm/resolvers/node.js +4 -5
  26. package/dist/esm/resolvers/node.js.map +1 -1
  27. package/dist/esm/resolvers/resolver.js +2 -2
  28. package/dist/esm/resolvers/resolver.js.map +1 -1
  29. package/dist/esm/utils.d.ts +181 -1
  30. package/dist/esm/utils.js +69 -21
  31. package/dist/esm/utils.js.map +1 -1
  32. package/package.json +8 -8
  33. package/src/client/queries.ts +26 -12
  34. package/src/db/generate.ts +22 -15
  35. package/src/generate/generate.ts +26 -34
  36. package/src/generate/utils.ts +11 -1
  37. package/src/migrations/generate.ts +84 -82
  38. package/src/models.ts +113 -157
  39. package/src/permissions/check.ts +2 -2
  40. package/src/permissions/generate.ts +2 -2
  41. package/src/resolvers/filters.ts +1 -1
  42. package/src/resolvers/mutations.ts +10 -9
  43. package/src/resolvers/node.ts +6 -6
  44. package/src/resolvers/resolver.ts +2 -2
  45. package/src/utils.ts +158 -57
  46. package/tests/unit/__snapshots__/generate.spec.ts.snap +3 -0
  47. package/tests/unit/__snapshots__/queries.spec.ts.snap +11 -0
  48. package/tests/unit/queries.spec.ts +10 -0
  49. package/tests/utils/database/schema.ts +2 -0
  50. package/tests/utils/models.ts +14 -6
@@ -106,7 +106,6 @@ __export(src_exports, {
106
106
  isFieldNode: () => isFieldNode,
107
107
  isFragmentSpreadNode: () => isFragmentSpreadNode,
108
108
  isInlineFragmentNode: () => isInlineFragmentNode,
109
- isJsonObjectModel: () => isJsonObjectModel,
110
109
  isListType: () => isListType,
111
110
  isObjectModel: () => isObjectModel,
112
111
  isQueriableBy: () => isQueriableBy,
@@ -162,35 +161,6 @@ var gql = (chunks, ...variables) => {
162
161
  // src/client/queries.ts
163
162
  var import_upperFirst = __toESM(require("lodash/upperFirst"), 1);
164
163
 
165
- // src/models.ts
166
- var isObjectModel = (model) => model.type === "object";
167
- var isEnumModel = (model) => model.type === "enum";
168
- var isRawEnumModel = (model) => model.type === "raw-enum";
169
- var isScalarModel = (model) => model.type === "scalar";
170
- var isRawObjectModel = (model) => model.type === "raw-object";
171
- var isJsonObjectModel = (model) => model.type === "json-object";
172
- var isEnumList = (models, field) => field?.list === true && models.find(({ name: name2 }) => name2 === field.type)?.type === "enum";
173
- var and = (...predicates) => (field) => predicates.every((predicate) => predicate(field));
174
- var not = (predicate) => (field) => !predicate(field);
175
- var isRelation = ({ relation }) => !!relation;
176
- var isVisibleRelation = (visibleRelationsByRole, modelName, role) => {
177
- const whitelist = visibleRelationsByRole[role]?.[modelName];
178
- return ({ name: name2 }) => whitelist ? whitelist.includes(name2) : true;
179
- };
180
- var isToOneRelation = ({ toOne }) => !!toOne;
181
- var isQueriableField = ({ queriable }) => queriable !== false;
182
- var isRaw = ({ raw }) => !!raw;
183
- var isVisible = ({ hidden }) => hidden !== true;
184
- var isSimpleField = and(not(isRelation), not(isRaw));
185
- var isUpdatable = ({ updatable }) => !!updatable;
186
- var isCreatable = ({ creatable }) => !!creatable;
187
- var isQueriableBy = (role) => (field) => isQueriableField(field) && (!field.queriableBy || field.queriableBy.includes(role));
188
- var isUpdatableBy = (role) => (field) => isUpdatable(field) && (!field.updatableBy || field.updatableBy.includes(role));
189
- var isCreatableBy = (role) => (field) => isCreatable(field) && (!field.creatableBy || field.creatableBy.includes(role));
190
- var actionableRelations = (model, action) => model.fields.filter(
191
- ({ relation, ...field }) => relation && field[`${action === "filter" ? action : action.slice(0, -1)}able`]
192
- );
193
-
194
164
  // src/utils.ts
195
165
  var import_assert = __toESM(require("assert"), 1);
196
166
  var import_inflection = require("inflection");
@@ -207,6 +177,28 @@ var getModelSlug = (model) => (0, import_kebabCase.default)(getModelPlural(model
207
177
  var getModelLabelPlural = (model) => getLabel(getModelPlural(model));
208
178
  var getModelLabel = (model) => getLabel(model.name);
209
179
  var getLabel = (s) => (0, import_startCase.default)((0, import_camelCase.default)(s));
180
+ var isObjectModel = (model) => model.type === "object";
181
+ var isEnumModel = (model) => model.type === "enum";
182
+ var isRawEnumModel = (model) => model.type === "raw-enum";
183
+ var isScalarModel = (model) => model.type === "scalar";
184
+ var isRawObjectModel = (model) => model.type === "raw";
185
+ var isEnumList = (models, field) => field?.list === true && models.find(({ name: name2 }) => name2 === field.type)?.type === "enum";
186
+ var and = (...predicates) => (field) => predicates.every((predicate) => predicate(field));
187
+ var not = (predicate) => (field) => !predicate(field);
188
+ var isRelation = (field) => field.type === "relation";
189
+ var isToOneRelation = (field) => isRelation(field) && !!field.toOne;
190
+ var isQueriableField = ({ queriable }) => queriable !== false;
191
+ var isRaw = (field) => field.type === "raw";
192
+ var isVisible = ({ hidden }) => hidden !== true;
193
+ var isSimpleField = and(not(isRelation), not(isRaw));
194
+ var isUpdatable = ({ updatable }) => !!updatable;
195
+ var isCreatable = ({ creatable }) => !!creatable;
196
+ var isQueriableBy = (role) => (field) => field.queriable !== false && (field.queriable == true || !field.queriable.roles || field.queriable.roles.includes(role));
197
+ var isUpdatableBy = (role) => (field) => field.updatable && (field.updatable === true || !field.updatable.roles || field.updatable.roles.includes(role));
198
+ var isCreatableBy = (role) => (field) => field.creatable && (field.creatable === true || !field.creatable.roles || field.creatable.roles.includes(role));
199
+ var actionableRelations = (model, action) => model.fields.filter(isRelation).filter(
200
+ (field) => field[`${action === "filter" ? action : action.slice(0, -1)}able`]
201
+ );
210
202
  var getModels = (rawModels) => {
211
203
  const models = rawModels.filter(isObjectModel).map((model) => {
212
204
  const objectModel = {
@@ -220,25 +212,41 @@ var getModels = (rawModels) => {
220
212
  { name: "id", type: "ID", nonNull: true, unique: true, primary: true, generated: true },
221
213
  ...model.fields,
222
214
  ...model.creatable ? [
223
- { name: "createdAt", type: "DateTime", nonNull: !model.nonStrict, orderable: true, generated: true },
215
+ {
216
+ name: "createdAt",
217
+ type: "DateTime",
218
+ nonNull: true,
219
+ orderable: true,
220
+ generated: true,
221
+ ...typeof model.creatable === "object" && model.creatable.createdAt
222
+ },
224
223
  {
225
224
  name: "createdBy",
226
- type: "User",
227
- relation: true,
228
- nonNull: !model.nonStrict,
225
+ type: "relation",
226
+ typeName: "User",
227
+ nonNull: true,
229
228
  reverse: `created${getModelPlural(model)}`,
230
- generated: true
229
+ generated: true,
230
+ ...typeof model.creatable === "object" && model.creatable.createdBy
231
231
  }
232
232
  ] : [],
233
233
  ...model.updatable ? [
234
- { name: "updatedAt", type: "DateTime", nonNull: !model.nonStrict, orderable: true, generated: true },
234
+ {
235
+ name: "updatedAt",
236
+ type: "DateTime",
237
+ nonNull: true,
238
+ orderable: true,
239
+ generated: true,
240
+ ...typeof model.updatable === "object" && model.updatable.updatedAt
241
+ },
235
242
  {
236
243
  name: "updatedBy",
237
- type: "User",
238
- relation: true,
239
- nonNull: !model.nonStrict,
244
+ type: "relation",
245
+ typeName: "User",
246
+ nonNull: true,
240
247
  reverse: `updated${getModelPlural(model)}`,
241
- generated: true
248
+ generated: true,
249
+ ...typeof model.updatable === "object" && model.updatable.updatedBy
242
250
  }
243
251
  ] : [],
244
252
  ...model.deletable ? [
@@ -247,23 +255,30 @@ var getModels = (rawModels) => {
247
255
  type: "Boolean",
248
256
  nonNull: true,
249
257
  default: false,
250
- filterable: true,
251
- defaultFilter: false,
252
- generated: true
258
+ filterable: { default: false },
259
+ generated: true,
260
+ ...typeof model.deletable === "object" && model.deletable.deleted
261
+ },
262
+ {
263
+ name: "deletedAt",
264
+ type: "DateTime",
265
+ orderable: true,
266
+ generated: true,
267
+ ...typeof model.deletable === "object" && model.deletable.deletedAt
253
268
  },
254
- { name: "deletedAt", type: "DateTime", orderable: true, generated: true },
255
269
  {
256
270
  name: "deletedBy",
257
- type: "User",
258
- relation: true,
271
+ type: "relation",
272
+ typeName: "User",
259
273
  reverse: `deleted${getModelPlural(model)}`,
260
- generated: true
274
+ generated: true,
275
+ ...typeof model.deletable === "object" && model.deletable.deletedBy
261
276
  }
262
277
  ] : []
263
- ].map(({ foreignKey, ...field }) => ({
278
+ ].map((field) => ({
264
279
  ...field,
265
- ...field.relation && {
266
- foreignKey: foreignKey || `${field.name}Id`
280
+ ...field.type === "relation" && {
281
+ foreignKey: field.foreignKey || `${field.name}Id`
267
282
  }
268
283
  }))
269
284
  };
@@ -273,12 +288,16 @@ var getModels = (rawModels) => {
273
288
  return objectModel;
274
289
  });
275
290
  for (const model of models) {
276
- for (const field of model.fields.filter(({ relation }) => relation)) {
277
- const fieldModel = summonByName(models, field.type);
291
+ for (const field of model.fields) {
292
+ if (field.type !== "relation") {
293
+ continue;
294
+ }
295
+ const fieldModel = summonByName(models, field.typeName);
278
296
  const reverseRelation = {
297
+ type: "relation",
279
298
  name: field.reverse || (field.toOne ? typeToField(model.name) : getModelPluralField(model)),
280
299
  foreignKey: get(field, "foreignKey"),
281
- type: model.name,
300
+ typeName: model.name,
282
301
  toOne: !!field.toOne,
283
302
  fieldModel,
284
303
  field,
@@ -356,11 +375,18 @@ var getEditEntityRelationsQuery = (models, model, action, fields2, ignoreFields,
356
375
  ({ name: name2 }) => (!fields2 || fields2.includes(name2)) && (!ignoreFields || !ignoreFields.includes(name2))
357
376
  );
358
377
  return !!relations.length && `query ${(0, import_upperFirst.default)(action)}${model.name}Relations {
359
- ${relations.map(({ name: name2, type }) => {
360
- const model2 = summonByName(models, type);
361
- return `${name2}: ${getModelPluralField(model2)} {
378
+ ${relations.map(({ name: name2, typeName }) => {
379
+ const model2 = summonByName(models, typeName);
380
+ let filters = "";
381
+ if (model2.displayField) {
382
+ const displayField2 = model2.fieldsByName[model2.displayField];
383
+ if (displayField2.orderable) {
384
+ filters = `(orderBy: [{ ${model2.displayField}: ASC }])`;
385
+ }
386
+ }
387
+ return `${name2}: ${getModelPluralField(model2)}${filters} {
362
388
  id
363
- display: ${model2.displayField || ""}
389
+ display: ${model2.displayField || "id"}
364
390
  ${additionalFields[name2] || ""}
365
391
  }`;
366
392
  }).join(" ")}
@@ -450,6 +476,10 @@ var getEntityListQuery = (model, role, additionalFields = "", root) => `query ${
450
476
  }
451
477
  ${root ? "}" : ""}
452
478
  }`;
479
+ var isVisibleRelation = (visibleRelationsByRole, modelName, role) => {
480
+ const whitelist = visibleRelationsByRole[role]?.[modelName];
481
+ return ({ name: name2 }) => whitelist ? whitelist.includes(name2) : true;
482
+ };
453
483
  var getEntityQuery = (models, model, role, visibleRelationsByRole, typesWithSubRelations) => `query Admin${model.name} ($id: ID!) {
454
484
  data: ${typeToField(model.name)}(where: { id: $id }) {
455
485
  ${displayField(model)}
@@ -506,14 +536,14 @@ var generateDBModels = (rawModels) => {
506
536
  }
507
537
  const models = getModels(rawModels);
508
538
  for (const model of models) {
509
- const fields2 = model.fields.some((field) => field.foreignKey === "id") ? model.fields.filter((field) => field.name !== "id") : model.fields;
539
+ const fields2 = model.fields.some((field) => field.type === "relation" && field.foreignKey === "id") ? model.fields.filter((field) => field.name !== "id") : model.fields;
510
540
  writer.write(`export type ${model.name} = `).inlineBlock(() => {
511
- for (const field of fields2.filter(({ raw }) => !raw)) {
541
+ for (const field of fields2.filter(not(isRaw))) {
512
542
  writer.write(`'${getFieldName(field)}': ${getFieldOutputType(field)}${field.nonNull ? "" : " | null"},`).newLine();
513
543
  }
514
544
  }).blankLine();
515
545
  writer.write(`export type ${model.name}Initializer = `).inlineBlock(() => {
516
- for (const field of fields2.filter(({ raw }) => !raw)) {
546
+ for (const field of fields2.filter(not(isRaw))) {
517
547
  writer.write(
518
548
  `'${getFieldName(field)}'${field.nonNull && field.default === void 0 ? "" : "?"}: ${getFieldInputType(
519
549
  field
@@ -522,12 +552,12 @@ var generateDBModels = (rawModels) => {
522
552
  }
523
553
  }).blankLine();
524
554
  writer.write(`export type ${model.name}Mutator = `).inlineBlock(() => {
525
- for (const field of fields2.filter(({ raw }) => !raw)) {
555
+ for (const field of fields2.filter(not(isRaw))) {
526
556
  writer.write(`'${getFieldName(field)}'?: ${getFieldInputType(field)}${field.nonNull ? "" : " | null"},`).newLine();
527
557
  }
528
558
  }).blankLine();
529
559
  writer.write(`export type ${model.name}Seed = `).inlineBlock(() => {
530
- for (const field of fields2.filter(({ raw }) => !raw)) {
560
+ for (const field of fields2.filter(not(isRaw))) {
531
561
  const fieldName = getFieldName(field);
532
562
  writer.write(
533
563
  `'${getFieldName(field)}'${field.nonNull && field.default === void 0 && !OPTIONAL_SEED_FIELDS.includes(fieldName) ? "" : "?"}: ${getFieldInputType(
@@ -545,14 +575,20 @@ var generateDBModels = (rawModels) => {
545
575
  });
546
576
  return writer.toString();
547
577
  };
548
- var getFieldName = ({ relation, name: name2, foreignKey }) => {
549
- return foreignKey || `${name2}${relation ? "Id" : ""}`;
550
- };
551
- var getFieldOutputType = ({ relation, type, list: list2, json }) => {
552
- if (json || relation) {
553
- return "string";
578
+ var getFieldName = (field) => field.type === "relation" ? field.foreignKey || `${field.name}Id` : field.name;
579
+ var getFieldOutputType = (field) => {
580
+ switch (field.type) {
581
+ case "json":
582
+ return "string";
583
+ case "relation":
584
+ return "string";
585
+ case "enum":
586
+ return field.typeName + field.list ? "[]" : "";
587
+ case "raw":
588
+ throw new Error(`Raw fields are not in the db.`);
589
+ default:
590
+ return get(PRIMITIVE_TYPES, field.type) + (field.list ? "[]" : "");
554
591
  }
555
- return (PRIMITIVE_TYPES[type] || type) + (list2 ? "[]" : "");
556
592
  };
557
593
  var getFieldInputType = (field, stringTypes = []) => {
558
594
  let outputType = getFieldOutputType(field);
@@ -757,14 +793,6 @@ var generateDefinitions = (rawModels) => {
757
793
  ...rawModels.filter(isRawEnumModel).map((model) => enm(model.name, model.values)),
758
794
  ...rawModels.filter(isScalarModel).map((model) => scalar(model.name)),
759
795
  ...rawModels.filter(isRawObjectModel).map((model) => object(model.name, model.fields)),
760
- ...rawModels.filter(isJsonObjectModel).map((model) => object(model.name, model.fields)),
761
- ...rawModels.filter(isRawObjectModel).filter(({ rawFilters }) => rawFilters).map(
762
- (model) => input(
763
- `${model.name}Where`,
764
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- array gets filtered above to only include models with rawFilters
765
- model.rawFilters.map(({ name: name2, type, list: list2 = false, nonNull: nonNull2 = false }) => ({ name: name2, type, list: list2, nonNull: nonNull2 }))
766
- )
767
- ),
768
796
  ...(0, import_flatMap.default)(
769
797
  models.map((model) => {
770
798
  const types = [
@@ -773,10 +801,8 @@ var generateDefinitions = (rawModels) => {
773
801
  [
774
802
  ...model.fields.filter(isQueriableField).map((field) => ({
775
803
  ...field,
776
- args: [
777
- ...field.args || [],
778
- ...hasRawFilters(rawModels, field.type) ? [{ name: "where", type: `${field.type}Where` }] : []
779
- ],
804
+ type: field.type === "relation" || field.type === "enum" || field.type === "raw" ? field.typeName : field.type,
805
+ args: [...field.args || []],
780
806
  directives: field.directives
781
807
  })),
782
808
  ...model.reverseRelations.map(({ name: name2, field, model: model2 }) => ({
@@ -796,7 +822,12 @@ var generateDefinitions = (rawModels) => {
796
822
  model.interfaces
797
823
  ),
798
824
  input(`${model.name}Where`, [
799
- ...model.fields.filter(({ unique, filterable, relation }) => (unique || filterable) && !relation).map(({ name: name2, type, defaultFilter }) => ({ name: name2, type, list: true, default: defaultFilter })),
825
+ ...model.fields.filter(({ type, unique, filterable }) => (unique || filterable) && type !== "relation").map(({ type, name: name2, filterable }) => ({
826
+ name: name2,
827
+ type,
828
+ list: true,
829
+ default: typeof filterable === "object" ? filterable.default : void 0
830
+ })),
800
831
  ...(0, import_flatMap.default)(
801
832
  model.fields.filter(({ comparable }) => comparable),
802
833
  ({ name: name2, type }) => [
@@ -806,9 +837,9 @@ var generateDefinitions = (rawModels) => {
806
837
  { name: `${name2}_LTE`, type }
807
838
  ]
808
839
  ),
809
- ...model.fields.filter(({ filterable, relation }) => filterable && relation).map(({ name: name2, type }) => ({
840
+ ...model.fields.filter(isRelation).filter(({ filterable }) => filterable).map(({ name: name2, typeName }) => ({
810
841
  name: name2,
811
- type: `${type}Where`
842
+ type: `${typeName}Where`
812
843
  }))
813
844
  ]),
814
845
  input(
@@ -827,7 +858,7 @@ var generateDefinitions = (rawModels) => {
827
858
  input(
828
859
  `Create${model.name}`,
829
860
  model.fields.filter(({ creatable }) => creatable).map(
830
- ({ name: name2, relation, type, nonNull: nonNull2, list: list2, default: defaultValue }) => relation ? { name: `${name2}Id`, type: "ID", nonNull: nonNull2 } : { name: name2, type, list: list2, nonNull: nonNull2 && defaultValue === void 0 }
861
+ ({ name: name2, nonNull: nonNull2, list: list2, default: defaultValue, ...field }) => field.type === "relation" ? { name: `${name2}Id`, type: "ID", nonNull: nonNull2 } : { name: name2, type: field.type, list: list2, nonNull: nonNull2 && defaultValue === void 0 }
831
862
  )
832
863
  )
833
864
  );
@@ -837,7 +868,7 @@ var generateDefinitions = (rawModels) => {
837
868
  input(
838
869
  `Update${model.name}`,
839
870
  model.fields.filter(({ updatable }) => updatable).map(
840
- ({ name: name2, relation, type, list: list2 }) => relation ? { name: `${name2}Id`, type: "ID" } : { name: name2, type, list: list2 }
871
+ ({ name: name2, type, list: list2 }) => type === "relation" ? { name: `${name2}Id`, type: "ID" } : { name: name2, type, list: list2 }
841
872
  )
842
873
  )
843
874
  );
@@ -955,7 +986,6 @@ var printSchema = (schema) => [
955
986
  ...Object.values(schema.getTypeMap()).filter((t) => !t.name.match(/^__/)).sort((a, b) => a.name > b.name ? 1 : -1).map((t) => t.astNode && (0, import_graphql.print)(t.astNode))
956
987
  ].filter(Boolean).map((s) => `${s}
957
988
  `).join("\n");
958
- var hasRawFilters = (models, type) => models.filter(isRawObjectModel).some(({ name: name2, rawFilters }) => name2 === type && !!rawFilters);
959
989
  var printSchemaFromDocument = (document2) => printSchema((0, import_graphql.buildASTSchema)(document2));
960
990
  var printSchemaFromModels = (models) => printSchema((0, import_graphql.buildASTSchema)(generate(models)));
961
991
 
@@ -1107,17 +1137,19 @@ var MigrationGenerator = class {
1107
1137
  this.createFields(
1108
1138
  model,
1109
1139
  model.fields.filter(
1110
- ({ name: name2, relation, raw, foreignKey }) => !raw && !this.columns[model.name].some((col) => col.name === (foreignKey || (relation ? `${name2}Id` : name2)))
1140
+ ({ name: name2, ...field }) => field.type !== "raw" && !this.columns[model.name].some(
1141
+ (col) => col.name === (field.type === "relation" ? field.foreignKey || `${name2}Id` : name2)
1142
+ )
1111
1143
  ),
1112
1144
  up,
1113
1145
  down
1114
1146
  );
1115
- const existingFields = model.fields.filter(({ name: name2, relation, nonNull: nonNull2 }) => {
1116
- const col = this.columns[model.name].find((col2) => col2.name === (relation ? `${name2}Id` : name2));
1147
+ const existingFields = model.fields.filter(({ name: name2, type, nonNull: nonNull2 }) => {
1148
+ const col = this.columns[model.name].find((col2) => col2.name === (type === "relation" ? `${name2}Id` : name2));
1117
1149
  if (!col) {
1118
1150
  return false;
1119
1151
  }
1120
- return !model.nonStrict && !nonNull2 && !col.is_nullable;
1152
+ return !nonNull2 && !col.is_nullable;
1121
1153
  });
1122
1154
  this.updateFields(model, existingFields, up, down);
1123
1155
  }
@@ -1140,8 +1172,8 @@ var MigrationGenerator = class {
1140
1172
  if (model.deletable) {
1141
1173
  writer.writeLine(`deleted: row.deleted,`);
1142
1174
  }
1143
- for (const { name: name2, relation } of model.fields.filter(({ updatable }) => updatable)) {
1144
- const col = relation ? `${name2}Id` : name2;
1175
+ for (const { name: name2, type } of model.fields.filter(({ updatable }) => updatable)) {
1176
+ const col = type === "relation" ? `${name2}Id` : name2;
1145
1177
  writer.writeLine(`${col}: row.${col},`);
1146
1178
  }
1147
1179
  }).write(")));").newLine();
@@ -1155,11 +1187,15 @@ var MigrationGenerator = class {
1155
1187
  } else {
1156
1188
  const revisionTable = `${model.name}Revision`;
1157
1189
  const missingRevisionFields = model.fields.filter(
1158
- ({ name: name2, relation, raw, foreignKey, updatable }) => !raw && updatable && !this.columns[revisionTable].some((col) => col.name === (foreignKey || (relation ? `${name2}Id` : name2)))
1190
+ ({ name: name2, updatable, ...field }) => field.type !== "raw" && updatable && !this.columns[revisionTable].some(
1191
+ (col) => col.name === (field.type === "relation" ? field.foreignKey || `${name2}Id` : name2)
1192
+ )
1159
1193
  );
1160
1194
  this.createRevisionFields(model, missingRevisionFields, up, down);
1161
1195
  const revisionFieldsToRemove = model.fields.filter(
1162
- ({ name: name2, updatable, foreignKey, relation, raw, generated }) => !generated && !raw && !updatable && foreignKey !== "id" && this.columns[revisionTable].some((col) => col.name === (foreignKey || (relation ? `${name2}Id` : name2)))
1196
+ ({ name: name2, updatable, generated, ...field }) => !generated && field.type !== "raw" && !updatable && !(field.type === "relation" && field.foreignKey === "id") && this.columns[revisionTable].some(
1197
+ (col) => col.name === (field.type === "relation" ? field.foreignKey || `${name2}Id` : name2)
1198
+ )
1163
1199
  );
1164
1200
  this.createRevisionFields(model, revisionFieldsToRemove, down, up);
1165
1201
  }
@@ -1211,8 +1247,8 @@ var MigrationGenerator = class {
1211
1247
  for (const field of fields2) {
1212
1248
  this.alterTable(model.name, () => {
1213
1249
  this.renameColumn(
1214
- field.relation ? `${field.oldName}Id` : get(field, "oldName"),
1215
- field.relation ? `${field.name}Id` : field.name
1250
+ field.type === "relation" ? `${field.oldName}Id` : get(field, "oldName"),
1251
+ field.type === "relation" ? `${field.name}Id` : field.name
1216
1252
  );
1217
1253
  });
1218
1254
  }
@@ -1221,14 +1257,14 @@ var MigrationGenerator = class {
1221
1257
  for (const field of fields2) {
1222
1258
  this.alterTable(model.name, () => {
1223
1259
  this.renameColumn(
1224
- field.relation ? `${field.name}Id` : field.name,
1225
- field.relation ? `${field.oldName}Id` : get(field, "oldName")
1260
+ field.type === "relation" ? `${field.name}Id` : field.name,
1261
+ field.type === "relation" ? `${field.oldName}Id` : get(field, "oldName")
1226
1262
  );
1227
1263
  });
1228
1264
  }
1229
1265
  });
1230
1266
  for (const field of fields2) {
1231
- summonByName(this.columns[model.name], field.relation ? `${field.oldName}Id` : field.oldName).name = field.relation ? `${field.name}Id` : field.name;
1267
+ summonByName(this.columns[model.name], field.type === "relation" ? `${field.oldName}Id` : field.oldName).name = field.type === "relation" ? `${field.name}Id` : field.name;
1232
1268
  }
1233
1269
  }
1234
1270
  createFields(model, fields2, up, down) {
@@ -1264,8 +1300,8 @@ var MigrationGenerator = class {
1264
1300
  });
1265
1301
  down.push(() => {
1266
1302
  this.alterTable(model.name, () => {
1267
- for (const { relation, name: name2 } of fields2) {
1268
- this.dropColumn(relation ? `${name2}Id` : name2);
1303
+ for (const { type, name: name2 } of fields2) {
1304
+ this.dropColumn(type === "relation" ? `${name2}Id` : name2);
1269
1305
  }
1270
1306
  });
1271
1307
  });
@@ -1287,7 +1323,7 @@ var MigrationGenerator = class {
1287
1323
  this.column(
1288
1324
  field,
1289
1325
  { alter: true },
1290
- summonByName(this.columns[model.name], field.relation ? `${field.name}Id` : field.name)
1326
+ summonByName(this.columns[model.name], field.type === "relation" ? `${field.name}Id` : field.name)
1291
1327
  );
1292
1328
  }
1293
1329
  });
@@ -1310,7 +1346,7 @@ var MigrationGenerator = class {
1310
1346
  this.column(
1311
1347
  field,
1312
1348
  { alter: true },
1313
- summonByName(this.columns[model.name], field.relation ? `${field.name}Id` : field.name)
1349
+ summonByName(this.columns[model.name], field.type === "relation" ? `${field.name}Id` : field.name)
1314
1350
  );
1315
1351
  }
1316
1352
  });
@@ -1323,9 +1359,7 @@ var MigrationGenerator = class {
1323
1359
  writer.writeLine(`table.uuid('id').notNullable().primary();`);
1324
1360
  writer.writeLine(`table.uuid('${typeToField(model.name)}Id').notNullable();`);
1325
1361
  writer.write(`table.uuid('createdById')`);
1326
- if (!model.nonStrict) {
1327
- writer.write(".notNullable()");
1328
- }
1362
+ writer.write(".notNullable()");
1329
1363
  writer.write(";").newLine();
1330
1364
  writer.writeLine(`table.timestamp('createdAt').notNullable().defaultTo(knex.fn.now(0));`);
1331
1365
  if (model.deletable) {
@@ -1346,8 +1380,8 @@ var MigrationGenerator = class {
1346
1380
  }
1347
1381
  });
1348
1382
  this.writer.write(`await knex('${model.name}Revision').update(`).inlineBlock(() => {
1349
- for (const { name: name2, relation } of missingRevisionFields) {
1350
- const col = relation ? `${name2}Id` : name2;
1383
+ for (const { name: name2, type } of missingRevisionFields) {
1384
+ const col = type === "relation" ? `${name2}Id` : name2;
1351
1385
  this.writer.write(
1352
1386
  `${col}: knex.raw('(select "${col}" from "${model.name}" where "${model.name}".id = "${model.name}Revision"."${typeToField(model.name)}Id")'),`
1353
1387
  ).newLine();
@@ -1365,7 +1399,7 @@ var MigrationGenerator = class {
1365
1399
  down.push(() => {
1366
1400
  this.alterTable(revisionTable, () => {
1367
1401
  for (const field of missingRevisionFields) {
1368
- this.dropColumn(field.relation ? `${field.name}Id` : field.name);
1402
+ this.dropColumn(field.type === "relation" ? `${field.name}Id` : field.name);
1369
1403
  }
1370
1404
  });
1371
1405
  });
@@ -1411,7 +1445,7 @@ var MigrationGenerator = class {
1411
1445
  }
1412
1446
  return value2;
1413
1447
  }
1414
- column({ name: name2, relation, type, primary, list: list2, ...field }, { setUnique = true, setNonNull = true, alter = false, foreign = true, setDefault = true } = {}, toColumn) {
1448
+ column({ name: name2, primary, list: list2, ...field }, { setUnique = true, setNonNull = true, alter = false, foreign = true, setDefault = true } = {}, toColumn) {
1415
1449
  const col = (what) => {
1416
1450
  if (what) {
1417
1451
  this.writer.write(what);
@@ -1444,55 +1478,55 @@ var MigrationGenerator = class {
1444
1478
  }
1445
1479
  this.writer.write(";").newLine();
1446
1480
  };
1447
- if (relation) {
1448
- col(`table.uuid('${name2}Id')`);
1449
- if (foreign && !alter) {
1450
- this.writer.writeLine(`table.foreign('${name2}Id').references('id').inTable('${type}');`);
1451
- }
1452
- } else if (this.rawModels.some((m) => m.name === type && m.type === "enum")) {
1453
- list2 ? this.writer.write(`table.specificType('${name2}', '"${typeToField(type)}"[]');`) : this.writer.write(`table.enum('${name2}', null as any, `).inlineBlock(() => {
1454
- this.writer.writeLine(`useNative: true,`);
1455
- this.writer.writeLine(`existingType: true,`);
1456
- this.writer.writeLine(`enumName: '${typeToField(type)}',`);
1457
- }).write(")");
1458
- col();
1459
- } else {
1460
- switch (type) {
1461
- case "Boolean":
1462
- col(`table.boolean('${name2}')`);
1463
- break;
1464
- case "Int":
1465
- col(`table.integer('${name2}')`);
1466
- break;
1467
- case "Float":
1468
- if (field.double) {
1469
- col(`table.double('${name2}')`);
1470
- } else {
1471
- col(`table.decimal('${name2}', ${get(field, "precision")}, ${get(field, "scale")})`);
1472
- }
1473
- break;
1474
- case "String":
1475
- if (field.large) {
1476
- col(`table.text('${name2}')`);
1477
- } else {
1478
- col(`table.string('${name2}', ${field.maxLength})`);
1479
- }
1480
- break;
1481
- case "DateTime":
1482
- col(`table.timestamp('${name2}')`);
1483
- break;
1484
- case "ID":
1485
- if (field.maxLength) {
1486
- col(`table.string('${name2}', ${get(field, "maxLength")})`);
1487
- } else {
1488
- col(`table.uuid('${name2}')`);
1489
- }
1490
- break;
1491
- case "Upload":
1492
- break;
1493
- default:
1494
- throw new Error(`Unknown field type ${type}`);
1495
- }
1481
+ switch (field.type) {
1482
+ case "Boolean":
1483
+ col(`table.boolean('${name2}')`);
1484
+ break;
1485
+ case "Int":
1486
+ col(`table.integer('${name2}')`);
1487
+ break;
1488
+ case "Float":
1489
+ if (field.double) {
1490
+ col(`table.double('${name2}')`);
1491
+ } else {
1492
+ col(`table.decimal('${name2}', ${get(field, "precision")}, ${get(field, "scale")})`);
1493
+ }
1494
+ break;
1495
+ case "String":
1496
+ if (field.large) {
1497
+ col(`table.text('${name2}')`);
1498
+ } else {
1499
+ col(`table.string('${name2}', ${field.maxLength})`);
1500
+ }
1501
+ break;
1502
+ case "DateTime":
1503
+ col(`table.timestamp('${name2}')`);
1504
+ break;
1505
+ case "ID":
1506
+ col(`table.uuid('${name2}')`);
1507
+ break;
1508
+ case "Upload":
1509
+ break;
1510
+ case "relation":
1511
+ col(`table.uuid('${name2}Id')`);
1512
+ if (foreign && !alter) {
1513
+ this.writer.writeLine(`table.foreign('${name2}Id').references('id').inTable('${field.typeName}');`);
1514
+ }
1515
+ break;
1516
+ case "enum":
1517
+ if (list2) {
1518
+ this.writer.write(`table.specificType('${name2}', '"${typeToField(field.type)}"[]');`);
1519
+ } else {
1520
+ this.writer.write(`table.enum('${name2}', null as any, `).inlineBlock(() => {
1521
+ this.writer.writeLine(`useNative: true,`);
1522
+ this.writer.writeLine(`existingType: true,`);
1523
+ this.writer.writeLine(`enumName: '${typeToField(field.type)}',`);
1524
+ }).write(")");
1525
+ }
1526
+ col();
1527
+ break;
1528
+ default:
1529
+ throw new Error(`Unknown field type ${field.type}`);
1496
1530
  }
1497
1531
  }
1498
1532
  };
@@ -1710,7 +1744,7 @@ var checkCanWrite = async (ctx, model, data, action) => {
1710
1744
  }
1711
1745
  const query = ctx.knex.select(1).first();
1712
1746
  let linked = false;
1713
- for (const field of model.fields.filter(({ relation }) => relation).filter((field2) => field2.generated || (action === "CREATE" ? field2.creatable : field2.updatable))) {
1747
+ for (const field of model.fields.filter(isRelation).filter((field2) => field2.generated || (action === "CREATE" ? field2.creatable : field2.updatable))) {
1714
1748
  const foreignKey = field.foreignKey || `${field.name}Id`;
1715
1749
  const foreignId = data[foreignKey];
1716
1750
  if (!foreignId) {
@@ -1846,7 +1880,7 @@ var addPermissions = (models, permissions, links, block) => {
1846
1880
  }
1847
1881
  if (block.RELATIONS) {
1848
1882
  for (const [relation, subBlock] of Object.entries(block.RELATIONS)) {
1849
- const field = model.fields.find((field2) => field2.relation && field2.name === relation);
1883
+ const field = model.fields.filter(isRelation).find((field2) => field2.name === relation);
1850
1884
  let link;
1851
1885
  if (field) {
1852
1886
  link = {
@@ -2031,7 +2065,7 @@ var applyWhere2 = (node, where, ops, joins) => {
2031
2065
  }
2032
2066
  const field = summonByName(node.model.fields, key);
2033
2067
  const fullKey = `${node.shortTableAlias}.${key}`;
2034
- if (field.relation) {
2068
+ if (field.type === "relation") {
2035
2069
  const relation = get(node.model.relationsByName, field.name);
2036
2070
  const tableAlias = `${node.model.name}__W__${key}`;
2037
2071
  const subNode = {
@@ -2145,7 +2179,7 @@ var getSimpleFields = (node) => {
2145
2179
  if (!selection.selectionSet) {
2146
2180
  return true;
2147
2181
  }
2148
- return node.model.fields.some(({ json, name: name2 }) => json && name2 === selection.name.value);
2182
+ return node.model.fields.some(({ type, name: name2 }) => type === "json" && name2 === selection.name.value);
2149
2183
  });
2150
2184
  };
2151
2185
  var getInlineFragments = (node) => node.selectionSet.filter(isInlineFragmentNode).map(
@@ -2175,7 +2209,7 @@ var getJoins = (node, toMany) => {
2175
2209
  const fieldNameOrAlias = getNameOrAlias(subNode);
2176
2210
  const fieldDefinition = summonByKey(baseTypeDefinition.fields || [], "name.value", fieldName);
2177
2211
  const typeName = getTypeName(fieldDefinition.type);
2178
- if (isJsonObjectModel(summonByName(ctx.rawModels, typeName))) {
2212
+ if (isRawObjectModel(summonByName(ctx.rawModels, typeName))) {
2179
2213
  continue;
2180
2214
  }
2181
2215
  const baseModel = summonByName(ctx.models, baseTypeDefinition.name.value);
@@ -2188,7 +2222,7 @@ var getJoins = (node, toMany) => {
2188
2222
  foreignKey = reverseRelation.foreignKey;
2189
2223
  } else {
2190
2224
  const modelField = baseModel.fieldsByName[fieldName];
2191
- if (!modelField || modelField.raw) {
2225
+ if (modelField?.type !== "relation") {
2192
2226
  continue;
2193
2227
  }
2194
2228
  foreignKey = modelField.foreignKey;
@@ -2281,10 +2315,10 @@ var applySelects = (node, query, joins) => {
2281
2315
  { field: "id", alias: ID_ALIAS },
2282
2316
  ...getSimpleFields(node).filter((n) => {
2283
2317
  const field = node.model.fields.find(({ name: name2 }) => name2 === n.name.value);
2284
- if (!field || field.relation || field.raw) {
2318
+ if (!field || field.type === "relation" || field.type === "raw") {
2285
2319
  return false;
2286
2320
  }
2287
- if (field.queriableBy && !field.queriableBy.includes(node.ctx.user.role)) {
2321
+ if (typeof field.queriable === "object" && !field.queriable.roles?.includes(node.ctx.user.role)) {
2288
2322
  throw new PermissionError(
2289
2323
  "READ",
2290
2324
  `${node.model.name}'s field "${field.name}"`,
@@ -2583,8 +2617,8 @@ var createRevision = async (model, data, ctx) => {
2583
2617
  if (model.deletable) {
2584
2618
  revisionData.deleted = data.deleted || false;
2585
2619
  }
2586
- for (const { name: name2, relation, nonNull: nonNull2, ...field } of model.fields.filter(({ updatable }) => updatable)) {
2587
- const col = relation ? `${name2}Id` : name2;
2620
+ for (const { type, name: name2, nonNull: nonNull2, ...field } of model.fields.filter(({ updatable }) => updatable)) {
2621
+ const col = type === "relation" ? `${name2}Id` : name2;
2588
2622
  if (nonNull2 && (!(col in data) || col === void 0 || col === null)) {
2589
2623
  revisionData[col] = get(field, "default");
2590
2624
  } else {
@@ -2614,7 +2648,7 @@ var sanitize = (ctx, model, data) => {
2614
2648
  }
2615
2649
  }
2616
2650
  };
2617
- var isEndOfDay = (field) => field?.endOfDay === true && field?.dateTimeType === "date" && field?.type === "DateTime";
2651
+ var isEndOfDay = (field) => field.type === "DateTime" && field?.endOfDay === true && field?.dateTimeType === "date" && field?.type === "DateTime";
2618
2652
 
2619
2653
  // src/resolvers/resolvers.ts
2620
2654
  var getResolvers = (models) => ({
@@ -2721,7 +2755,6 @@ var getResolvers = (models) => ({
2721
2755
  isFieldNode,
2722
2756
  isFragmentSpreadNode,
2723
2757
  isInlineFragmentNode,
2724
- isJsonObjectModel,
2725
2758
  isListType,
2726
2759
  isObjectModel,
2727
2760
  isQueriableBy,