@smartive/graphql-magic 2.1.0 → 3.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 (39) hide show
  1. package/.github/workflows/release.yml +1 -1
  2. package/.github/workflows/testing.yml +3 -2
  3. package/.nvmrc +1 -1
  4. package/CHANGELOG.md +1 -6
  5. package/dist/cjs/index.cjs +53 -15
  6. package/dist/esm/db/generate.js +45 -8
  7. package/dist/esm/db/generate.js.map +1 -1
  8. package/dist/esm/migrations/generate.js.map +1 -1
  9. package/dist/esm/permissions/check.js.map +1 -1
  10. package/dist/esm/permissions/generate.js.map +1 -1
  11. package/dist/esm/resolvers/filters.js.map +1 -1
  12. package/dist/esm/resolvers/mutations.js +7 -6
  13. package/dist/esm/resolvers/mutations.js.map +1 -1
  14. package/dist/esm/resolvers/node.js.map +1 -1
  15. package/dist/esm/resolvers/resolver.js.map +1 -1
  16. package/dist/esm/resolvers/utils.js.map +1 -1
  17. package/docker-compose.yml +17 -0
  18. package/package.json +15 -9
  19. package/src/db/generate.ts +63 -17
  20. package/src/migrations/generate.ts +9 -9
  21. package/src/permissions/check.ts +1 -1
  22. package/src/permissions/generate.ts +7 -7
  23. package/src/resolvers/filters.ts +3 -3
  24. package/src/resolvers/mutations.ts +17 -14
  25. package/src/resolvers/node.ts +1 -1
  26. package/src/resolvers/resolver.ts +2 -2
  27. package/src/resolvers/utils.ts +2 -2
  28. package/tests/api/__snapshots__/query.spec.ts.snap +22 -0
  29. package/tests/api/query.spec.ts +28 -0
  30. package/tests/unit/__snapshots__/generate.spec.ts.snap +6 -0
  31. package/tests/unit/generate.spec.ts +2 -2
  32. package/tests/unit/resolve.spec.ts +2 -2
  33. package/tests/utils/database/knex.ts +19 -0
  34. package/tests/utils/database/schema.ts +51 -0
  35. package/tests/utils/database/seed.ts +53 -0
  36. package/tests/utils/generate-migration.ts +35 -0
  37. package/tests/{unit/utils.ts → utils/models.ts} +16 -5
  38. package/tests/utils/server.ts +108 -0
  39. package/tsconfig.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/resolvers/utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/resolvers/utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ version: '3.4'
2
+ services:
3
+ postgres:
4
+ image: postgres:13-alpine
5
+ shm_size: 1gb
6
+ environment:
7
+ POSTGRES_DB: postgres
8
+ POSTGRES_USER: postgres
9
+ POSTGRES_PASSWORD: password
10
+ POSTGRES_HOST_AUTH_METHOD: trust
11
+ TZ: 'Europe/Zurich'
12
+ ports:
13
+ - '5432:5432'
14
+ networks:
15
+ default:
16
+ aliases:
17
+ - postgres.local
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartive/graphql-magic",
3
- "version": "2.1.0",
3
+ "version": "3.0.0",
4
4
  "description": "",
5
5
  "source": "src/index.ts",
6
6
  "type": "module",
@@ -8,7 +8,7 @@
8
8
  "main": "dist/cjs/index.cjs",
9
9
  "types": "dist/esm/index.d.ts",
10
10
  "engines": {
11
- "node": ">=18"
11
+ "node": ">=20"
12
12
  },
13
13
  "sideEffecs": false,
14
14
  "scripts": {
@@ -17,8 +17,11 @@
17
17
  "generate:index-files": "cti create ./src --excludes types --withoutbackup",
18
18
  "lint": "eslint src",
19
19
  "lint:fix": "eslint src --fix",
20
- "test": "npm run lint && npm run test:unit && npm run build",
20
+ "deps": "docker-compose up",
21
+ "test": "npm run lint && npm run test:unit && npm run test:api && npm run build",
21
22
  "test:unit": "jest tests/unit --no-cache --no-watchman",
23
+ "test:api": "jest tests/api --no-cache --no-watchman",
24
+ "generate-migration": "esbuild tests/utils/generate-migration.ts --bundle --platform=node --outdir=tmp --out-extension:.js=.cjs --format=cjs --packages=external && node tmp/generate-migration.cjs",
22
25
  "clean": "del-cli dist/**",
23
26
  "prebuild": "npm run clean",
24
27
  "build": "npm run build:esm && npm run build:cjs",
@@ -27,7 +30,7 @@
27
30
  },
28
31
  "overrides": {
29
32
  "graphql": "$graphql",
30
- "rollup": "3.26.2"
33
+ "rollup": "3.27.2"
31
34
  },
32
35
  "browserslist": "> 0.25%, not dead",
33
36
  "publishConfig": {
@@ -48,16 +51,19 @@
48
51
  "@smartive/eslint-config": "3.2.0",
49
52
  "@smartive/prettier-config": "3.1.2",
50
53
  "@types/jest": "29.5.3",
51
- "@types/lodash": "4.14.195",
52
- "@types/luxon": "3.3.0",
54
+ "@types/lodash": "4.14.196",
55
+ "@types/luxon": "3.3.1",
53
56
  "@types/uuid": "9.0.2",
54
57
  "create-ts-index": "1.14.0",
55
58
  "del-cli": "5.0.0",
56
- "esbuild": "0.18.11",
57
- "eslint": "8.44.0",
58
- "jest": "29.6.1",
59
+ "esbuild": "0.19.0",
60
+ "eslint": "8.46.0",
61
+ "graphql-request": "^6.1.0",
62
+ "jest": "29.6.2",
59
63
  "mock-knex": "0.4.12",
64
+ "pg": "^8.11.2",
60
65
  "prettier": "2.8.8",
66
+ "simple-git": "^3.19.1",
61
67
  "ts-jest": "29.1.1",
62
68
  "ts-node": "10.9.1",
63
69
  "typescript": "5.1.6"
@@ -1,5 +1,5 @@
1
1
  import CodeBlockWriter from 'code-block-writer';
2
- import { RawModels, getModels, isEnumModel } from '..';
2
+ import { ModelField, RawModels, getModels, isEnumModel } from '..';
3
3
 
4
4
  const PRIMITIVE_TYPES = {
5
5
  ID: 'string',
@@ -8,8 +8,11 @@ const PRIMITIVE_TYPES = {
8
8
  Int: 'number',
9
9
  Float: 'number',
10
10
  String: 'string',
11
+ DateTime: 'DateTime | string',
11
12
  };
12
13
 
14
+ const OPTIONAL_SEED_FIELDS = ['createdAt', 'createdById', 'updatedAt', 'updatedById', 'deletedAt', 'deletedById'];
15
+
13
16
  export const generateDBModels = (rawModels: RawModels) => {
14
17
  const writer: CodeBlockWriter = new CodeBlockWriter['default']({
15
18
  useSingleQuote: true,
@@ -25,17 +28,16 @@ export const generateDBModels = (rawModels: RawModels) => {
25
28
  const models = getModels(rawModels);
26
29
 
27
30
  for (const model of models) {
31
+ // TODO: deprecate allowing to define foreignKey
32
+ const fields = model.fields.some((field) => field.foreignKey === 'id')
33
+ ? model.fields.filter((field) => field.name !== 'id')
34
+ : model.fields;
35
+
28
36
  writer
29
37
  .write(`export type ${model.name} = `)
30
38
  .inlineBlock(() => {
31
- for (const { name, type, nonNull, relation } of model.fields.filter(({ raw }) => !raw)) {
32
- writer
33
- .write(
34
- `'${name}${relation ? 'Id' : ''}': ${relation ? 'string' : PRIMITIVE_TYPES[type] || type}${
35
- nonNull ? '' : ' | null'
36
- },`
37
- )
38
- .newLine();
39
+ for (const field of fields.filter(({ raw }) => !raw)) {
40
+ writer.write(`'${getFieldName(field)}': ${getFieldOutputType(field)}${field.nonNull ? '' : ' | null'},`).newLine();
39
41
  }
40
42
  })
41
43
  .blankLine();
@@ -43,12 +45,12 @@ export const generateDBModels = (rawModels: RawModels) => {
43
45
  writer
44
46
  .write(`export type ${model.name}Initializer = `)
45
47
  .inlineBlock(() => {
46
- for (const { name, type, nonNull, default: def, relation } of model.fields.filter(({ raw }) => !raw)) {
48
+ for (const field of fields.filter(({ raw }) => !raw)) {
47
49
  writer
48
50
  .write(
49
- `'${name}${relation ? 'Id' : ''}'${nonNull && def === undefined ? '' : '?'}: ${
50
- relation ? 'string' : PRIMITIVE_TYPES[type] || type
51
- }${nonNull ? '' : ' | null'},`
51
+ `'${getFieldName(field)}'${field.nonNull && field.default === undefined ? '' : '?'}: ${getFieldInputType(
52
+ field
53
+ )}${field.nonNull ? '' : ' | null'},`
52
54
  )
53
55
  .newLine();
54
56
  }
@@ -58,12 +60,25 @@ export const generateDBModels = (rawModels: RawModels) => {
58
60
  writer
59
61
  .write(`export type ${model.name}Mutator = `)
60
62
  .inlineBlock(() => {
61
- for (const { name, type, nonNull, relation } of model.fields.filter(({ raw }) => !raw)) {
63
+ for (const field of fields.filter(({ raw }) => !raw)) {
64
+ writer.write(`'${getFieldName(field)}'?: ${getFieldInputType(field)}${field.nonNull ? '' : ' | null'},`).newLine();
65
+ }
66
+ })
67
+ .blankLine();
68
+
69
+ writer
70
+ .write(`export type ${model.name}Seed = `)
71
+ .inlineBlock(() => {
72
+ for (const field of fields.filter(({ raw }) => !raw)) {
73
+ const fieldName = getFieldName(field);
62
74
  writer
63
75
  .write(
64
- `'${name}${relation ? 'Id' : ''}'?: ${relation ? 'string' : PRIMITIVE_TYPES[type] || type}${
65
- nonNull ? '' : ' | null'
66
- },`
76
+ `'${getFieldName(field)}'${
77
+ field.nonNull && field.default === undefined && !OPTIONAL_SEED_FIELDS.includes(fieldName) ? '' : '?'
78
+ }: ${getFieldInputType(
79
+ field,
80
+ rawModels.filter(isEnumModel).map(({ name }) => name)
81
+ )}${field.list ? ' | string' : ''}${field.nonNull ? '' : ' | null'},`
67
82
  )
68
83
  .newLine();
69
84
  }
@@ -71,9 +86,40 @@ export const generateDBModels = (rawModels: RawModels) => {
71
86
  .blankLine();
72
87
  }
73
88
 
89
+ writer.write(`export type SeedData = `).inlineBlock(() => {
90
+ for (const model of models) {
91
+ writer.write(`${model.name}: ${model.name}Seed[],`).newLine();
92
+ }
93
+ });
94
+
74
95
  return writer.toString();
75
96
  };
76
97
 
98
+ const getFieldName = ({ relation, name, foreignKey }: ModelField) => {
99
+ return foreignKey || `${name}${relation ? 'Id' : ''}`;
100
+ };
101
+
102
+ const getFieldOutputType = ({ relation, type, list, json }: ModelField) => {
103
+ if (json || relation) {
104
+ return 'string';
105
+ }
106
+
107
+ return (PRIMITIVE_TYPES[type] || type) + (list ? '[]' : '');
108
+ };
109
+
110
+ const getFieldInputType = (field: ModelField, stringTypes: string[] = []) => {
111
+ let outputType = getFieldOutputType(field);
112
+
113
+ if (field.list || stringTypes.includes(field.type)) {
114
+ outputType += ' | string';
115
+ if (field.list && stringTypes.includes(field.type)) {
116
+ outputType += ' | string[]';
117
+ }
118
+ }
119
+
120
+ return outputType;
121
+ };
122
+
77
123
  export const generateKnexTables = (rawModels: RawModels) => {
78
124
  const writer: CodeBlockWriter = new CodeBlockWriter['default']({
79
125
  useSingleQuote: true,
@@ -80,7 +80,7 @@ export class MigrationGenerator {
80
80
  this.renameTable(model.name, model.oldName!);
81
81
  });
82
82
  tables[tables.indexOf(model.oldName)] = model.name;
83
- this.columns[model.name] = this.columns[model.oldName]!;
83
+ this.columns[model.name] = this.columns[model.oldName];
84
84
  delete this.columns[model.oldName];
85
85
 
86
86
  if (model.updatable) {
@@ -99,7 +99,7 @@ export class MigrationGenerator {
99
99
  });
100
100
  });
101
101
  tables[tables.indexOf(`${model.oldName}Revision`)] = `${model.name}Revision`;
102
- this.columns[`${model.name}Revision`] = this.columns[`${model.oldName}Revision`]!;
102
+ this.columns[`${model.name}Revision`] = this.columns[`${model.oldName}Revision`];
103
103
  delete this.columns[`${model.oldName}Revision`];
104
104
  }
105
105
  }
@@ -131,7 +131,7 @@ export class MigrationGenerator {
131
131
  model,
132
132
  model.fields.filter(
133
133
  ({ name, relation, raw, foreignKey }) =>
134
- !raw && !this.columns[model.name]!.some((col) => col.name === (foreignKey || (relation ? `${name}Id` : name)))
134
+ !raw && !this.columns[model.name].some((col) => col.name === (foreignKey || (relation ? `${name}Id` : name)))
135
135
  ),
136
136
  up,
137
137
  down
@@ -139,7 +139,7 @@ export class MigrationGenerator {
139
139
 
140
140
  // Update fields
141
141
  const existingFields = model.fields.filter(({ name, relation, nonNull }) => {
142
- const col = this.columns[model.name]!.find((col) => col.name === (relation ? `${name}Id` : name));
142
+ const col = this.columns[model.name].find((col) => col.name === (relation ? `${name}Id` : name));
143
143
  if (!col) {
144
144
  return false;
145
145
  }
@@ -197,7 +197,7 @@ export class MigrationGenerator {
197
197
  ({ name, relation, raw, foreignKey, updatable }) =>
198
198
  !raw &&
199
199
  updatable &&
200
- !this.columns[revisionTable]!.some((col) => col.name === (foreignKey || (relation ? `${name}Id` : name)))
200
+ !this.columns[revisionTable].some((col) => col.name === (foreignKey || (relation ? `${name}Id` : name)))
201
201
  );
202
202
 
203
203
  this.createRevisionFields(model, missingRevisionFields, up, down);
@@ -208,7 +208,7 @@ export class MigrationGenerator {
208
208
  !raw &&
209
209
  !updatable &&
210
210
  foreignKey !== 'id' &&
211
- this.columns[revisionTable]!.some((col) => col.name === (foreignKey || (relation ? `${name}Id` : name)))
211
+ this.columns[revisionTable].some((col) => col.name === (foreignKey || (relation ? `${name}Id` : name)))
212
212
  );
213
213
  this.createRevisionFields(model, revisionFieldsToRemove, down, up);
214
214
  }
@@ -219,7 +219,7 @@ export class MigrationGenerator {
219
219
  if (tables.includes(model.name)) {
220
220
  this.createFields(
221
221
  model,
222
- model.fields.filter(({ name, deleted }) => deleted && this.columns[model.name]!.some((col) => col.name === name)),
222
+ model.fields.filter(({ name, deleted }) => deleted && this.columns[model.name].some((col) => col.name === name)),
223
223
  down,
224
224
  up
225
225
  );
@@ -363,7 +363,7 @@ export class MigrationGenerator {
363
363
  this.column(
364
364
  field,
365
365
  { alter: true },
366
- summonByName(this.columns[model.name]!, field.relation ? `${field.name}Id` : field.name)
366
+ summonByName(this.columns[model.name], field.relation ? `${field.name}Id` : field.name)
367
367
  );
368
368
  }
369
369
  });
@@ -389,7 +389,7 @@ export class MigrationGenerator {
389
389
  this.column(
390
390
  field,
391
391
  { alter: true },
392
- summonByName(this.columns[model.name]!, field.relation ? `${field.name}Id` : field.name)
392
+ summonByName(this.columns[model.name], field.relation ? `${field.name}Id` : field.name)
393
393
  );
394
394
  }
395
395
  });
@@ -194,7 +194,7 @@ const permissionLinkQuery = (
194
194
  ) => {
195
195
  const aliases = new AliasGenerator();
196
196
  let alias = aliases.getShort();
197
- const { type, me, where } = links[0]!;
197
+ const { type, me, where } = links[0];
198
198
  // eslint-disable-next-line @typescript-eslint/no-floating-promises -- we do not need to await knex here
199
199
  subQuery.from(`${type} as ${alias}`);
200
200
  if (me) {
@@ -71,7 +71,7 @@ export const generatePermissions = (models: Models, config: PermissionsConfig) =
71
71
  rolePermissions[type] = {};
72
72
  for (const action of ACTIONS) {
73
73
  if (action === 'READ' || action in block) {
74
- rolePermissions[type]![action] = true;
74
+ rolePermissions[type][action] = true;
75
75
  }
76
76
  }
77
77
  }
@@ -95,7 +95,7 @@ export const generatePermissions = (models: Models, config: PermissionsConfig) =
95
95
  };
96
96
 
97
97
  const addPermissions = (models: Models, permissions: RolePermissions, links: PermissionLink[], block: PermissionsBlock) => {
98
- const { type } = links[links.length - 1]!;
98
+ const { type } = links[links.length - 1];
99
99
  const model = summonByName(models, type);
100
100
 
101
101
  for (const action of ACTIONS) {
@@ -103,11 +103,11 @@ const addPermissions = (models: Models, permissions: RolePermissions, links: Per
103
103
  if (!permissions[type]) {
104
104
  permissions[type] = {};
105
105
  }
106
- if (!permissions[type]![action]) {
107
- permissions[type]![action] = [];
106
+ if (!permissions[type][action]) {
107
+ permissions[type][action] = [];
108
108
  }
109
- if (permissions[type]![action] !== true) {
110
- (permissions[type]![action] as PermissionStack).push(links);
109
+ if (permissions[type][action] !== true) {
110
+ (permissions[type][action] as PermissionStack).push(links);
111
111
  }
112
112
  }
113
113
  }
@@ -123,7 +123,7 @@ const addPermissions = (models: Models, permissions: RolePermissions, links: Per
123
123
  reverse: true,
124
124
  };
125
125
  } else {
126
- const field = model.reverseRelationsByName[relation]!;
126
+ const field = model.reverseRelationsByName[relation];
127
127
 
128
128
  if (!field) {
129
129
  throw new Error(`Relation ${relation} in model ${model.name} does not exist.`);
@@ -72,12 +72,12 @@ const applyWhere = (node: WhereNode, where: Where, ops: Ops<Knex.QueryBuilder>,
72
72
  const specialFilter = key.match(/^(\w+)_(\w+)$/);
73
73
  if (specialFilter) {
74
74
  const [, actualKey, filter] = specialFilter;
75
- if (!SPECIAL_FILTERS[filter!]) {
75
+ if (!SPECIAL_FILTERS[filter]) {
76
76
  // Should not happen
77
77
  throw new Error(`Invalid filter ${key}.`);
78
78
  }
79
79
  ops.push((query) =>
80
- query.whereRaw(SPECIAL_FILTERS[filter!]!, [`${node.shortTableAlias}.${actualKey}`, value as string])
80
+ query.whereRaw(SPECIAL_FILTERS[filter], [`${node.shortTableAlias}.${actualKey}`, value as string])
81
81
  );
82
82
  continue;
83
83
  }
@@ -154,7 +154,7 @@ const applyOrderBy = (node: FieldResolverNode, orderBy: OrderBy, query: Knex.Que
154
154
  throw new UserInputError(`You need to specify exactly 1 value to order by for each orderBy entry.`);
155
155
  }
156
156
  const key = keys[0];
157
- const value = vals[key!];
157
+ const value = vals[key];
158
158
 
159
159
  // Simple field
160
160
  // eslint-disable-next-line @typescript-eslint/no-floating-promises -- we do not need to await knex here
@@ -12,7 +12,7 @@ export const mutationResolver = async (_parent: any, args: any, partialCtx: Cont
12
12
  return await partialCtx.knex.transaction(async (knex) => {
13
13
  const [, mutation, modelName] = it(info.fieldName.match(/^(create|update|delete|restore)(.+)$/));
14
14
  const ctx = { ...partialCtx, knex, info, aliases: new AliasGenerator() };
15
- const model = summonByName(ctx.models, modelName!);
15
+ const model = summonByName(ctx.models, modelName);
16
16
  switch (mutation) {
17
17
  case 'create':
18
18
  return await create(model, args, ctx);
@@ -110,17 +110,20 @@ const del = async (model: Model, { where, dryRun }: { where: any; dryRun: boolea
110
110
  return;
111
111
  }
112
112
 
113
- if (dryRun) {
114
- if (!(currentModel.name in toDelete)) {
115
- toDelete[currentModel.name] = {};
116
- }
117
- toDelete[currentModel.name]![entity.id] = entity[currentModel.displayField || 'id'] || entity.id;
118
- } else {
113
+ if (!(currentModel.name in toDelete)) {
114
+ toDelete[currentModel.name] = {};
115
+ }
116
+ if (entity.id in toDelete[currentModel.name]) {
117
+ return;
118
+ }
119
+ entity[currentModel.displayField || 'id'] || entity.id;
120
+
121
+ if (!dryRun) {
119
122
  const normalizedInput = { deleted: true, deletedAt: ctx.now, deletedById: ctx.user.id };
120
123
  const data = { prev: entity, input: {}, normalizedInput, next: { ...entity, ...normalizedInput } };
121
124
  if (ctx.mutationHook) {
122
125
  beforeHooks.push(async () => {
123
- await ctx.mutationHook!(currentModel, 'delete', 'before', data, ctx);
126
+ await ctx.mutationHook(currentModel, 'delete', 'before', data, ctx);
124
127
  });
125
128
  }
126
129
  mutations.push(async () => {
@@ -129,7 +132,7 @@ const del = async (model: Model, { where, dryRun }: { where: any; dryRun: boolea
129
132
  });
130
133
  if (ctx.mutationHook) {
131
134
  afterHooks.push(async () => {
132
- await ctx.mutationHook!(currentModel, 'delete', 'after', data, ctx);
135
+ await ctx.mutationHook(currentModel, 'delete', 'after', data, ctx);
133
136
  });
134
137
  }
135
138
  }
@@ -148,13 +151,13 @@ const del = async (model: Model, { where, dryRun }: { where: any; dryRun: boolea
148
151
  if (!toUnlink[descendantModel.name]) {
149
152
  toUnlink[descendantModel.name] = {};
150
153
  }
151
- if (!toUnlink[descendantModel.name]![descendant.id]) {
152
- toUnlink[descendantModel.name]![descendant.id] = {
154
+ if (!toUnlink[descendantModel.name][descendant.id]) {
155
+ toUnlink[descendantModel.name][descendant.id] = {
153
156
  display: descendant[descendantModel.displayField || 'id'] || entity.id,
154
157
  fields: [],
155
158
  };
156
159
  }
157
- toUnlink[descendantModel.name]![descendant.id]!.fields.push(name);
160
+ toUnlink[descendantModel.name][descendant.id].fields.push(name);
158
161
  } else {
159
162
  mutations.push(async () => {
160
163
  await ctx
@@ -225,7 +228,7 @@ const restore = async (model: Model, { where }: { where: any }, ctx: FullContext
225
228
  const data = { prev: relatedEntity, input: {}, normalizedInput, next: { ...relatedEntity, ...normalizedInput } };
226
229
  if (ctx.mutationHook) {
227
230
  beforeHooks.push(async () => {
228
- await ctx.mutationHook!(model, 'restore', 'before', data, ctx);
231
+ await ctx.mutationHook(model, 'restore', 'before', data, ctx);
229
232
  });
230
233
  }
231
234
  mutations.push(async () => {
@@ -234,7 +237,7 @@ const restore = async (model: Model, { where }: { where: any }, ctx: FullContext
234
237
  });
235
238
  if (ctx.mutationHook) {
236
239
  afterHooks.push(async () => {
237
- await ctx.mutationHook!(model, 'restore', 'after', data, ctx);
240
+ await ctx.mutationHook(model, 'restore', 'after', data, ctx);
238
241
  });
239
242
  }
240
243
 
@@ -132,7 +132,7 @@ export const getFragmentSpreads = (node: ResolverNode) =>
132
132
  node.selectionSet.filter(isFragmentSpreadNode).map((subNode) =>
133
133
  getResolverNode({
134
134
  ctx: node.ctx,
135
- node: node.ctx.info.fragments[subNode.name.value]!,
135
+ node: node.ctx.info.fragments[subNode.name.value],
136
136
  tableAlias: node.tableAlias,
137
137
  baseTypeDefinition: node.baseTypeDefinition,
138
138
  typeName: node.model.name,
@@ -165,7 +165,7 @@ const applySubQueries = async (
165
165
  if (!entriesById[entry[ID_ALIAS]]) {
166
166
  entriesById[entry[ID_ALIAS]] = [];
167
167
  }
168
- entriesById[entry[ID_ALIAS]!]!.push(entry);
168
+ entriesById[entry[ID_ALIAS]].push(entry);
169
169
  }
170
170
  const ids = Object.keys(entriesById);
171
171
 
@@ -189,7 +189,7 @@ const applySubQueries = async (
189
189
  const children = hydrate(subNode, rawChildren);
190
190
 
191
191
  for (const child of children) {
192
- for (const entry of entriesById[child[foreignKey] as string]!) {
192
+ for (const entry of entriesById[child[foreignKey] as string]) {
193
193
  if (isList) {
194
194
  (entry[fieldName] as Entry[]).push(cloneDeep(child));
195
195
  } else {
@@ -72,13 +72,13 @@ export function hydrate<T extends Entry>(
72
72
  outer: for (const [column, value] of Object.entries(entry)) {
73
73
  let current = res;
74
74
  const shortParts = column.split('__');
75
- const fieldName = shortParts.pop()!;
75
+ const fieldName = shortParts.pop();
76
76
  const columnWithoutField = shortParts.join('__');
77
77
  const longColumn = node.ctx.aliases.getLong(columnWithoutField);
78
78
  const longColumnWithoutRoot = longColumn.replace(new RegExp(`^${tableAlias}(__)?`), '');
79
79
  const allParts = [tableAlias, ...(longColumnWithoutRoot ? longColumnWithoutRoot.split('__') : []), fieldName];
80
80
  for (let i = 0; i < allParts.length - 1; i++) {
81
- const part = allParts[i]!;
81
+ const part = allParts[i];
82
82
 
83
83
  if (!current[part]) {
84
84
  const idField = [node.ctx.aliases.getShort(allParts.slice(0, i + 1).join('__')), ID_ALIAS].join('__');
@@ -0,0 +1,22 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`query can be executed 1`] = `
4
+ {
5
+ "manyObjects": [
6
+ {
7
+ "another": {
8
+ "id": "226a20e8-5c18-4423-99ca-eb0df6ff4fdd",
9
+ "manyObjects": [
10
+ {
11
+ "field": null,
12
+ "id": "604ab55d-ec3e-4857-9f27-219158f80e64",
13
+ },
14
+ ],
15
+ },
16
+ "field": null,
17
+ "id": "604ab55d-ec3e-4857-9f27-219158f80e64",
18
+ "xyz": 1,
19
+ },
20
+ ],
21
+ }
22
+ `;
@@ -0,0 +1,28 @@
1
+ import { gql } from '../../src';
2
+ import { ANOTHER_ID, SOME_ID } from '../utils/database/seed';
3
+ import { withServer } from '../utils/server';
4
+
5
+ describe('query', () => {
6
+ it('can be executed', async () => {
7
+ await withServer(async (request) => {
8
+ expect(
9
+ await request(gql`
10
+ query SomeQuery {
11
+ manyObjects(where: { another: { id: "${ANOTHER_ID}" } }, orderBy: [{ xyz: DESC }]) {
12
+ id
13
+ field
14
+ xyz
15
+ another {
16
+ id
17
+ manyObjects(where: { id: "${SOME_ID}" }) {
18
+ id
19
+ field
20
+ }
21
+ }
22
+ }
23
+ }
24
+ `)
25
+ ).toMatchSnapshot();
26
+ });
27
+ });
28
+ });
@@ -38,6 +38,11 @@ type Query {
38
38
  manyObjects(where: SomeObjectWhere, search: String, orderBy: [SomeObjectOrderBy!], limit: Int, offset: Int): [SomeObject!]!
39
39
  }
40
40
 
41
+ enum Role {
42
+ ADMIN
43
+ USER
44
+ }
45
+
41
46
  enum SomeEnum {
42
47
  A
43
48
  B
@@ -89,6 +94,7 @@ scalar Upload
89
94
  type User {
90
95
  id: ID!
91
96
  username: String
97
+ role: Role
92
98
  createdManyObjects(where: SomeObjectWhere, search: String, orderBy: [SomeObjectOrderBy!], limit: Int, offset: Int): [SomeObject!]!
93
99
  updatedManyObjects(where: SomeObjectWhere, search: String, orderBy: [SomeObjectOrderBy!], limit: Int, offset: Int): [SomeObject!]!
94
100
  deletedManyObjects(where: SomeObjectWhere, search: String, orderBy: [SomeObjectOrderBy!], limit: Int, offset: Int): [SomeObject!]!
@@ -1,5 +1,5 @@
1
- import { printSchemaFromModels } from '../../src/generate';
2
- import { rawModels } from './utils';
1
+ import { printSchemaFromModels } from '../../src';
2
+ import { rawModels } from '../utils/models';
3
3
 
4
4
  describe('generate', () => {
5
5
  it('generates a schema', () => {
@@ -1,12 +1,12 @@
1
1
  import { makeExecutableSchema } from '@graphql-tools/schema';
2
2
  import { execute, parse, Source } from 'graphql';
3
3
  import knex from 'knex';
4
+ import { DateTime } from 'luxon';
4
5
  import { gql } from '../../src/client/gql';
5
6
  import { Context } from '../../src/context';
6
7
  import { generate } from '../../src/generate';
7
8
  import { getResolvers } from '../../src/resolvers';
8
- import { models, permissions, rawModels } from './utils';
9
- import { DateTime } from 'luxon';
9
+ import { models, permissions, rawModels } from '../utils/models';
10
10
 
11
11
  const test = async (operationName: string, query: string, variableValues: object, responses: unknown[]) => {
12
12
  const knexInstance = knex({
@@ -0,0 +1,19 @@
1
+ import knex from 'knex';
2
+
3
+ export const getKnex = (database = 'postgres') =>
4
+ knex({
5
+ client: 'postgresql',
6
+ connection: {
7
+ host: 'localhost',
8
+ database,
9
+ user: 'postgres',
10
+ password: 'password',
11
+ },
12
+ migrations: {
13
+ tableName: 'knex_migrations',
14
+ },
15
+ pool: {
16
+ min: 0,
17
+ max: 30,
18
+ },
19
+ });