@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.
- package/CHANGELOG.md +1 -6
- package/dist/cjs/index.cjs +205 -172
- package/dist/esm/client/queries.d.ts +4 -1
- package/dist/esm/client/queries.js +16 -6
- package/dist/esm/client/queries.js.map +1 -1
- package/dist/esm/db/generate.js +21 -13
- package/dist/esm/db/generate.js.map +1 -1
- package/dist/esm/generate/generate.js +17 -22
- package/dist/esm/generate/generate.js.map +1 -1
- package/dist/esm/generate/utils.d.ts +10 -1
- package/dist/esm/generate/utils.js.map +1 -1
- package/dist/esm/migrations/generate.js +82 -89
- package/dist/esm/migrations/generate.js.map +1 -1
- package/dist/esm/models.d.ts +115 -93
- package/dist/esm/models.js +1 -26
- package/dist/esm/models.js.map +1 -1
- package/dist/esm/permissions/check.js +2 -2
- package/dist/esm/permissions/check.js.map +1 -1
- package/dist/esm/permissions/generate.js +2 -2
- package/dist/esm/permissions/generate.js.map +1 -1
- package/dist/esm/resolvers/filters.js +1 -1
- package/dist/esm/resolvers/filters.js.map +1 -1
- package/dist/esm/resolvers/mutations.js +5 -6
- package/dist/esm/resolvers/mutations.js.map +1 -1
- package/dist/esm/resolvers/node.js +4 -5
- package/dist/esm/resolvers/node.js.map +1 -1
- package/dist/esm/resolvers/resolver.js +2 -2
- package/dist/esm/resolvers/resolver.js.map +1 -1
- package/dist/esm/utils.d.ts +181 -1
- package/dist/esm/utils.js +69 -21
- package/dist/esm/utils.js.map +1 -1
- package/package.json +8 -8
- package/src/client/queries.ts +26 -12
- package/src/db/generate.ts +22 -15
- package/src/generate/generate.ts +26 -34
- package/src/generate/utils.ts +11 -1
- package/src/migrations/generate.ts +84 -82
- package/src/models.ts +113 -157
- package/src/permissions/check.ts +2 -2
- package/src/permissions/generate.ts +2 -2
- package/src/resolvers/filters.ts +1 -1
- package/src/resolvers/mutations.ts +10 -9
- package/src/resolvers/node.ts +6 -6
- package/src/resolvers/resolver.ts +2 -2
- package/src/utils.ts +158 -57
- package/tests/unit/__snapshots__/generate.spec.ts.snap +3 -0
- package/tests/unit/__snapshots__/queries.spec.ts.snap +11 -0
- package/tests/unit/queries.spec.ts +10 -0
- package/tests/utils/database/schema.ts +2 -0
- package/tests/utils/models.ts +14 -6
package/dist/cjs/index.cjs
CHANGED
|
@@ -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
|
-
{
|
|
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: "
|
|
227
|
-
|
|
228
|
-
nonNull:
|
|
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
|
-
{
|
|
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: "
|
|
238
|
-
|
|
239
|
-
nonNull:
|
|
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:
|
|
251
|
-
|
|
252
|
-
|
|
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: "
|
|
258
|
-
|
|
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((
|
|
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
|
|
277
|
-
|
|
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
|
-
|
|
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,
|
|
360
|
-
const model2 = summonByName(models,
|
|
361
|
-
|
|
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((
|
|
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((
|
|
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((
|
|
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((
|
|
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 = (
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
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
|
-
|
|
777
|
-
|
|
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
|
|
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
|
|
840
|
+
...model.fields.filter(isRelation).filter(({ filterable }) => filterable).map(({ name: name2, typeName }) => ({
|
|
810
841
|
name: name2,
|
|
811
|
-
type: `${
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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 !
|
|
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,
|
|
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,
|
|
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,
|
|
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 {
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
col(`table.
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
}
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
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(
|
|
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.
|
|
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(({
|
|
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 (
|
|
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 (
|
|
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.
|
|
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,
|
|
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,
|