@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.
- package/CHANGELOG.md +1 -6
- package/dist/cjs/index.cjs +196 -170
- package/dist/esm/client/queries.d.ts +4 -1
- package/dist/esm/client/queries.js +7 -4
- 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 +2 -2
- package/src/client/queries.ts +16 -10
- 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/utils/models.ts +7 -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,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,
|
|
360
|
-
const model2 = summonByName(models,
|
|
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((
|
|
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((
|
|
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((
|
|
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((
|
|
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 = (
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
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
|
-
|
|
784
|
-
|
|
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
|
|
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
|
|
840
|
+
...model.fields.filter(isRelation).filter(({ filterable }) => filterable).map(({ name: name2, typeName }) => ({
|
|
817
841
|
name: name2,
|
|
818
|
-
type: `${
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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 !
|
|
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,
|
|
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,
|
|
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,
|
|
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 {
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
col(`table.
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
}
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
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(
|
|
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.
|
|
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(({
|
|
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 (
|
|
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 (
|
|
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.
|
|
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,
|
|
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,
|