@smartive/graphql-magic 9.1.2 → 10.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/.eslintrc +2 -10
- package/.github/workflows/release.yml +1 -1
- package/.gqmrc.json +6 -0
- package/CHANGELOG.md +2 -2
- package/README.md +1 -1
- package/dist/bin/gqm.cjs +684 -330
- package/dist/cjs/index.cjs +998 -554
- package/dist/esm/api/execute.js +1 -1
- package/dist/esm/api/execute.js.map +1 -1
- package/dist/esm/client/mutations.d.ts +2 -2
- package/dist/esm/client/mutations.js +5 -4
- package/dist/esm/client/mutations.js.map +1 -1
- package/dist/esm/client/queries.d.ts +12 -17
- package/dist/esm/client/queries.js +30 -50
- package/dist/esm/client/queries.js.map +1 -1
- package/dist/esm/context.d.ts +1 -2
- package/dist/esm/db/generate.d.ts +3 -3
- package/dist/esm/db/generate.js +31 -29
- package/dist/esm/db/generate.js.map +1 -1
- package/dist/esm/migrations/generate.d.ts +3 -4
- package/dist/esm/migrations/generate.js +114 -107
- package/dist/esm/migrations/generate.js.map +1 -1
- package/dist/esm/models/index.d.ts +1 -0
- package/dist/esm/models/index.js +1 -0
- package/dist/esm/models/index.js.map +1 -1
- package/dist/esm/models/model-definitions.d.ts +189 -0
- package/dist/esm/models/model-definitions.js +2 -0
- package/dist/esm/models/model-definitions.js.map +1 -0
- package/dist/esm/models/models.d.ts +128 -174
- package/dist/esm/models/models.js +411 -1
- package/dist/esm/models/models.js.map +1 -1
- package/dist/esm/models/mutation-hook.d.ts +2 -2
- package/dist/esm/models/utils.d.ts +35 -497
- package/dist/esm/models/utils.js +21 -144
- package/dist/esm/models/utils.js.map +1 -1
- package/dist/esm/permissions/check.d.ts +3 -3
- package/dist/esm/permissions/check.js +14 -7
- package/dist/esm/permissions/check.js.map +1 -1
- package/dist/esm/permissions/generate.js +6 -6
- package/dist/esm/permissions/generate.js.map +1 -1
- package/dist/esm/resolvers/filters.d.ts +8 -0
- package/dist/esm/resolvers/filters.js +28 -25
- package/dist/esm/resolvers/filters.js.map +1 -1
- package/dist/esm/resolvers/index.d.ts +1 -0
- package/dist/esm/resolvers/index.js +1 -0
- package/dist/esm/resolvers/index.js.map +1 -1
- package/dist/esm/resolvers/mutations.js +85 -21
- package/dist/esm/resolvers/mutations.js.map +1 -1
- package/dist/esm/resolvers/node.d.ts +13 -15
- package/dist/esm/resolvers/node.js +41 -36
- package/dist/esm/resolvers/node.js.map +1 -1
- package/dist/esm/resolvers/resolver.js +19 -49
- package/dist/esm/resolvers/resolver.js.map +1 -1
- package/dist/esm/resolvers/resolvers.d.ts +1 -8
- package/dist/esm/resolvers/resolvers.js +15 -7
- package/dist/esm/resolvers/resolvers.js.map +1 -1
- package/dist/esm/resolvers/selects.d.ts +3 -0
- package/dist/esm/resolvers/selects.js +50 -0
- package/dist/esm/resolvers/selects.js.map +1 -0
- package/dist/esm/resolvers/utils.d.ts +12 -4
- package/dist/esm/resolvers/utils.js +30 -22
- package/dist/esm/resolvers/utils.js.map +1 -1
- package/dist/esm/schema/generate.d.ts +4 -4
- package/dist/esm/schema/generate.js +122 -131
- package/dist/esm/schema/generate.js.map +1 -1
- package/dist/esm/schema/utils.d.ts +1 -1
- package/dist/esm/schema/utils.js +2 -1
- package/dist/esm/schema/utils.js.map +1 -1
- package/knexfile.ts +31 -0
- package/migrations/20230912185644_setup.ts +127 -0
- package/package.json +16 -14
- package/src/api/execute.ts +1 -1
- package/src/bin/gqm/gqm.ts +25 -23
- package/src/bin/gqm/parse-models.ts +5 -5
- package/src/bin/gqm/settings.ts +13 -4
- package/src/bin/gqm/static-eval.ts +5 -0
- package/src/bin/gqm/templates.ts +23 -3
- package/src/client/mutations.ts +11 -5
- package/src/client/queries.ts +43 -80
- package/src/context.ts +1 -2
- package/src/db/generate.ts +41 -41
- package/src/migrations/generate.ts +165 -146
- package/src/models/index.ts +1 -0
- package/src/models/model-definitions.ts +168 -0
- package/src/models/models.ts +510 -166
- package/src/models/mutation-hook.ts +2 -2
- package/src/models/utils.ts +53 -187
- package/src/permissions/check.ts +19 -11
- package/src/permissions/generate.ts +6 -6
- package/src/resolvers/filters.ts +44 -28
- package/src/resolvers/index.ts +1 -0
- package/src/resolvers/mutations.ts +98 -36
- package/src/resolvers/node.ts +79 -51
- package/src/resolvers/resolver.ts +20 -74
- package/src/resolvers/resolvers.ts +18 -7
- package/src/resolvers/selects.ts +77 -0
- package/src/resolvers/utils.ts +41 -25
- package/src/schema/generate.ts +106 -127
- package/src/schema/utils.ts +2 -1
- package/tests/api/__snapshots__/inheritance.spec.ts.snap +83 -0
- package/tests/api/inheritance.spec.ts +130 -0
- package/tests/generated/api/index.ts +1174 -0
- package/tests/generated/client/index.ts +1163 -0
- package/tests/generated/client/mutations.ts +109 -0
- package/tests/generated/db/index.ts +291 -0
- package/tests/generated/db/knex.ts +14 -0
- package/tests/generated/models.json +675 -0
- package/tests/generated/schema.graphql +325 -0
- package/tests/unit/__snapshots__/resolve.spec.ts.snap +23 -0
- package/tests/unit/queries.spec.ts +5 -5
- package/tests/unit/resolve.spec.ts +8 -8
- package/tests/utils/database/knex.ts +5 -13
- package/tests/utils/database/seed.ts +57 -18
- package/tests/utils/models.ts +62 -7
- package/tests/utils/server.ts +5 -5
- package/tsconfig.eslint.json +1 -0
- package/tests/unit/__snapshots__/generate.spec.ts.snap +0 -128
- package/tests/unit/generate.spec.ts +0 -8
- package/tests/utils/database/schema.ts +0 -64
- package/tests/utils/generate-migration.ts +0 -24
package/dist/cjs/index.cjs
CHANGED
|
@@ -30,13 +30,27 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
var src_exports = {};
|
|
31
31
|
__export(src_exports, {
|
|
32
32
|
AliasGenerator: () => AliasGenerator,
|
|
33
|
+
EntityModel: () => EntityModel,
|
|
34
|
+
EnumModel: () => EnumModel,
|
|
33
35
|
ForbiddenError: () => ForbiddenError,
|
|
34
36
|
GraphQLError: () => GraphQLError,
|
|
35
37
|
ID_ALIAS: () => ID_ALIAS,
|
|
38
|
+
InputModel: () => InputModel,
|
|
39
|
+
InterfaceModel: () => InterfaceModel,
|
|
40
|
+
ManyToManyRelation: () => ManyToManyRelation,
|
|
36
41
|
MigrationGenerator: () => MigrationGenerator,
|
|
42
|
+
Model: () => Model,
|
|
43
|
+
Models: () => Models,
|
|
44
|
+
NormalRelation: () => NormalRelation,
|
|
37
45
|
NotFoundError: () => NotFoundError,
|
|
46
|
+
ObjectModel: () => ObjectModel,
|
|
38
47
|
PermissionError: () => PermissionError,
|
|
48
|
+
RawEnumModel: () => RawEnumModel,
|
|
49
|
+
Relation: () => Relation,
|
|
50
|
+
ReverseRelation: () => ReverseRelation,
|
|
39
51
|
SPECIAL_FILTERS: () => SPECIAL_FILTERS,
|
|
52
|
+
ScalarModel: () => ScalarModel,
|
|
53
|
+
TYPE_ALIAS: () => TYPE_ALIAS,
|
|
40
54
|
UserInputError: () => UserInputError,
|
|
41
55
|
actionableRelations: () => actionableRelations,
|
|
42
56
|
addJoin: () => addJoin,
|
|
@@ -45,6 +59,7 @@ __export(src_exports, {
|
|
|
45
59
|
applyFilters: () => applyFilters,
|
|
46
60
|
applyJoins: () => applyJoins,
|
|
47
61
|
applyPermissions: () => applyPermissions,
|
|
62
|
+
applySelects: () => applySelects,
|
|
48
63
|
args: () => args,
|
|
49
64
|
checkCanWrite: () => checkCanWrite,
|
|
50
65
|
directive: () => directive,
|
|
@@ -62,6 +77,8 @@ __export(src_exports, {
|
|
|
62
77
|
generateMutations: () => generateMutations,
|
|
63
78
|
generatePermissions: () => generatePermissions,
|
|
64
79
|
get: () => get,
|
|
80
|
+
getColumn: () => getColumn,
|
|
81
|
+
getColumnName: () => getColumnName,
|
|
65
82
|
getEditEntityRelationsQuery: () => getEditEntityRelationsQuery,
|
|
66
83
|
getEntityListQuery: () => getEntityListQuery,
|
|
67
84
|
getEntityQuery: () => getEntityQuery,
|
|
@@ -72,16 +89,8 @@ __export(src_exports, {
|
|
|
72
89
|
getInlineFragments: () => getInlineFragments,
|
|
73
90
|
getJoins: () => getJoins,
|
|
74
91
|
getLabel: () => getLabel,
|
|
75
|
-
getManyToManyRelation: () => getManyToManyRelation,
|
|
76
|
-
getManyToManyRelations: () => getManyToManyRelations,
|
|
77
92
|
getManyToManyRelationsQuery: () => getManyToManyRelationsQuery,
|
|
78
93
|
getMigrationDate: () => getMigrationDate,
|
|
79
|
-
getModelLabel: () => getModelLabel,
|
|
80
|
-
getModelLabelPlural: () => getModelLabelPlural,
|
|
81
|
-
getModelPlural: () => getModelPlural,
|
|
82
|
-
getModelPluralField: () => getModelPluralField,
|
|
83
|
-
getModelSlug: () => getModelSlug,
|
|
84
|
-
getModels: () => getModels,
|
|
85
94
|
getMutationQuery: () => getMutationQuery,
|
|
86
95
|
getNameOrAlias: () => getNameOrAlias,
|
|
87
96
|
getPermissionStack: () => getPermissionStack,
|
|
@@ -94,6 +103,7 @@ __export(src_exports, {
|
|
|
94
103
|
getTypeName: () => getTypeName,
|
|
95
104
|
getUpdateEntityQuery: () => getUpdateEntityQuery,
|
|
96
105
|
gql: () => gql,
|
|
106
|
+
hasName: () => hasName,
|
|
97
107
|
hash: () => hash,
|
|
98
108
|
hydrate: () => hydrate,
|
|
99
109
|
iface: () => iface,
|
|
@@ -105,12 +115,14 @@ __export(src_exports, {
|
|
|
105
115
|
isCustomField: () => isCustomField,
|
|
106
116
|
isEntityModel: () => isEntityModel,
|
|
107
117
|
isEnum: () => isEnum,
|
|
108
|
-
isEnumList: () => isEnumList,
|
|
109
118
|
isEnumModel: () => isEnumModel,
|
|
110
119
|
isFieldNode: () => isFieldNode,
|
|
111
120
|
isFragmentSpreadNode: () => isFragmentSpreadNode,
|
|
121
|
+
isInTable: () => isInTable,
|
|
122
|
+
isInherited: () => isInherited,
|
|
112
123
|
isInlineFragmentNode: () => isInlineFragmentNode,
|
|
113
124
|
isInputModel: () => isInputModel,
|
|
125
|
+
isInterfaceModel: () => isInterfaceModel,
|
|
114
126
|
isListType: () => isListType,
|
|
115
127
|
isObjectModel: () => isObjectModel,
|
|
116
128
|
isPrimitive: () => isPrimitive,
|
|
@@ -118,16 +130,20 @@ __export(src_exports, {
|
|
|
118
130
|
isQueriableField: () => isQueriableField,
|
|
119
131
|
isRawEnumModel: () => isRawEnumModel,
|
|
120
132
|
isRelation: () => isRelation,
|
|
133
|
+
isRootModel: () => isRootModel,
|
|
121
134
|
isScalarModel: () => isScalarModel,
|
|
122
135
|
isSimpleField: () => isSimpleField,
|
|
123
136
|
isToOneRelation: () => isToOneRelation,
|
|
124
137
|
isUpdatable: () => isUpdatable,
|
|
125
138
|
isUpdatableBy: () => isUpdatableBy,
|
|
139
|
+
isUpdatableField: () => isUpdatableField,
|
|
140
|
+
isUpdatableModel: () => isUpdatableModel,
|
|
126
141
|
isVisible: () => isVisible,
|
|
127
142
|
isVisibleRelation: () => isVisibleRelation,
|
|
128
143
|
it: () => it,
|
|
129
144
|
list: () => list,
|
|
130
145
|
merge: () => merge2,
|
|
146
|
+
modelNeedsTable: () => modelNeedsTable,
|
|
131
147
|
mutationResolver: () => mutationResolver,
|
|
132
148
|
name: () => name,
|
|
133
149
|
namedType: () => namedType,
|
|
@@ -137,6 +153,7 @@ __export(src_exports, {
|
|
|
137
153
|
normalizeValueByTypeDefinition: () => normalizeValueByTypeDefinition,
|
|
138
154
|
not: () => not,
|
|
139
155
|
object: () => object,
|
|
156
|
+
or: () => or,
|
|
140
157
|
ors: () => ors,
|
|
141
158
|
printSchema: () => printSchema,
|
|
142
159
|
printSchemaFromDocument: () => printSchemaFromDocument,
|
|
@@ -163,7 +180,7 @@ var execute = async ({
|
|
|
163
180
|
body,
|
|
164
181
|
...ctx
|
|
165
182
|
}) => {
|
|
166
|
-
const document2 = generate(ctx.
|
|
183
|
+
const document2 = generate(ctx.models);
|
|
167
184
|
const generatedResolvers = getResolvers(ctx.models);
|
|
168
185
|
const schema = (0, import_schema.makeExecutableSchema)({
|
|
169
186
|
typeDefs: document2,
|
|
@@ -199,9 +216,9 @@ var gql = (chunks, ...variables) => {
|
|
|
199
216
|
// src/client/mutations.ts
|
|
200
217
|
var import_upperCase = __toESM(require("lodash/upperCase"), 1);
|
|
201
218
|
var constantCase = (str) => (0, import_upperCase.default)(str).replace(/ /g, "_");
|
|
202
|
-
var generateMutations = (models) => {
|
|
219
|
+
var generateMutations = (models, gqmModule = "@smartive/graphql-magic") => {
|
|
203
220
|
const parts = [];
|
|
204
|
-
for (const { name: name2, creatable, updatable, deletable } of models.filter(
|
|
221
|
+
for (const { name: name2, creatable, updatable, deletable } of models.entities.filter(not(isRootModel))) {
|
|
205
222
|
if (creatable) {
|
|
206
223
|
parts.push(
|
|
207
224
|
`export const CREATE_${constantCase(
|
|
@@ -232,11 +249,20 @@ var generateMutations = (models) => {
|
|
|
232
249
|
mutation Delete${name2}Mutation($id: ID!) {
|
|
233
250
|
delete${name2}(where: { id: $id })
|
|
234
251
|
}
|
|
252
|
+
\`;`
|
|
253
|
+
);
|
|
254
|
+
parts.push(
|
|
255
|
+
`export const RESTORE_${constantCase(
|
|
256
|
+
name2
|
|
257
|
+
)} = gql\`
|
|
258
|
+
mutation Restore${name2}Mutation($id: ID!) {
|
|
259
|
+
restore${name2}(where: { id: $id })
|
|
260
|
+
}
|
|
235
261
|
\`;`
|
|
236
262
|
);
|
|
237
263
|
}
|
|
238
264
|
}
|
|
239
|
-
return `import { gql } from "
|
|
265
|
+
return `import { gql } from "${gqmModule}";
|
|
240
266
|
|
|
241
267
|
${parts.join("\n\n")}`;
|
|
242
268
|
};
|
|
@@ -246,96 +272,104 @@ var import_upperFirst = __toESM(require("lodash/upperFirst"), 1);
|
|
|
246
272
|
|
|
247
273
|
// src/models/utils.ts
|
|
248
274
|
var import_assert = __toESM(require("assert"), 1);
|
|
249
|
-
var
|
|
250
|
-
var import_camelCase = __toESM(require("lodash/camelCase"), 1);
|
|
275
|
+
var import_lodash3 = require("lodash");
|
|
251
276
|
var import_get = __toESM(require("lodash/get"), 1);
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
var
|
|
255
|
-
var
|
|
256
|
-
var
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
)
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
...
|
|
300
|
-
|
|
277
|
+
|
|
278
|
+
// src/models/models.ts
|
|
279
|
+
var import_inflection = require("inflection");
|
|
280
|
+
var import_lodash2 = require("lodash");
|
|
281
|
+
var Models = class {
|
|
282
|
+
models;
|
|
283
|
+
modelsByName = {};
|
|
284
|
+
scalars;
|
|
285
|
+
rawEnums;
|
|
286
|
+
enums;
|
|
287
|
+
inputs;
|
|
288
|
+
interfaces;
|
|
289
|
+
objects;
|
|
290
|
+
entities;
|
|
291
|
+
definitions;
|
|
292
|
+
constructor(definitions) {
|
|
293
|
+
this.definitions = (0, import_lodash2.cloneDeep)(definitions);
|
|
294
|
+
this.definitions.push(
|
|
295
|
+
{
|
|
296
|
+
kind: "scalar",
|
|
297
|
+
name: "DateTime"
|
|
298
|
+
},
|
|
299
|
+
{ kind: "scalar", name: "Upload" },
|
|
300
|
+
{
|
|
301
|
+
kind: "raw-enum",
|
|
302
|
+
name: "Order",
|
|
303
|
+
values: ["ASC", "DESC"]
|
|
304
|
+
}
|
|
305
|
+
);
|
|
306
|
+
const entities = this.definitions.filter(isEntityModelDefinition);
|
|
307
|
+
for (const entity of entities) {
|
|
308
|
+
if (entity.root) {
|
|
309
|
+
this.definitions.push({
|
|
310
|
+
kind: "enum",
|
|
311
|
+
name: `${entity.name}Type`,
|
|
312
|
+
values: entities.filter((subModel) => subModel.parent === entity.name).map((subModel) => subModel.name)
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
entity.fields = [
|
|
316
|
+
{
|
|
317
|
+
name: "id",
|
|
318
|
+
type: "ID",
|
|
319
|
+
nonNull: true,
|
|
320
|
+
unique: true,
|
|
321
|
+
primary: true,
|
|
322
|
+
generated: true
|
|
323
|
+
},
|
|
324
|
+
...entity.root ? [
|
|
325
|
+
{
|
|
326
|
+
name: "type",
|
|
327
|
+
kind: "enum",
|
|
328
|
+
type: `${entity.name}Type`,
|
|
329
|
+
nonNull: true,
|
|
330
|
+
generated: true
|
|
331
|
+
}
|
|
332
|
+
] : [],
|
|
333
|
+
...entity.fields,
|
|
334
|
+
...entity.creatable ? [
|
|
301
335
|
{
|
|
302
336
|
name: "createdAt",
|
|
303
337
|
type: "DateTime",
|
|
304
338
|
nonNull: true,
|
|
305
339
|
orderable: true,
|
|
306
340
|
generated: true,
|
|
307
|
-
...typeof
|
|
341
|
+
...typeof entity.creatable === "object" && entity.creatable.createdAt
|
|
308
342
|
},
|
|
309
343
|
{
|
|
310
344
|
name: "createdBy",
|
|
311
345
|
kind: "relation",
|
|
312
346
|
type: "User",
|
|
313
347
|
nonNull: true,
|
|
314
|
-
reverse: `created${getModelPlural(
|
|
348
|
+
reverse: `created${getModelPlural(entity)}`,
|
|
315
349
|
generated: true,
|
|
316
|
-
...typeof
|
|
350
|
+
...typeof entity.creatable === "object" && entity.creatable.createdBy
|
|
317
351
|
}
|
|
318
352
|
] : [],
|
|
319
|
-
...
|
|
353
|
+
...entity.updatable ? [
|
|
320
354
|
{
|
|
321
355
|
name: "updatedAt",
|
|
322
356
|
type: "DateTime",
|
|
323
357
|
nonNull: true,
|
|
324
358
|
orderable: true,
|
|
325
359
|
generated: true,
|
|
326
|
-
...typeof
|
|
360
|
+
...typeof entity.updatable === "object" && entity.updatable.updatedAt
|
|
327
361
|
},
|
|
328
362
|
{
|
|
329
363
|
name: "updatedBy",
|
|
330
364
|
kind: "relation",
|
|
331
365
|
type: "User",
|
|
332
366
|
nonNull: true,
|
|
333
|
-
reverse: `updated${getModelPlural(
|
|
367
|
+
reverse: `updated${getModelPlural(entity)}`,
|
|
334
368
|
generated: true,
|
|
335
|
-
...typeof
|
|
369
|
+
...typeof entity.updatable === "object" && entity.updatable.updatedBy
|
|
336
370
|
}
|
|
337
371
|
] : [],
|
|
338
|
-
...
|
|
372
|
+
...entity.deletable ? [
|
|
339
373
|
{
|
|
340
374
|
name: "deleted",
|
|
341
375
|
type: "Boolean",
|
|
@@ -343,65 +377,349 @@ var getModels = (rawModels) => {
|
|
|
343
377
|
defaultValue: false,
|
|
344
378
|
filterable: { default: false },
|
|
345
379
|
generated: true,
|
|
346
|
-
...typeof
|
|
380
|
+
...typeof entity.deletable === "object" && entity.deletable.deleted
|
|
347
381
|
},
|
|
348
382
|
{
|
|
349
383
|
name: "deletedAt",
|
|
350
384
|
type: "DateTime",
|
|
351
385
|
orderable: true,
|
|
352
386
|
generated: true,
|
|
353
|
-
...typeof
|
|
387
|
+
...typeof entity.deletable === "object" && entity.deletable.deletedAt
|
|
354
388
|
},
|
|
355
389
|
{
|
|
356
390
|
name: "deletedBy",
|
|
357
391
|
kind: "relation",
|
|
358
392
|
type: "User",
|
|
359
|
-
reverse: `deleted${getModelPlural(
|
|
393
|
+
reverse: `deleted${getModelPlural(entity)}`,
|
|
360
394
|
generated: true,
|
|
361
|
-
...typeof
|
|
395
|
+
...typeof entity.deletable === "object" && entity.deletable.deletedBy
|
|
362
396
|
}
|
|
363
397
|
] : []
|
|
364
|
-
]
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
foreignKey
|
|
398
|
+
];
|
|
399
|
+
for (const field of entity.fields) {
|
|
400
|
+
if (field.kind === "relation") {
|
|
401
|
+
field.foreignKey = field.foreignKey || `${field.name}Id`;
|
|
368
402
|
}
|
|
369
|
-
}
|
|
370
|
-
};
|
|
371
|
-
for (const field of objectModel.fields) {
|
|
372
|
-
objectModel.fieldsByName[field.name] = field;
|
|
403
|
+
}
|
|
373
404
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
405
|
+
for (const model of entities) {
|
|
406
|
+
if (model.parent) {
|
|
407
|
+
const parent = summonByName(entities, model.parent);
|
|
408
|
+
const INHERITED_FIELDS = ["queriable", "listQueriable", "creatable", "updatable", "deletable"];
|
|
409
|
+
Object.assign(model, (0, import_lodash2.pick)(parent, INHERITED_FIELDS), (0, import_lodash2.pick)(model, INHERITED_FIELDS));
|
|
410
|
+
model.fields = [
|
|
411
|
+
...parent.fields.map((field) => ({
|
|
412
|
+
...field,
|
|
413
|
+
...field.kind === "relation" && field.reverse && { reverse: field.reverse.replace(getModelPlural(parent), getModelPlural(model)) },
|
|
414
|
+
...model.fields.find((childField) => childField.name === field.name),
|
|
415
|
+
inherited: true
|
|
416
|
+
})),
|
|
417
|
+
...model.fields.filter((field) => !parent.fields.some((parentField) => parentField.name === field.name))
|
|
418
|
+
];
|
|
380
419
|
}
|
|
381
|
-
const fieldModel = summonByName(models, field.type);
|
|
382
|
-
const reverseRelation = {
|
|
383
|
-
kind: "relation",
|
|
384
|
-
name: field.reverse || (field.toOne ? typeToField(model.name) : getModelPluralField(model)),
|
|
385
|
-
foreignKey: get(field, "foreignKey"),
|
|
386
|
-
type: model.name,
|
|
387
|
-
toOne: !!field.toOne,
|
|
388
|
-
fieldModel,
|
|
389
|
-
field,
|
|
390
|
-
model
|
|
391
|
-
};
|
|
392
|
-
const relation = {
|
|
393
|
-
field,
|
|
394
|
-
model: fieldModel,
|
|
395
|
-
reverseRelation
|
|
396
|
-
};
|
|
397
|
-
model.relations.push(relation);
|
|
398
|
-
model.relationsByName[relation.field.name] = relation;
|
|
399
|
-
fieldModel.reverseRelations.push(reverseRelation);
|
|
400
|
-
fieldModel.reverseRelationsByName[reverseRelation.name] = reverseRelation;
|
|
401
420
|
}
|
|
421
|
+
this.models = this.definitions.map(
|
|
422
|
+
(definition) => new MODEL_KIND_TO_CLASS_MAPPING[definition.kind](this, definition)
|
|
423
|
+
);
|
|
424
|
+
for (const model of this.models) {
|
|
425
|
+
this.modelsByName[model.name] = model;
|
|
426
|
+
}
|
|
427
|
+
this.entities = this.models.filter((model) => model instanceof EntityModel);
|
|
428
|
+
this.enums = this.models.filter((model) => model instanceof EnumModel);
|
|
429
|
+
this.inputs = this.models.filter((model) => model instanceof InputModel);
|
|
430
|
+
this.interfaces = this.models.filter((model) => model instanceof InterfaceModel);
|
|
431
|
+
this.objects = this.models.filter((model) => model instanceof ObjectModel);
|
|
432
|
+
this.rawEnums = this.models.filter((model) => model instanceof RawEnumModel);
|
|
433
|
+
this.scalars = this.models.filter((model) => model instanceof ScalarModel);
|
|
434
|
+
}
|
|
435
|
+
getModel(name2, kind) {
|
|
436
|
+
const model = get(this.modelsByName, name2);
|
|
437
|
+
if (!kind) {
|
|
438
|
+
return model;
|
|
439
|
+
}
|
|
440
|
+
const expectedType = MODEL_KIND_TO_CLASS_MAPPING[kind];
|
|
441
|
+
if (!(model instanceof expectedType)) {
|
|
442
|
+
throw new Error(`Model ${name2} is not of kind ${kind}.`);
|
|
443
|
+
}
|
|
444
|
+
return model;
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
var Model = class {
|
|
448
|
+
constructor(models, definition) {
|
|
449
|
+
this.models = models;
|
|
450
|
+
Object.assign(this, definition);
|
|
451
|
+
this.plural = definition.plural || (0, import_inflection.pluralize)(definition.name);
|
|
452
|
+
}
|
|
453
|
+
name;
|
|
454
|
+
plural;
|
|
455
|
+
description;
|
|
456
|
+
};
|
|
457
|
+
var ScalarModel = class extends Model {
|
|
458
|
+
kind;
|
|
459
|
+
};
|
|
460
|
+
var EnumModel = class extends Model {
|
|
461
|
+
kind;
|
|
462
|
+
values;
|
|
463
|
+
deleted;
|
|
464
|
+
constructor(models, definition) {
|
|
465
|
+
super(models, definition);
|
|
466
|
+
Object.assign(this, (0, import_lodash2.omit)(definition, "name", "plural", "description"));
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
var RawEnumModel = class extends Model {
|
|
470
|
+
kind;
|
|
471
|
+
values;
|
|
472
|
+
constructor(models, definition) {
|
|
473
|
+
super(models, definition);
|
|
474
|
+
Object.assign(this, (0, import_lodash2.omit)(definition, "name", "plural", "description"));
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
var InterfaceModel = class extends Model {
|
|
478
|
+
kind;
|
|
479
|
+
fields;
|
|
480
|
+
constructor(models, definition) {
|
|
481
|
+
super(models, definition);
|
|
482
|
+
Object.assign(this, (0, import_lodash2.omit)(definition, "name", "plural", "description"));
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
var InputModel = class extends Model {
|
|
486
|
+
kind;
|
|
487
|
+
fields;
|
|
488
|
+
constructor(models, definition) {
|
|
489
|
+
super(models, definition);
|
|
490
|
+
Object.assign(this, (0, import_lodash2.omit)(definition, "name", "plural", "description"));
|
|
491
|
+
}
|
|
492
|
+
};
|
|
493
|
+
var ObjectModel = class extends Model {
|
|
494
|
+
kind;
|
|
495
|
+
fields;
|
|
496
|
+
constructor(models, definition) {
|
|
497
|
+
super(models, definition);
|
|
498
|
+
Object.assign(this, (0, import_lodash2.omit)(definition, "name", "plural", "description"));
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
var EntityModel = class extends Model {
|
|
502
|
+
kind;
|
|
503
|
+
root;
|
|
504
|
+
parent;
|
|
505
|
+
interfaces;
|
|
506
|
+
queriable;
|
|
507
|
+
listQueriable;
|
|
508
|
+
creatable;
|
|
509
|
+
updatable;
|
|
510
|
+
deletable;
|
|
511
|
+
displayField;
|
|
512
|
+
defaultOrderBy;
|
|
513
|
+
fields;
|
|
514
|
+
// temporary fields for the generation of migrations
|
|
515
|
+
deleted;
|
|
516
|
+
oldName;
|
|
517
|
+
fieldsByName = {};
|
|
518
|
+
fieldsByColumnName = {};
|
|
519
|
+
_relations;
|
|
520
|
+
_relationsByName;
|
|
521
|
+
_reverseRelations;
|
|
522
|
+
_reverseRelationsByName;
|
|
523
|
+
_manyToManyRelations;
|
|
524
|
+
_manyToManyRelationsByName;
|
|
525
|
+
pluralField;
|
|
526
|
+
slug;
|
|
527
|
+
labelPlural;
|
|
528
|
+
label;
|
|
529
|
+
_parentModel;
|
|
530
|
+
constructor(models, definition) {
|
|
531
|
+
super(models, definition);
|
|
532
|
+
Object.assign(this, (0, import_lodash2.omit)(definition, "name", "plural", "description"));
|
|
533
|
+
this.pluralField = typeToField(this.plural);
|
|
534
|
+
this.slug = (0, import_lodash2.kebabCase)(this.plural);
|
|
535
|
+
this.labelPlural = getLabel(this.plural);
|
|
536
|
+
this.label = getLabel(definition.name);
|
|
537
|
+
for (const field of definition.fields) {
|
|
538
|
+
this.fieldsByName[field.name] = field;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
getField(name2) {
|
|
542
|
+
return get(this.fieldsByName, name2);
|
|
543
|
+
}
|
|
544
|
+
get relations() {
|
|
545
|
+
if (!this._relations) {
|
|
546
|
+
this._relations = this.fields.filter(isRelation).map((relationField) => new NormalRelation(this, relationField, this.models.getModel(relationField.type, "entity")));
|
|
547
|
+
}
|
|
548
|
+
return this._relations;
|
|
549
|
+
}
|
|
550
|
+
get relationsByName() {
|
|
551
|
+
if (!this._relationsByName) {
|
|
552
|
+
this._relationsByName = {};
|
|
553
|
+
for (const relation of this.relations) {
|
|
554
|
+
this._relationsByName[relation.name] = relation;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
return this._relationsByName;
|
|
558
|
+
}
|
|
559
|
+
getRelation(name2) {
|
|
560
|
+
return get(this.relationsByName, name2);
|
|
561
|
+
}
|
|
562
|
+
get reverseRelations() {
|
|
563
|
+
if (!this._reverseRelations) {
|
|
564
|
+
this._reverseRelations = this.models.entities.flatMap(
|
|
565
|
+
(model) => model.relations.filter((relation) => relation.targetModel.name === this.name || relation.targetModel.name === this.rootModel.name).map((relation) => relation.reverse)
|
|
566
|
+
);
|
|
567
|
+
}
|
|
568
|
+
return this._reverseRelations;
|
|
569
|
+
}
|
|
570
|
+
get reverseRelationsByName() {
|
|
571
|
+
if (!this._reverseRelationsByName) {
|
|
572
|
+
this._reverseRelationsByName = {};
|
|
573
|
+
for (const reverseRelation of this.reverseRelations) {
|
|
574
|
+
this._reverseRelationsByName[reverseRelation.name] = reverseRelation;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
return this._reverseRelationsByName;
|
|
578
|
+
}
|
|
579
|
+
getReverseRelation(name2) {
|
|
580
|
+
return get(this.reverseRelationsByName, name2);
|
|
581
|
+
}
|
|
582
|
+
get manyToManyRelations() {
|
|
583
|
+
if (!this._manyToManyRelations) {
|
|
584
|
+
this._manyToManyRelations = [];
|
|
585
|
+
for (const relationFromSource of this.reverseRelations) {
|
|
586
|
+
const relationToTarget = relationFromSource.targetModel.relations.find(
|
|
587
|
+
(relation) => !relation.field.generated && relation.field.name !== relationFromSource.field.name
|
|
588
|
+
);
|
|
589
|
+
if (!relationToTarget) {
|
|
590
|
+
continue;
|
|
591
|
+
}
|
|
592
|
+
const inapplicableFields = relationFromSource.targetModel.fields.filter(
|
|
593
|
+
(otherField) => !otherField.generated && ![relationFromSource.field.name, relationToTarget.field.name].includes(otherField.name)
|
|
594
|
+
);
|
|
595
|
+
if (inapplicableFields.length) {
|
|
596
|
+
continue;
|
|
597
|
+
}
|
|
598
|
+
this._manyToManyRelations.push(new ManyToManyRelation(relationFromSource, relationToTarget));
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
return this._manyToManyRelations;
|
|
602
|
+
}
|
|
603
|
+
get manyToManyRelationsByName() {
|
|
604
|
+
if (!this._manyToManyRelationsByName) {
|
|
605
|
+
this._manyToManyRelationsByName = {};
|
|
606
|
+
for (const manyToManyRelation of this.manyToManyRelations) {
|
|
607
|
+
this._manyToManyRelationsByName[manyToManyRelation.name] = manyToManyRelation;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
return this._manyToManyRelationsByName;
|
|
611
|
+
}
|
|
612
|
+
getManyToManyRelation(name2) {
|
|
613
|
+
return get(this.manyToManyRelationsByName, name2);
|
|
614
|
+
}
|
|
615
|
+
get parentModel() {
|
|
616
|
+
if (this.parent) {
|
|
617
|
+
if (!this._parentModel) {
|
|
618
|
+
this._parentModel = this.models.getModel(this.parent, "entity");
|
|
619
|
+
}
|
|
620
|
+
return this._parentModel;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
get rootModel() {
|
|
624
|
+
return this.parentModel || this;
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
var MODEL_KIND_TO_CLASS_MAPPING = {
|
|
628
|
+
entity: EntityModel,
|
|
629
|
+
enum: EnumModel,
|
|
630
|
+
input: InputModel,
|
|
631
|
+
interface: InterfaceModel,
|
|
632
|
+
object: ObjectModel,
|
|
633
|
+
"raw-enum": RawEnumModel,
|
|
634
|
+
scalar: ScalarModel
|
|
635
|
+
};
|
|
636
|
+
var Relation = class {
|
|
637
|
+
constructor(name2, sourceModel, field, targetModel) {
|
|
638
|
+
this.name = name2;
|
|
639
|
+
this.sourceModel = sourceModel;
|
|
640
|
+
this.field = field;
|
|
641
|
+
this.targetModel = targetModel;
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
var NormalRelation = class extends Relation {
|
|
645
|
+
constructor(sourceModel, field, targetModel) {
|
|
646
|
+
super(field.name, sourceModel, field, targetModel);
|
|
647
|
+
this.field = field;
|
|
648
|
+
this.reverse = new ReverseRelation(this);
|
|
649
|
+
}
|
|
650
|
+
reverse;
|
|
651
|
+
};
|
|
652
|
+
var ReverseRelation = class extends Relation {
|
|
653
|
+
constructor(reverse) {
|
|
654
|
+
super(
|
|
655
|
+
reverse.field.reverse || (reverse.field.toOne ? typeToField(reverse.sourceModel.name) : reverse.sourceModel.pluralField),
|
|
656
|
+
reverse.targetModel,
|
|
657
|
+
reverse.field,
|
|
658
|
+
reverse.sourceModel
|
|
659
|
+
);
|
|
660
|
+
this.reverse = reverse;
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
var ManyToManyRelation = class {
|
|
664
|
+
name;
|
|
665
|
+
sourceModel;
|
|
666
|
+
relationFromSource;
|
|
667
|
+
relationModel;
|
|
668
|
+
relationToTarget;
|
|
669
|
+
targetModel;
|
|
670
|
+
constructor(relationFromSource, relationToTarget) {
|
|
671
|
+
this.name = relationFromSource.name;
|
|
672
|
+
this.sourceModel = relationFromSource.sourceModel;
|
|
673
|
+
this.relationFromSource = relationFromSource;
|
|
674
|
+
this.relationModel = relationFromSource.targetModel;
|
|
675
|
+
if (this.relationModel !== relationToTarget.sourceModel) {
|
|
676
|
+
throw new Error(`Relation model is ambiguous.`);
|
|
677
|
+
}
|
|
678
|
+
this.relationToTarget = relationToTarget;
|
|
679
|
+
this.targetModel = relationToTarget.targetModel;
|
|
402
680
|
}
|
|
403
|
-
return models;
|
|
404
681
|
};
|
|
682
|
+
var isEntityModelDefinition = (definition) => definition.kind === "entity";
|
|
683
|
+
var getModelPlural = (model) => model.plural || (0, import_inflection.pluralize)(model.name);
|
|
684
|
+
|
|
685
|
+
// src/models/utils.ts
|
|
686
|
+
var isNotFalsy = (v) => typeof v !== "undefined" && v !== null && v !== false;
|
|
687
|
+
var merge2 = (objects) => (objects || []).filter(isNotFalsy).reduce((i, acc) => ({ ...acc, ...i }), {});
|
|
688
|
+
var typeToField = (type) => type.substr(0, 1).toLowerCase() + type.substr(1);
|
|
689
|
+
var getLabel = (s) => (0, import_lodash3.startCase)((0, import_lodash3.camelCase)(s));
|
|
690
|
+
var or = (...predicates) => (field) => predicates.some((predicate) => predicate(field));
|
|
691
|
+
var and = (...predicates) => (field) => predicates.every((predicate) => predicate(field));
|
|
692
|
+
var not = (predicate) => (field) => !predicate(field);
|
|
693
|
+
var isRootModel = (model) => model.root;
|
|
694
|
+
var isEntityModel = (model) => model instanceof EntityModel;
|
|
695
|
+
var isEnumModel = (model) => model instanceof EnumModel;
|
|
696
|
+
var isRawEnumModel = (model) => model instanceof RawEnumModel;
|
|
697
|
+
var isScalarModel = (model) => model instanceof ScalarModel;
|
|
698
|
+
var isObjectModel = (model) => model instanceof ObjectModel;
|
|
699
|
+
var isInputModel = (model) => model instanceof InputModel;
|
|
700
|
+
var isInterfaceModel = (model) => model instanceof InterfaceModel;
|
|
701
|
+
var isUpdatableModel = (model) => model.updatable && model.fields.some(isUpdatableField);
|
|
702
|
+
var isUpdatableField = (field) => !field.inherited && !!field.updatable;
|
|
703
|
+
var modelNeedsTable = (model) => model.fields.some((field) => !field.inherited);
|
|
704
|
+
var hasName = (name2) => (field) => field.name == name2;
|
|
705
|
+
var isPrimitive = (field) => field.kind === void 0 || field.kind === "primitive";
|
|
706
|
+
var isEnum = (field) => field.kind === "enum";
|
|
707
|
+
var isRelation = (field) => field.kind === "relation";
|
|
708
|
+
var isInherited = (field) => field.inherited;
|
|
709
|
+
var isInTable = (field) => field.name === "id" || !field.inherited;
|
|
710
|
+
var isToOneRelation = (field) => isRelation(field) && !!field.toOne;
|
|
711
|
+
var isQueriableField = ({ queriable }) => queriable !== false;
|
|
712
|
+
var isCustomField = (field) => field.kind === "custom";
|
|
713
|
+
var isVisible = ({ hidden }) => hidden !== true;
|
|
714
|
+
var isSimpleField = and(not(isRelation), not(isCustomField));
|
|
715
|
+
var isUpdatable = ({ updatable }) => !!updatable;
|
|
716
|
+
var isCreatable = ({ creatable }) => !!creatable;
|
|
717
|
+
var isQueriableBy = (role) => (field) => field.queriable !== false && (field.queriable === void 0 || field.queriable === true || !field.queriable.roles || field.queriable.roles.includes(role));
|
|
718
|
+
var isUpdatableBy = (role) => (field) => field.updatable && (field.updatable === true || !field.updatable.roles || field.updatable.roles.includes(role));
|
|
719
|
+
var isCreatableBy = (role) => (field) => field.creatable && (field.creatable === true || !field.creatable.roles || field.creatable.roles.includes(role));
|
|
720
|
+
var actionableRelations = (model, action) => model.relations.filter(
|
|
721
|
+
(relation) => relation.field[`${action === "filter" ? action : action.slice(0, -1)}able`]
|
|
722
|
+
);
|
|
405
723
|
var summonByName = (array, value2) => summonByKey(array, "name", value2);
|
|
406
724
|
var summonByKey = (array, key, value2) => summon(array, (element) => (0, import_get.default)(element, key) === value2, `No element found with ${key} ${value2}`);
|
|
407
725
|
var summon = (array, cb, errorMessage) => {
|
|
@@ -426,8 +744,9 @@ var it = (object2) => {
|
|
|
426
744
|
var get = (object2, key) => {
|
|
427
745
|
const value2 = it(object2)[key];
|
|
428
746
|
if (value2 === void 0 || value2 === null) {
|
|
429
|
-
|
|
430
|
-
|
|
747
|
+
const error = new Error(`Object doesn't have ${String(key)}`);
|
|
748
|
+
console.warn(error);
|
|
749
|
+
throw error;
|
|
431
750
|
}
|
|
432
751
|
return value2;
|
|
433
752
|
};
|
|
@@ -456,73 +775,49 @@ var getUpdateEntityQuery = (model, role, fields2, additionalFields = "") => `que
|
|
|
456
775
|
${additionalFields}
|
|
457
776
|
}
|
|
458
777
|
}`;
|
|
459
|
-
var getEditEntityRelationsQuery = (
|
|
778
|
+
var getEditEntityRelationsQuery = (model, action, fields2, ignoreFields, additionalFields = {}) => {
|
|
460
779
|
const relations = actionableRelations(model, action).filter(
|
|
461
780
|
({ name: name2 }) => (!fields2 || fields2.includes(name2)) && (!ignoreFields || !ignoreFields.includes(name2))
|
|
462
781
|
);
|
|
463
782
|
return !!relations.length && `query ${(0, import_upperFirst.default)(action)}${model.name}Relations {
|
|
464
|
-
${relations.map((
|
|
465
|
-
const model2 = summonByName(models, type);
|
|
783
|
+
${relations.map((relation) => {
|
|
466
784
|
let filters = "";
|
|
467
|
-
if (
|
|
468
|
-
const displayField2 =
|
|
785
|
+
if (relation.targetModel.displayField) {
|
|
786
|
+
const displayField2 = relation.targetModel.fieldsByName[relation.targetModel.displayField];
|
|
469
787
|
if (displayField2.orderable) {
|
|
470
|
-
filters = `(orderBy: [{ ${
|
|
788
|
+
filters = `(orderBy: [{ ${relation.targetModel.displayField}: ASC }])`;
|
|
471
789
|
}
|
|
472
790
|
}
|
|
473
|
-
return `${
|
|
791
|
+
return `${relation.name}: ${relation.targetModel.pluralField}${filters} {
|
|
474
792
|
id
|
|
475
|
-
display: ${
|
|
476
|
-
${additionalFields[
|
|
793
|
+
display: ${relation.targetModel.displayField || "id"}
|
|
794
|
+
${additionalFields[relation.name] || ""}
|
|
477
795
|
}`;
|
|
478
796
|
}).join(" ")}
|
|
479
797
|
}`;
|
|
480
798
|
};
|
|
481
|
-
var getManyToManyRelations = (model, fields2, ignoreFields) => {
|
|
482
|
-
const manyToManyRelations = [];
|
|
483
|
-
for (const field of model.reverseRelations) {
|
|
484
|
-
if (fields2 && !fields2.includes(field.name) || ignoreFields && ignoreFields.includes(field.name)) {
|
|
485
|
-
continue;
|
|
486
|
-
}
|
|
487
|
-
const relation = field.model.relations.find(
|
|
488
|
-
(relation2) => !relation2.field.generated && relation2.field.name !== field.field.name
|
|
489
|
-
);
|
|
490
|
-
if (!relation) {
|
|
491
|
-
continue;
|
|
492
|
-
}
|
|
493
|
-
const inapplicableFields = field.model.fields.filter(
|
|
494
|
-
(otherField) => !otherField.generated && ![field.field.name, relation.field.name].includes(otherField.name)
|
|
495
|
-
);
|
|
496
|
-
if (inapplicableFields.length) {
|
|
497
|
-
continue;
|
|
498
|
-
}
|
|
499
|
-
manyToManyRelations.push([field, relation]);
|
|
500
|
-
}
|
|
501
|
-
return manyToManyRelations;
|
|
502
|
-
};
|
|
503
|
-
var getManyToManyRelation = (model, name2) => getManyToManyRelations(model, [name2])[0];
|
|
504
799
|
var getManyToManyRelationsQuery = (model, action, manyToManyRelations) => !!manyToManyRelations.length && (action === "update" ? `query Update${model.name}ManyToManyRelations($id: ID!) {
|
|
505
800
|
${typeToField(model.name)}(where: { id: $id }) {
|
|
506
|
-
${manyToManyRelations.map((
|
|
507
|
-
return `${
|
|
801
|
+
${manyToManyRelations.map((relation) => {
|
|
802
|
+
return `${relation.name} {
|
|
508
803
|
id
|
|
509
|
-
${
|
|
804
|
+
${relation.relationToTarget.name} {
|
|
510
805
|
id
|
|
511
806
|
}
|
|
512
807
|
}`;
|
|
513
808
|
}).join(" ")}
|
|
514
809
|
}
|
|
515
|
-
${manyToManyRelations.map((
|
|
516
|
-
return `${
|
|
810
|
+
${manyToManyRelations.map((relation) => {
|
|
811
|
+
return `${relation.name}: ${relation.targetModel.pluralField} {
|
|
517
812
|
id
|
|
518
|
-
${
|
|
813
|
+
${relation.targetModel.displayField || ""}
|
|
519
814
|
}`;
|
|
520
815
|
}).join(" ")}
|
|
521
816
|
}` : `query Create${model.name}ManyToManyRelations {
|
|
522
|
-
${manyToManyRelations.map((
|
|
523
|
-
return `${
|
|
817
|
+
${manyToManyRelations.map((relation) => {
|
|
818
|
+
return `${relation.name}: ${relation.targetModel.pluralField} {
|
|
524
819
|
id
|
|
525
|
-
${
|
|
820
|
+
${relation.targetModel.displayField || ""}
|
|
526
821
|
}`;
|
|
527
822
|
}).join(" ")}
|
|
528
823
|
}`);
|
|
@@ -548,14 +843,14 @@ var getMutationQuery = (model, action) => action === "create" ? `
|
|
|
548
843
|
var displayField = (model) => `
|
|
549
844
|
${model.displayField ? `display: ${model.displayField}` : ""}
|
|
550
845
|
`;
|
|
551
|
-
var getEntityListQuery = (model, role, additionalFields = "", root) => `query ${
|
|
846
|
+
var getEntityListQuery = (model, role, additionalFields = "", root) => `query ${model.plural}List(
|
|
552
847
|
${root ? "$id: ID!," : ""}
|
|
553
848
|
$limit: Int!,
|
|
554
849
|
$where: ${model.name}Where!,
|
|
555
850
|
${model.fields.some(({ searchable }) => searchable) ? "$search: String," : ""}
|
|
556
851
|
) {
|
|
557
852
|
${root ? `root: ${typeToField(root.model.name)}(where: { id: $id }) {` : ""}
|
|
558
|
-
data: ${root ? root.reverseRelationName :
|
|
853
|
+
data: ${root ? root.reverseRelationName : model.pluralField}(limit: $limit, where: $where, ${model.fields.some(({ searchable }) => searchable) ? ", search: $search" : ""}) {
|
|
559
854
|
${displayField(model)}
|
|
560
855
|
${model.fields.filter(and(isSimpleField, isQueriableBy(role))).map(({ name: name2 }) => name2)}
|
|
561
856
|
${additionalFields}
|
|
@@ -564,37 +859,38 @@ var getEntityListQuery = (model, role, additionalFields = "", root) => `query ${
|
|
|
564
859
|
}`;
|
|
565
860
|
var isVisibleRelation = (visibleRelationsByRole, modelName, role) => {
|
|
566
861
|
const whitelist = visibleRelationsByRole[role]?.[modelName];
|
|
567
|
-
return (
|
|
862
|
+
return (relation) => whitelist ? whitelist.includes(relation.name) : true;
|
|
568
863
|
};
|
|
569
|
-
var getEntityQuery = (
|
|
864
|
+
var getEntityQuery = (model, role, visibleRelationsByRole, typesWithSubRelations) => `query Admin${model.name} ($id: ID!) {
|
|
570
865
|
data: ${typeToField(model.name)}(where: { id: $id }) {
|
|
571
866
|
${displayField(model)}
|
|
572
867
|
${model.fields.filter(and(isSimpleField, isQueriableBy(role))).map(({ name: name2 }) => name2)}
|
|
573
868
|
${queryRelations(
|
|
574
|
-
models,
|
|
575
|
-
model.
|
|
869
|
+
model.models,
|
|
870
|
+
model.relations.filter(isVisibleRelation(visibleRelationsByRole, model.name, role)),
|
|
576
871
|
role,
|
|
577
872
|
typesWithSubRelations
|
|
578
873
|
)}
|
|
579
874
|
${queryRelations(
|
|
580
|
-
models,
|
|
581
|
-
model.reverseRelations.filter(
|
|
875
|
+
model.models,
|
|
876
|
+
model.reverseRelations.filter(
|
|
877
|
+
(reverseRelation) => isToOneRelation(reverseRelation.field) && isVisibleRelation(visibleRelationsByRole, model.name, role)(reverseRelation)
|
|
878
|
+
),
|
|
582
879
|
role,
|
|
583
880
|
typesWithSubRelations
|
|
584
881
|
)}
|
|
585
882
|
}
|
|
586
883
|
}`;
|
|
587
884
|
var getFindEntityQuery = (model, role) => `query Find${model.name}($where: ${model.name}Where!, $orderBy: [${model.name}OrderBy!]) {
|
|
588
|
-
data: ${
|
|
885
|
+
data: ${model.pluralField}(limit: 1, where: $where, orderBy: $orderBy) {
|
|
589
886
|
${model.fields.filter(and(isSimpleField, isQueriableBy(role))).map(({ name: name2 }) => name2)}
|
|
590
887
|
}
|
|
591
888
|
}`;
|
|
592
|
-
var queryRelations = (models, relations, role, typesWithSubRelations) => relations.map((
|
|
593
|
-
const
|
|
594
|
-
|
|
595
|
-
return `${name2} {
|
|
889
|
+
var queryRelations = (models, relations, role, typesWithSubRelations) => relations.map((relation) => {
|
|
890
|
+
const subRelations = typesWithSubRelations.includes(relation.targetModel.name) ? relation.targetModel.relations : [];
|
|
891
|
+
return `${relation.name} {
|
|
596
892
|
id
|
|
597
|
-
${displayField(
|
|
893
|
+
${displayField(relation.targetModel)}
|
|
598
894
|
${subRelations.length > 0 ? queryRelations(models, subRelations, role, typesWithSubRelations) : ""}
|
|
599
895
|
}`;
|
|
600
896
|
}).join("\n");
|
|
@@ -611,56 +907,59 @@ var PRIMITIVE_TYPES = {
|
|
|
611
907
|
DateTime: "DateTime | string"
|
|
612
908
|
};
|
|
613
909
|
var OPTIONAL_SEED_FIELDS = ["createdAt", "createdById", "updatedAt", "updatedById", "deletedAt", "deletedById"];
|
|
614
|
-
var generateDBModels = (
|
|
910
|
+
var generateDBModels = (models) => {
|
|
615
911
|
const writer = new import_code_block_writer.default["default"]({
|
|
616
912
|
useSingleQuote: true,
|
|
617
913
|
indentNumberOfSpaces: 2
|
|
618
914
|
});
|
|
619
915
|
writer.write(`import { DateTime } from 'luxon';`).blankLine();
|
|
620
|
-
for (const enm2 of
|
|
916
|
+
for (const enm2 of models.enums) {
|
|
621
917
|
writer.write(`export type ${enm2.name} = ${enm2.values.map((v) => `'${v}'`).join(" | ")};`).blankLine();
|
|
622
918
|
}
|
|
623
|
-
const
|
|
624
|
-
|
|
625
|
-
const fields2 = model.fields.some((field) => field.kind === "relation" && field.foreignKey === "id") ? model.fields.filter((field) => field.name !== "id") : model.fields;
|
|
919
|
+
for (const model of models.entities) {
|
|
920
|
+
const fields2 = model.relations.some((relation) => relation.field.foreignKey === "id") ? model.fields.filter((field) => field.name !== "id") : model.fields;
|
|
626
921
|
writer.write(`export type ${model.name} = `).inlineBlock(() => {
|
|
627
922
|
for (const field of fields2.filter(not(isCustomField))) {
|
|
628
|
-
writer.write(`'${
|
|
923
|
+
writer.write(`'${getColumnName(field)}': ${getFieldType(field)}${field.nonNull ? "" : " | null"};`).newLine();
|
|
629
924
|
}
|
|
630
925
|
}).blankLine();
|
|
631
926
|
writer.write(`export type ${model.name}Initializer = `).inlineBlock(() => {
|
|
632
|
-
for (const field of fields2.filter(not(isCustomField))) {
|
|
927
|
+
for (const field of fields2.filter(not(isCustomField)).filter(isInTable)) {
|
|
633
928
|
writer.write(
|
|
634
|
-
`'${
|
|
929
|
+
`'${getColumnName(field)}'${field.nonNull && field.defaultValue === void 0 ? "" : "?"}: ${getFieldType(
|
|
635
930
|
field
|
|
636
|
-
)}${field.list ? " | string" : ""}${field.nonNull ? "" : " | null"}
|
|
931
|
+
)}${field.list ? " | string" : ""}${field.nonNull ? "" : " | null"};`
|
|
637
932
|
).newLine();
|
|
638
933
|
}
|
|
639
934
|
}).blankLine();
|
|
640
935
|
writer.write(`export type ${model.name}Mutator = `).inlineBlock(() => {
|
|
641
|
-
for (const field of fields2.filter(not(isCustomField))) {
|
|
642
|
-
writer.write(
|
|
643
|
-
`'${getFieldName(field)}'?: ${getFieldType(field)}${field.list ? " | string" : ""}${field.nonNull ? "" : " | null"},`
|
|
644
|
-
).newLine();
|
|
645
|
-
}
|
|
646
|
-
}).blankLine();
|
|
647
|
-
writer.write(`export type ${model.name}Seed = `).inlineBlock(() => {
|
|
648
|
-
for (const field of fields2.filter(not(isCustomField))) {
|
|
649
|
-
const fieldName = getFieldName(field);
|
|
936
|
+
for (const field of fields2.filter(not(isCustomField)).filter(isInTable)) {
|
|
650
937
|
writer.write(
|
|
651
|
-
`'${
|
|
938
|
+
`'${getColumnName(field)}'?: ${getFieldType(field)}${field.list ? " | string" : ""}${field.nonNull ? "" : " | null"};`
|
|
652
939
|
).newLine();
|
|
653
940
|
}
|
|
654
941
|
}).blankLine();
|
|
942
|
+
if (!isRootModel(model)) {
|
|
943
|
+
writer.write(`export type ${model.name}Seed = `).inlineBlock(() => {
|
|
944
|
+
for (const field of fields2.filter(not(isCustomField))) {
|
|
945
|
+
if (model.parent && field.name === "type") {
|
|
946
|
+
continue;
|
|
947
|
+
}
|
|
948
|
+
const fieldName = getColumnName(field);
|
|
949
|
+
writer.write(
|
|
950
|
+
`'${getColumnName(field)}'${field.nonNull && field.defaultValue === void 0 && !OPTIONAL_SEED_FIELDS.includes(fieldName) ? "" : "?"}: ${field.kind === "enum" ? field.list ? "string[]" : "string" : getFieldType(field)}${field.list ? " | string" : ""}${field.nonNull ? "" : " | null"};`
|
|
951
|
+
).newLine();
|
|
952
|
+
}
|
|
953
|
+
}).blankLine();
|
|
954
|
+
}
|
|
655
955
|
}
|
|
656
956
|
writer.write(`export type SeedData = `).inlineBlock(() => {
|
|
657
|
-
for (const model of models) {
|
|
658
|
-
writer.write(`${model.name}: ${model.name}Seed[]
|
|
957
|
+
for (const model of models.entities.filter(not(isRootModel))) {
|
|
958
|
+
writer.write(`${model.name}: ${model.name}Seed[];`).newLine();
|
|
659
959
|
}
|
|
660
960
|
});
|
|
661
961
|
return writer.toString();
|
|
662
962
|
};
|
|
663
|
-
var getFieldName = (field) => field.kind === "relation" ? field.foreignKey || `${field.name}Id` : field.name;
|
|
664
963
|
var getFieldType = (field) => {
|
|
665
964
|
const kind = field.kind;
|
|
666
965
|
switch (kind) {
|
|
@@ -681,19 +980,18 @@ var getFieldType = (field) => {
|
|
|
681
980
|
}
|
|
682
981
|
}
|
|
683
982
|
};
|
|
684
|
-
var generateKnexTables = (
|
|
983
|
+
var generateKnexTables = (models) => {
|
|
685
984
|
const writer = new import_code_block_writer.default["default"]({
|
|
686
985
|
useSingleQuote: true,
|
|
687
986
|
indentNumberOfSpaces: 2
|
|
688
987
|
});
|
|
689
|
-
const models = getModels(rawModels);
|
|
690
988
|
writer.write(`import { Knex } from 'knex';`).newLine();
|
|
691
989
|
writer.write(
|
|
692
|
-
`import { ${models.map((model) => `${model.name}, ${model.name}Initializer, ${model.name}Mutator`).join(", ")} } from '.';`
|
|
990
|
+
`import { ${models.entities.map((model) => `${model.name}, ${model.name}Initializer, ${model.name}Mutator`).join(", ")} } from '.';`
|
|
693
991
|
).blankLine();
|
|
694
992
|
writer.write(`declare module 'knex/types/tables' `).inlineBlock(() => {
|
|
695
993
|
writer.write(`interface Tables `).inlineBlock(() => {
|
|
696
|
-
for (const model of models) {
|
|
994
|
+
for (const model of models.entities) {
|
|
697
995
|
writer.write(`'${model.name}': Knex.CompositeTableType<${model.name}, ${model.name}Initializer, ${model.name}Mutator>,`).newLine();
|
|
698
996
|
}
|
|
699
997
|
});
|
|
@@ -706,10 +1004,9 @@ var import_code_block_writer2 = __toESM(require("code-block-writer"), 1);
|
|
|
706
1004
|
var import_knex_schema_inspector = require("knex-schema-inspector");
|
|
707
1005
|
var import_lowerFirst = __toESM(require("lodash/lowerFirst"), 1);
|
|
708
1006
|
var MigrationGenerator = class {
|
|
709
|
-
constructor(knex,
|
|
710
|
-
this.
|
|
1007
|
+
constructor(knex, models) {
|
|
1008
|
+
this.models = models;
|
|
711
1009
|
this.schema = (0, import_knex_schema_inspector.SchemaInspector)(knex);
|
|
712
|
-
this.models = getModels(rawModels);
|
|
713
1010
|
}
|
|
714
1011
|
writer = new import_code_block_writer2.default["default"]({
|
|
715
1012
|
useSingleQuote: true,
|
|
@@ -719,9 +1016,8 @@ var MigrationGenerator = class {
|
|
|
719
1016
|
columns = {};
|
|
720
1017
|
uuidUsed;
|
|
721
1018
|
nowUsed;
|
|
722
|
-
models;
|
|
723
1019
|
async generate() {
|
|
724
|
-
const { writer, schema,
|
|
1020
|
+
const { writer, schema, models } = this;
|
|
725
1021
|
const enums = (await schema.knex("pg_type").where({ typtype: "e" }).select("typname")).map(({ typname }) => typname);
|
|
726
1022
|
const tables = await schema.tables();
|
|
727
1023
|
for (const table of tables) {
|
|
@@ -730,11 +1026,11 @@ var MigrationGenerator = class {
|
|
|
730
1026
|
const up = [];
|
|
731
1027
|
const down = [];
|
|
732
1028
|
this.createEnums(
|
|
733
|
-
|
|
1029
|
+
this.models.enums.filter((enm2) => !enums.includes((0, import_lowerFirst.default)(enm2.name))),
|
|
734
1030
|
up,
|
|
735
1031
|
down
|
|
736
1032
|
);
|
|
737
|
-
for (const model of models) {
|
|
1033
|
+
for (const model of models.entities) {
|
|
738
1034
|
if (model.deleted) {
|
|
739
1035
|
up.push(() => {
|
|
740
1036
|
this.dropTable(model.name);
|
|
@@ -746,7 +1042,7 @@ var MigrationGenerator = class {
|
|
|
746
1042
|
}
|
|
747
1043
|
});
|
|
748
1044
|
});
|
|
749
|
-
if (model
|
|
1045
|
+
if (isUpdatableModel(model)) {
|
|
750
1046
|
up.push(() => {
|
|
751
1047
|
this.dropTable(`${model.name}Revision`);
|
|
752
1048
|
});
|
|
@@ -765,7 +1061,7 @@ var MigrationGenerator = class {
|
|
|
765
1061
|
tables[tables.indexOf(model.oldName)] = model.name;
|
|
766
1062
|
this.columns[model.name] = this.columns[model.oldName];
|
|
767
1063
|
delete this.columns[model.oldName];
|
|
768
|
-
if (model
|
|
1064
|
+
if (isUpdatableModel(model)) {
|
|
769
1065
|
up.push(() => {
|
|
770
1066
|
this.renameTable(`${model.oldName}Revision`, `${model.name}Revision`);
|
|
771
1067
|
this.alterTable(`${model.name}Revision`, () => {
|
|
@@ -783,92 +1079,102 @@ var MigrationGenerator = class {
|
|
|
783
1079
|
delete this.columns[`${model.oldName}Revision`];
|
|
784
1080
|
}
|
|
785
1081
|
}
|
|
786
|
-
if (
|
|
787
|
-
|
|
788
|
-
this.createTable(model.name, () => {
|
|
789
|
-
for (const field of model.fields) {
|
|
790
|
-
this.column(field);
|
|
791
|
-
}
|
|
792
|
-
});
|
|
793
|
-
});
|
|
794
|
-
down.push(() => {
|
|
795
|
-
this.dropTable(model.name);
|
|
796
|
-
});
|
|
797
|
-
} else {
|
|
798
|
-
this.renameFields(
|
|
799
|
-
model,
|
|
800
|
-
model.fields.filter(({ oldName }) => oldName),
|
|
801
|
-
up,
|
|
802
|
-
down
|
|
803
|
-
);
|
|
804
|
-
this.createFields(
|
|
805
|
-
model,
|
|
806
|
-
model.fields.filter(
|
|
807
|
-
({ name: name2, ...field }) => field.kind !== "custom" && !this.columns[model.name].some(
|
|
808
|
-
(col) => col.name === (field.kind === "relation" ? field.foreignKey || `${name2}Id` : name2)
|
|
809
|
-
)
|
|
810
|
-
),
|
|
811
|
-
up,
|
|
812
|
-
down
|
|
813
|
-
);
|
|
814
|
-
const existingFields = model.fields.filter(({ name: name2, kind, nonNull: nonNull2 }) => {
|
|
815
|
-
const col = this.columns[model.name].find((col2) => col2.name === (kind === "relation" ? `${name2}Id` : name2));
|
|
816
|
-
if (!col) {
|
|
817
|
-
return false;
|
|
818
|
-
}
|
|
819
|
-
return !nonNull2 && !col.is_nullable;
|
|
820
|
-
});
|
|
821
|
-
this.updateFields(model, existingFields, up, down);
|
|
822
|
-
}
|
|
823
|
-
if (model.updatable) {
|
|
824
|
-
if (!tables.includes(`${model.name}Revision`)) {
|
|
1082
|
+
if (modelNeedsTable(model)) {
|
|
1083
|
+
if (!tables.includes(model.name)) {
|
|
825
1084
|
up.push(() => {
|
|
826
|
-
this.
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
writer.write(`await knex.batchInsert('${model.name}Revision', data.map((row) => (`).inlineBlock(() => {
|
|
834
|
-
writer.writeLine(`id: uuid(),`);
|
|
835
|
-
writer.writeLine(`${typeToField(model.name)}Id: row.id,`);
|
|
836
|
-
this.nowUsed = true;
|
|
837
|
-
writer.writeLine(`createdAt: row.updatedAt || row.createdAt || now,`);
|
|
838
|
-
writer.writeLine(`createdById: row.updatedById || row.createdById,`);
|
|
839
|
-
if (model.deletable) {
|
|
840
|
-
writer.writeLine(`deleted: row.deleted,`);
|
|
841
|
-
}
|
|
842
|
-
for (const { name: name2, kind } of model.fields.filter(({ updatable }) => updatable)) {
|
|
843
|
-
const col = kind === "relation" ? `${name2}Id` : name2;
|
|
844
|
-
writer.writeLine(`${col}: row.${col},`);
|
|
845
|
-
}
|
|
846
|
-
}).write(")));").newLine();
|
|
1085
|
+
this.createTable(model.name, () => {
|
|
1086
|
+
if (model.parent) {
|
|
1087
|
+
this.column({
|
|
1088
|
+
...model.fieldsByName.id,
|
|
1089
|
+
kind: "relation",
|
|
1090
|
+
type: model.parent,
|
|
1091
|
+
foreignKey: "id"
|
|
847
1092
|
});
|
|
848
|
-
}
|
|
1093
|
+
}
|
|
1094
|
+
for (const field of model.fields.filter(not(isInherited))) {
|
|
1095
|
+
this.column(field);
|
|
1096
|
+
}
|
|
849
1097
|
});
|
|
850
|
-
}
|
|
1098
|
+
});
|
|
851
1099
|
down.push(() => {
|
|
852
|
-
this.dropTable(
|
|
1100
|
+
this.dropTable(model.name);
|
|
853
1101
|
});
|
|
854
1102
|
} else {
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
({
|
|
858
|
-
|
|
859
|
-
|
|
1103
|
+
this.renameFields(
|
|
1104
|
+
model,
|
|
1105
|
+
model.fields.filter(not(isInherited)).filter(({ oldName }) => oldName),
|
|
1106
|
+
up,
|
|
1107
|
+
down
|
|
860
1108
|
);
|
|
861
|
-
this.
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
(
|
|
865
|
-
|
|
1109
|
+
this.createFields(
|
|
1110
|
+
model,
|
|
1111
|
+
model.fields.filter(not(isInherited)).filter(
|
|
1112
|
+
({ name: name2, ...field }) => field.kind !== "custom" && !this.columns[model.name].some(
|
|
1113
|
+
(col) => col.name === (field.kind === "relation" ? field.foreignKey || `${name2}Id` : name2)
|
|
1114
|
+
)
|
|
1115
|
+
),
|
|
1116
|
+
up,
|
|
1117
|
+
down
|
|
866
1118
|
);
|
|
867
|
-
|
|
1119
|
+
const existingFields = model.fields.filter(({ name: name2, kind, nonNull: nonNull2 }) => {
|
|
1120
|
+
const col = this.columns[model.name].find((col2) => col2.name === (kind === "relation" ? `${name2}Id` : name2));
|
|
1121
|
+
if (!col) {
|
|
1122
|
+
return false;
|
|
1123
|
+
}
|
|
1124
|
+
return !nonNull2 && !col.is_nullable;
|
|
1125
|
+
});
|
|
1126
|
+
this.updateFields(model, existingFields, up, down);
|
|
1127
|
+
}
|
|
1128
|
+
if (isUpdatableModel(model)) {
|
|
1129
|
+
if (!tables.includes(`${model.name}Revision`)) {
|
|
1130
|
+
up.push(() => {
|
|
1131
|
+
this.createRevisionTable(model);
|
|
1132
|
+
});
|
|
1133
|
+
if (tables.includes(model.name)) {
|
|
1134
|
+
up.push(() => {
|
|
1135
|
+
writer.block(() => {
|
|
1136
|
+
writer.writeLine(`const data = await knex('${model.name}');`);
|
|
1137
|
+
writer.write(`if (data.length)`).block(() => {
|
|
1138
|
+
writer.write(`await knex.batchInsert('${model.name}Revision', data.map((row) => (`).inlineBlock(() => {
|
|
1139
|
+
writer.writeLine(`id: uuid(),`);
|
|
1140
|
+
writer.writeLine(`${typeToField(model.name)}Id: row.id,`);
|
|
1141
|
+
this.nowUsed = true;
|
|
1142
|
+
writer.writeLine(`createdAt: row.updatedAt || row.createdAt || now,`);
|
|
1143
|
+
writer.writeLine(`createdById: row.updatedById || row.createdById,`);
|
|
1144
|
+
if (model.deletable) {
|
|
1145
|
+
writer.writeLine(`deleted: row.deleted,`);
|
|
1146
|
+
}
|
|
1147
|
+
for (const { name: name2, kind } of model.fields.filter(isUpdatableField)) {
|
|
1148
|
+
const col = kind === "relation" ? `${name2}Id` : name2;
|
|
1149
|
+
writer.writeLine(`${col}: row.${col},`);
|
|
1150
|
+
}
|
|
1151
|
+
}).write(")));").newLine();
|
|
1152
|
+
});
|
|
1153
|
+
}).blankLine();
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
down.push(() => {
|
|
1157
|
+
this.dropTable(`${model.name}Revision`);
|
|
1158
|
+
});
|
|
1159
|
+
} else {
|
|
1160
|
+
const revisionTable = `${model.name}Revision`;
|
|
1161
|
+
const missingRevisionFields = model.fields.filter(isUpdatableField).filter(
|
|
1162
|
+
({ name: name2, ...field }) => field.kind !== "custom" && !this.columns[revisionTable].some(
|
|
1163
|
+
(col) => col.name === (field.kind === "relation" ? field.foreignKey || `${name2}Id` : name2)
|
|
1164
|
+
)
|
|
1165
|
+
);
|
|
1166
|
+
this.createRevisionFields(model, missingRevisionFields, up, down);
|
|
1167
|
+
const revisionFieldsToRemove = model.fields.filter(
|
|
1168
|
+
({ name: name2, updatable, generated, ...field }) => !generated && field.kind !== "custom" && !updatable && !(field.kind === "relation" && field.foreignKey === "id") && this.columns[revisionTable].some(
|
|
1169
|
+
(col) => col.name === (field.kind === "relation" ? field.foreignKey || `${name2}Id` : name2)
|
|
1170
|
+
)
|
|
1171
|
+
);
|
|
1172
|
+
this.createRevisionFields(model, revisionFieldsToRemove, down, up);
|
|
1173
|
+
}
|
|
868
1174
|
}
|
|
869
1175
|
}
|
|
870
1176
|
}
|
|
871
|
-
for (const model of
|
|
1177
|
+
for (const model of models.entities) {
|
|
872
1178
|
if (tables.includes(model.name)) {
|
|
873
1179
|
this.createFields(
|
|
874
1180
|
model,
|
|
@@ -876,10 +1182,10 @@ var MigrationGenerator = class {
|
|
|
876
1182
|
down,
|
|
877
1183
|
up
|
|
878
1184
|
);
|
|
879
|
-
if (model
|
|
1185
|
+
if (isUpdatableModel(model)) {
|
|
880
1186
|
this.createRevisionFields(
|
|
881
1187
|
model,
|
|
882
|
-
model.fields.filter(({ deleted
|
|
1188
|
+
model.fields.filter(isUpdatableField).filter(({ deleted }) => deleted),
|
|
883
1189
|
down,
|
|
884
1190
|
up
|
|
885
1191
|
);
|
|
@@ -887,7 +1193,7 @@ var MigrationGenerator = class {
|
|
|
887
1193
|
}
|
|
888
1194
|
}
|
|
889
1195
|
this.createEnums(
|
|
890
|
-
|
|
1196
|
+
this.models.enums.filter((enm2) => enm2.deleted),
|
|
891
1197
|
down,
|
|
892
1198
|
up
|
|
893
1199
|
);
|
|
@@ -995,8 +1301,8 @@ var MigrationGenerator = class {
|
|
|
995
1301
|
}
|
|
996
1302
|
});
|
|
997
1303
|
});
|
|
998
|
-
if (model
|
|
999
|
-
const updatableFields = fields2.filter(
|
|
1304
|
+
if (isUpdatableModel(model)) {
|
|
1305
|
+
const updatableFields = fields2.filter(isUpdatableField);
|
|
1000
1306
|
if (!updatableFields.length) {
|
|
1001
1307
|
return;
|
|
1002
1308
|
}
|
|
@@ -1024,15 +1330,15 @@ var MigrationGenerator = class {
|
|
|
1024
1330
|
const writer = this.writer;
|
|
1025
1331
|
this.createTable(`${model.name}Revision`, () => {
|
|
1026
1332
|
writer.writeLine(`table.uuid('id').notNullable().primary();`);
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1333
|
+
if (!model.parent) {
|
|
1334
|
+
writer.writeLine(`table.uuid('${typeToField(model.name)}Id').notNullable();`);
|
|
1335
|
+
writer.writeLine(`table.uuid('createdById').notNullable();`);
|
|
1336
|
+
writer.writeLine(`table.timestamp('createdAt').notNullable().defaultTo(knex.fn.now(0));`);
|
|
1337
|
+
if (model.deletable) {
|
|
1338
|
+
writer.writeLine(`table.boolean('deleted').notNullable();`);
|
|
1339
|
+
}
|
|
1034
1340
|
}
|
|
1035
|
-
for (const field of model.fields.filter((
|
|
1341
|
+
for (const field of model.fields.filter(and(isUpdatableField, not(isInherited)))) {
|
|
1036
1342
|
this.column(field, { setUnique: false, setDefault: false });
|
|
1037
1343
|
}
|
|
1038
1344
|
});
|
|
@@ -1080,7 +1386,7 @@ var MigrationGenerator = class {
|
|
|
1080
1386
|
`await knex.raw(\`CREATE TYPE "${name2}" AS ENUM (${enm2.values.map((value2) => `'${value2}'`).join(",")})\`);`
|
|
1081
1387
|
).newLine()
|
|
1082
1388
|
);
|
|
1083
|
-
down.push(() => this.writer.writeLine(`await knex.raw('DROP TYPE "${name2}"')
|
|
1389
|
+
down.push(() => this.writer.writeLine(`await knex.raw('DROP TYPE "${name2}"');`));
|
|
1084
1390
|
}
|
|
1085
1391
|
}
|
|
1086
1392
|
migration(name2, cbs) {
|
|
@@ -1160,7 +1466,7 @@ var MigrationGenerator = class {
|
|
|
1160
1466
|
if (field.double) {
|
|
1161
1467
|
col(`table.double('${name2}')`);
|
|
1162
1468
|
} else {
|
|
1163
|
-
col(`table.decimal('${name2}', ${
|
|
1469
|
+
col(`table.decimal('${name2}', ${field.precision ?? "undefined"}, ${field.scale ?? "undefined"})`);
|
|
1164
1470
|
}
|
|
1165
1471
|
break;
|
|
1166
1472
|
case "String":
|
|
@@ -1181,14 +1487,16 @@ var MigrationGenerator = class {
|
|
|
1181
1487
|
}
|
|
1182
1488
|
break;
|
|
1183
1489
|
case "relation":
|
|
1184
|
-
col(`table.uuid('${
|
|
1490
|
+
col(`table.uuid('${field.foreignKey}')`);
|
|
1185
1491
|
if (foreign && !alter) {
|
|
1186
|
-
this.writer.writeLine(
|
|
1492
|
+
this.writer.writeLine(
|
|
1493
|
+
`table.foreign('${field.foreignKey}').references('id').inTable('${field.type}').onDelete('CASCADE');`
|
|
1494
|
+
);
|
|
1187
1495
|
}
|
|
1188
1496
|
break;
|
|
1189
1497
|
case "enum":
|
|
1190
1498
|
if (list2) {
|
|
1191
|
-
this.writer.write(`table.specificType('${name2}', '"${typeToField(field.type)}"[]')
|
|
1499
|
+
this.writer.write(`table.specificType('${name2}', '"${typeToField(field.type)}"[]')`);
|
|
1192
1500
|
} else {
|
|
1193
1501
|
this.writer.write(`table.enum('${name2}', null as any, `).inlineBlock(() => {
|
|
1194
1502
|
this.writer.writeLine(`useNative: true,`);
|
|
@@ -1252,7 +1560,9 @@ var PermissionError = class extends ForbiddenError {
|
|
|
1252
1560
|
// src/resolvers/utils.ts
|
|
1253
1561
|
var import_crypto = require("crypto");
|
|
1254
1562
|
var import_graphql3 = require("graphql");
|
|
1563
|
+
var import_lodash4 = require("lodash");
|
|
1255
1564
|
var ID_ALIAS = "ID";
|
|
1565
|
+
var TYPE_ALIAS = "TYPE";
|
|
1256
1566
|
var getTypeName = (t) => {
|
|
1257
1567
|
switch (t.kind) {
|
|
1258
1568
|
case "ListType":
|
|
@@ -1278,18 +1588,16 @@ var isFragmentSpreadNode = (n) => n.kind === import_graphql3.Kind.FRAGMENT_SPREA
|
|
|
1278
1588
|
var getType = (schema, name2) => get(schema.getType(name2), "astNode");
|
|
1279
1589
|
var getFragmentTypeName = (node) => get(get(node.typeCondition, "name"), "value");
|
|
1280
1590
|
function hydrate(node, raw) {
|
|
1281
|
-
const
|
|
1591
|
+
const resultAlias = node.resultAlias;
|
|
1282
1592
|
const res = raw.map((entry) => {
|
|
1283
1593
|
const res2 = {};
|
|
1284
1594
|
outer:
|
|
1285
1595
|
for (const [column, value2] of Object.entries(entry)) {
|
|
1286
1596
|
let current = res2;
|
|
1287
|
-
const
|
|
1288
|
-
const fieldName = shortParts.pop();
|
|
1289
|
-
const columnWithoutField = shortParts.join("__");
|
|
1597
|
+
const [, columnWithoutField, fieldName] = column.match(/^(.*\w)__(\w+)$/);
|
|
1290
1598
|
const longColumn = node.ctx.aliases.getLong(columnWithoutField);
|
|
1291
|
-
const longColumnWithoutRoot = longColumn.replace(new RegExp(`^${
|
|
1292
|
-
const allParts = [
|
|
1599
|
+
const longColumnWithoutRoot = longColumn.replace(new RegExp(`^${resultAlias}(__)?`), "");
|
|
1600
|
+
const allParts = [resultAlias, ...longColumnWithoutRoot ? longColumnWithoutRoot.split("__") : [], fieldName];
|
|
1293
1601
|
for (let i = 0; i < allParts.length - 1; i++) {
|
|
1294
1602
|
const part = allParts[i];
|
|
1295
1603
|
if (!current[part]) {
|
|
@@ -1303,7 +1611,7 @@ function hydrate(node, raw) {
|
|
|
1303
1611
|
}
|
|
1304
1612
|
current[it(fieldName)] = value2;
|
|
1305
1613
|
}
|
|
1306
|
-
return res2[
|
|
1614
|
+
return res2[resultAlias];
|
|
1307
1615
|
});
|
|
1308
1616
|
return res;
|
|
1309
1617
|
}
|
|
@@ -1312,12 +1620,12 @@ var ors = (query, [first, ...rest]) => {
|
|
|
1312
1620
|
return query;
|
|
1313
1621
|
}
|
|
1314
1622
|
return query.where((subQuery) => {
|
|
1315
|
-
subQuery.where((subSubQuery) => {
|
|
1316
|
-
first(subSubQuery);
|
|
1623
|
+
void subQuery.where((subSubQuery) => {
|
|
1624
|
+
void first(subSubQuery);
|
|
1317
1625
|
});
|
|
1318
1626
|
for (const cb of rest) {
|
|
1319
|
-
subQuery.orWhere((subSubQuery) => {
|
|
1320
|
-
cb(subSubQuery);
|
|
1627
|
+
void subQuery.orWhere((subSubQuery) => {
|
|
1628
|
+
void cb(subSubQuery);
|
|
1321
1629
|
});
|
|
1322
1630
|
}
|
|
1323
1631
|
});
|
|
@@ -1331,15 +1639,26 @@ var getNameOrAlias = (node) => {
|
|
|
1331
1639
|
};
|
|
1332
1640
|
var apply = (target, ops) => ops.reduce((target2, op) => op(target2), target);
|
|
1333
1641
|
var applyJoins = (aliases, query, joins) => {
|
|
1334
|
-
for (const
|
|
1335
|
-
const [table, alias] = tableName.split(":");
|
|
1642
|
+
for (const { table1Alias, table2Name, table2Alias, column1, column2 } of joins) {
|
|
1336
1643
|
const table1ShortAlias = aliases.getShort(table1Alias);
|
|
1337
|
-
const table2ShortAlias = aliases.getShort(
|
|
1338
|
-
query.leftJoin(
|
|
1644
|
+
const table2ShortAlias = aliases.getShort(table2Alias);
|
|
1645
|
+
void query.leftJoin(
|
|
1646
|
+
`${table2Name} as ${table2ShortAlias}`,
|
|
1647
|
+
`${table1ShortAlias}.${column1}`,
|
|
1648
|
+
`${table2ShortAlias}.${column2}`
|
|
1649
|
+
);
|
|
1339
1650
|
}
|
|
1340
1651
|
};
|
|
1341
|
-
var addJoin = (joins, table1Alias,
|
|
1342
|
-
|
|
1652
|
+
var addJoin = (joins, table1Alias, table2Name, table2Alias, column1, column2) => {
|
|
1653
|
+
const join = { table1Alias, table2Name, table2Alias, column1, column2 };
|
|
1654
|
+
const existingJoin = joins.find((j) => j.table2Alias === join.table2Alias);
|
|
1655
|
+
if (existingJoin) {
|
|
1656
|
+
if (!(0, import_lodash4.isEqual)(existingJoin, join)) {
|
|
1657
|
+
throw new Error(`Join collision: ${existingJoin}, ${join}`);
|
|
1658
|
+
}
|
|
1659
|
+
} else {
|
|
1660
|
+
joins.push(join);
|
|
1661
|
+
}
|
|
1343
1662
|
};
|
|
1344
1663
|
var AliasGenerator = class {
|
|
1345
1664
|
reverse = {};
|
|
@@ -1362,6 +1681,11 @@ var AliasGenerator = class {
|
|
|
1362
1681
|
}
|
|
1363
1682
|
};
|
|
1364
1683
|
var hash = (s) => (0, import_crypto.createHash)("md5").update(JSON.stringify(s)).digest("hex");
|
|
1684
|
+
var getColumnName = (field) => field.kind === "relation" ? field.foreignKey || `${field.name}Id` : field.name;
|
|
1685
|
+
var getColumn = (node, key) => {
|
|
1686
|
+
const field = node.model.fields.find((field2) => getColumnName(field2) === key);
|
|
1687
|
+
return `${node.ctx.aliases.getShort(field.inherited ? node.rootTableAlias : node.tableAlias)}.${key}`;
|
|
1688
|
+
};
|
|
1365
1689
|
|
|
1366
1690
|
// src/permissions/check.ts
|
|
1367
1691
|
var getPermissionStack = (ctx, type, action) => {
|
|
@@ -1406,7 +1730,7 @@ var applyPermissions = (ctx, type, tableAlias, query, action, verifiedPermission
|
|
|
1406
1730
|
return permissionStack;
|
|
1407
1731
|
};
|
|
1408
1732
|
var getEntityToMutate = async (ctx, model, where, action) => {
|
|
1409
|
-
const query = ctx.knex(model.name).where(where).first();
|
|
1733
|
+
const query = ctx.knex(model.parent || model.name).where(where).first();
|
|
1410
1734
|
let entity = await query.clone();
|
|
1411
1735
|
if (!entity) {
|
|
1412
1736
|
console.error(
|
|
@@ -1422,6 +1746,10 @@ var getEntityToMutate = async (ctx, model, where, action) => {
|
|
|
1422
1746
|
);
|
|
1423
1747
|
throw new PermissionError(action, `this ${model.name}`, "no available permissions applied");
|
|
1424
1748
|
}
|
|
1749
|
+
if (model.parent) {
|
|
1750
|
+
const subEntity = await ctx.knex(model.name).where({ id: entity.id }).first();
|
|
1751
|
+
Object.assign(entity, subEntity);
|
|
1752
|
+
}
|
|
1425
1753
|
return entity;
|
|
1426
1754
|
};
|
|
1427
1755
|
var checkCanWrite = async (ctx, model, data, action) => {
|
|
@@ -1430,7 +1758,7 @@ var checkCanWrite = async (ctx, model, data, action) => {
|
|
|
1430
1758
|
return;
|
|
1431
1759
|
}
|
|
1432
1760
|
if (permissionStack === false) {
|
|
1433
|
-
throw new PermissionError(action,
|
|
1761
|
+
throw new PermissionError(action, model.plural, "no applicable permissions");
|
|
1434
1762
|
}
|
|
1435
1763
|
const query = ctx.knex.select(1).first();
|
|
1436
1764
|
let linked = false;
|
|
@@ -1478,10 +1806,10 @@ var permissionLinkQuery = (ctx, subQuery, links, id) => {
|
|
|
1478
1806
|
subQuery.where({ [`${alias}.id`]: ctx.user.id });
|
|
1479
1807
|
}
|
|
1480
1808
|
if (where) {
|
|
1481
|
-
applyWhere(
|
|
1809
|
+
applyWhere(ctx.models.getModel(type, "entity"), subQuery, alias, where, aliases);
|
|
1482
1810
|
}
|
|
1483
1811
|
for (const { type: type2, foreignKey, reverse, where: where2 } of links) {
|
|
1484
|
-
const model =
|
|
1812
|
+
const model = ctx.models.getModel(type2, "entity");
|
|
1485
1813
|
const subAlias = aliases.getShort();
|
|
1486
1814
|
if (reverse) {
|
|
1487
1815
|
subQuery.leftJoin(`${type2} as ${subAlias}`, `${alias}.${foreignKey || "id"}`, `${subAlias}.id`);
|
|
@@ -1502,11 +1830,11 @@ var applyWhere = (model, query, alias, where, aliases) => {
|
|
|
1502
1830
|
if (relation) {
|
|
1503
1831
|
const subAlias = aliases.getShort();
|
|
1504
1832
|
query.leftJoin(
|
|
1505
|
-
`${relation.
|
|
1833
|
+
`${relation.targetModel.name} as ${subAlias}`,
|
|
1506
1834
|
`${alias}.${relation.field.foreignKey || `${relation.field.name}Id`}`,
|
|
1507
1835
|
`${subAlias}.id`
|
|
1508
1836
|
);
|
|
1509
|
-
applyWhere(relation.
|
|
1837
|
+
applyWhere(relation.targetModel, query, subAlias, value2, aliases);
|
|
1510
1838
|
} else if (Array.isArray(value2)) {
|
|
1511
1839
|
query.whereIn(`${alias}.${key}`, value2);
|
|
1512
1840
|
} else {
|
|
@@ -1554,7 +1882,7 @@ var generatePermissions = (models, config) => {
|
|
|
1554
1882
|
};
|
|
1555
1883
|
var addPermissions = (models, permissions, links, block) => {
|
|
1556
1884
|
const { type } = links[links.length - 1];
|
|
1557
|
-
const model =
|
|
1885
|
+
const model = models.getModel(type, "entity");
|
|
1558
1886
|
for (const action of ACTIONS) {
|
|
1559
1887
|
if (action === "READ" || action in block) {
|
|
1560
1888
|
if (!permissions[type]) {
|
|
@@ -1579,13 +1907,13 @@ var addPermissions = (models, permissions, links, block) => {
|
|
|
1579
1907
|
reverse: true
|
|
1580
1908
|
};
|
|
1581
1909
|
} else {
|
|
1582
|
-
const
|
|
1583
|
-
if (!
|
|
1910
|
+
const reverseRelation = model.reverseRelationsByName[relation];
|
|
1911
|
+
if (!reverseRelation) {
|
|
1584
1912
|
throw new Error(`Relation ${relation} in model ${model.name} does not exist.`);
|
|
1585
1913
|
}
|
|
1586
1914
|
link = {
|
|
1587
|
-
type:
|
|
1588
|
-
foreignKey:
|
|
1915
|
+
type: reverseRelation.targetModel.name,
|
|
1916
|
+
foreignKey: reverseRelation.field.foreignKey
|
|
1589
1917
|
};
|
|
1590
1918
|
}
|
|
1591
1919
|
if (subBlock.WHERE) {
|
|
@@ -1730,13 +2058,18 @@ var applyFilters = (node, query, joins) => {
|
|
|
1730
2058
|
if (orderBy) {
|
|
1731
2059
|
applyOrderBy(node, orderBy, query);
|
|
1732
2060
|
}
|
|
2061
|
+
if (node.model.parent) {
|
|
2062
|
+
void query.where({
|
|
2063
|
+
[getColumn(node, "type")]: node.model.name
|
|
2064
|
+
});
|
|
2065
|
+
}
|
|
1733
2066
|
if (where) {
|
|
1734
2067
|
const ops = [];
|
|
1735
2068
|
applyWhere2(node, where, ops, joins);
|
|
1736
|
-
apply(query, ops);
|
|
2069
|
+
void apply(query, ops);
|
|
1737
2070
|
}
|
|
1738
2071
|
if (search) {
|
|
1739
|
-
applySearch(node, search, query);
|
|
2072
|
+
void applySearch(node, search, query);
|
|
1740
2073
|
}
|
|
1741
2074
|
};
|
|
1742
2075
|
var applyWhere2 = (node, where, ops, joins) => {
|
|
@@ -1748,34 +2081,34 @@ var applyWhere2 = (node, where, ops, joins) => {
|
|
|
1748
2081
|
if (!SPECIAL_FILTERS[filter]) {
|
|
1749
2082
|
throw new Error(`Invalid filter ${key}.`);
|
|
1750
2083
|
}
|
|
1751
|
-
ops.push(
|
|
1752
|
-
(query) => query.whereRaw(SPECIAL_FILTERS[filter], [`${node.shortTableAlias}.${actualKey}`, value2])
|
|
1753
|
-
);
|
|
2084
|
+
ops.push((query) => query.whereRaw(SPECIAL_FILTERS[filter], [getColumn(node, actualKey), value2]));
|
|
1754
2085
|
continue;
|
|
1755
2086
|
}
|
|
1756
|
-
const field =
|
|
1757
|
-
const fullKey = `${node.shortTableAlias}.${key}`;
|
|
2087
|
+
const field = node.model.getField(key);
|
|
1758
2088
|
if (field.kind === "relation") {
|
|
1759
|
-
const relation =
|
|
1760
|
-
const
|
|
2089
|
+
const relation = node.model.getRelation(field.name);
|
|
2090
|
+
const targetModel = relation.targetModel;
|
|
2091
|
+
const rootModel = targetModel.parentModel || targetModel;
|
|
2092
|
+
const rootTableAlias = `${node.model.name}__W__${key}`;
|
|
2093
|
+
const tableAlias = targetModel === rootModel ? rootTableAlias : `${node.model.name}__WS__${key}`;
|
|
1761
2094
|
const subNode = {
|
|
1762
2095
|
ctx: node.ctx,
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
foreignKey: relation.field.foreignKey
|
|
2096
|
+
rootModel,
|
|
2097
|
+
rootTableAlias,
|
|
2098
|
+
model: targetModel,
|
|
2099
|
+
tableAlias
|
|
1768
2100
|
};
|
|
1769
|
-
addJoin(joins, node.tableAlias, subNode.
|
|
2101
|
+
addJoin(joins, node.tableAlias, subNode.model.name, subNode.tableAlias, relation.field.foreignKey, "id");
|
|
1770
2102
|
applyWhere2(subNode, value2, ops, joins);
|
|
1771
2103
|
continue;
|
|
1772
2104
|
}
|
|
2105
|
+
const column = getColumn(node, key);
|
|
1773
2106
|
if (Array.isArray(value2)) {
|
|
1774
2107
|
if (field && field.list) {
|
|
1775
2108
|
ops.push(
|
|
1776
2109
|
(query) => ors(
|
|
1777
2110
|
query,
|
|
1778
|
-
value2.map((v) => (subQuery) => subQuery.whereRaw("? = ANY(??)", [v,
|
|
2111
|
+
value2.map((v) => (subQuery) => subQuery.whereRaw("? = ANY(??)", [v, column]))
|
|
1779
2112
|
)
|
|
1780
2113
|
);
|
|
1781
2114
|
continue;
|
|
@@ -1784,25 +2117,25 @@ var applyWhere2 = (node, where, ops, joins) => {
|
|
|
1784
2117
|
if (value2.some((v) => v !== null)) {
|
|
1785
2118
|
ops.push(
|
|
1786
2119
|
(query) => ors(query, [
|
|
1787
|
-
(subQuery) => subQuery.whereIn(
|
|
1788
|
-
(subQuery) => subQuery.whereNull(
|
|
2120
|
+
(subQuery) => subQuery.whereIn(column, value2.filter((v) => v !== null)),
|
|
2121
|
+
(subQuery) => subQuery.whereNull(column)
|
|
1789
2122
|
])
|
|
1790
2123
|
);
|
|
1791
2124
|
continue;
|
|
1792
2125
|
}
|
|
1793
|
-
ops.push((query) => query.whereNull(
|
|
2126
|
+
ops.push((query) => query.whereNull(column));
|
|
1794
2127
|
continue;
|
|
1795
2128
|
}
|
|
1796
|
-
ops.push((query) => query.whereIn(
|
|
2129
|
+
ops.push((query) => query.whereIn(column, value2));
|
|
1797
2130
|
continue;
|
|
1798
2131
|
}
|
|
1799
|
-
ops.push((query) => query.where({ [
|
|
2132
|
+
ops.push((query) => query.where({ [column]: value2 }));
|
|
1800
2133
|
}
|
|
1801
2134
|
};
|
|
1802
2135
|
var applySearch = (node, search, query) => ors(
|
|
1803
2136
|
query,
|
|
1804
2137
|
node.model.fields.filter(({ searchable }) => searchable).map(
|
|
1805
|
-
({ name: name2 }) => (query2) => query2.whereILike(
|
|
2138
|
+
({ name: name2 }) => (query2) => query2.whereILike(getColumn(node, name2), `%${search}%`)
|
|
1806
2139
|
)
|
|
1807
2140
|
);
|
|
1808
2141
|
var applyOrderBy = (node, orderBy, query) => {
|
|
@@ -1813,7 +2146,7 @@ var applyOrderBy = (node, orderBy, query) => {
|
|
|
1813
2146
|
}
|
|
1814
2147
|
const key = keys[0];
|
|
1815
2148
|
const value2 = vals[key];
|
|
1816
|
-
query.orderBy(
|
|
2149
|
+
void query.orderBy(getColumn(node, key), value2);
|
|
1817
2150
|
}
|
|
1818
2151
|
};
|
|
1819
2152
|
|
|
@@ -1829,19 +2162,26 @@ var getResolverNode = ({
|
|
|
1829
2162
|
ctx,
|
|
1830
2163
|
node,
|
|
1831
2164
|
tableAlias,
|
|
2165
|
+
rootTableAlias,
|
|
2166
|
+
resultAlias,
|
|
1832
2167
|
baseTypeDefinition,
|
|
1833
2168
|
typeName
|
|
1834
|
-
}) =>
|
|
1835
|
-
ctx,
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
2169
|
+
}) => {
|
|
2170
|
+
const model = ctx.models.getModel(typeName, "entity");
|
|
2171
|
+
const rootModel = model.parent ? ctx.models.getModel(model.parent, "entity") : model;
|
|
2172
|
+
return {
|
|
2173
|
+
ctx,
|
|
2174
|
+
rootModel,
|
|
2175
|
+
rootTableAlias,
|
|
2176
|
+
model,
|
|
2177
|
+
tableAlias,
|
|
2178
|
+
resultAlias,
|
|
2179
|
+
baseTypeDefinition,
|
|
2180
|
+
baseModel: ctx.models.entities.find((model2) => model2.name === baseTypeDefinition.name.value),
|
|
2181
|
+
typeDefinition: getType(ctx.info.schema, typeName),
|
|
2182
|
+
selectionSet: get(node.selectionSet, "selections")
|
|
2183
|
+
};
|
|
2184
|
+
};
|
|
1845
2185
|
var getRootFieldNode = ({
|
|
1846
2186
|
ctx,
|
|
1847
2187
|
node,
|
|
@@ -1850,14 +2190,17 @@ var getRootFieldNode = ({
|
|
|
1850
2190
|
const fieldName = node.name.value;
|
|
1851
2191
|
const fieldDefinition = summonByKey(baseTypeDefinition.fields || [], "name.value", fieldName);
|
|
1852
2192
|
const typeName = getTypeName(fieldDefinition.type);
|
|
2193
|
+
const model = ctx.models.getModel(typeName, "entity");
|
|
2194
|
+
const rootModel = model.parent ? ctx.models.getModel(model.parent, "entity") : model;
|
|
1853
2195
|
return {
|
|
1854
2196
|
ctx,
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
2197
|
+
rootModel,
|
|
2198
|
+
rootTableAlias: rootModel.name,
|
|
2199
|
+
model,
|
|
2200
|
+
tableAlias: model.name,
|
|
2201
|
+
resultAlias: rootModel.name,
|
|
1858
2202
|
baseTypeDefinition,
|
|
1859
2203
|
typeDefinition: getType(ctx.info.schema, typeName),
|
|
1860
|
-
model: summonByName(ctx.models, typeName),
|
|
1861
2204
|
selectionSet: get(node.selectionSet, "selections"),
|
|
1862
2205
|
field: node,
|
|
1863
2206
|
fieldDefinition,
|
|
@@ -1876,7 +2219,9 @@ var getInlineFragments = (node) => node.selectionSet.filter(isInlineFragmentNode
|
|
|
1876
2219
|
(subNode) => getResolverNode({
|
|
1877
2220
|
ctx: node.ctx,
|
|
1878
2221
|
node: subNode,
|
|
2222
|
+
rootTableAlias: node.rootTableAlias,
|
|
1879
2223
|
tableAlias: node.tableAlias + "__" + getFragmentTypeName(subNode),
|
|
2224
|
+
resultAlias: node.resultAlias,
|
|
1880
2225
|
baseTypeDefinition: node.baseTypeDefinition,
|
|
1881
2226
|
typeName: getFragmentTypeName(subNode)
|
|
1882
2227
|
})
|
|
@@ -1885,7 +2230,9 @@ var getFragmentSpreads = (node) => node.selectionSet.filter(isFragmentSpreadNode
|
|
|
1885
2230
|
(subNode) => getResolverNode({
|
|
1886
2231
|
ctx: node.ctx,
|
|
1887
2232
|
node: node.ctx.info.fragments[subNode.name.value],
|
|
2233
|
+
rootTableAlias: node.rootTableAlias,
|
|
1888
2234
|
tableAlias: node.tableAlias,
|
|
2235
|
+
resultAlias: node.resultAlias,
|
|
1889
2236
|
baseTypeDefinition: node.baseTypeDefinition,
|
|
1890
2237
|
typeName: node.model.name
|
|
1891
2238
|
})
|
|
@@ -1899,44 +2246,90 @@ var getJoins = (node, toMany) => {
|
|
|
1899
2246
|
const fieldNameOrAlias = getNameOrAlias(subNode);
|
|
1900
2247
|
const fieldDefinition = summonByKey(baseTypeDefinition.fields || [], "name.value", fieldName);
|
|
1901
2248
|
const typeName = getTypeName(fieldDefinition.type);
|
|
1902
|
-
if (isObjectModel(
|
|
2249
|
+
if (isObjectModel(ctx.models.getModel(typeName))) {
|
|
1903
2250
|
continue;
|
|
1904
2251
|
}
|
|
1905
|
-
const baseModel =
|
|
1906
|
-
|
|
1907
|
-
if (
|
|
1908
|
-
|
|
1909
|
-
if (!reverseRelation) {
|
|
1910
|
-
continue;
|
|
1911
|
-
}
|
|
1912
|
-
foreignKey = reverseRelation.foreignKey;
|
|
1913
|
-
} else {
|
|
1914
|
-
const modelField = baseModel.fieldsByName[fieldName];
|
|
1915
|
-
if (modelField?.kind !== "relation") {
|
|
1916
|
-
continue;
|
|
1917
|
-
}
|
|
1918
|
-
foreignKey = modelField.foreignKey;
|
|
2252
|
+
const baseModel = ctx.models.getModel(baseTypeDefinition.name.value, "entity");
|
|
2253
|
+
const relation = (toMany ? baseModel.reverseRelationsByName : baseModel.relationsByName)[fieldName];
|
|
2254
|
+
if (!relation) {
|
|
2255
|
+
continue;
|
|
1919
2256
|
}
|
|
1920
2257
|
const tableAlias = node.tableAlias + "__" + fieldNameOrAlias;
|
|
2258
|
+
const model = ctx.models.getModel(typeName, "entity");
|
|
2259
|
+
const rootModel = model;
|
|
1921
2260
|
nodes.push({
|
|
1922
2261
|
ctx,
|
|
1923
|
-
|
|
2262
|
+
rootModel,
|
|
2263
|
+
rootTableAlias: tableAlias,
|
|
2264
|
+
model,
|
|
1924
2265
|
tableAlias,
|
|
1925
|
-
|
|
2266
|
+
resultAlias: tableAlias,
|
|
1926
2267
|
baseTypeDefinition,
|
|
1927
2268
|
baseModel,
|
|
1928
2269
|
typeDefinition: getType(ctx.info.schema, typeName),
|
|
1929
|
-
model: summonByName(ctx.models, typeName),
|
|
1930
2270
|
selectionSet: get(subNode.selectionSet, "selections"),
|
|
1931
2271
|
field: subNode,
|
|
1932
2272
|
fieldDefinition,
|
|
1933
|
-
|
|
2273
|
+
relation,
|
|
2274
|
+
foreignKey: relation.field.foreignKey,
|
|
1934
2275
|
isList: isListType(fieldDefinition.type)
|
|
1935
2276
|
});
|
|
1936
2277
|
}
|
|
1937
2278
|
return nodes;
|
|
1938
2279
|
};
|
|
1939
2280
|
|
|
2281
|
+
// src/resolvers/selects.ts
|
|
2282
|
+
var applySelects = (node, query, joins) => {
|
|
2283
|
+
void query.select(
|
|
2284
|
+
...[
|
|
2285
|
+
{ tableAlias: node.rootTableAlias, resultAlias: node.resultAlias, field: "id", fieldAlias: ID_ALIAS },
|
|
2286
|
+
...node.model.root ? [{ tableAlias: node.rootTableAlias, resultAlias: node.resultAlias, field: "type", fieldAlias: TYPE_ALIAS }] : [],
|
|
2287
|
+
...getSimpleFields(node).filter((fieldNode) => {
|
|
2288
|
+
const field = node.model.fieldsByName[fieldNode.name.value];
|
|
2289
|
+
if (!field || field.kind === "relation" || field.kind === "custom") {
|
|
2290
|
+
return false;
|
|
2291
|
+
}
|
|
2292
|
+
if (typeof field.queriable === "object" && !field.queriable.roles?.includes(node.ctx.user.role)) {
|
|
2293
|
+
throw new PermissionError(
|
|
2294
|
+
"READ",
|
|
2295
|
+
`${node.model.name}'s field "${field.name}"`,
|
|
2296
|
+
"field permission not available"
|
|
2297
|
+
);
|
|
2298
|
+
}
|
|
2299
|
+
return true;
|
|
2300
|
+
}).map((fieldNode) => {
|
|
2301
|
+
const field = node.model.getField(fieldNode.name.value);
|
|
2302
|
+
if (node.model.parent && !field.inherited) {
|
|
2303
|
+
addJoin(joins, node.rootTableAlias, node.model.name, node.tableAlias, "id", "id");
|
|
2304
|
+
}
|
|
2305
|
+
const fieldAlias = getNameOrAlias(fieldNode);
|
|
2306
|
+
if ([ID_ALIAS, TYPE_ALIAS].includes(fieldAlias)) {
|
|
2307
|
+
throw new UserInputError(`Keyword ${fieldAlias} is reserved by graphql-magic.`);
|
|
2308
|
+
}
|
|
2309
|
+
return {
|
|
2310
|
+
fieldNode,
|
|
2311
|
+
field: fieldNode.name.value,
|
|
2312
|
+
tableAlias: field.inherited ? node.rootTableAlias : node.tableAlias,
|
|
2313
|
+
resultAlias: node.resultAlias,
|
|
2314
|
+
fieldAlias
|
|
2315
|
+
};
|
|
2316
|
+
})
|
|
2317
|
+
].map(
|
|
2318
|
+
({ tableAlias, resultAlias, field, fieldAlias }) => `${node.ctx.aliases.getShort(tableAlias)}.${field} as ${node.ctx.aliases.getShort(resultAlias)}__${fieldAlias}`
|
|
2319
|
+
)
|
|
2320
|
+
);
|
|
2321
|
+
for (const subNode of getInlineFragments(node)) {
|
|
2322
|
+
applySelects(subNode, query, joins);
|
|
2323
|
+
}
|
|
2324
|
+
for (const subNode of getFragmentSpreads(node)) {
|
|
2325
|
+
applySelects(subNode, query, joins);
|
|
2326
|
+
}
|
|
2327
|
+
for (const subNode of getJoins(node, false)) {
|
|
2328
|
+
addJoin(joins, node.tableAlias, subNode.rootModel.name, subNode.rootTableAlias, subNode.foreignKey, "id");
|
|
2329
|
+
applySelects(subNode, query, joins);
|
|
2330
|
+
}
|
|
2331
|
+
};
|
|
2332
|
+
|
|
1940
2333
|
// src/resolvers/resolver.ts
|
|
1941
2334
|
var queryResolver = (_parent, _args, ctx, info) => resolve({ ...ctx, info, aliases: new AliasGenerator() });
|
|
1942
2335
|
var resolve = async (ctx, id) => {
|
|
@@ -1952,13 +2345,13 @@ var resolve = async (ctx, id) => {
|
|
|
1952
2345
|
});
|
|
1953
2346
|
const { query, verifiedPermissionStacks } = await buildQuery(node);
|
|
1954
2347
|
if (ctx.info.fieldName === "me") {
|
|
1955
|
-
query.where({ [
|
|
1956
|
-
}
|
|
1957
|
-
if (!node.isList) {
|
|
1958
|
-
query.limit(1);
|
|
2348
|
+
void query.where({ [getColumn(node, "id")]: node.ctx.user.id });
|
|
1959
2349
|
}
|
|
1960
2350
|
if (id) {
|
|
1961
|
-
query.where({ id });
|
|
2351
|
+
void query.where({ [getColumn(node, "id")]: id });
|
|
2352
|
+
}
|
|
2353
|
+
if (!node.isList) {
|
|
2354
|
+
void query.limit(1);
|
|
1962
2355
|
}
|
|
1963
2356
|
const raw = await query;
|
|
1964
2357
|
const res = hydrate(node, raw);
|
|
@@ -1973,20 +2366,19 @@ var resolve = async (ctx, id) => {
|
|
|
1973
2366
|
return res[0];
|
|
1974
2367
|
};
|
|
1975
2368
|
var buildQuery = async (node, parentVerifiedPermissionStacks) => {
|
|
1976
|
-
const
|
|
1977
|
-
const
|
|
1978
|
-
const joins = {};
|
|
2369
|
+
const query = node.ctx.knex.fromRaw(`"${node.rootModel.name}" as "${node.ctx.aliases.getShort(node.resultAlias)}"`);
|
|
2370
|
+
const joins = [];
|
|
1979
2371
|
applyFilters(node, query, joins);
|
|
1980
2372
|
applySelects(node, query, joins);
|
|
1981
2373
|
applyJoins(node.ctx.aliases, query, joins);
|
|
1982
2374
|
const tables = [
|
|
1983
|
-
[
|
|
1984
|
-
...
|
|
2375
|
+
[node.rootModel.name, node.rootTableAlias],
|
|
2376
|
+
...joins.map(({ table2Name, table2Alias }) => [table2Name, table2Alias])
|
|
1985
2377
|
];
|
|
1986
2378
|
const verifiedPermissionStacks = {};
|
|
1987
2379
|
for (const [table, alias] of tables) {
|
|
1988
2380
|
const verifiedPermissionStack = applyPermissions(
|
|
1989
|
-
ctx,
|
|
2381
|
+
node.ctx,
|
|
1990
2382
|
table,
|
|
1991
2383
|
node.ctx.aliases.getShort(alias),
|
|
1992
2384
|
query,
|
|
@@ -1999,39 +2391,6 @@ var buildQuery = async (node, parentVerifiedPermissionStacks) => {
|
|
|
1999
2391
|
}
|
|
2000
2392
|
return { query, verifiedPermissionStacks };
|
|
2001
2393
|
};
|
|
2002
|
-
var applySelects = (node, query, joins) => {
|
|
2003
|
-
query.select(
|
|
2004
|
-
...[
|
|
2005
|
-
{ field: "id", alias: ID_ALIAS },
|
|
2006
|
-
...getSimpleFields(node).filter((n) => {
|
|
2007
|
-
const field = node.model.fields.find(({ name: name2 }) => name2 === n.name.value);
|
|
2008
|
-
if (!field || field.kind === "relation" || field.kind === "custom") {
|
|
2009
|
-
return false;
|
|
2010
|
-
}
|
|
2011
|
-
if (typeof field.queriable === "object" && !field.queriable.roles?.includes(node.ctx.user.role)) {
|
|
2012
|
-
throw new PermissionError(
|
|
2013
|
-
"READ",
|
|
2014
|
-
`${node.model.name}'s field "${field.name}"`,
|
|
2015
|
-
"field permission not available"
|
|
2016
|
-
);
|
|
2017
|
-
}
|
|
2018
|
-
return true;
|
|
2019
|
-
}).map((n) => ({ field: n.name.value, alias: getNameOrAlias(n) }))
|
|
2020
|
-
].map(
|
|
2021
|
-
({ field, alias }) => `${node.shortTableAlias}.${field} as ${node.shortTableAlias}__${alias}`
|
|
2022
|
-
)
|
|
2023
|
-
);
|
|
2024
|
-
for (const subNode of getInlineFragments(node)) {
|
|
2025
|
-
applySelects(subNode, query, joins);
|
|
2026
|
-
}
|
|
2027
|
-
for (const subNode of getFragmentSpreads(node)) {
|
|
2028
|
-
applySelects(subNode, query, joins);
|
|
2029
|
-
}
|
|
2030
|
-
for (const subNode of getJoins(node, false)) {
|
|
2031
|
-
addJoin(joins, node.tableAlias, subNode.tableName, subNode.tableAlias, get(subNode, "foreignKey"), "id");
|
|
2032
|
-
applySelects(subNode, query, joins);
|
|
2033
|
-
}
|
|
2034
|
-
};
|
|
2035
2394
|
var applySubQueries = async (node, entries, parentVerifiedPermissionStacks) => {
|
|
2036
2395
|
if (!entries.length) {
|
|
2037
2396
|
return;
|
|
@@ -2048,10 +2407,12 @@ var applySubQueries = async (node, entries, parentVerifiedPermissionStacks) => {
|
|
|
2048
2407
|
const fieldName = getNameOrAlias(subNode.field);
|
|
2049
2408
|
const isList = isListType(subNode.fieldDefinition.type);
|
|
2050
2409
|
entries.forEach((entry) => entry[fieldName] = isList ? [] : null);
|
|
2051
|
-
const foreignKey =
|
|
2410
|
+
const foreignKey = subNode.foreignKey;
|
|
2052
2411
|
const { query, verifiedPermissionStacks } = await buildQuery(subNode, parentVerifiedPermissionStacks);
|
|
2412
|
+
const shortTableAlias = subNode.ctx.aliases.getShort(subNode.tableAlias);
|
|
2413
|
+
const shortResultAlias = subNode.ctx.aliases.getShort(subNode.resultAlias);
|
|
2053
2414
|
const queries = ids.map(
|
|
2054
|
-
(id) => query.clone().select(`${
|
|
2415
|
+
(id) => query.clone().select(`${shortTableAlias}.${foreignKey} as ${shortResultAlias}__${foreignKey}`).where({ [`${shortTableAlias}.${foreignKey}`]: id })
|
|
2055
2416
|
);
|
|
2056
2417
|
const rawChildren = (await Promise.all(queries)).flat();
|
|
2057
2418
|
const children = hydrate(subNode, rawChildren);
|
|
@@ -2095,7 +2456,7 @@ var mutationResolver = async (_parent, args2, partialCtx, info) => {
|
|
|
2095
2456
|
return await partialCtx.knex.transaction(async (knex) => {
|
|
2096
2457
|
const [, mutation, modelName] = it(info.fieldName.match(/^(create|update|delete|restore)(.+)$/));
|
|
2097
2458
|
const ctx = { ...partialCtx, knex, info, aliases: new AliasGenerator() };
|
|
2098
|
-
const model =
|
|
2459
|
+
const model = ctx.models.getModel(modelName, "entity");
|
|
2099
2460
|
switch (mutation) {
|
|
2100
2461
|
case "create":
|
|
2101
2462
|
return await create(model, args2, ctx);
|
|
@@ -2113,12 +2474,32 @@ var create = async (model, { data: input2 }, ctx) => {
|
|
|
2113
2474
|
normalizedInput.id = (0, import_uuid.v4)();
|
|
2114
2475
|
normalizedInput.createdAt = ctx.now;
|
|
2115
2476
|
normalizedInput.createdById = ctx.user.id;
|
|
2477
|
+
if (model.parent) {
|
|
2478
|
+
normalizedInput.type = model.name;
|
|
2479
|
+
}
|
|
2116
2480
|
sanitize(ctx, model, normalizedInput);
|
|
2117
2481
|
await checkCanWrite(ctx, model, normalizedInput, "CREATE");
|
|
2118
2482
|
await ctx.handleUploads?.(normalizedInput);
|
|
2119
2483
|
const data = { prev: {}, input: input2, normalizedInput, next: normalizedInput };
|
|
2120
2484
|
await ctx.mutationHook?.(model, "create", "before", data, ctx);
|
|
2121
|
-
|
|
2485
|
+
if (model.parent) {
|
|
2486
|
+
const rootInput = {};
|
|
2487
|
+
const childInput = { id: normalizedInput.id };
|
|
2488
|
+
for (const field of model.fields) {
|
|
2489
|
+
const columnName = field.kind === "relation" ? `${field.name}Id` : field.name;
|
|
2490
|
+
if (columnName in normalizedInput) {
|
|
2491
|
+
if (field.inherited) {
|
|
2492
|
+
rootInput[columnName] = normalizedInput[columnName];
|
|
2493
|
+
} else {
|
|
2494
|
+
childInput[columnName] = normalizedInput[columnName];
|
|
2495
|
+
}
|
|
2496
|
+
}
|
|
2497
|
+
}
|
|
2498
|
+
await ctx.knex(model.parent).insert(rootInput);
|
|
2499
|
+
await ctx.knex(model.name).insert(childInput);
|
|
2500
|
+
} else {
|
|
2501
|
+
await ctx.knex(model.name).insert(normalizedInput);
|
|
2502
|
+
}
|
|
2122
2503
|
await createRevision(model, normalizedInput, ctx);
|
|
2123
2504
|
await ctx.mutationHook?.(model, "create", "after", data, ctx);
|
|
2124
2505
|
return await resolve(ctx, normalizedInput.id);
|
|
@@ -2141,7 +2522,28 @@ var update = async (model, { where, data: input2 }, ctx) => {
|
|
|
2141
2522
|
const next = { ...prev, ...normalizedInput };
|
|
2142
2523
|
const data = { prev, input: input2, normalizedInput, next };
|
|
2143
2524
|
await ctx.mutationHook?.(model, "update", "before", data, ctx);
|
|
2144
|
-
|
|
2525
|
+
if (model.parent) {
|
|
2526
|
+
const rootInput = {};
|
|
2527
|
+
const childInput = {};
|
|
2528
|
+
for (const field of model.fields) {
|
|
2529
|
+
const columnName = field.kind === "relation" ? `${field.name}Id` : field.name;
|
|
2530
|
+
if (columnName in normalizedInput) {
|
|
2531
|
+
if (field.inherited) {
|
|
2532
|
+
rootInput[columnName] = normalizedInput[columnName];
|
|
2533
|
+
} else {
|
|
2534
|
+
childInput[columnName] = normalizedInput[columnName];
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
if (Object.keys(rootInput).length) {
|
|
2539
|
+
await ctx.knex(model.parent).where({ id: prev.id }).update(rootInput);
|
|
2540
|
+
}
|
|
2541
|
+
if (Object.keys(childInput).length) {
|
|
2542
|
+
await ctx.knex(model.name).where({ id: prev.id }).update(childInput);
|
|
2543
|
+
}
|
|
2544
|
+
} else {
|
|
2545
|
+
await ctx.knex(model.name).where({ id: prev.id }).update(normalizedInput);
|
|
2546
|
+
}
|
|
2145
2547
|
await createRevision(model, next, ctx);
|
|
2146
2548
|
await ctx.mutationHook?.(model, "update", "after", data, ctx);
|
|
2147
2549
|
}
|
|
@@ -2151,7 +2553,8 @@ var del = async (model, { where, dryRun }, ctx) => {
|
|
|
2151
2553
|
if (Object.keys(where).length === 0) {
|
|
2152
2554
|
throw new Error(`No ${model.name} specified.`);
|
|
2153
2555
|
}
|
|
2154
|
-
const
|
|
2556
|
+
const rootModel = model.rootModel;
|
|
2557
|
+
const entity = await getEntityToMutate(ctx, rootModel, where, "DELETE");
|
|
2155
2558
|
if (entity.deleted) {
|
|
2156
2559
|
throw new ForbiddenError("Entity is already deleted.");
|
|
2157
2560
|
}
|
|
@@ -2190,10 +2593,9 @@ var del = async (model, { where, dryRun }, ctx) => {
|
|
|
2190
2593
|
}
|
|
2191
2594
|
}
|
|
2192
2595
|
for (const {
|
|
2193
|
-
|
|
2194
|
-
foreignKey,
|
|
2195
|
-
|
|
2196
|
-
} of currentModel.reverseRelations) {
|
|
2596
|
+
targetModel: descendantModel,
|
|
2597
|
+
field: { name: name2, foreignKey, onDelete }
|
|
2598
|
+
} of currentModel.reverseRelations.filter((reverseRelation) => !reverseRelation.field.inherited)) {
|
|
2197
2599
|
const query = ctx.knex(descendantModel.name).where({ [foreignKey]: entity2.id });
|
|
2198
2600
|
switch (onDelete) {
|
|
2199
2601
|
case "set-null": {
|
|
@@ -2235,7 +2637,7 @@ var del = async (model, { where, dryRun }, ctx) => {
|
|
|
2235
2637
|
}
|
|
2236
2638
|
}
|
|
2237
2639
|
};
|
|
2238
|
-
await deleteCascade(
|
|
2640
|
+
await deleteCascade(rootModel, entity);
|
|
2239
2641
|
for (const callback of [...beforeHooks, ...mutations, ...afterHooks]) {
|
|
2240
2642
|
await callback();
|
|
2241
2643
|
}
|
|
@@ -2252,7 +2654,8 @@ var restore = async (model, { where }, ctx) => {
|
|
|
2252
2654
|
if (Object.keys(where).length === 0) {
|
|
2253
2655
|
throw new Error(`No ${model.name} specified.`);
|
|
2254
2656
|
}
|
|
2255
|
-
const
|
|
2657
|
+
const rootModel = model.rootModel;
|
|
2658
|
+
const entity = await getEntityToMutate(ctx, rootModel, where, "RESTORE");
|
|
2256
2659
|
if (!entity.deleted) {
|
|
2257
2660
|
throw new ForbiddenError("Entity is not deleted.");
|
|
2258
2661
|
}
|
|
@@ -2279,9 +2682,10 @@ var restore = async (model, { where }, ctx) => {
|
|
|
2279
2682
|
await ctx.mutationHook(model, "restore", "after", data, ctx);
|
|
2280
2683
|
});
|
|
2281
2684
|
}
|
|
2282
|
-
for (const {
|
|
2283
|
-
|
|
2284
|
-
|
|
2685
|
+
for (const {
|
|
2686
|
+
targetModel: descendantModel,
|
|
2687
|
+
field: { foreignKey }
|
|
2688
|
+
} of currentModel.reverseRelations.filter((reverseRelation) => !reverseRelation.field.inherited).filter(({ targetModel: { deletable } }) => deletable)) {
|
|
2285
2689
|
const query = ctx.knex(descendantModel.name).where({ [foreignKey]: relatedEntity.id });
|
|
2286
2690
|
applyPermissions(ctx, descendantModel.name, descendantModel.name, query, "RESTORE");
|
|
2287
2691
|
const descendants = await query;
|
|
@@ -2290,7 +2694,7 @@ var restore = async (model, { where }, ctx) => {
|
|
|
2290
2694
|
}
|
|
2291
2695
|
}
|
|
2292
2696
|
};
|
|
2293
|
-
await restoreCascade(
|
|
2697
|
+
await restoreCascade(rootModel, entity);
|
|
2294
2698
|
for (const callback of [...beforeHooks, ...mutations, ...afterHooks]) {
|
|
2295
2699
|
await callback();
|
|
2296
2700
|
}
|
|
@@ -2298,24 +2702,37 @@ var restore = async (model, { where }, ctx) => {
|
|
|
2298
2702
|
};
|
|
2299
2703
|
var createRevision = async (model, data, ctx) => {
|
|
2300
2704
|
if (model.updatable) {
|
|
2301
|
-
const
|
|
2302
|
-
|
|
2303
|
-
|
|
2705
|
+
const revisionId = (0, import_uuid.v4)();
|
|
2706
|
+
const rootRevisionData = {
|
|
2707
|
+
id: revisionId,
|
|
2708
|
+
[`${typeToField(model.parent || model.name)}Id`]: data.id,
|
|
2304
2709
|
createdAt: ctx.now,
|
|
2305
2710
|
createdById: ctx.user.id
|
|
2306
2711
|
};
|
|
2307
2712
|
if (model.deletable) {
|
|
2308
|
-
|
|
2309
|
-
}
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2713
|
+
rootRevisionData.deleted = data.deleted || false;
|
|
2714
|
+
}
|
|
2715
|
+
const childRevisionData = { id: revisionId };
|
|
2716
|
+
for (const field of model.fields.filter(({ updatable }) => updatable)) {
|
|
2717
|
+
const col = field.kind === "relation" ? `${field.name}Id` : field.name;
|
|
2718
|
+
let value2;
|
|
2719
|
+
if (field.nonNull && (!(col in data) || col === void 0 || col === null)) {
|
|
2720
|
+
value2 = get(field, "defaultValue");
|
|
2721
|
+
} else {
|
|
2722
|
+
value2 = data[col];
|
|
2723
|
+
}
|
|
2724
|
+
if (!model.parent || field.inherited) {
|
|
2725
|
+
rootRevisionData[col] = value2;
|
|
2314
2726
|
} else {
|
|
2315
|
-
|
|
2727
|
+
childRevisionData[col] = value2;
|
|
2316
2728
|
}
|
|
2317
2729
|
}
|
|
2318
|
-
|
|
2730
|
+
if (model.parent) {
|
|
2731
|
+
await ctx.knex(`${model.parent}Revision`).insert(rootRevisionData);
|
|
2732
|
+
await ctx.knex(`${model.name}Revision`).insert(childRevisionData);
|
|
2733
|
+
} else {
|
|
2734
|
+
await ctx.knex(`${model.name}Revision`).insert(rootRevisionData);
|
|
2735
|
+
}
|
|
2319
2736
|
}
|
|
2320
2737
|
};
|
|
2321
2738
|
var sanitize = (ctx, model, data) => {
|
|
@@ -2332,7 +2749,7 @@ var sanitize = (ctx, model, data) => {
|
|
|
2332
2749
|
data[key] = data[key].endOf("day");
|
|
2333
2750
|
continue;
|
|
2334
2751
|
}
|
|
2335
|
-
if (
|
|
2752
|
+
if (field.list && field.kind === "enum" && Array.isArray(data[key])) {
|
|
2336
2753
|
data[key] = `{${data[key].join(",")}}`;
|
|
2337
2754
|
continue;
|
|
2338
2755
|
}
|
|
@@ -2346,30 +2763,37 @@ var getResolvers = (models) => ({
|
|
|
2346
2763
|
{
|
|
2347
2764
|
me: queryResolver
|
|
2348
2765
|
},
|
|
2349
|
-
...models.filter(({ queriable }) => queriable).map((model) => ({
|
|
2766
|
+
...models.entities.filter(({ queriable }) => queriable).map((model) => ({
|
|
2350
2767
|
[typeToField(model.name)]: queryResolver
|
|
2351
2768
|
})),
|
|
2352
|
-
...models.filter(({ listQueriable }) => listQueriable).map((model) => ({
|
|
2353
|
-
[
|
|
2769
|
+
...models.entities.filter(({ listQueriable }) => listQueriable).map((model) => ({
|
|
2770
|
+
[model.pluralField]: queryResolver
|
|
2354
2771
|
}))
|
|
2355
2772
|
]),
|
|
2356
2773
|
Mutation: merge2([
|
|
2357
|
-
...models.filter(({ creatable }) => creatable).map((model) => ({
|
|
2774
|
+
...models.entities.filter(not(isRootModel)).filter(({ creatable }) => creatable).map((model) => ({
|
|
2358
2775
|
[`create${model.name}`]: mutationResolver
|
|
2359
2776
|
})),
|
|
2360
|
-
...models.filter(({ updatable }) => updatable).map((model) => ({
|
|
2777
|
+
...models.entities.filter(not(isRootModel)).filter(({ updatable }) => updatable).map((model) => ({
|
|
2361
2778
|
[`update${model.name}`]: mutationResolver
|
|
2362
2779
|
})),
|
|
2363
|
-
...models.filter(({ deletable }) => deletable).map((model) => ({
|
|
2780
|
+
...models.entities.filter(not(isRootModel)).filter(({ deletable }) => deletable).map((model) => ({
|
|
2364
2781
|
[`delete${model.name}`]: mutationResolver,
|
|
2365
2782
|
[`restore${model.name}`]: mutationResolver
|
|
2366
2783
|
}))
|
|
2367
|
-
])
|
|
2784
|
+
]),
|
|
2785
|
+
...Object.assign(
|
|
2786
|
+
{},
|
|
2787
|
+
...models.entities.filter(isRootModel).map((model) => ({
|
|
2788
|
+
[model.name]: {
|
|
2789
|
+
__resolveType: ({ TYPE }) => TYPE
|
|
2790
|
+
}
|
|
2791
|
+
}))
|
|
2792
|
+
)
|
|
2368
2793
|
});
|
|
2369
2794
|
|
|
2370
2795
|
// src/schema/generate.ts
|
|
2371
2796
|
var import_graphql5 = require("graphql");
|
|
2372
|
-
var import_flatMap2 = __toESM(require("lodash/flatMap"), 1);
|
|
2373
2797
|
|
|
2374
2798
|
// src/schema/utils.ts
|
|
2375
2799
|
var import_luxon = require("luxon");
|
|
@@ -2401,10 +2825,11 @@ var object = (nme, fds, interfaces, dvs) => ({
|
|
|
2401
2825
|
interfaces: interfaces && interfaces.map((i) => namedType(i)),
|
|
2402
2826
|
directives: directives(dvs)
|
|
2403
2827
|
});
|
|
2404
|
-
var iface = (nme, fds, dvs) => ({
|
|
2828
|
+
var iface = (nme, fds, interfaces, dvs) => ({
|
|
2405
2829
|
name: name(nme),
|
|
2406
2830
|
fields: fields(fds),
|
|
2407
2831
|
kind: "InterfaceTypeDefinition",
|
|
2832
|
+
interfaces: interfaces && interfaces.map((i) => namedType(i)),
|
|
2408
2833
|
directives: directives(dvs)
|
|
2409
2834
|
});
|
|
2410
2835
|
var inputValues = (fields2) => fields2.map(
|
|
@@ -2520,84 +2945,86 @@ var value = (val = null) => val === null ? {
|
|
|
2520
2945
|
};
|
|
2521
2946
|
|
|
2522
2947
|
// src/schema/generate.ts
|
|
2523
|
-
var generateDefinitions = (
|
|
2524
|
-
|
|
2948
|
+
var generateDefinitions = ({
|
|
2949
|
+
scalars,
|
|
2950
|
+
rawEnums,
|
|
2951
|
+
enums,
|
|
2952
|
+
inputs,
|
|
2953
|
+
interfaces,
|
|
2954
|
+
entities,
|
|
2955
|
+
objects
|
|
2956
|
+
}) => {
|
|
2525
2957
|
return [
|
|
2526
2958
|
// Predefined types
|
|
2527
|
-
enm(
|
|
2528
|
-
|
|
2529
|
-
scalar(
|
|
2530
|
-
...
|
|
2531
|
-
...
|
|
2532
|
-
...
|
|
2533
|
-
...
|
|
2534
|
-
|
|
2535
|
-
...rawModels.filter(isObjectModel).filter(
|
|
2536
|
-
(model) => models.some((m) => m.creatable && m.fields.some((f) => f.creatable && f.kind === "json" && f.type === model.name))
|
|
2959
|
+
...rawEnums.map((model) => enm(model.name, model.values)),
|
|
2960
|
+
...enums.map((model) => enm(model.name, model.values)),
|
|
2961
|
+
...scalars.map((model) => scalar(model.name)),
|
|
2962
|
+
...objects.filter(({ name: name2 }) => !["Query", "Mutation"].includes(name2)).map((model) => object(model.name, model.fields)),
|
|
2963
|
+
...interfaces.map(({ name: name2, fields: fields2 }) => iface(name2, fields2)),
|
|
2964
|
+
...inputs.map((model) => input(model.name, model.fields)),
|
|
2965
|
+
...objects.filter(
|
|
2966
|
+
(model) => entities.some((m) => m.creatable && m.fields.some((f) => f.creatable && f.kind === "json" && f.type === model.name))
|
|
2537
2967
|
).map((model) => input(`Create${model.name}`, model.fields)),
|
|
2538
|
-
...
|
|
2539
|
-
(model) =>
|
|
2968
|
+
...objects.filter(
|
|
2969
|
+
(model) => entities.some((m) => m.updatable && m.fields.some((f) => f.updatable && f.kind === "json" && f.type === model.name))
|
|
2540
2970
|
).map((model) => input(`Update${model.name}`, model.fields)),
|
|
2541
|
-
...(
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
...
|
|
2548
|
-
...field,
|
|
2549
|
-
type: field.type,
|
|
2550
|
-
args: [...field.args || []],
|
|
2551
|
-
directives: field.directives
|
|
2552
|
-
})),
|
|
2553
|
-
...model.reverseRelations.map(({ name: name2, field, model: model2 }) => ({
|
|
2554
|
-
name: name2,
|
|
2555
|
-
type: model2.name,
|
|
2556
|
-
list: !field.toOne,
|
|
2557
|
-
nonNull: !field.toOne,
|
|
2558
|
-
args: [
|
|
2559
|
-
{ name: "where", type: `${model2.name}Where` },
|
|
2560
|
-
...model2.fields.some(({ searchable }) => searchable) ? [{ name: "search", type: "String" }] : [],
|
|
2561
|
-
...model2.fields.some(({ orderable }) => orderable) ? [{ name: "orderBy", type: `${model2.name}OrderBy`, list: true }] : [],
|
|
2562
|
-
{ name: "limit", type: "Int" },
|
|
2563
|
-
{ name: "offset", type: "Int" }
|
|
2564
|
-
]
|
|
2565
|
-
}))
|
|
2566
|
-
],
|
|
2567
|
-
model.interfaces
|
|
2568
|
-
),
|
|
2569
|
-
input(`${model.name}Where`, [
|
|
2570
|
-
...model.fields.filter(({ kind, unique, filterable }) => (unique || filterable) && kind !== "relation").map((field) => ({
|
|
2571
|
-
name: field.name,
|
|
2971
|
+
...entities.flatMap((model) => {
|
|
2972
|
+
const types = [
|
|
2973
|
+
(isRootModel(model) ? iface : object)(
|
|
2974
|
+
model.name,
|
|
2975
|
+
[
|
|
2976
|
+
...model.fields.filter(isQueriableField).map((field) => ({
|
|
2977
|
+
...field,
|
|
2572
2978
|
type: field.type,
|
|
2573
|
-
|
|
2574
|
-
|
|
2979
|
+
args: [...field.args || []],
|
|
2980
|
+
directives: field.directives
|
|
2575
2981
|
})),
|
|
2576
|
-
...(
|
|
2577
|
-
model.fields.filter(({ comparable }) => comparable),
|
|
2578
|
-
(field) => [
|
|
2579
|
-
{ name: `${field.name}_GT`, type: field.type },
|
|
2580
|
-
{ name: `${field.name}_GTE`, type: field.type },
|
|
2581
|
-
{ name: `${field.name}_LT`, type: field.type },
|
|
2582
|
-
{ name: `${field.name}_LTE`, type: field.type }
|
|
2583
|
-
]
|
|
2584
|
-
),
|
|
2585
|
-
...model.fields.filter(isRelation).filter(({ filterable }) => filterable).map(({ name: name2, type }) => ({
|
|
2982
|
+
...model.reverseRelations.map(({ name: name2, field, targetModel }) => ({
|
|
2586
2983
|
name: name2,
|
|
2587
|
-
type:
|
|
2984
|
+
type: targetModel.name,
|
|
2985
|
+
list: !field.toOne,
|
|
2986
|
+
nonNull: !field.toOne,
|
|
2987
|
+
args: [
|
|
2988
|
+
{ name: "where", type: `${targetModel.name}Where` },
|
|
2989
|
+
...targetModel.fields.some(({ searchable }) => searchable) ? [{ name: "search", type: "String" }] : [],
|
|
2990
|
+
...targetModel.fields.some(({ orderable }) => orderable) ? [{ name: "orderBy", type: `${targetModel.name}OrderBy`, list: true }] : [],
|
|
2991
|
+
{ name: "limit", type: "Int" },
|
|
2992
|
+
{ name: "offset", type: "Int" }
|
|
2993
|
+
]
|
|
2588
2994
|
}))
|
|
2995
|
+
],
|
|
2996
|
+
[...model.parent ? [model.parent] : [], ...model.interfaces || []]
|
|
2997
|
+
),
|
|
2998
|
+
input(`${model.name}Where`, [
|
|
2999
|
+
...model.fields.filter(({ kind, unique, filterable }) => (unique || filterable) && kind !== "relation").map((field) => ({
|
|
3000
|
+
name: field.name,
|
|
3001
|
+
type: field.type,
|
|
3002
|
+
list: true,
|
|
3003
|
+
default: typeof field.filterable === "object" ? field.filterable.default : void 0
|
|
3004
|
+
})),
|
|
3005
|
+
...model.fields.filter(({ comparable }) => comparable).flatMap((field) => [
|
|
3006
|
+
{ name: `${field.name}_GT`, type: field.type },
|
|
3007
|
+
{ name: `${field.name}_GTE`, type: field.type },
|
|
3008
|
+
{ name: `${field.name}_LT`, type: field.type },
|
|
3009
|
+
{ name: `${field.name}_LTE`, type: field.type }
|
|
2589
3010
|
]),
|
|
3011
|
+
...model.fields.filter(isRelation).filter(({ filterable }) => filterable).map(({ name: name2, type }) => ({
|
|
3012
|
+
name: name2,
|
|
3013
|
+
type: `${type}Where`
|
|
3014
|
+
}))
|
|
3015
|
+
]),
|
|
3016
|
+
input(
|
|
3017
|
+
`${model.name}WhereUnique`,
|
|
3018
|
+
model.fields.filter(({ unique }) => unique).map((field) => ({ name: field.name, type: field.type }))
|
|
3019
|
+
),
|
|
3020
|
+
...model.fields.some(({ orderable }) => orderable) ? [
|
|
2590
3021
|
input(
|
|
2591
|
-
`${model.name}
|
|
2592
|
-
model.fields.filter(({
|
|
2593
|
-
)
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
model.fields.filter(({ orderable }) => orderable).map(({ name: name2 }) => ({ name: name2, type: "Order" }))
|
|
2598
|
-
)
|
|
2599
|
-
] : []
|
|
2600
|
-
];
|
|
3022
|
+
`${model.name}OrderBy`,
|
|
3023
|
+
model.fields.filter(({ orderable }) => orderable).map(({ name: name2 }) => ({ name: name2, type: "Order" }))
|
|
3024
|
+
)
|
|
3025
|
+
] : []
|
|
3026
|
+
];
|
|
3027
|
+
if (!isRootModel(model)) {
|
|
2601
3028
|
if (model.creatable) {
|
|
2602
3029
|
types.push(
|
|
2603
3030
|
input(
|
|
@@ -2627,15 +3054,15 @@ var generateDefinitions = (rawModels) => {
|
|
|
2627
3054
|
)
|
|
2628
3055
|
);
|
|
2629
3056
|
}
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
),
|
|
3057
|
+
}
|
|
3058
|
+
return types;
|
|
3059
|
+
}),
|
|
2633
3060
|
object("Query", [
|
|
2634
3061
|
{
|
|
2635
3062
|
name: "me",
|
|
2636
3063
|
type: "User"
|
|
2637
3064
|
},
|
|
2638
|
-
...
|
|
3065
|
+
...entities.filter(({ queriable }) => queriable).map(({ name: name2 }) => ({
|
|
2639
3066
|
name: typeToField(name2),
|
|
2640
3067
|
type: name2,
|
|
2641
3068
|
nonNull: true,
|
|
@@ -2647,8 +3074,8 @@ var generateDefinitions = (rawModels) => {
|
|
|
2647
3074
|
}
|
|
2648
3075
|
]
|
|
2649
3076
|
})),
|
|
2650
|
-
...
|
|
2651
|
-
name:
|
|
3077
|
+
...entities.filter(({ listQueriable }) => listQueriable).map((model) => ({
|
|
3078
|
+
name: model.pluralField,
|
|
2652
3079
|
type: model.name,
|
|
2653
3080
|
list: true,
|
|
2654
3081
|
nonNull: true,
|
|
@@ -2660,12 +3087,12 @@ var generateDefinitions = (rawModels) => {
|
|
|
2660
3087
|
{ name: "offset", type: "Int" }
|
|
2661
3088
|
]
|
|
2662
3089
|
})),
|
|
2663
|
-
...
|
|
3090
|
+
...objects.filter((model) => model.name === "Query").flatMap((model) => model.fields)
|
|
2664
3091
|
]),
|
|
2665
3092
|
object("Mutation", [
|
|
2666
|
-
...(
|
|
2667
|
-
|
|
2668
|
-
|
|
3093
|
+
...entities.flatMap((model) => {
|
|
3094
|
+
const mutations = [];
|
|
3095
|
+
if (!isRootModel(model)) {
|
|
2669
3096
|
if (model.creatable) {
|
|
2670
3097
|
mutations.push({
|
|
2671
3098
|
name: `create${model.name}`,
|
|
@@ -2729,14 +3156,14 @@ var generateDefinitions = (rawModels) => {
|
|
|
2729
3156
|
]
|
|
2730
3157
|
});
|
|
2731
3158
|
}
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
),
|
|
2735
|
-
...
|
|
3159
|
+
}
|
|
3160
|
+
return mutations;
|
|
3161
|
+
}),
|
|
3162
|
+
...objects.filter((model) => model.name === "Mutation").flatMap((model) => model.fields)
|
|
2736
3163
|
])
|
|
2737
3164
|
];
|
|
2738
3165
|
};
|
|
2739
|
-
var generate = (
|
|
3166
|
+
var generate = (models) => document(generateDefinitions(models));
|
|
2740
3167
|
var printSchema = (schema) => [
|
|
2741
3168
|
...schema.getDirectives().map((d) => d.astNode && (0, import_graphql5.print)(d.astNode)),
|
|
2742
3169
|
...Object.values(schema.getTypeMap()).filter((t) => !t.name.match(/^__/)).sort((a, b) => a.name > b.name ? 1 : -1).map((t) => t.astNode && (0, import_graphql5.print)(t.astNode))
|
|
@@ -2747,13 +3174,27 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql5.buildAST
|
|
|
2747
3174
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2748
3175
|
0 && (module.exports = {
|
|
2749
3176
|
AliasGenerator,
|
|
3177
|
+
EntityModel,
|
|
3178
|
+
EnumModel,
|
|
2750
3179
|
ForbiddenError,
|
|
2751
3180
|
GraphQLError,
|
|
2752
3181
|
ID_ALIAS,
|
|
3182
|
+
InputModel,
|
|
3183
|
+
InterfaceModel,
|
|
3184
|
+
ManyToManyRelation,
|
|
2753
3185
|
MigrationGenerator,
|
|
3186
|
+
Model,
|
|
3187
|
+
Models,
|
|
3188
|
+
NormalRelation,
|
|
2754
3189
|
NotFoundError,
|
|
3190
|
+
ObjectModel,
|
|
2755
3191
|
PermissionError,
|
|
3192
|
+
RawEnumModel,
|
|
3193
|
+
Relation,
|
|
3194
|
+
ReverseRelation,
|
|
2756
3195
|
SPECIAL_FILTERS,
|
|
3196
|
+
ScalarModel,
|
|
3197
|
+
TYPE_ALIAS,
|
|
2757
3198
|
UserInputError,
|
|
2758
3199
|
actionableRelations,
|
|
2759
3200
|
addJoin,
|
|
@@ -2762,6 +3203,7 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql5.buildAST
|
|
|
2762
3203
|
applyFilters,
|
|
2763
3204
|
applyJoins,
|
|
2764
3205
|
applyPermissions,
|
|
3206
|
+
applySelects,
|
|
2765
3207
|
args,
|
|
2766
3208
|
checkCanWrite,
|
|
2767
3209
|
directive,
|
|
@@ -2779,6 +3221,8 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql5.buildAST
|
|
|
2779
3221
|
generateMutations,
|
|
2780
3222
|
generatePermissions,
|
|
2781
3223
|
get,
|
|
3224
|
+
getColumn,
|
|
3225
|
+
getColumnName,
|
|
2782
3226
|
getEditEntityRelationsQuery,
|
|
2783
3227
|
getEntityListQuery,
|
|
2784
3228
|
getEntityQuery,
|
|
@@ -2789,16 +3233,8 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql5.buildAST
|
|
|
2789
3233
|
getInlineFragments,
|
|
2790
3234
|
getJoins,
|
|
2791
3235
|
getLabel,
|
|
2792
|
-
getManyToManyRelation,
|
|
2793
|
-
getManyToManyRelations,
|
|
2794
3236
|
getManyToManyRelationsQuery,
|
|
2795
3237
|
getMigrationDate,
|
|
2796
|
-
getModelLabel,
|
|
2797
|
-
getModelLabelPlural,
|
|
2798
|
-
getModelPlural,
|
|
2799
|
-
getModelPluralField,
|
|
2800
|
-
getModelSlug,
|
|
2801
|
-
getModels,
|
|
2802
3238
|
getMutationQuery,
|
|
2803
3239
|
getNameOrAlias,
|
|
2804
3240
|
getPermissionStack,
|
|
@@ -2811,6 +3247,7 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql5.buildAST
|
|
|
2811
3247
|
getTypeName,
|
|
2812
3248
|
getUpdateEntityQuery,
|
|
2813
3249
|
gql,
|
|
3250
|
+
hasName,
|
|
2814
3251
|
hash,
|
|
2815
3252
|
hydrate,
|
|
2816
3253
|
iface,
|
|
@@ -2822,12 +3259,14 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql5.buildAST
|
|
|
2822
3259
|
isCustomField,
|
|
2823
3260
|
isEntityModel,
|
|
2824
3261
|
isEnum,
|
|
2825
|
-
isEnumList,
|
|
2826
3262
|
isEnumModel,
|
|
2827
3263
|
isFieldNode,
|
|
2828
3264
|
isFragmentSpreadNode,
|
|
3265
|
+
isInTable,
|
|
3266
|
+
isInherited,
|
|
2829
3267
|
isInlineFragmentNode,
|
|
2830
3268
|
isInputModel,
|
|
3269
|
+
isInterfaceModel,
|
|
2831
3270
|
isListType,
|
|
2832
3271
|
isObjectModel,
|
|
2833
3272
|
isPrimitive,
|
|
@@ -2835,16 +3274,20 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql5.buildAST
|
|
|
2835
3274
|
isQueriableField,
|
|
2836
3275
|
isRawEnumModel,
|
|
2837
3276
|
isRelation,
|
|
3277
|
+
isRootModel,
|
|
2838
3278
|
isScalarModel,
|
|
2839
3279
|
isSimpleField,
|
|
2840
3280
|
isToOneRelation,
|
|
2841
3281
|
isUpdatable,
|
|
2842
3282
|
isUpdatableBy,
|
|
3283
|
+
isUpdatableField,
|
|
3284
|
+
isUpdatableModel,
|
|
2843
3285
|
isVisible,
|
|
2844
3286
|
isVisibleRelation,
|
|
2845
3287
|
it,
|
|
2846
3288
|
list,
|
|
2847
3289
|
merge,
|
|
3290
|
+
modelNeedsTable,
|
|
2848
3291
|
mutationResolver,
|
|
2849
3292
|
name,
|
|
2850
3293
|
namedType,
|
|
@@ -2854,6 +3297,7 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql5.buildAST
|
|
|
2854
3297
|
normalizeValueByTypeDefinition,
|
|
2855
3298
|
not,
|
|
2856
3299
|
object,
|
|
3300
|
+
or,
|
|
2857
3301
|
ors,
|
|
2858
3302
|
printSchema,
|
|
2859
3303
|
printSchemaFromDocument,
|