@smartive/graphql-magic 5.1.2 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/CHANGELOG.md +1 -6
  2. package/dist/cjs/index.cjs +149 -140
  3. package/dist/esm/client/index.d.ts +1 -0
  4. package/dist/esm/client/index.js +1 -0
  5. package/dist/esm/client/index.js.map +1 -1
  6. package/dist/esm/client/models.d.ts +1 -0
  7. package/dist/esm/client/models.js +2 -0
  8. package/dist/esm/client/models.js.map +1 -0
  9. package/dist/esm/client/queries.d.ts +2 -2
  10. package/dist/esm/client/queries.js +3 -3
  11. package/dist/esm/client/queries.js.map +1 -1
  12. package/dist/esm/context.d.ts +5 -1
  13. package/dist/esm/db/generate.js +17 -19
  14. package/dist/esm/db/generate.js.map +1 -1
  15. package/dist/esm/migrations/generate.js +69 -57
  16. package/dist/esm/migrations/generate.js.map +1 -1
  17. package/dist/esm/models/index.d.ts +1 -0
  18. package/dist/esm/models/index.js +1 -0
  19. package/dist/esm/models/index.js.map +1 -1
  20. package/dist/esm/models/models.d.ts +65 -59
  21. package/dist/esm/models/mutation-hook.d.ts +17 -0
  22. package/dist/esm/models/mutation-hook.js +2 -0
  23. package/dist/esm/models/mutation-hook.js.map +1 -0
  24. package/dist/esm/models/utils.d.ts +398 -22
  25. package/dist/esm/models/utils.js +22 -20
  26. package/dist/esm/models/utils.js.map +1 -1
  27. package/dist/esm/permissions/check.js +2 -2
  28. package/dist/esm/permissions/check.js.map +1 -1
  29. package/dist/esm/resolvers/filters.js +1 -1
  30. package/dist/esm/resolvers/mutations.js +4 -4
  31. package/dist/esm/resolvers/mutations.js.map +1 -1
  32. package/dist/esm/resolvers/node.js +2 -2
  33. package/dist/esm/resolvers/node.js.map +1 -1
  34. package/dist/esm/resolvers/resolver.js +1 -1
  35. package/dist/esm/schema/generate.js +27 -37
  36. package/dist/esm/schema/generate.js.map +1 -1
  37. package/dist/esm/schema/utils.d.ts +1 -1
  38. package/dist/esm/schema/utils.js +2 -2
  39. package/dist/esm/schema/utils.js.map +1 -1
  40. package/package.json +5 -5
  41. package/src/client/index.ts +1 -0
  42. package/src/client/models.ts +1 -0
  43. package/src/client/queries.ts +5 -5
  44. package/src/context.ts +4 -1
  45. package/src/db/generate.ts +25 -27
  46. package/src/migrations/generate.ts +69 -57
  47. package/src/models/index.ts +1 -0
  48. package/src/models/models.ts +88 -97
  49. package/src/models/mutation-hook.ts +17 -0
  50. package/src/models/utils.ts +27 -21
  51. package/src/permissions/check.ts +2 -2
  52. package/src/resolvers/filters.ts +1 -1
  53. package/src/resolvers/mutations.ts +9 -8
  54. package/src/resolvers/node.ts +2 -2
  55. package/src/resolvers/resolver.ts +1 -1
  56. package/src/schema/generate.ts +31 -48
  57. package/src/schema/utils.ts +3 -3
  58. package/tests/unit/__snapshots__/generate.spec.ts.snap +2 -2
  59. package/tests/unit/resolve.spec.ts +1 -0
  60. package/tests/utils/models.ts +12 -12
  61. package/tests/utils/server.ts +1 -0
@@ -3,8 +3,9 @@ import { DateTime } from 'luxon';
3
3
  import { v4 as uuid } from 'uuid';
4
4
  import { Context, FullContext } from '../context';
5
5
  import { ForbiddenError, GraphQLError } from '../errors';
6
- import { Entity, Model, ModelField } from '../models/models';
7
- import { get, isEnumList, it, summonByName, typeToField } from '../models/utils';
6
+ import { Model, ModelField } from '../models/models';
7
+ import { Entity, FullEntity } from '../models/mutation-hook';
8
+ import { get, isEnumList, isPrimitive, it, summonByName, typeToField } from '../models/utils';
8
9
  import { applyPermissions, checkCanWrite, getEntityToMutate } from '../permissions/check';
9
10
  import { resolve } from './resolver';
10
11
  import { AliasGenerator } from './utils';
@@ -106,7 +107,7 @@ const del = async (model: Model, { where, dryRun }: { where: any; dryRun: boolea
106
107
  const mutations: Callbacks = [];
107
108
  const afterHooks: Callbacks = [];
108
109
 
109
- const deleteCascade = async (currentModel: Model, entity: Entity) => {
110
+ const deleteCascade = async (currentModel: Model, entity: FullEntity) => {
110
111
  if (entity.deleted) {
111
112
  return;
112
113
  }
@@ -220,7 +221,7 @@ const restore = async (model: Model, { where }: { where: any }, ctx: FullContext
220
221
  const mutations: Callbacks = [];
221
222
  const afterHooks: Callbacks = [];
222
223
 
223
- const restoreCascade = async (currentModel: Model, relatedEntity: Entity) => {
224
+ const restoreCascade = async (currentModel: Model, relatedEntity: FullEntity) => {
224
225
  if (!relatedEntity.deleted || !relatedEntity.deletedAt || !relatedEntity.deletedAt.equals(entity.deletedAt)) {
225
226
  return;
226
227
  }
@@ -265,7 +266,7 @@ const restore = async (model: Model, { where }: { where: any }, ctx: FullContext
265
266
 
266
267
  const createRevision = async (model: Model, data: Entity, ctx: Context) => {
267
268
  if (model.updatable) {
268
- const revisionData = {
269
+ const revisionData: Entity = {
269
270
  id: uuid(),
270
271
  [`${typeToField(model.name)}Id`]: data.id,
271
272
  createdAt: ctx.now,
@@ -276,10 +277,10 @@ const createRevision = async (model: Model, data: Entity, ctx: Context) => {
276
277
  revisionData.deleted = data.deleted || false;
277
278
  }
278
279
 
279
- for (const { type, name, nonNull, ...field } of model.fields.filter(({ updatable }) => updatable)) {
280
+ for (const { kind: type, name, nonNull, ...field } of model.fields.filter(({ updatable }) => updatable)) {
280
281
  const col = type === 'relation' ? `${name}Id` : name;
281
282
  if (nonNull && (!(col in data) || col === undefined || col === null)) {
282
- revisionData[col] = get(field, 'default');
283
+ revisionData[col] = get(field, 'defaultValue');
283
284
  } else {
284
285
  revisionData[col] = data[col];
285
286
  }
@@ -314,4 +315,4 @@ const sanitize = (ctx: FullContext, model: Model, data: Entity) => {
314
315
  };
315
316
 
316
317
  const isEndOfDay = (field?: ModelField) =>
317
- field.type === 'DateTime' && field?.endOfDay === true && field?.dateTimeType === 'date' && field?.type === 'DateTime';
318
+ isPrimitive(field) && field.type === 'DateTime' && field?.endOfDay === true && field?.dateTimeType === 'date';
@@ -113,7 +113,7 @@ export const getSimpleFields = (node: ResolverNode) => {
113
113
  return true;
114
114
  }
115
115
 
116
- return node.model.fields.some(({ type, name }) => type === 'json' && name === selection.name.value);
116
+ return node.model.fields.some(({ kind: type, name }) => type === 'json' && name === selection.name.value);
117
117
  });
118
118
  };
119
119
 
@@ -165,7 +165,7 @@ export const getJoins = (node: ResolverNode, toMany: boolean) => {
165
165
  foreignKey = reverseRelation.foreignKey;
166
166
  } else {
167
167
  const modelField = baseModel.fieldsByName[fieldName];
168
- if (modelField?.type !== 'relation') {
168
+ if (modelField?.kind !== 'relation') {
169
169
  continue;
170
170
  }
171
171
  foreignKey = modelField.foreignKey;
@@ -115,7 +115,7 @@ const applySelects = (node: ResolverNode, query: Knex.QueryBuilder, joins: Joins
115
115
  .filter((n) => {
116
116
  const field = node.model.fields.find(({ name }) => name === n.name.value);
117
117
 
118
- if (!field || field.type === 'relation' || field.type === 'raw') {
118
+ if (!field || field.kind === 'relation' || field.kind === 'raw') {
119
119
  return false;
120
120
  }
121
121
 
@@ -1,4 +1,4 @@
1
- import { buildASTSchema, DefinitionNode, DocumentNode, GraphQLSchema, print } from 'graphql';
1
+ import { DefinitionNode, DocumentNode, GraphQLSchema, buildASTSchema, print } from 'graphql';
2
2
  import flatMap from 'lodash/flatMap';
3
3
  import { RawModels } from '../models/models';
4
4
  import {
@@ -12,7 +12,7 @@ import {
12
12
  isScalarModel,
13
13
  typeToField,
14
14
  } from '../models/utils';
15
- import { document, enm, Field, input, object, scalar } from './utils';
15
+ import { Field, document, enm, input, object, scalar } from './utils';
16
16
 
17
17
  export const generateDefinitions = (rawModels: RawModels): DefinitionNode[] => {
18
18
  const models = getModels(rawModels);
@@ -30,17 +30,13 @@ export const generateDefinitions = (rawModels: RawModels): DefinitionNode[] => {
30
30
  ...rawModels
31
31
  .filter(isRawObjectModel)
32
32
  .filter((model) =>
33
- models.some(
34
- (m) => m.creatable && m.fields.some((f) => f.creatable && f.type === 'json' && f.typeName === model.name)
35
- )
33
+ models.some((m) => m.creatable && m.fields.some((f) => f.creatable && f.kind === 'json' && f.type === model.name))
36
34
  )
37
35
  .map((model) => input(`Create${model.name}`, model.fields)),
38
36
  ...rawModels
39
37
  .filter(isRawObjectModel)
40
38
  .filter((model) =>
41
- models.some(
42
- (m) => m.creatable && m.fields.some((f) => f.creatable && f.type === 'json' && f.typeName === model.name)
43
- )
39
+ models.some((m) => m.creatable && m.fields.some((f) => f.creatable && f.kind === 'json' && f.type === model.name))
44
40
  )
45
41
  .map((model) => input(`Update${model.name}`, model.fields)),
46
42
 
@@ -52,10 +48,7 @@ export const generateDefinitions = (rawModels: RawModels): DefinitionNode[] => {
52
48
  [
53
49
  ...model.fields.filter(isQueriableField).map((field) => ({
54
50
  ...field,
55
- type:
56
- field.type === 'relation' || field.type === 'enum' || field.type === 'raw' || field.type === 'json'
57
- ? field.typeName
58
- : field.type,
51
+ type: field.type,
59
52
  args: [...(field.args || [])],
60
53
  directives: field.directives,
61
54
  })),
@@ -79,33 +72,33 @@ export const generateDefinitions = (rawModels: RawModels): DefinitionNode[] => {
79
72
  ),
80
73
  input(`${model.name}Where`, [
81
74
  ...model.fields
82
- .filter(({ type, unique, filterable }) => (unique || filterable) && type !== 'relation')
83
- .map(({ type, name, filterable }) => ({
84
- name,
85
- type,
75
+ .filter(({ kind, unique, filterable }) => (unique || filterable) && kind !== 'relation')
76
+ .map((field) => ({
77
+ name: field.name,
78
+ type: field.type,
86
79
  list: true,
87
- default: typeof filterable === 'object' ? filterable.default : undefined,
80
+ default: typeof field.filterable === 'object' ? field.filterable.default : undefined,
88
81
  })),
89
82
  ...flatMap(
90
83
  model.fields.filter(({ comparable }) => comparable),
91
- ({ name, type }) => [
92
- { name: `${name}_GT`, type },
93
- { name: `${name}_GTE`, type },
94
- { name: `${name}_LT`, type },
95
- { name: `${name}_LTE`, type },
84
+ (field) => [
85
+ { name: `${field.name}_GT`, type: field.type },
86
+ { name: `${field.name}_GTE`, type: field.type },
87
+ { name: `${field.name}_LT`, type: field.type },
88
+ { name: `${field.name}_LTE`, type: field.type },
96
89
  ]
97
90
  ),
98
91
  ...model.fields
99
92
  .filter(isRelation)
100
93
  .filter(({ filterable }) => filterable)
101
- .map(({ name, typeName }) => ({
94
+ .map(({ name, type }) => ({
102
95
  name,
103
- type: `${typeName}Where`,
96
+ type: `${type}Where`,
104
97
  })),
105
98
  ]),
106
99
  input(
107
100
  `${model.name}WhereUnique`,
108
- model.fields.filter(({ unique }) => unique).map(({ name, type }) => ({ name, type }))
101
+ model.fields.filter(({ unique }) => unique).map((field) => ({ name: field.name, type: field.type }))
109
102
  ),
110
103
  ...(model.fields.some(({ orderable }) => orderable)
111
104
  ? [
@@ -123,19 +116,14 @@ export const generateDefinitions = (rawModels: RawModels): DefinitionNode[] => {
123
116
  `Create${model.name}`,
124
117
  model.fields
125
118
  .filter(({ creatable }) => creatable)
126
- .map(({ name, nonNull, list, default: defaultValue, ...field }) =>
127
- field.type === 'relation'
128
- ? { name: `${name}Id`, type: 'ID', nonNull }
119
+ .map((field) =>
120
+ field.kind === 'relation'
121
+ ? { name: `${field.name}Id`, type: 'ID', nonNull: field.nonNull }
129
122
  : {
130
- name,
131
- type:
132
- field.type === 'enum'
133
- ? field.typeName
134
- : field.type === 'json'
135
- ? `Create${field.typeName}`
136
- : field.type,
137
- list,
138
- nonNull: nonNull && defaultValue === undefined,
123
+ name: field.name,
124
+ type: field.kind === 'json' ? `Create${field.type}` : field.type,
125
+ list: field.list,
126
+ nonNull: field.nonNull && field.defaultValue === undefined,
139
127
  }
140
128
  )
141
129
  )
@@ -148,18 +136,13 @@ export const generateDefinitions = (rawModels: RawModels): DefinitionNode[] => {
148
136
  `Update${model.name}`,
149
137
  model.fields
150
138
  .filter(({ updatable }) => updatable)
151
- .map(({ name, list, ...field }) =>
152
- field.type === 'relation'
153
- ? { name: `${name}Id`, type: 'ID' }
139
+ .map((field) =>
140
+ field.kind === 'relation'
141
+ ? { name: `${field.name}Id`, type: 'ID' }
154
142
  : {
155
- name,
156
- type:
157
- field.type === 'enum'
158
- ? field.typeName
159
- : field.type === 'json'
160
- ? `Update${field.typeName}`
161
- : field.type,
162
- list,
143
+ name: field.name,
144
+ type: field.kind === 'json' ? `Update${field.type}` : field.type,
145
+ list: field.list,
163
146
  }
164
147
  )
165
148
  )
@@ -30,7 +30,7 @@ export type Field = {
30
30
  description?: string;
31
31
  list?: boolean;
32
32
  nonNull?: boolean;
33
- default?: Value;
33
+ defaultValue?: Value;
34
34
  args?: Field[];
35
35
  directives?: Directive[];
36
36
  };
@@ -90,7 +90,7 @@ export const inputValues = (fields: Field[]): InputValueDefinitionNode[] =>
90
90
  kind: 'InputValueDefinition',
91
91
  name: name(field.name),
92
92
  type: fieldType(field),
93
- defaultValue: field.default === undefined ? undefined : value(field.default),
93
+ defaultValue: field.defaultValue === undefined ? undefined : value(field.defaultValue),
94
94
  directives: directives(field.directives),
95
95
  })
96
96
  );
@@ -105,7 +105,7 @@ export const fields = (fields: Field[]): FieldDefinitionNode[] =>
105
105
  kind: 'InputValueDefinition',
106
106
  name: name(arg.name),
107
107
  type: fieldType(arg),
108
- defaultValue: arg.default === undefined ? undefined : value(arg.default),
108
+ defaultValue: arg.defaultValue === undefined ? undefined : value(arg.defaultValue),
109
109
  })),
110
110
  directives: directives(field.directives),
111
111
  })
@@ -19,7 +19,7 @@ input AnotherObjectOrderBy {
19
19
 
20
20
  input AnotherObjectWhere {
21
21
  id: [ID!]
22
- deleted: [Boolean!] = false
22
+ deleted: [Boolean!]
23
23
  }
24
24
 
25
25
  input AnotherObjectWhereUnique {
@@ -88,7 +88,7 @@ input SomeObjectOrderBy {
88
88
 
89
89
  input SomeObjectWhere {
90
90
  id: [ID!]
91
- deleted: [Boolean!] = false
91
+ deleted: [Boolean!]
92
92
  another: AnotherObjectWhere
93
93
  }
94
94
 
@@ -23,6 +23,7 @@ const test = async (operationName: string, query: string, variables: object, res
23
23
 
24
24
  const user = await knexInstance('User').where({ id: 1 }).first();
25
25
  const result = await execute({
26
+ req: null as any,
26
27
  knex: knexInstance,
27
28
  locale: 'en',
28
29
  locales: ['en'],
@@ -5,23 +5,23 @@ import { generatePermissions, PermissionsConfig } from '../../src/permissions/ge
5
5
  export const rawModels: RawModels = [
6
6
  {
7
7
  name: 'SomeEnum',
8
- type: 'enum',
8
+ kind: 'enum',
9
9
  values: ['A', 'B', 'C'],
10
10
  },
11
11
  {
12
12
  name: 'Role',
13
- type: 'enum',
13
+ kind: 'enum',
14
14
  values: ['ADMIN', 'USER'],
15
15
  },
16
16
 
17
17
  {
18
18
  name: 'SomeRawObject',
19
- type: 'raw',
19
+ kind: 'raw',
20
20
  fields: [{ name: 'field', type: 'String' }],
21
21
  },
22
22
 
23
23
  {
24
- type: 'object',
24
+ kind: 'object',
25
25
  name: 'User',
26
26
  fields: [
27
27
  {
@@ -30,13 +30,13 @@ export const rawModels: RawModels = [
30
30
  },
31
31
  {
32
32
  name: 'role',
33
- type: 'enum',
34
- typeName: 'Role',
33
+ kind: 'enum',
34
+ type: 'Role',
35
35
  },
36
36
  ],
37
37
  },
38
38
  {
39
- type: 'object',
39
+ kind: 'object',
40
40
  name: 'AnotherObject',
41
41
  listQueriable: true,
42
42
  deletable: true,
@@ -48,8 +48,8 @@ export const rawModels: RawModels = [
48
48
  orderable: true,
49
49
  },
50
50
  {
51
- type: 'relation',
52
- typeName: 'AnotherObject',
51
+ kind: 'relation',
52
+ type: 'AnotherObject',
53
53
  name: 'myself',
54
54
  toOne: true,
55
55
  reverse: 'self',
@@ -57,7 +57,7 @@ export const rawModels: RawModels = [
57
57
  ],
58
58
  },
59
59
  {
60
- type: 'object',
60
+ kind: 'object',
61
61
  name: 'SomeObject',
62
62
  plural: 'ManyObjects',
63
63
  description: 'An object',
@@ -74,8 +74,8 @@ export const rawModels: RawModels = [
74
74
  },
75
75
  {
76
76
  name: 'another',
77
- type: 'relation',
78
- typeName: 'AnotherObject',
77
+ kind: 'relation',
78
+ type: 'AnotherObject',
79
79
  filterable: true,
80
80
  updatable: true,
81
81
  nonNull: true,
@@ -58,6 +58,7 @@ export const withServer = async (
58
58
  });
59
59
  });
60
60
  const result = await execute({
61
+ req,
61
62
  knex,
62
63
  locale: 'en',
63
64
  locales: ['en'],