@smartive/graphql-magic 9.1.3 → 11.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 +1 -6
- package/README.md +1 -1
- package/dist/bin/gqm.cjs +676 -324
- package/dist/cjs/index.cjs +1016 -561
- 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/errors.d.ts +1 -1
- package/dist/esm/errors.js +2 -2
- package/dist/esm/errors.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 +19 -12
- 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 +16 -16
- 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 +44 -81
- package/src/context.ts +1 -2
- package/src/db/generate.ts +41 -41
- package/src/errors.ts +2 -2
- 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 +34 -16
- 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 +78 -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"));
|
|
402
499
|
}
|
|
403
|
-
return models;
|
|
404
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;
|
|
680
|
+
}
|
|
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 Get${model.name}Entity ($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,`);
|
|
@@ -1244,15 +1552,17 @@ var UserInputError = class extends GraphQLError {
|
|
|
1244
1552
|
}
|
|
1245
1553
|
};
|
|
1246
1554
|
var PermissionError = class extends ForbiddenError {
|
|
1247
|
-
constructor(action, what, why) {
|
|
1248
|
-
super(`
|
|
1555
|
+
constructor(role, action, what, why) {
|
|
1556
|
+
super(`Role ${role} does not have sufficient permissions to ${action.toLowerCase()} ${what} (${why}).`);
|
|
1249
1557
|
}
|
|
1250
1558
|
};
|
|
1251
1559
|
|
|
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(
|
|
@@ -1420,7 +1744,11 @@ var getEntityToMutate = async (ctx, model, where, action) => {
|
|
|
1420
1744
|
console.error(
|
|
1421
1745
|
`Permission error: ${Object.entries(where).map(([key, value2]) => `${key}: ${value2}`).join(", ")}`
|
|
1422
1746
|
);
|
|
1423
|
-
throw new PermissionError(action, `this ${model.name}`, "no available permissions applied");
|
|
1747
|
+
throw new PermissionError(ctx.user.role, action, `this ${model.name}`, "no available permissions applied");
|
|
1748
|
+
}
|
|
1749
|
+
if (model.parent) {
|
|
1750
|
+
const subEntity = await ctx.knex(model.name).where({ id: entity.id }).first();
|
|
1751
|
+
Object.assign(entity, subEntity);
|
|
1424
1752
|
}
|
|
1425
1753
|
return entity;
|
|
1426
1754
|
};
|
|
@@ -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(ctx.user.role, action, model.plural, "no applicable permissions");
|
|
1434
1762
|
}
|
|
1435
1763
|
const query = ctx.knex.select(1).first();
|
|
1436
1764
|
let linked = false;
|
|
@@ -1442,7 +1770,12 @@ var checkCanWrite = async (ctx, model, data, action) => {
|
|
|
1442
1770
|
}
|
|
1443
1771
|
const fieldPermissions = field[action === "CREATE" ? "creatable" : "updatable"];
|
|
1444
1772
|
if (fieldPermissions && typeof fieldPermissions === "object" && !fieldPermissions.roles?.includes(ctx.user.role)) {
|
|
1445
|
-
throw new PermissionError(
|
|
1773
|
+
throw new PermissionError(
|
|
1774
|
+
ctx.user.role,
|
|
1775
|
+
action,
|
|
1776
|
+
`this ${model.name}'s ${field.name}`,
|
|
1777
|
+
"field permission not available"
|
|
1778
|
+
);
|
|
1446
1779
|
}
|
|
1447
1780
|
linked = true;
|
|
1448
1781
|
const fieldPermissionStack = getPermissionStack(ctx, field.type, "LINK");
|
|
@@ -1451,7 +1784,12 @@ var checkCanWrite = async (ctx, model, data, action) => {
|
|
|
1451
1784
|
continue;
|
|
1452
1785
|
}
|
|
1453
1786
|
if (fieldPermissionStack === false || !fieldPermissionStack.length) {
|
|
1454
|
-
throw new PermissionError(
|
|
1787
|
+
throw new PermissionError(
|
|
1788
|
+
ctx.user.role,
|
|
1789
|
+
action,
|
|
1790
|
+
`this ${model.name}'s ${field.name}`,
|
|
1791
|
+
"no applicable permissions on data to link"
|
|
1792
|
+
);
|
|
1455
1793
|
}
|
|
1456
1794
|
ors(
|
|
1457
1795
|
query,
|
|
@@ -1463,10 +1801,10 @@ var checkCanWrite = async (ctx, model, data, action) => {
|
|
|
1463
1801
|
if (linked) {
|
|
1464
1802
|
const canMutate = await query;
|
|
1465
1803
|
if (!canMutate) {
|
|
1466
|
-
throw new PermissionError(action, `this ${model.name}`, "no linkable entities");
|
|
1804
|
+
throw new PermissionError(ctx.user.role, action, `this ${model.name}`, "no linkable entities");
|
|
1467
1805
|
}
|
|
1468
1806
|
} else if (action === "CREATE") {
|
|
1469
|
-
throw new PermissionError(action, `this ${model.name}`, "no linkable entities");
|
|
1807
|
+
throw new PermissionError(ctx.user.role, action, `this ${model.name}`, "no linkable entities");
|
|
1470
1808
|
}
|
|
1471
1809
|
};
|
|
1472
1810
|
var permissionLinkQuery = (ctx, subQuery, links, id) => {
|
|
@@ -1478,10 +1816,10 @@ var permissionLinkQuery = (ctx, subQuery, links, id) => {
|
|
|
1478
1816
|
subQuery.where({ [`${alias}.id`]: ctx.user.id });
|
|
1479
1817
|
}
|
|
1480
1818
|
if (where) {
|
|
1481
|
-
applyWhere(
|
|
1819
|
+
applyWhere(ctx.models.getModel(type, "entity"), subQuery, alias, where, aliases);
|
|
1482
1820
|
}
|
|
1483
1821
|
for (const { type: type2, foreignKey, reverse, where: where2 } of links) {
|
|
1484
|
-
const model =
|
|
1822
|
+
const model = ctx.models.getModel(type2, "entity");
|
|
1485
1823
|
const subAlias = aliases.getShort();
|
|
1486
1824
|
if (reverse) {
|
|
1487
1825
|
subQuery.leftJoin(`${type2} as ${subAlias}`, `${alias}.${foreignKey || "id"}`, `${subAlias}.id`);
|
|
@@ -1502,11 +1840,11 @@ var applyWhere = (model, query, alias, where, aliases) => {
|
|
|
1502
1840
|
if (relation) {
|
|
1503
1841
|
const subAlias = aliases.getShort();
|
|
1504
1842
|
query.leftJoin(
|
|
1505
|
-
`${relation.
|
|
1843
|
+
`${relation.targetModel.name} as ${subAlias}`,
|
|
1506
1844
|
`${alias}.${relation.field.foreignKey || `${relation.field.name}Id`}`,
|
|
1507
1845
|
`${subAlias}.id`
|
|
1508
1846
|
);
|
|
1509
|
-
applyWhere(relation.
|
|
1847
|
+
applyWhere(relation.targetModel, query, subAlias, value2, aliases);
|
|
1510
1848
|
} else if (Array.isArray(value2)) {
|
|
1511
1849
|
query.whereIn(`${alias}.${key}`, value2);
|
|
1512
1850
|
} else {
|
|
@@ -1554,7 +1892,7 @@ var generatePermissions = (models, config) => {
|
|
|
1554
1892
|
};
|
|
1555
1893
|
var addPermissions = (models, permissions, links, block) => {
|
|
1556
1894
|
const { type } = links[links.length - 1];
|
|
1557
|
-
const model =
|
|
1895
|
+
const model = models.getModel(type, "entity");
|
|
1558
1896
|
for (const action of ACTIONS) {
|
|
1559
1897
|
if (action === "READ" || action in block) {
|
|
1560
1898
|
if (!permissions[type]) {
|
|
@@ -1579,13 +1917,13 @@ var addPermissions = (models, permissions, links, block) => {
|
|
|
1579
1917
|
reverse: true
|
|
1580
1918
|
};
|
|
1581
1919
|
} else {
|
|
1582
|
-
const
|
|
1583
|
-
if (!
|
|
1920
|
+
const reverseRelation = model.reverseRelationsByName[relation];
|
|
1921
|
+
if (!reverseRelation) {
|
|
1584
1922
|
throw new Error(`Relation ${relation} in model ${model.name} does not exist.`);
|
|
1585
1923
|
}
|
|
1586
1924
|
link = {
|
|
1587
|
-
type:
|
|
1588
|
-
foreignKey:
|
|
1925
|
+
type: reverseRelation.targetModel.name,
|
|
1926
|
+
foreignKey: reverseRelation.field.foreignKey
|
|
1589
1927
|
};
|
|
1590
1928
|
}
|
|
1591
1929
|
if (subBlock.WHERE) {
|
|
@@ -1730,13 +2068,18 @@ var applyFilters = (node, query, joins) => {
|
|
|
1730
2068
|
if (orderBy) {
|
|
1731
2069
|
applyOrderBy(node, orderBy, query);
|
|
1732
2070
|
}
|
|
2071
|
+
if (node.model.parent) {
|
|
2072
|
+
void query.where({
|
|
2073
|
+
[getColumn(node, "type")]: node.model.name
|
|
2074
|
+
});
|
|
2075
|
+
}
|
|
1733
2076
|
if (where) {
|
|
1734
2077
|
const ops = [];
|
|
1735
2078
|
applyWhere2(node, where, ops, joins);
|
|
1736
|
-
apply(query, ops);
|
|
2079
|
+
void apply(query, ops);
|
|
1737
2080
|
}
|
|
1738
2081
|
if (search) {
|
|
1739
|
-
applySearch(node, search, query);
|
|
2082
|
+
void applySearch(node, search, query);
|
|
1740
2083
|
}
|
|
1741
2084
|
};
|
|
1742
2085
|
var applyWhere2 = (node, where, ops, joins) => {
|
|
@@ -1748,34 +2091,34 @@ var applyWhere2 = (node, where, ops, joins) => {
|
|
|
1748
2091
|
if (!SPECIAL_FILTERS[filter]) {
|
|
1749
2092
|
throw new Error(`Invalid filter ${key}.`);
|
|
1750
2093
|
}
|
|
1751
|
-
ops.push(
|
|
1752
|
-
(query) => query.whereRaw(SPECIAL_FILTERS[filter], [`${node.shortTableAlias}.${actualKey}`, value2])
|
|
1753
|
-
);
|
|
2094
|
+
ops.push((query) => query.whereRaw(SPECIAL_FILTERS[filter], [getColumn(node, actualKey), value2]));
|
|
1754
2095
|
continue;
|
|
1755
2096
|
}
|
|
1756
|
-
const field =
|
|
1757
|
-
const fullKey = `${node.shortTableAlias}.${key}`;
|
|
2097
|
+
const field = node.model.getField(key);
|
|
1758
2098
|
if (field.kind === "relation") {
|
|
1759
|
-
const relation =
|
|
1760
|
-
const
|
|
2099
|
+
const relation = node.model.getRelation(field.name);
|
|
2100
|
+
const targetModel = relation.targetModel;
|
|
2101
|
+
const rootModel = targetModel.parentModel || targetModel;
|
|
2102
|
+
const rootTableAlias = `${node.model.name}__W__${key}`;
|
|
2103
|
+
const tableAlias = targetModel === rootModel ? rootTableAlias : `${node.model.name}__WS__${key}`;
|
|
1761
2104
|
const subNode = {
|
|
1762
2105
|
ctx: node.ctx,
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
foreignKey: relation.field.foreignKey
|
|
2106
|
+
rootModel,
|
|
2107
|
+
rootTableAlias,
|
|
2108
|
+
model: targetModel,
|
|
2109
|
+
tableAlias
|
|
1768
2110
|
};
|
|
1769
|
-
addJoin(joins, node.tableAlias, subNode.
|
|
2111
|
+
addJoin(joins, node.tableAlias, subNode.model.name, subNode.tableAlias, relation.field.foreignKey, "id");
|
|
1770
2112
|
applyWhere2(subNode, value2, ops, joins);
|
|
1771
2113
|
continue;
|
|
1772
2114
|
}
|
|
2115
|
+
const column = getColumn(node, key);
|
|
1773
2116
|
if (Array.isArray(value2)) {
|
|
1774
2117
|
if (field && field.list) {
|
|
1775
2118
|
ops.push(
|
|
1776
2119
|
(query) => ors(
|
|
1777
2120
|
query,
|
|
1778
|
-
value2.map((v) => (subQuery) => subQuery.whereRaw("? = ANY(??)", [v,
|
|
2121
|
+
value2.map((v) => (subQuery) => subQuery.whereRaw("? = ANY(??)", [v, column]))
|
|
1779
2122
|
)
|
|
1780
2123
|
);
|
|
1781
2124
|
continue;
|
|
@@ -1784,25 +2127,25 @@ var applyWhere2 = (node, where, ops, joins) => {
|
|
|
1784
2127
|
if (value2.some((v) => v !== null)) {
|
|
1785
2128
|
ops.push(
|
|
1786
2129
|
(query) => ors(query, [
|
|
1787
|
-
(subQuery) => subQuery.whereIn(
|
|
1788
|
-
(subQuery) => subQuery.whereNull(
|
|
2130
|
+
(subQuery) => subQuery.whereIn(column, value2.filter((v) => v !== null)),
|
|
2131
|
+
(subQuery) => subQuery.whereNull(column)
|
|
1789
2132
|
])
|
|
1790
2133
|
);
|
|
1791
2134
|
continue;
|
|
1792
2135
|
}
|
|
1793
|
-
ops.push((query) => query.whereNull(
|
|
2136
|
+
ops.push((query) => query.whereNull(column));
|
|
1794
2137
|
continue;
|
|
1795
2138
|
}
|
|
1796
|
-
ops.push((query) => query.whereIn(
|
|
2139
|
+
ops.push((query) => query.whereIn(column, value2));
|
|
1797
2140
|
continue;
|
|
1798
2141
|
}
|
|
1799
|
-
ops.push((query) => query.where({ [
|
|
2142
|
+
ops.push((query) => query.where({ [column]: value2 }));
|
|
1800
2143
|
}
|
|
1801
2144
|
};
|
|
1802
2145
|
var applySearch = (node, search, query) => ors(
|
|
1803
2146
|
query,
|
|
1804
2147
|
node.model.fields.filter(({ searchable }) => searchable).map(
|
|
1805
|
-
({ name: name2 }) => (query2) => query2.whereILike(
|
|
2148
|
+
({ name: name2 }) => (query2) => query2.whereILike(getColumn(node, name2), `%${search}%`)
|
|
1806
2149
|
)
|
|
1807
2150
|
);
|
|
1808
2151
|
var applyOrderBy = (node, orderBy, query) => {
|
|
@@ -1813,7 +2156,7 @@ var applyOrderBy = (node, orderBy, query) => {
|
|
|
1813
2156
|
}
|
|
1814
2157
|
const key = keys[0];
|
|
1815
2158
|
const value2 = vals[key];
|
|
1816
|
-
query.orderBy(
|
|
2159
|
+
void query.orderBy(getColumn(node, key), value2);
|
|
1817
2160
|
}
|
|
1818
2161
|
};
|
|
1819
2162
|
|
|
@@ -1829,19 +2172,26 @@ var getResolverNode = ({
|
|
|
1829
2172
|
ctx,
|
|
1830
2173
|
node,
|
|
1831
2174
|
tableAlias,
|
|
2175
|
+
rootTableAlias,
|
|
2176
|
+
resultAlias,
|
|
1832
2177
|
baseTypeDefinition,
|
|
1833
2178
|
typeName
|
|
1834
|
-
}) =>
|
|
1835
|
-
ctx,
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
2179
|
+
}) => {
|
|
2180
|
+
const model = ctx.models.getModel(typeName, "entity");
|
|
2181
|
+
const rootModel = model.parent ? ctx.models.getModel(model.parent, "entity") : model;
|
|
2182
|
+
return {
|
|
2183
|
+
ctx,
|
|
2184
|
+
rootModel,
|
|
2185
|
+
rootTableAlias,
|
|
2186
|
+
model,
|
|
2187
|
+
tableAlias,
|
|
2188
|
+
resultAlias,
|
|
2189
|
+
baseTypeDefinition,
|
|
2190
|
+
baseModel: ctx.models.entities.find((model2) => model2.name === baseTypeDefinition.name.value),
|
|
2191
|
+
typeDefinition: getType(ctx.info.schema, typeName),
|
|
2192
|
+
selectionSet: get(node.selectionSet, "selections")
|
|
2193
|
+
};
|
|
2194
|
+
};
|
|
1845
2195
|
var getRootFieldNode = ({
|
|
1846
2196
|
ctx,
|
|
1847
2197
|
node,
|
|
@@ -1850,14 +2200,17 @@ var getRootFieldNode = ({
|
|
|
1850
2200
|
const fieldName = node.name.value;
|
|
1851
2201
|
const fieldDefinition = summonByKey(baseTypeDefinition.fields || [], "name.value", fieldName);
|
|
1852
2202
|
const typeName = getTypeName(fieldDefinition.type);
|
|
2203
|
+
const model = ctx.models.getModel(typeName, "entity");
|
|
2204
|
+
const rootModel = model.parent ? ctx.models.getModel(model.parent, "entity") : model;
|
|
1853
2205
|
return {
|
|
1854
2206
|
ctx,
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
2207
|
+
rootModel,
|
|
2208
|
+
rootTableAlias: rootModel.name,
|
|
2209
|
+
model,
|
|
2210
|
+
tableAlias: model.name,
|
|
2211
|
+
resultAlias: rootModel.name,
|
|
1858
2212
|
baseTypeDefinition,
|
|
1859
2213
|
typeDefinition: getType(ctx.info.schema, typeName),
|
|
1860
|
-
model: summonByName(ctx.models, typeName),
|
|
1861
2214
|
selectionSet: get(node.selectionSet, "selections"),
|
|
1862
2215
|
field: node,
|
|
1863
2216
|
fieldDefinition,
|
|
@@ -1876,7 +2229,9 @@ var getInlineFragments = (node) => node.selectionSet.filter(isInlineFragmentNode
|
|
|
1876
2229
|
(subNode) => getResolverNode({
|
|
1877
2230
|
ctx: node.ctx,
|
|
1878
2231
|
node: subNode,
|
|
2232
|
+
rootTableAlias: node.rootTableAlias,
|
|
1879
2233
|
tableAlias: node.tableAlias + "__" + getFragmentTypeName(subNode),
|
|
2234
|
+
resultAlias: node.resultAlias,
|
|
1880
2235
|
baseTypeDefinition: node.baseTypeDefinition,
|
|
1881
2236
|
typeName: getFragmentTypeName(subNode)
|
|
1882
2237
|
})
|
|
@@ -1885,7 +2240,9 @@ var getFragmentSpreads = (node) => node.selectionSet.filter(isFragmentSpreadNode
|
|
|
1885
2240
|
(subNode) => getResolverNode({
|
|
1886
2241
|
ctx: node.ctx,
|
|
1887
2242
|
node: node.ctx.info.fragments[subNode.name.value],
|
|
2243
|
+
rootTableAlias: node.rootTableAlias,
|
|
1888
2244
|
tableAlias: node.tableAlias,
|
|
2245
|
+
resultAlias: node.resultAlias,
|
|
1889
2246
|
baseTypeDefinition: node.baseTypeDefinition,
|
|
1890
2247
|
typeName: node.model.name
|
|
1891
2248
|
})
|
|
@@ -1899,44 +2256,91 @@ var getJoins = (node, toMany) => {
|
|
|
1899
2256
|
const fieldNameOrAlias = getNameOrAlias(subNode);
|
|
1900
2257
|
const fieldDefinition = summonByKey(baseTypeDefinition.fields || [], "name.value", fieldName);
|
|
1901
2258
|
const typeName = getTypeName(fieldDefinition.type);
|
|
1902
|
-
if (isObjectModel(
|
|
2259
|
+
if (isObjectModel(ctx.models.getModel(typeName))) {
|
|
1903
2260
|
continue;
|
|
1904
2261
|
}
|
|
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;
|
|
2262
|
+
const baseModel = ctx.models.getModel(baseTypeDefinition.name.value, "entity");
|
|
2263
|
+
const relation = (toMany ? baseModel.reverseRelationsByName : baseModel.relationsByName)[fieldName];
|
|
2264
|
+
if (!relation) {
|
|
2265
|
+
continue;
|
|
1919
2266
|
}
|
|
1920
2267
|
const tableAlias = node.tableAlias + "__" + fieldNameOrAlias;
|
|
2268
|
+
const model = ctx.models.getModel(typeName, "entity");
|
|
2269
|
+
const rootModel = model;
|
|
1921
2270
|
nodes.push({
|
|
1922
2271
|
ctx,
|
|
1923
|
-
|
|
2272
|
+
rootModel,
|
|
2273
|
+
rootTableAlias: tableAlias,
|
|
2274
|
+
model,
|
|
1924
2275
|
tableAlias,
|
|
1925
|
-
|
|
2276
|
+
resultAlias: tableAlias,
|
|
1926
2277
|
baseTypeDefinition,
|
|
1927
2278
|
baseModel,
|
|
1928
2279
|
typeDefinition: getType(ctx.info.schema, typeName),
|
|
1929
|
-
model: summonByName(ctx.models, typeName),
|
|
1930
2280
|
selectionSet: get(subNode.selectionSet, "selections"),
|
|
1931
2281
|
field: subNode,
|
|
1932
2282
|
fieldDefinition,
|
|
1933
|
-
|
|
2283
|
+
relation,
|
|
2284
|
+
foreignKey: relation.field.foreignKey,
|
|
1934
2285
|
isList: isListType(fieldDefinition.type)
|
|
1935
2286
|
});
|
|
1936
2287
|
}
|
|
1937
2288
|
return nodes;
|
|
1938
2289
|
};
|
|
1939
2290
|
|
|
2291
|
+
// src/resolvers/selects.ts
|
|
2292
|
+
var applySelects = (node, query, joins) => {
|
|
2293
|
+
void query.select(
|
|
2294
|
+
...[
|
|
2295
|
+
{ tableAlias: node.rootTableAlias, resultAlias: node.resultAlias, field: "id", fieldAlias: ID_ALIAS },
|
|
2296
|
+
...node.model.root ? [{ tableAlias: node.rootTableAlias, resultAlias: node.resultAlias, field: "type", fieldAlias: TYPE_ALIAS }] : [],
|
|
2297
|
+
...getSimpleFields(node).filter((fieldNode) => {
|
|
2298
|
+
const field = node.model.fieldsByName[fieldNode.name.value];
|
|
2299
|
+
if (!field || field.kind === "relation" || field.kind === "custom") {
|
|
2300
|
+
return false;
|
|
2301
|
+
}
|
|
2302
|
+
if (typeof field.queriable === "object" && !field.queriable.roles?.includes(node.ctx.user.role)) {
|
|
2303
|
+
throw new PermissionError(
|
|
2304
|
+
node.ctx.user.role,
|
|
2305
|
+
"READ",
|
|
2306
|
+
`${node.model.name}'s field "${field.name}"`,
|
|
2307
|
+
"field permission not available"
|
|
2308
|
+
);
|
|
2309
|
+
}
|
|
2310
|
+
return true;
|
|
2311
|
+
}).map((fieldNode) => {
|
|
2312
|
+
const field = node.model.getField(fieldNode.name.value);
|
|
2313
|
+
if (node.model.parent && !field.inherited) {
|
|
2314
|
+
addJoin(joins, node.rootTableAlias, node.model.name, node.tableAlias, "id", "id");
|
|
2315
|
+
}
|
|
2316
|
+
const fieldAlias = getNameOrAlias(fieldNode);
|
|
2317
|
+
if ([ID_ALIAS, TYPE_ALIAS].includes(fieldAlias)) {
|
|
2318
|
+
throw new UserInputError(`Keyword ${fieldAlias} is reserved by graphql-magic.`);
|
|
2319
|
+
}
|
|
2320
|
+
return {
|
|
2321
|
+
fieldNode,
|
|
2322
|
+
field: fieldNode.name.value,
|
|
2323
|
+
tableAlias: field.inherited ? node.rootTableAlias : node.tableAlias,
|
|
2324
|
+
resultAlias: node.resultAlias,
|
|
2325
|
+
fieldAlias
|
|
2326
|
+
};
|
|
2327
|
+
})
|
|
2328
|
+
].map(
|
|
2329
|
+
({ tableAlias, resultAlias, field, fieldAlias }) => `${node.ctx.aliases.getShort(tableAlias)}.${field} as ${node.ctx.aliases.getShort(resultAlias)}__${fieldAlias}`
|
|
2330
|
+
)
|
|
2331
|
+
);
|
|
2332
|
+
for (const subNode of getInlineFragments(node)) {
|
|
2333
|
+
applySelects(subNode, query, joins);
|
|
2334
|
+
}
|
|
2335
|
+
for (const subNode of getFragmentSpreads(node)) {
|
|
2336
|
+
applySelects(subNode, query, joins);
|
|
2337
|
+
}
|
|
2338
|
+
for (const subNode of getJoins(node, false)) {
|
|
2339
|
+
addJoin(joins, node.tableAlias, subNode.rootModel.name, subNode.rootTableAlias, subNode.foreignKey, "id");
|
|
2340
|
+
applySelects(subNode, query, joins);
|
|
2341
|
+
}
|
|
2342
|
+
};
|
|
2343
|
+
|
|
1940
2344
|
// src/resolvers/resolver.ts
|
|
1941
2345
|
var queryResolver = (_parent, _args, ctx, info) => resolve({ ...ctx, info, aliases: new AliasGenerator() });
|
|
1942
2346
|
var resolve = async (ctx, id) => {
|
|
@@ -1952,13 +2356,13 @@ var resolve = async (ctx, id) => {
|
|
|
1952
2356
|
});
|
|
1953
2357
|
const { query, verifiedPermissionStacks } = await buildQuery(node);
|
|
1954
2358
|
if (ctx.info.fieldName === "me") {
|
|
1955
|
-
query.where({ [
|
|
1956
|
-
}
|
|
1957
|
-
if (!node.isList) {
|
|
1958
|
-
query.limit(1);
|
|
2359
|
+
void query.where({ [getColumn(node, "id")]: node.ctx.user.id });
|
|
1959
2360
|
}
|
|
1960
2361
|
if (id) {
|
|
1961
|
-
query.where({ id });
|
|
2362
|
+
void query.where({ [getColumn(node, "id")]: id });
|
|
2363
|
+
}
|
|
2364
|
+
if (!node.isList) {
|
|
2365
|
+
void query.limit(1);
|
|
1962
2366
|
}
|
|
1963
2367
|
const raw = await query;
|
|
1964
2368
|
const res = hydrate(node, raw);
|
|
@@ -1973,20 +2377,19 @@ var resolve = async (ctx, id) => {
|
|
|
1973
2377
|
return res[0];
|
|
1974
2378
|
};
|
|
1975
2379
|
var buildQuery = async (node, parentVerifiedPermissionStacks) => {
|
|
1976
|
-
const
|
|
1977
|
-
const
|
|
1978
|
-
const joins = {};
|
|
2380
|
+
const query = node.ctx.knex.fromRaw(`"${node.rootModel.name}" as "${node.ctx.aliases.getShort(node.resultAlias)}"`);
|
|
2381
|
+
const joins = [];
|
|
1979
2382
|
applyFilters(node, query, joins);
|
|
1980
2383
|
applySelects(node, query, joins);
|
|
1981
2384
|
applyJoins(node.ctx.aliases, query, joins);
|
|
1982
2385
|
const tables = [
|
|
1983
|
-
[
|
|
1984
|
-
...
|
|
2386
|
+
[node.rootModel.name, node.rootTableAlias],
|
|
2387
|
+
...joins.map(({ table2Name, table2Alias }) => [table2Name, table2Alias])
|
|
1985
2388
|
];
|
|
1986
2389
|
const verifiedPermissionStacks = {};
|
|
1987
2390
|
for (const [table, alias] of tables) {
|
|
1988
2391
|
const verifiedPermissionStack = applyPermissions(
|
|
1989
|
-
ctx,
|
|
2392
|
+
node.ctx,
|
|
1990
2393
|
table,
|
|
1991
2394
|
node.ctx.aliases.getShort(alias),
|
|
1992
2395
|
query,
|
|
@@ -1999,39 +2402,6 @@ var buildQuery = async (node, parentVerifiedPermissionStacks) => {
|
|
|
1999
2402
|
}
|
|
2000
2403
|
return { query, verifiedPermissionStacks };
|
|
2001
2404
|
};
|
|
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
2405
|
var applySubQueries = async (node, entries, parentVerifiedPermissionStacks) => {
|
|
2036
2406
|
if (!entries.length) {
|
|
2037
2407
|
return;
|
|
@@ -2048,10 +2418,12 @@ var applySubQueries = async (node, entries, parentVerifiedPermissionStacks) => {
|
|
|
2048
2418
|
const fieldName = getNameOrAlias(subNode.field);
|
|
2049
2419
|
const isList = isListType(subNode.fieldDefinition.type);
|
|
2050
2420
|
entries.forEach((entry) => entry[fieldName] = isList ? [] : null);
|
|
2051
|
-
const foreignKey =
|
|
2421
|
+
const foreignKey = subNode.foreignKey;
|
|
2052
2422
|
const { query, verifiedPermissionStacks } = await buildQuery(subNode, parentVerifiedPermissionStacks);
|
|
2423
|
+
const shortTableAlias = subNode.ctx.aliases.getShort(subNode.tableAlias);
|
|
2424
|
+
const shortResultAlias = subNode.ctx.aliases.getShort(subNode.resultAlias);
|
|
2053
2425
|
const queries = ids.map(
|
|
2054
|
-
(id) => query.clone().select(`${
|
|
2426
|
+
(id) => query.clone().select(`${shortTableAlias}.${foreignKey} as ${shortResultAlias}__${foreignKey}`).where({ [`${shortTableAlias}.${foreignKey}`]: id })
|
|
2055
2427
|
);
|
|
2056
2428
|
const rawChildren = (await Promise.all(queries)).flat();
|
|
2057
2429
|
const children = hydrate(subNode, rawChildren);
|
|
@@ -2095,7 +2467,7 @@ var mutationResolver = async (_parent, args2, partialCtx, info) => {
|
|
|
2095
2467
|
return await partialCtx.knex.transaction(async (knex) => {
|
|
2096
2468
|
const [, mutation, modelName] = it(info.fieldName.match(/^(create|update|delete|restore)(.+)$/));
|
|
2097
2469
|
const ctx = { ...partialCtx, knex, info, aliases: new AliasGenerator() };
|
|
2098
|
-
const model =
|
|
2470
|
+
const model = ctx.models.getModel(modelName, "entity");
|
|
2099
2471
|
switch (mutation) {
|
|
2100
2472
|
case "create":
|
|
2101
2473
|
return await create(model, args2, ctx);
|
|
@@ -2113,12 +2485,32 @@ var create = async (model, { data: input2 }, ctx) => {
|
|
|
2113
2485
|
normalizedInput.id = (0, import_uuid.v4)();
|
|
2114
2486
|
normalizedInput.createdAt = ctx.now;
|
|
2115
2487
|
normalizedInput.createdById = ctx.user.id;
|
|
2488
|
+
if (model.parent) {
|
|
2489
|
+
normalizedInput.type = model.name;
|
|
2490
|
+
}
|
|
2116
2491
|
sanitize(ctx, model, normalizedInput);
|
|
2117
2492
|
await checkCanWrite(ctx, model, normalizedInput, "CREATE");
|
|
2118
2493
|
await ctx.handleUploads?.(normalizedInput);
|
|
2119
2494
|
const data = { prev: {}, input: input2, normalizedInput, next: normalizedInput };
|
|
2120
2495
|
await ctx.mutationHook?.(model, "create", "before", data, ctx);
|
|
2121
|
-
|
|
2496
|
+
if (model.parent) {
|
|
2497
|
+
const rootInput = {};
|
|
2498
|
+
const childInput = { id: normalizedInput.id };
|
|
2499
|
+
for (const field of model.fields) {
|
|
2500
|
+
const columnName = field.kind === "relation" ? `${field.name}Id` : field.name;
|
|
2501
|
+
if (columnName in normalizedInput) {
|
|
2502
|
+
if (field.inherited) {
|
|
2503
|
+
rootInput[columnName] = normalizedInput[columnName];
|
|
2504
|
+
} else {
|
|
2505
|
+
childInput[columnName] = normalizedInput[columnName];
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
await ctx.knex(model.parent).insert(rootInput);
|
|
2510
|
+
await ctx.knex(model.name).insert(childInput);
|
|
2511
|
+
} else {
|
|
2512
|
+
await ctx.knex(model.name).insert(normalizedInput);
|
|
2513
|
+
}
|
|
2122
2514
|
await createRevision(model, normalizedInput, ctx);
|
|
2123
2515
|
await ctx.mutationHook?.(model, "create", "after", data, ctx);
|
|
2124
2516
|
return await resolve(ctx, normalizedInput.id);
|
|
@@ -2141,7 +2533,28 @@ var update = async (model, { where, data: input2 }, ctx) => {
|
|
|
2141
2533
|
const next = { ...prev, ...normalizedInput };
|
|
2142
2534
|
const data = { prev, input: input2, normalizedInput, next };
|
|
2143
2535
|
await ctx.mutationHook?.(model, "update", "before", data, ctx);
|
|
2144
|
-
|
|
2536
|
+
if (model.parent) {
|
|
2537
|
+
const rootInput = {};
|
|
2538
|
+
const childInput = {};
|
|
2539
|
+
for (const field of model.fields) {
|
|
2540
|
+
const columnName = field.kind === "relation" ? `${field.name}Id` : field.name;
|
|
2541
|
+
if (columnName in normalizedInput) {
|
|
2542
|
+
if (field.inherited) {
|
|
2543
|
+
rootInput[columnName] = normalizedInput[columnName];
|
|
2544
|
+
} else {
|
|
2545
|
+
childInput[columnName] = normalizedInput[columnName];
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
if (Object.keys(rootInput).length) {
|
|
2550
|
+
await ctx.knex(model.parent).where({ id: prev.id }).update(rootInput);
|
|
2551
|
+
}
|
|
2552
|
+
if (Object.keys(childInput).length) {
|
|
2553
|
+
await ctx.knex(model.name).where({ id: prev.id }).update(childInput);
|
|
2554
|
+
}
|
|
2555
|
+
} else {
|
|
2556
|
+
await ctx.knex(model.name).where({ id: prev.id }).update(normalizedInput);
|
|
2557
|
+
}
|
|
2145
2558
|
await createRevision(model, next, ctx);
|
|
2146
2559
|
await ctx.mutationHook?.(model, "update", "after", data, ctx);
|
|
2147
2560
|
}
|
|
@@ -2151,7 +2564,8 @@ var del = async (model, { where, dryRun }, ctx) => {
|
|
|
2151
2564
|
if (Object.keys(where).length === 0) {
|
|
2152
2565
|
throw new Error(`No ${model.name} specified.`);
|
|
2153
2566
|
}
|
|
2154
|
-
const
|
|
2567
|
+
const rootModel = model.rootModel;
|
|
2568
|
+
const entity = await getEntityToMutate(ctx, rootModel, where, "DELETE");
|
|
2155
2569
|
if (entity.deleted) {
|
|
2156
2570
|
throw new ForbiddenError("Entity is already deleted.");
|
|
2157
2571
|
}
|
|
@@ -2190,10 +2604,9 @@ var del = async (model, { where, dryRun }, ctx) => {
|
|
|
2190
2604
|
}
|
|
2191
2605
|
}
|
|
2192
2606
|
for (const {
|
|
2193
|
-
|
|
2194
|
-
foreignKey,
|
|
2195
|
-
|
|
2196
|
-
} of currentModel.reverseRelations) {
|
|
2607
|
+
targetModel: descendantModel,
|
|
2608
|
+
field: { name: name2, foreignKey, onDelete }
|
|
2609
|
+
} of currentModel.reverseRelations.filter((reverseRelation) => !reverseRelation.field.inherited)) {
|
|
2197
2610
|
const query = ctx.knex(descendantModel.name).where({ [foreignKey]: entity2.id });
|
|
2198
2611
|
switch (onDelete) {
|
|
2199
2612
|
case "set-null": {
|
|
@@ -2235,7 +2648,7 @@ var del = async (model, { where, dryRun }, ctx) => {
|
|
|
2235
2648
|
}
|
|
2236
2649
|
}
|
|
2237
2650
|
};
|
|
2238
|
-
await deleteCascade(
|
|
2651
|
+
await deleteCascade(rootModel, entity);
|
|
2239
2652
|
for (const callback of [...beforeHooks, ...mutations, ...afterHooks]) {
|
|
2240
2653
|
await callback();
|
|
2241
2654
|
}
|
|
@@ -2252,7 +2665,8 @@ var restore = async (model, { where }, ctx) => {
|
|
|
2252
2665
|
if (Object.keys(where).length === 0) {
|
|
2253
2666
|
throw new Error(`No ${model.name} specified.`);
|
|
2254
2667
|
}
|
|
2255
|
-
const
|
|
2668
|
+
const rootModel = model.rootModel;
|
|
2669
|
+
const entity = await getEntityToMutate(ctx, rootModel, where, "RESTORE");
|
|
2256
2670
|
if (!entity.deleted) {
|
|
2257
2671
|
throw new ForbiddenError("Entity is not deleted.");
|
|
2258
2672
|
}
|
|
@@ -2279,9 +2693,10 @@ var restore = async (model, { where }, ctx) => {
|
|
|
2279
2693
|
await ctx.mutationHook(model, "restore", "after", data, ctx);
|
|
2280
2694
|
});
|
|
2281
2695
|
}
|
|
2282
|
-
for (const {
|
|
2283
|
-
|
|
2284
|
-
|
|
2696
|
+
for (const {
|
|
2697
|
+
targetModel: descendantModel,
|
|
2698
|
+
field: { foreignKey }
|
|
2699
|
+
} of currentModel.reverseRelations.filter((reverseRelation) => !reverseRelation.field.inherited).filter(({ targetModel: { deletable } }) => deletable)) {
|
|
2285
2700
|
const query = ctx.knex(descendantModel.name).where({ [foreignKey]: relatedEntity.id });
|
|
2286
2701
|
applyPermissions(ctx, descendantModel.name, descendantModel.name, query, "RESTORE");
|
|
2287
2702
|
const descendants = await query;
|
|
@@ -2290,7 +2705,7 @@ var restore = async (model, { where }, ctx) => {
|
|
|
2290
2705
|
}
|
|
2291
2706
|
}
|
|
2292
2707
|
};
|
|
2293
|
-
await restoreCascade(
|
|
2708
|
+
await restoreCascade(rootModel, entity);
|
|
2294
2709
|
for (const callback of [...beforeHooks, ...mutations, ...afterHooks]) {
|
|
2295
2710
|
await callback();
|
|
2296
2711
|
}
|
|
@@ -2298,24 +2713,37 @@ var restore = async (model, { where }, ctx) => {
|
|
|
2298
2713
|
};
|
|
2299
2714
|
var createRevision = async (model, data, ctx) => {
|
|
2300
2715
|
if (model.updatable) {
|
|
2301
|
-
const
|
|
2302
|
-
|
|
2303
|
-
|
|
2716
|
+
const revisionId = (0, import_uuid.v4)();
|
|
2717
|
+
const rootRevisionData = {
|
|
2718
|
+
id: revisionId,
|
|
2719
|
+
[`${typeToField(model.parent || model.name)}Id`]: data.id,
|
|
2304
2720
|
createdAt: ctx.now,
|
|
2305
2721
|
createdById: ctx.user.id
|
|
2306
2722
|
};
|
|
2307
2723
|
if (model.deletable) {
|
|
2308
|
-
|
|
2309
|
-
}
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2724
|
+
rootRevisionData.deleted = data.deleted || false;
|
|
2725
|
+
}
|
|
2726
|
+
const childRevisionData = { id: revisionId };
|
|
2727
|
+
for (const field of model.fields.filter(({ updatable }) => updatable)) {
|
|
2728
|
+
const col = field.kind === "relation" ? `${field.name}Id` : field.name;
|
|
2729
|
+
let value2;
|
|
2730
|
+
if (field.nonNull && (!(col in data) || col === void 0 || col === null)) {
|
|
2731
|
+
value2 = get(field, "defaultValue");
|
|
2314
2732
|
} else {
|
|
2315
|
-
|
|
2733
|
+
value2 = data[col];
|
|
2316
2734
|
}
|
|
2735
|
+
if (!model.parent || field.inherited) {
|
|
2736
|
+
rootRevisionData[col] = value2;
|
|
2737
|
+
} else {
|
|
2738
|
+
childRevisionData[col] = value2;
|
|
2739
|
+
}
|
|
2740
|
+
}
|
|
2741
|
+
if (model.parent) {
|
|
2742
|
+
await ctx.knex(`${model.parent}Revision`).insert(rootRevisionData);
|
|
2743
|
+
await ctx.knex(`${model.name}Revision`).insert(childRevisionData);
|
|
2744
|
+
} else {
|
|
2745
|
+
await ctx.knex(`${model.name}Revision`).insert(rootRevisionData);
|
|
2317
2746
|
}
|
|
2318
|
-
await ctx.knex(`${model.name}Revision`).insert(revisionData);
|
|
2319
2747
|
}
|
|
2320
2748
|
};
|
|
2321
2749
|
var sanitize = (ctx, model, data) => {
|
|
@@ -2332,7 +2760,7 @@ var sanitize = (ctx, model, data) => {
|
|
|
2332
2760
|
data[key] = data[key].endOf("day");
|
|
2333
2761
|
continue;
|
|
2334
2762
|
}
|
|
2335
|
-
if (
|
|
2763
|
+
if (field.list && field.kind === "enum" && Array.isArray(data[key])) {
|
|
2336
2764
|
data[key] = `{${data[key].join(",")}}`;
|
|
2337
2765
|
continue;
|
|
2338
2766
|
}
|
|
@@ -2346,30 +2774,37 @@ var getResolvers = (models) => ({
|
|
|
2346
2774
|
{
|
|
2347
2775
|
me: queryResolver
|
|
2348
2776
|
},
|
|
2349
|
-
...models.filter(({ queriable }) => queriable).map((model) => ({
|
|
2777
|
+
...models.entities.filter(({ queriable }) => queriable).map((model) => ({
|
|
2350
2778
|
[typeToField(model.name)]: queryResolver
|
|
2351
2779
|
})),
|
|
2352
|
-
...models.filter(({ listQueriable }) => listQueriable).map((model) => ({
|
|
2353
|
-
[
|
|
2780
|
+
...models.entities.filter(({ listQueriable }) => listQueriable).map((model) => ({
|
|
2781
|
+
[model.pluralField]: queryResolver
|
|
2354
2782
|
}))
|
|
2355
2783
|
]),
|
|
2356
2784
|
Mutation: merge2([
|
|
2357
|
-
...models.filter(({ creatable }) => creatable).map((model) => ({
|
|
2785
|
+
...models.entities.filter(not(isRootModel)).filter(({ creatable }) => creatable).map((model) => ({
|
|
2358
2786
|
[`create${model.name}`]: mutationResolver
|
|
2359
2787
|
})),
|
|
2360
|
-
...models.filter(({ updatable }) => updatable).map((model) => ({
|
|
2788
|
+
...models.entities.filter(not(isRootModel)).filter(({ updatable }) => updatable).map((model) => ({
|
|
2361
2789
|
[`update${model.name}`]: mutationResolver
|
|
2362
2790
|
})),
|
|
2363
|
-
...models.filter(({ deletable }) => deletable).map((model) => ({
|
|
2791
|
+
...models.entities.filter(not(isRootModel)).filter(({ deletable }) => deletable).map((model) => ({
|
|
2364
2792
|
[`delete${model.name}`]: mutationResolver,
|
|
2365
2793
|
[`restore${model.name}`]: mutationResolver
|
|
2366
2794
|
}))
|
|
2367
|
-
])
|
|
2795
|
+
]),
|
|
2796
|
+
...Object.assign(
|
|
2797
|
+
{},
|
|
2798
|
+
...models.entities.filter(isRootModel).map((model) => ({
|
|
2799
|
+
[model.name]: {
|
|
2800
|
+
__resolveType: ({ TYPE }) => TYPE
|
|
2801
|
+
}
|
|
2802
|
+
}))
|
|
2803
|
+
)
|
|
2368
2804
|
});
|
|
2369
2805
|
|
|
2370
2806
|
// src/schema/generate.ts
|
|
2371
2807
|
var import_graphql5 = require("graphql");
|
|
2372
|
-
var import_flatMap2 = __toESM(require("lodash/flatMap"), 1);
|
|
2373
2808
|
|
|
2374
2809
|
// src/schema/utils.ts
|
|
2375
2810
|
var import_luxon = require("luxon");
|
|
@@ -2401,10 +2836,11 @@ var object = (nme, fds, interfaces, dvs) => ({
|
|
|
2401
2836
|
interfaces: interfaces && interfaces.map((i) => namedType(i)),
|
|
2402
2837
|
directives: directives(dvs)
|
|
2403
2838
|
});
|
|
2404
|
-
var iface = (nme, fds, dvs) => ({
|
|
2839
|
+
var iface = (nme, fds, interfaces, dvs) => ({
|
|
2405
2840
|
name: name(nme),
|
|
2406
2841
|
fields: fields(fds),
|
|
2407
2842
|
kind: "InterfaceTypeDefinition",
|
|
2843
|
+
interfaces: interfaces && interfaces.map((i) => namedType(i)),
|
|
2408
2844
|
directives: directives(dvs)
|
|
2409
2845
|
});
|
|
2410
2846
|
var inputValues = (fields2) => fields2.map(
|
|
@@ -2520,84 +2956,86 @@ var value = (val = null) => val === null ? {
|
|
|
2520
2956
|
};
|
|
2521
2957
|
|
|
2522
2958
|
// src/schema/generate.ts
|
|
2523
|
-
var generateDefinitions = (
|
|
2524
|
-
|
|
2959
|
+
var generateDefinitions = ({
|
|
2960
|
+
scalars,
|
|
2961
|
+
rawEnums,
|
|
2962
|
+
enums,
|
|
2963
|
+
inputs,
|
|
2964
|
+
interfaces,
|
|
2965
|
+
entities,
|
|
2966
|
+
objects
|
|
2967
|
+
}) => {
|
|
2525
2968
|
return [
|
|
2526
2969
|
// 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))
|
|
2970
|
+
...rawEnums.map((model) => enm(model.name, model.values)),
|
|
2971
|
+
...enums.map((model) => enm(model.name, model.values)),
|
|
2972
|
+
...scalars.map((model) => scalar(model.name)),
|
|
2973
|
+
...objects.filter(({ name: name2 }) => !["Query", "Mutation"].includes(name2)).map((model) => object(model.name, model.fields)),
|
|
2974
|
+
...interfaces.map(({ name: name2, fields: fields2 }) => iface(name2, fields2)),
|
|
2975
|
+
...inputs.map((model) => input(model.name, model.fields)),
|
|
2976
|
+
...objects.filter(
|
|
2977
|
+
(model) => entities.some((m) => m.creatable && m.fields.some((f) => f.creatable && f.kind === "json" && f.type === model.name))
|
|
2537
2978
|
).map((model) => input(`Create${model.name}`, model.fields)),
|
|
2538
|
-
...
|
|
2539
|
-
(model) =>
|
|
2979
|
+
...objects.filter(
|
|
2980
|
+
(model) => entities.some((m) => m.updatable && m.fields.some((f) => f.updatable && f.kind === "json" && f.type === model.name))
|
|
2540
2981
|
).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,
|
|
2982
|
+
...entities.flatMap((model) => {
|
|
2983
|
+
const types = [
|
|
2984
|
+
(isRootModel(model) ? iface : object)(
|
|
2985
|
+
model.name,
|
|
2986
|
+
[
|
|
2987
|
+
...model.fields.filter(isQueriableField).map((field) => ({
|
|
2988
|
+
...field,
|
|
2572
2989
|
type: field.type,
|
|
2573
|
-
|
|
2574
|
-
|
|
2990
|
+
args: [...field.args || []],
|
|
2991
|
+
directives: field.directives
|
|
2575
2992
|
})),
|
|
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 }) => ({
|
|
2993
|
+
...model.reverseRelations.map(({ name: name2, field, targetModel }) => ({
|
|
2586
2994
|
name: name2,
|
|
2587
|
-
type:
|
|
2995
|
+
type: targetModel.name,
|
|
2996
|
+
list: !field.toOne,
|
|
2997
|
+
nonNull: !field.toOne,
|
|
2998
|
+
args: [
|
|
2999
|
+
{ name: "where", type: `${targetModel.name}Where` },
|
|
3000
|
+
...targetModel.fields.some(({ searchable }) => searchable) ? [{ name: "search", type: "String" }] : [],
|
|
3001
|
+
...targetModel.fields.some(({ orderable }) => orderable) ? [{ name: "orderBy", type: `${targetModel.name}OrderBy`, list: true }] : [],
|
|
3002
|
+
{ name: "limit", type: "Int" },
|
|
3003
|
+
{ name: "offset", type: "Int" }
|
|
3004
|
+
]
|
|
2588
3005
|
}))
|
|
3006
|
+
],
|
|
3007
|
+
[...model.parent ? [model.parent] : [], ...model.interfaces || []]
|
|
3008
|
+
),
|
|
3009
|
+
input(`${model.name}Where`, [
|
|
3010
|
+
...model.fields.filter(({ kind, unique, filterable }) => (unique || filterable) && kind !== "relation").map((field) => ({
|
|
3011
|
+
name: field.name,
|
|
3012
|
+
type: field.type,
|
|
3013
|
+
list: true,
|
|
3014
|
+
default: typeof field.filterable === "object" ? field.filterable.default : void 0
|
|
3015
|
+
})),
|
|
3016
|
+
...model.fields.filter(({ comparable }) => comparable).flatMap((field) => [
|
|
3017
|
+
{ name: `${field.name}_GT`, type: field.type },
|
|
3018
|
+
{ name: `${field.name}_GTE`, type: field.type },
|
|
3019
|
+
{ name: `${field.name}_LT`, type: field.type },
|
|
3020
|
+
{ name: `${field.name}_LTE`, type: field.type }
|
|
2589
3021
|
]),
|
|
3022
|
+
...model.fields.filter(isRelation).filter(({ filterable }) => filterable).map(({ name: name2, type }) => ({
|
|
3023
|
+
name: name2,
|
|
3024
|
+
type: `${type}Where`
|
|
3025
|
+
}))
|
|
3026
|
+
]),
|
|
3027
|
+
input(
|
|
3028
|
+
`${model.name}WhereUnique`,
|
|
3029
|
+
model.fields.filter(({ unique }) => unique).map((field) => ({ name: field.name, type: field.type }))
|
|
3030
|
+
),
|
|
3031
|
+
...model.fields.some(({ orderable }) => orderable) ? [
|
|
2590
3032
|
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
|
-
];
|
|
3033
|
+
`${model.name}OrderBy`,
|
|
3034
|
+
model.fields.filter(({ orderable }) => orderable).map(({ name: name2 }) => ({ name: name2, type: "Order" }))
|
|
3035
|
+
)
|
|
3036
|
+
] : []
|
|
3037
|
+
];
|
|
3038
|
+
if (!isRootModel(model)) {
|
|
2601
3039
|
if (model.creatable) {
|
|
2602
3040
|
types.push(
|
|
2603
3041
|
input(
|
|
@@ -2627,15 +3065,15 @@ var generateDefinitions = (rawModels) => {
|
|
|
2627
3065
|
)
|
|
2628
3066
|
);
|
|
2629
3067
|
}
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
),
|
|
3068
|
+
}
|
|
3069
|
+
return types;
|
|
3070
|
+
}),
|
|
2633
3071
|
object("Query", [
|
|
2634
3072
|
{
|
|
2635
3073
|
name: "me",
|
|
2636
3074
|
type: "User"
|
|
2637
3075
|
},
|
|
2638
|
-
...
|
|
3076
|
+
...entities.filter(({ queriable }) => queriable).map(({ name: name2 }) => ({
|
|
2639
3077
|
name: typeToField(name2),
|
|
2640
3078
|
type: name2,
|
|
2641
3079
|
nonNull: true,
|
|
@@ -2647,8 +3085,8 @@ var generateDefinitions = (rawModels) => {
|
|
|
2647
3085
|
}
|
|
2648
3086
|
]
|
|
2649
3087
|
})),
|
|
2650
|
-
...
|
|
2651
|
-
name:
|
|
3088
|
+
...entities.filter(({ listQueriable }) => listQueriable).map((model) => ({
|
|
3089
|
+
name: model.pluralField,
|
|
2652
3090
|
type: model.name,
|
|
2653
3091
|
list: true,
|
|
2654
3092
|
nonNull: true,
|
|
@@ -2660,12 +3098,12 @@ var generateDefinitions = (rawModels) => {
|
|
|
2660
3098
|
{ name: "offset", type: "Int" }
|
|
2661
3099
|
]
|
|
2662
3100
|
})),
|
|
2663
|
-
...
|
|
3101
|
+
...objects.filter((model) => model.name === "Query").flatMap((model) => model.fields)
|
|
2664
3102
|
]),
|
|
2665
3103
|
object("Mutation", [
|
|
2666
|
-
...(
|
|
2667
|
-
|
|
2668
|
-
|
|
3104
|
+
...entities.flatMap((model) => {
|
|
3105
|
+
const mutations = [];
|
|
3106
|
+
if (!isRootModel(model)) {
|
|
2669
3107
|
if (model.creatable) {
|
|
2670
3108
|
mutations.push({
|
|
2671
3109
|
name: `create${model.name}`,
|
|
@@ -2729,14 +3167,14 @@ var generateDefinitions = (rawModels) => {
|
|
|
2729
3167
|
]
|
|
2730
3168
|
});
|
|
2731
3169
|
}
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
),
|
|
2735
|
-
...
|
|
3170
|
+
}
|
|
3171
|
+
return mutations;
|
|
3172
|
+
}),
|
|
3173
|
+
...objects.filter((model) => model.name === "Mutation").flatMap((model) => model.fields)
|
|
2736
3174
|
])
|
|
2737
3175
|
];
|
|
2738
3176
|
};
|
|
2739
|
-
var generate = (
|
|
3177
|
+
var generate = (models) => document(generateDefinitions(models));
|
|
2740
3178
|
var printSchema = (schema) => [
|
|
2741
3179
|
...schema.getDirectives().map((d) => d.astNode && (0, import_graphql5.print)(d.astNode)),
|
|
2742
3180
|
...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 +3185,27 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql5.buildAST
|
|
|
2747
3185
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2748
3186
|
0 && (module.exports = {
|
|
2749
3187
|
AliasGenerator,
|
|
3188
|
+
EntityModel,
|
|
3189
|
+
EnumModel,
|
|
2750
3190
|
ForbiddenError,
|
|
2751
3191
|
GraphQLError,
|
|
2752
3192
|
ID_ALIAS,
|
|
3193
|
+
InputModel,
|
|
3194
|
+
InterfaceModel,
|
|
3195
|
+
ManyToManyRelation,
|
|
2753
3196
|
MigrationGenerator,
|
|
3197
|
+
Model,
|
|
3198
|
+
Models,
|
|
3199
|
+
NormalRelation,
|
|
2754
3200
|
NotFoundError,
|
|
3201
|
+
ObjectModel,
|
|
2755
3202
|
PermissionError,
|
|
3203
|
+
RawEnumModel,
|
|
3204
|
+
Relation,
|
|
3205
|
+
ReverseRelation,
|
|
2756
3206
|
SPECIAL_FILTERS,
|
|
3207
|
+
ScalarModel,
|
|
3208
|
+
TYPE_ALIAS,
|
|
2757
3209
|
UserInputError,
|
|
2758
3210
|
actionableRelations,
|
|
2759
3211
|
addJoin,
|
|
@@ -2762,6 +3214,7 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql5.buildAST
|
|
|
2762
3214
|
applyFilters,
|
|
2763
3215
|
applyJoins,
|
|
2764
3216
|
applyPermissions,
|
|
3217
|
+
applySelects,
|
|
2765
3218
|
args,
|
|
2766
3219
|
checkCanWrite,
|
|
2767
3220
|
directive,
|
|
@@ -2779,6 +3232,8 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql5.buildAST
|
|
|
2779
3232
|
generateMutations,
|
|
2780
3233
|
generatePermissions,
|
|
2781
3234
|
get,
|
|
3235
|
+
getColumn,
|
|
3236
|
+
getColumnName,
|
|
2782
3237
|
getEditEntityRelationsQuery,
|
|
2783
3238
|
getEntityListQuery,
|
|
2784
3239
|
getEntityQuery,
|
|
@@ -2789,16 +3244,8 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql5.buildAST
|
|
|
2789
3244
|
getInlineFragments,
|
|
2790
3245
|
getJoins,
|
|
2791
3246
|
getLabel,
|
|
2792
|
-
getManyToManyRelation,
|
|
2793
|
-
getManyToManyRelations,
|
|
2794
3247
|
getManyToManyRelationsQuery,
|
|
2795
3248
|
getMigrationDate,
|
|
2796
|
-
getModelLabel,
|
|
2797
|
-
getModelLabelPlural,
|
|
2798
|
-
getModelPlural,
|
|
2799
|
-
getModelPluralField,
|
|
2800
|
-
getModelSlug,
|
|
2801
|
-
getModels,
|
|
2802
3249
|
getMutationQuery,
|
|
2803
3250
|
getNameOrAlias,
|
|
2804
3251
|
getPermissionStack,
|
|
@@ -2811,6 +3258,7 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql5.buildAST
|
|
|
2811
3258
|
getTypeName,
|
|
2812
3259
|
getUpdateEntityQuery,
|
|
2813
3260
|
gql,
|
|
3261
|
+
hasName,
|
|
2814
3262
|
hash,
|
|
2815
3263
|
hydrate,
|
|
2816
3264
|
iface,
|
|
@@ -2822,12 +3270,14 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql5.buildAST
|
|
|
2822
3270
|
isCustomField,
|
|
2823
3271
|
isEntityModel,
|
|
2824
3272
|
isEnum,
|
|
2825
|
-
isEnumList,
|
|
2826
3273
|
isEnumModel,
|
|
2827
3274
|
isFieldNode,
|
|
2828
3275
|
isFragmentSpreadNode,
|
|
3276
|
+
isInTable,
|
|
3277
|
+
isInherited,
|
|
2829
3278
|
isInlineFragmentNode,
|
|
2830
3279
|
isInputModel,
|
|
3280
|
+
isInterfaceModel,
|
|
2831
3281
|
isListType,
|
|
2832
3282
|
isObjectModel,
|
|
2833
3283
|
isPrimitive,
|
|
@@ -2835,16 +3285,20 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql5.buildAST
|
|
|
2835
3285
|
isQueriableField,
|
|
2836
3286
|
isRawEnumModel,
|
|
2837
3287
|
isRelation,
|
|
3288
|
+
isRootModel,
|
|
2838
3289
|
isScalarModel,
|
|
2839
3290
|
isSimpleField,
|
|
2840
3291
|
isToOneRelation,
|
|
2841
3292
|
isUpdatable,
|
|
2842
3293
|
isUpdatableBy,
|
|
3294
|
+
isUpdatableField,
|
|
3295
|
+
isUpdatableModel,
|
|
2843
3296
|
isVisible,
|
|
2844
3297
|
isVisibleRelation,
|
|
2845
3298
|
it,
|
|
2846
3299
|
list,
|
|
2847
3300
|
merge,
|
|
3301
|
+
modelNeedsTable,
|
|
2848
3302
|
mutationResolver,
|
|
2849
3303
|
name,
|
|
2850
3304
|
namedType,
|
|
@@ -2854,6 +3308,7 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql5.buildAST
|
|
|
2854
3308
|
normalizeValueByTypeDefinition,
|
|
2855
3309
|
not,
|
|
2856
3310
|
object,
|
|
3311
|
+
or,
|
|
2857
3312
|
ors,
|
|
2858
3313
|
printSchema,
|
|
2859
3314
|
printSchemaFromDocument,
|