@smartive/graphql-magic 3.1.0 → 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 (46) hide show
  1. package/CHANGELOG.md +1 -6
  2. package/dist/cjs/index.cjs +196 -170
  3. package/dist/esm/client/queries.d.ts +4 -1
  4. package/dist/esm/client/queries.js +7 -4
  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 +2 -2
  33. package/src/client/queries.ts +16 -10
  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/utils/models.ts +7 -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,8 +375,8 @@ 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);
378
+ ${relations.map(({ name: name2, typeName }) => {
379
+ const model2 = summonByName(models, typeName);
361
380
  let filters = "";
362
381
  if (model2.displayField) {
363
382
  const displayField2 = model2.fieldsByName[model2.displayField];
@@ -457,6 +476,10 @@ var getEntityListQuery = (model, role, additionalFields = "", root) => `query ${
457
476
  }
458
477
  ${root ? "}" : ""}
459
478
  }`;
479
+ var isVisibleRelation = (visibleRelationsByRole, modelName, role) => {
480
+ const whitelist = visibleRelationsByRole[role]?.[modelName];
481
+ return ({ name: name2 }) => whitelist ? whitelist.includes(name2) : true;
482
+ };
460
483
  var getEntityQuery = (models, model, role, visibleRelationsByRole, typesWithSubRelations) => `query Admin${model.name} ($id: ID!) {
461
484
  data: ${typeToField(model.name)}(where: { id: $id }) {
462
485
  ${displayField(model)}
@@ -513,14 +536,14 @@ var generateDBModels = (rawModels) => {
513
536
  }
514
537
  const models = getModels(rawModels);
515
538
  for (const model of models) {
516
- 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;
517
540
  writer.write(`export type ${model.name} = `).inlineBlock(() => {
518
- for (const field of fields2.filter(({ raw }) => !raw)) {
541
+ for (const field of fields2.filter(not(isRaw))) {
519
542
  writer.write(`'${getFieldName(field)}': ${getFieldOutputType(field)}${field.nonNull ? "" : " | null"},`).newLine();
520
543
  }
521
544
  }).blankLine();
522
545
  writer.write(`export type ${model.name}Initializer = `).inlineBlock(() => {
523
- for (const field of fields2.filter(({ raw }) => !raw)) {
546
+ for (const field of fields2.filter(not(isRaw))) {
524
547
  writer.write(
525
548
  `'${getFieldName(field)}'${field.nonNull && field.default === void 0 ? "" : "?"}: ${getFieldInputType(
526
549
  field
@@ -529,12 +552,12 @@ var generateDBModels = (rawModels) => {
529
552
  }
530
553
  }).blankLine();
531
554
  writer.write(`export type ${model.name}Mutator = `).inlineBlock(() => {
532
- for (const field of fields2.filter(({ raw }) => !raw)) {
555
+ for (const field of fields2.filter(not(isRaw))) {
533
556
  writer.write(`'${getFieldName(field)}'?: ${getFieldInputType(field)}${field.nonNull ? "" : " | null"},`).newLine();
534
557
  }
535
558
  }).blankLine();
536
559
  writer.write(`export type ${model.name}Seed = `).inlineBlock(() => {
537
- for (const field of fields2.filter(({ raw }) => !raw)) {
560
+ for (const field of fields2.filter(not(isRaw))) {
538
561
  const fieldName = getFieldName(field);
539
562
  writer.write(
540
563
  `'${getFieldName(field)}'${field.nonNull && field.default === void 0 && !OPTIONAL_SEED_FIELDS.includes(fieldName) ? "" : "?"}: ${getFieldInputType(
@@ -552,14 +575,20 @@ var generateDBModels = (rawModels) => {
552
575
  });
553
576
  return writer.toString();
554
577
  };
555
- var getFieldName = ({ relation, name: name2, foreignKey }) => {
556
- return foreignKey || `${name2}${relation ? "Id" : ""}`;
557
- };
558
- var getFieldOutputType = ({ relation, type, list: list2, json }) => {
559
- if (json || relation) {
560
- 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 ? "[]" : "");
561
591
  }
562
- return (PRIMITIVE_TYPES[type] || type) + (list2 ? "[]" : "");
563
592
  };
564
593
  var getFieldInputType = (field, stringTypes = []) => {
565
594
  let outputType = getFieldOutputType(field);
@@ -764,14 +793,6 @@ var generateDefinitions = (rawModels) => {
764
793
  ...rawModels.filter(isRawEnumModel).map((model) => enm(model.name, model.values)),
765
794
  ...rawModels.filter(isScalarModel).map((model) => scalar(model.name)),
766
795
  ...rawModels.filter(isRawObjectModel).map((model) => object(model.name, model.fields)),
767
- ...rawModels.filter(isJsonObjectModel).map((model) => object(model.name, model.fields)),
768
- ...rawModels.filter(isRawObjectModel).filter(({ rawFilters }) => rawFilters).map(
769
- (model) => input(
770
- `${model.name}Where`,
771
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- array gets filtered above to only include models with rawFilters
772
- model.rawFilters.map(({ name: name2, type, list: list2 = false, nonNull: nonNull2 = false }) => ({ name: name2, type, list: list2, nonNull: nonNull2 }))
773
- )
774
- ),
775
796
  ...(0, import_flatMap.default)(
776
797
  models.map((model) => {
777
798
  const types = [
@@ -780,10 +801,8 @@ var generateDefinitions = (rawModels) => {
780
801
  [
781
802
  ...model.fields.filter(isQueriableField).map((field) => ({
782
803
  ...field,
783
- args: [
784
- ...field.args || [],
785
- ...hasRawFilters(rawModels, field.type) ? [{ name: "where", type: `${field.type}Where` }] : []
786
- ],
804
+ type: field.type === "relation" || field.type === "enum" || field.type === "raw" ? field.typeName : field.type,
805
+ args: [...field.args || []],
787
806
  directives: field.directives
788
807
  })),
789
808
  ...model.reverseRelations.map(({ name: name2, field, model: model2 }) => ({
@@ -803,7 +822,12 @@ var generateDefinitions = (rawModels) => {
803
822
  model.interfaces
804
823
  ),
805
824
  input(`${model.name}Where`, [
806
- ...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
+ })),
807
831
  ...(0, import_flatMap.default)(
808
832
  model.fields.filter(({ comparable }) => comparable),
809
833
  ({ name: name2, type }) => [
@@ -813,9 +837,9 @@ var generateDefinitions = (rawModels) => {
813
837
  { name: `${name2}_LTE`, type }
814
838
  ]
815
839
  ),
816
- ...model.fields.filter(({ filterable, relation }) => filterable && relation).map(({ name: name2, type }) => ({
840
+ ...model.fields.filter(isRelation).filter(({ filterable }) => filterable).map(({ name: name2, typeName }) => ({
817
841
  name: name2,
818
- type: `${type}Where`
842
+ type: `${typeName}Where`
819
843
  }))
820
844
  ]),
821
845
  input(
@@ -834,7 +858,7 @@ var generateDefinitions = (rawModels) => {
834
858
  input(
835
859
  `Create${model.name}`,
836
860
  model.fields.filter(({ creatable }) => creatable).map(
837
- ({ 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 }
838
862
  )
839
863
  )
840
864
  );
@@ -844,7 +868,7 @@ var generateDefinitions = (rawModels) => {
844
868
  input(
845
869
  `Update${model.name}`,
846
870
  model.fields.filter(({ updatable }) => updatable).map(
847
- ({ 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 }
848
872
  )
849
873
  )
850
874
  );
@@ -962,7 +986,6 @@ var printSchema = (schema) => [
962
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))
963
987
  ].filter(Boolean).map((s) => `${s}
964
988
  `).join("\n");
965
- var hasRawFilters = (models, type) => models.filter(isRawObjectModel).some(({ name: name2, rawFilters }) => name2 === type && !!rawFilters);
966
989
  var printSchemaFromDocument = (document2) => printSchema((0, import_graphql.buildASTSchema)(document2));
967
990
  var printSchemaFromModels = (models) => printSchema((0, import_graphql.buildASTSchema)(generate(models)));
968
991
 
@@ -1114,17 +1137,19 @@ var MigrationGenerator = class {
1114
1137
  this.createFields(
1115
1138
  model,
1116
1139
  model.fields.filter(
1117
- ({ 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
+ )
1118
1143
  ),
1119
1144
  up,
1120
1145
  down
1121
1146
  );
1122
- const existingFields = model.fields.filter(({ name: name2, relation, nonNull: nonNull2 }) => {
1123
- 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));
1124
1149
  if (!col) {
1125
1150
  return false;
1126
1151
  }
1127
- return !model.nonStrict && !nonNull2 && !col.is_nullable;
1152
+ return !nonNull2 && !col.is_nullable;
1128
1153
  });
1129
1154
  this.updateFields(model, existingFields, up, down);
1130
1155
  }
@@ -1147,8 +1172,8 @@ var MigrationGenerator = class {
1147
1172
  if (model.deletable) {
1148
1173
  writer.writeLine(`deleted: row.deleted,`);
1149
1174
  }
1150
- for (const { name: name2, relation } of model.fields.filter(({ updatable }) => updatable)) {
1151
- 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;
1152
1177
  writer.writeLine(`${col}: row.${col},`);
1153
1178
  }
1154
1179
  }).write(")));").newLine();
@@ -1162,11 +1187,15 @@ var MigrationGenerator = class {
1162
1187
  } else {
1163
1188
  const revisionTable = `${model.name}Revision`;
1164
1189
  const missingRevisionFields = model.fields.filter(
1165
- ({ 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
+ )
1166
1193
  );
1167
1194
  this.createRevisionFields(model, missingRevisionFields, up, down);
1168
1195
  const revisionFieldsToRemove = model.fields.filter(
1169
- ({ 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
+ )
1170
1199
  );
1171
1200
  this.createRevisionFields(model, revisionFieldsToRemove, down, up);
1172
1201
  }
@@ -1218,8 +1247,8 @@ var MigrationGenerator = class {
1218
1247
  for (const field of fields2) {
1219
1248
  this.alterTable(model.name, () => {
1220
1249
  this.renameColumn(
1221
- field.relation ? `${field.oldName}Id` : get(field, "oldName"),
1222
- 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
1223
1252
  );
1224
1253
  });
1225
1254
  }
@@ -1228,14 +1257,14 @@ var MigrationGenerator = class {
1228
1257
  for (const field of fields2) {
1229
1258
  this.alterTable(model.name, () => {
1230
1259
  this.renameColumn(
1231
- field.relation ? `${field.name}Id` : field.name,
1232
- 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")
1233
1262
  );
1234
1263
  });
1235
1264
  }
1236
1265
  });
1237
1266
  for (const field of fields2) {
1238
- 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;
1239
1268
  }
1240
1269
  }
1241
1270
  createFields(model, fields2, up, down) {
@@ -1271,8 +1300,8 @@ var MigrationGenerator = class {
1271
1300
  });
1272
1301
  down.push(() => {
1273
1302
  this.alterTable(model.name, () => {
1274
- for (const { relation, name: name2 } of fields2) {
1275
- this.dropColumn(relation ? `${name2}Id` : name2);
1303
+ for (const { type, name: name2 } of fields2) {
1304
+ this.dropColumn(type === "relation" ? `${name2}Id` : name2);
1276
1305
  }
1277
1306
  });
1278
1307
  });
@@ -1294,7 +1323,7 @@ var MigrationGenerator = class {
1294
1323
  this.column(
1295
1324
  field,
1296
1325
  { alter: true },
1297
- 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)
1298
1327
  );
1299
1328
  }
1300
1329
  });
@@ -1317,7 +1346,7 @@ var MigrationGenerator = class {
1317
1346
  this.column(
1318
1347
  field,
1319
1348
  { alter: true },
1320
- 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)
1321
1350
  );
1322
1351
  }
1323
1352
  });
@@ -1330,9 +1359,7 @@ var MigrationGenerator = class {
1330
1359
  writer.writeLine(`table.uuid('id').notNullable().primary();`);
1331
1360
  writer.writeLine(`table.uuid('${typeToField(model.name)}Id').notNullable();`);
1332
1361
  writer.write(`table.uuid('createdById')`);
1333
- if (!model.nonStrict) {
1334
- writer.write(".notNullable()");
1335
- }
1362
+ writer.write(".notNullable()");
1336
1363
  writer.write(";").newLine();
1337
1364
  writer.writeLine(`table.timestamp('createdAt').notNullable().defaultTo(knex.fn.now(0));`);
1338
1365
  if (model.deletable) {
@@ -1353,8 +1380,8 @@ var MigrationGenerator = class {
1353
1380
  }
1354
1381
  });
1355
1382
  this.writer.write(`await knex('${model.name}Revision').update(`).inlineBlock(() => {
1356
- for (const { name: name2, relation } of missingRevisionFields) {
1357
- const col = relation ? `${name2}Id` : name2;
1383
+ for (const { name: name2, type } of missingRevisionFields) {
1384
+ const col = type === "relation" ? `${name2}Id` : name2;
1358
1385
  this.writer.write(
1359
1386
  `${col}: knex.raw('(select "${col}" from "${model.name}" where "${model.name}".id = "${model.name}Revision"."${typeToField(model.name)}Id")'),`
1360
1387
  ).newLine();
@@ -1372,7 +1399,7 @@ var MigrationGenerator = class {
1372
1399
  down.push(() => {
1373
1400
  this.alterTable(revisionTable, () => {
1374
1401
  for (const field of missingRevisionFields) {
1375
- this.dropColumn(field.relation ? `${field.name}Id` : field.name);
1402
+ this.dropColumn(field.type === "relation" ? `${field.name}Id` : field.name);
1376
1403
  }
1377
1404
  });
1378
1405
  });
@@ -1418,7 +1445,7 @@ var MigrationGenerator = class {
1418
1445
  }
1419
1446
  return value2;
1420
1447
  }
1421
- 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) {
1422
1449
  const col = (what) => {
1423
1450
  if (what) {
1424
1451
  this.writer.write(what);
@@ -1451,55 +1478,55 @@ var MigrationGenerator = class {
1451
1478
  }
1452
1479
  this.writer.write(";").newLine();
1453
1480
  };
1454
- if (relation) {
1455
- col(`table.uuid('${name2}Id')`);
1456
- if (foreign && !alter) {
1457
- this.writer.writeLine(`table.foreign('${name2}Id').references('id').inTable('${type}');`);
1458
- }
1459
- } else if (this.rawModels.some((m) => m.name === type && m.type === "enum")) {
1460
- list2 ? this.writer.write(`table.specificType('${name2}', '"${typeToField(type)}"[]');`) : this.writer.write(`table.enum('${name2}', null as any, `).inlineBlock(() => {
1461
- this.writer.writeLine(`useNative: true,`);
1462
- this.writer.writeLine(`existingType: true,`);
1463
- this.writer.writeLine(`enumName: '${typeToField(type)}',`);
1464
- }).write(")");
1465
- col();
1466
- } else {
1467
- switch (type) {
1468
- case "Boolean":
1469
- col(`table.boolean('${name2}')`);
1470
- break;
1471
- case "Int":
1472
- col(`table.integer('${name2}')`);
1473
- break;
1474
- case "Float":
1475
- if (field.double) {
1476
- col(`table.double('${name2}')`);
1477
- } else {
1478
- col(`table.decimal('${name2}', ${get(field, "precision")}, ${get(field, "scale")})`);
1479
- }
1480
- break;
1481
- case "String":
1482
- if (field.large) {
1483
- col(`table.text('${name2}')`);
1484
- } else {
1485
- col(`table.string('${name2}', ${field.maxLength})`);
1486
- }
1487
- break;
1488
- case "DateTime":
1489
- col(`table.timestamp('${name2}')`);
1490
- break;
1491
- case "ID":
1492
- if (field.maxLength) {
1493
- col(`table.string('${name2}', ${get(field, "maxLength")})`);
1494
- } else {
1495
- col(`table.uuid('${name2}')`);
1496
- }
1497
- break;
1498
- case "Upload":
1499
- break;
1500
- default:
1501
- throw new Error(`Unknown field type ${type}`);
1502
- }
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}`);
1503
1530
  }
1504
1531
  }
1505
1532
  };
@@ -1717,7 +1744,7 @@ var checkCanWrite = async (ctx, model, data, action) => {
1717
1744
  }
1718
1745
  const query = ctx.knex.select(1).first();
1719
1746
  let linked = false;
1720
- 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))) {
1721
1748
  const foreignKey = field.foreignKey || `${field.name}Id`;
1722
1749
  const foreignId = data[foreignKey];
1723
1750
  if (!foreignId) {
@@ -1853,7 +1880,7 @@ var addPermissions = (models, permissions, links, block) => {
1853
1880
  }
1854
1881
  if (block.RELATIONS) {
1855
1882
  for (const [relation, subBlock] of Object.entries(block.RELATIONS)) {
1856
- const field = model.fields.find((field2) => field2.relation && field2.name === relation);
1883
+ const field = model.fields.filter(isRelation).find((field2) => field2.name === relation);
1857
1884
  let link;
1858
1885
  if (field) {
1859
1886
  link = {
@@ -2038,7 +2065,7 @@ var applyWhere2 = (node, where, ops, joins) => {
2038
2065
  }
2039
2066
  const field = summonByName(node.model.fields, key);
2040
2067
  const fullKey = `${node.shortTableAlias}.${key}`;
2041
- if (field.relation) {
2068
+ if (field.type === "relation") {
2042
2069
  const relation = get(node.model.relationsByName, field.name);
2043
2070
  const tableAlias = `${node.model.name}__W__${key}`;
2044
2071
  const subNode = {
@@ -2152,7 +2179,7 @@ var getSimpleFields = (node) => {
2152
2179
  if (!selection.selectionSet) {
2153
2180
  return true;
2154
2181
  }
2155
- 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);
2156
2183
  });
2157
2184
  };
2158
2185
  var getInlineFragments = (node) => node.selectionSet.filter(isInlineFragmentNode).map(
@@ -2182,7 +2209,7 @@ var getJoins = (node, toMany) => {
2182
2209
  const fieldNameOrAlias = getNameOrAlias(subNode);
2183
2210
  const fieldDefinition = summonByKey(baseTypeDefinition.fields || [], "name.value", fieldName);
2184
2211
  const typeName = getTypeName(fieldDefinition.type);
2185
- if (isJsonObjectModel(summonByName(ctx.rawModels, typeName))) {
2212
+ if (isRawObjectModel(summonByName(ctx.rawModels, typeName))) {
2186
2213
  continue;
2187
2214
  }
2188
2215
  const baseModel = summonByName(ctx.models, baseTypeDefinition.name.value);
@@ -2195,7 +2222,7 @@ var getJoins = (node, toMany) => {
2195
2222
  foreignKey = reverseRelation.foreignKey;
2196
2223
  } else {
2197
2224
  const modelField = baseModel.fieldsByName[fieldName];
2198
- if (!modelField || modelField.raw) {
2225
+ if (modelField?.type !== "relation") {
2199
2226
  continue;
2200
2227
  }
2201
2228
  foreignKey = modelField.foreignKey;
@@ -2288,10 +2315,10 @@ var applySelects = (node, query, joins) => {
2288
2315
  { field: "id", alias: ID_ALIAS },
2289
2316
  ...getSimpleFields(node).filter((n) => {
2290
2317
  const field = node.model.fields.find(({ name: name2 }) => name2 === n.name.value);
2291
- if (!field || field.relation || field.raw) {
2318
+ if (!field || field.type === "relation" || field.type === "raw") {
2292
2319
  return false;
2293
2320
  }
2294
- if (field.queriableBy && !field.queriableBy.includes(node.ctx.user.role)) {
2321
+ if (typeof field.queriable === "object" && !field.queriable.roles?.includes(node.ctx.user.role)) {
2295
2322
  throw new PermissionError(
2296
2323
  "READ",
2297
2324
  `${node.model.name}'s field "${field.name}"`,
@@ -2590,8 +2617,8 @@ var createRevision = async (model, data, ctx) => {
2590
2617
  if (model.deletable) {
2591
2618
  revisionData.deleted = data.deleted || false;
2592
2619
  }
2593
- for (const { name: name2, relation, nonNull: nonNull2, ...field } of model.fields.filter(({ updatable }) => updatable)) {
2594
- 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;
2595
2622
  if (nonNull2 && (!(col in data) || col === void 0 || col === null)) {
2596
2623
  revisionData[col] = get(field, "default");
2597
2624
  } else {
@@ -2621,7 +2648,7 @@ var sanitize = (ctx, model, data) => {
2621
2648
  }
2622
2649
  }
2623
2650
  };
2624
- 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";
2625
2652
 
2626
2653
  // src/resolvers/resolvers.ts
2627
2654
  var getResolvers = (models) => ({
@@ -2728,7 +2755,6 @@ var getResolvers = (models) => ({
2728
2755
  isFieldNode,
2729
2756
  isFragmentSpreadNode,
2730
2757
  isInlineFragmentNode,
2731
- isJsonObjectModel,
2732
2758
  isListType,
2733
2759
  isObjectModel,
2734
2760
  isQueriableBy,