@smartive/graphql-magic 16.3.7 → 16.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -2
- package/dist/bin/gqm.cjs +37 -35
- package/dist/cjs/index.cjs +51 -48
- package/dist/esm/api/execute.d.ts +1 -5
- package/dist/esm/api/execute.js.map +1 -1
- package/dist/esm/client/queries.d.ts +4 -4
- package/dist/esm/client/queries.js.map +1 -1
- package/dist/esm/db/generate.js +2 -0
- package/dist/esm/db/generate.js.map +1 -1
- package/dist/esm/migrations/generate.js +1 -1
- package/dist/esm/migrations/generate.js.map +1 -1
- package/dist/esm/models/models.d.ts +1 -1
- package/dist/esm/models/models.js.map +1 -1
- package/dist/esm/models/utils.d.ts +8 -12
- package/dist/esm/models/utils.js +3 -5
- package/dist/esm/models/utils.js.map +1 -1
- package/dist/esm/permissions/check.js +0 -15
- package/dist/esm/permissions/check.js.map +1 -1
- package/dist/esm/permissions/generate.d.ts +5 -19
- package/dist/esm/permissions/generate.js.map +1 -1
- package/dist/esm/resolvers/arguments.js.map +1 -1
- package/dist/esm/resolvers/filters.js +0 -2
- package/dist/esm/resolvers/filters.js.map +1 -1
- package/dist/esm/resolvers/mutations.js +5 -4
- package/dist/esm/resolvers/mutations.js.map +1 -1
- package/dist/esm/resolvers/node.js.map +1 -1
- package/dist/esm/resolvers/resolver.d.ts +2 -2
- package/dist/esm/resolvers/resolver.js +1 -1
- package/dist/esm/resolvers/resolver.js.map +1 -1
- package/dist/esm/resolvers/selects.js.map +1 -1
- package/dist/esm/resolvers/utils.d.ts +2 -6
- package/dist/esm/resolvers/utils.js +4 -2
- package/dist/esm/resolvers/utils.js.map +1 -1
- package/dist/esm/schema/utils.d.ts +4 -4
- package/dist/esm/schema/utils.js +31 -30
- package/dist/esm/schema/utils.js.map +1 -1
- package/dist/esm/utils/dates.d.ts +2 -4
- package/dist/esm/utils/dates.js +1 -3
- package/dist/esm/utils/dates.js.map +1 -1
- package/docs/docs/1-tutorial.md +1 -1
- package/eslint.config.mjs +42 -0
- package/migrations/20230912185644_setup.ts +1 -1
- package/package.json +6 -11
- package/src/api/execute.ts +1 -0
- package/src/bin/gqm/codegen.ts +1 -1
- package/src/client/gql.ts +1 -1
- package/src/client/mutations.ts +8 -8
- package/src/client/queries.ts +15 -14
- package/src/db/generate.ts +8 -5
- package/src/migrations/generate.ts +26 -22
- package/src/models/models.ts +24 -9
- package/src/models/mutation-hook.ts +1 -1
- package/src/models/utils.ts +8 -7
- package/src/permissions/check.ts +22 -30
- package/src/permissions/generate.ts +8 -25
- package/src/resolvers/arguments.ts +7 -2
- package/src/resolvers/filters.ts +8 -10
- package/src/resolvers/mutations.ts +19 -16
- package/src/resolvers/node.ts +3 -2
- package/src/resolvers/resolver.ts +11 -10
- package/src/resolvers/selects.ts +4 -3
- package/src/resolvers/utils.ts +15 -10
- package/src/schema/generate.ts +11 -11
- package/src/schema/utils.ts +84 -82
- package/src/utils/dates.ts +3 -3
- package/tests/generated/api/index.ts +2 -2
- package/tests/generated/client/index.ts +1 -193
- package/tests/generated/db/index.ts +4 -4
- package/tests/generated/models.json +2 -1
- package/tests/generated/schema.graphql +1 -1
- package/tests/utils/graphql-client.ts +49 -0
- package/tests/utils/models.ts +1 -0
- package/tests/utils/server.ts +4 -5
- package/tsconfig.eslint.json +18 -3
- package/tsconfig.json +3 -1
- package/.eslintrc +0 -13
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smartive/graphql-magic",
|
|
3
|
-
"version": "16.3.
|
|
3
|
+
"version": "16.3.8",
|
|
4
4
|
"description": "",
|
|
5
5
|
"source": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"generate:index-files": "cti create ./src --excludes bin --withoutbackup",
|
|
18
18
|
"generate:gqm-stuff": "npx gqm generate",
|
|
19
19
|
"generate:setup-migration": "npm run build:bin && npx gqm generate-migration setup 20230912185644",
|
|
20
|
-
"lint": "eslint src",
|
|
20
|
+
"lint": "eslint src/**/*.ts",
|
|
21
21
|
"lint:fix": "eslint src --fix",
|
|
22
22
|
"deps": "docker compose up",
|
|
23
23
|
"test": "npm run lint && npm run test:all && npm run build",
|
|
@@ -34,9 +34,6 @@
|
|
|
34
34
|
"bin": {
|
|
35
35
|
"gqm": "dist/bin/gqm.cjs"
|
|
36
36
|
},
|
|
37
|
-
"overrides": {
|
|
38
|
-
"graphql": "$graphql"
|
|
39
|
-
},
|
|
40
37
|
"browserslist": "> 0.25%, not dead",
|
|
41
38
|
"publishConfig": {
|
|
42
39
|
"access": "public"
|
|
@@ -46,7 +43,6 @@
|
|
|
46
43
|
"@graphql-codegen/add": "^5.0.0",
|
|
47
44
|
"@graphql-codegen/cli": "^5.0.0",
|
|
48
45
|
"@graphql-codegen/typescript": "^4.0.1",
|
|
49
|
-
"@graphql-codegen/typescript-compatibility": "^2.1.5",
|
|
50
46
|
"@graphql-codegen/typescript-operations": "^4.0.1",
|
|
51
47
|
"@graphql-codegen/typescript-resolvers": "^4.0.1",
|
|
52
48
|
"@types/node": "^22.13.5",
|
|
@@ -54,7 +50,7 @@
|
|
|
54
50
|
"commander": "^13.0.0",
|
|
55
51
|
"dayjs": "^1.11.10",
|
|
56
52
|
"dotenv": "^16.3.1",
|
|
57
|
-
"graphql": "^
|
|
53
|
+
"graphql": "^16.0.0",
|
|
58
54
|
"inflection": "^3.0.0",
|
|
59
55
|
"knex": "^3.0.1",
|
|
60
56
|
"knex-schema-inspector": "^3.1.0",
|
|
@@ -69,7 +65,7 @@
|
|
|
69
65
|
"knex": "^3.0.1"
|
|
70
66
|
},
|
|
71
67
|
"devDependencies": {
|
|
72
|
-
"@smartive/eslint-config": "
|
|
68
|
+
"@smartive/eslint-config": "6.5.0",
|
|
73
69
|
"@smartive/prettier-config": "3.1.2",
|
|
74
70
|
"@types/jest": "29.5.14",
|
|
75
71
|
"@types/lodash": "4.17.15",
|
|
@@ -79,11 +75,10 @@
|
|
|
79
75
|
"create-ts-index": "1.14.0",
|
|
80
76
|
"del-cli": "6.0.0",
|
|
81
77
|
"esbuild": "0.25.0",
|
|
82
|
-
"eslint": "
|
|
83
|
-
"graphql-request": "6.1.0",
|
|
78
|
+
"eslint": "9.21.0",
|
|
84
79
|
"jest": "29.7.0",
|
|
85
80
|
"mock-knex": "0.4.13",
|
|
86
|
-
"prettier": "
|
|
81
|
+
"prettier": "3.5.2",
|
|
87
82
|
"ts-jest": "29.2.6",
|
|
88
83
|
"ts-node": "10.9.2",
|
|
89
84
|
"typescript": "5.7.3"
|
package/src/api/execute.ts
CHANGED
package/src/bin/gqm/codegen.ts
CHANGED
|
@@ -30,7 +30,7 @@ export const generateGraphqlClientTypes = async () => {
|
|
|
30
30
|
documents: [graphqlQueriesPath, `${generatedFolderPath}/client/mutations.ts`],
|
|
31
31
|
generates: {
|
|
32
32
|
[`${generatedFolderPath}/client/index.ts`]: {
|
|
33
|
-
plugins: ['typescript', 'typescript-operations'
|
|
33
|
+
plugins: ['typescript', 'typescript-operations'],
|
|
34
34
|
},
|
|
35
35
|
},
|
|
36
36
|
config: {
|
package/src/client/gql.ts
CHANGED
package/src/client/mutations.ts
CHANGED
|
@@ -10,30 +10,30 @@ export const generateMutations = (models: Models, gqmModule = '@smartive/graphql
|
|
|
10
10
|
if (creatable) {
|
|
11
11
|
parts.push(
|
|
12
12
|
`export const CREATE_${constantCase(
|
|
13
|
-
name
|
|
14
|
-
)} = gql\`\n mutation Create${name}Mutation($data: Create${name}!) {\n create${name}(data: $data) { id }\n }\n
|
|
13
|
+
name,
|
|
14
|
+
)} = gql\`\n mutation Create${name}Mutation($data: Create${name}!) {\n create${name}(data: $data) { id }\n }\n\`;`,
|
|
15
15
|
);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
if (updatable) {
|
|
19
19
|
parts.push(
|
|
20
20
|
`export const UPDATE_${constantCase(
|
|
21
|
-
name
|
|
22
|
-
)} = gql\`\n mutation Update${name}Mutation($id: ID!, $data: Update${name}!) {\n update${name}(where: { id: $id }, data: $data) { id }\n }\n
|
|
21
|
+
name,
|
|
22
|
+
)} = gql\`\n mutation Update${name}Mutation($id: ID!, $data: Update${name}!) {\n update${name}(where: { id: $id }, data: $data) { id }\n }\n\`;`,
|
|
23
23
|
);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
if (deletable) {
|
|
27
27
|
parts.push(
|
|
28
28
|
`export const DELETE_${constantCase(
|
|
29
|
-
name
|
|
30
|
-
)} = gql\`\n mutation Delete${name}Mutation($id: ID!) {\n delete${name}(where: { id: $id })\n }\n
|
|
29
|
+
name,
|
|
30
|
+
)} = gql\`\n mutation Delete${name}Mutation($id: ID!) {\n delete${name}(where: { id: $id })\n }\n\`;`,
|
|
31
31
|
);
|
|
32
32
|
|
|
33
33
|
parts.push(
|
|
34
34
|
`export const RESTORE_${constantCase(
|
|
35
|
-
name
|
|
36
|
-
)} = gql\`\n mutation Restore${name}Mutation($id: ID!) {\n restore${name}(where: { id: $id })\n }\n
|
|
35
|
+
name,
|
|
36
|
+
)} = gql\`\n mutation Restore${name}Mutation($id: ID!) {\n restore${name}(where: { id: $id })\n }\n\`;`,
|
|
37
37
|
);
|
|
38
38
|
}
|
|
39
39
|
}
|
package/src/client/queries.ts
CHANGED
|
@@ -15,8 +15,8 @@ import {
|
|
|
15
15
|
export const getUpdateEntityQuery = (
|
|
16
16
|
model: EntityModel,
|
|
17
17
|
role: string,
|
|
18
|
-
fields?: string[]
|
|
19
|
-
additionalFields = ''
|
|
18
|
+
fields?: string[],
|
|
19
|
+
additionalFields = '',
|
|
20
20
|
) => `query Update${model.name}Fields ($id: ID!) {
|
|
21
21
|
data: ${typeToField(model.name)}(where: { id: $id }) {
|
|
22
22
|
id
|
|
@@ -39,6 +39,7 @@ export const fieldIsSearchable = (model: EntityModel, fieldName: string) => {
|
|
|
39
39
|
const relation = model.getRelation(fieldName);
|
|
40
40
|
const targetModel = relation.targetModel;
|
|
41
41
|
const displayField = targetModel.getField(targetModel.displayField || 'id');
|
|
42
|
+
|
|
42
43
|
return displayField.searchable;
|
|
43
44
|
};
|
|
44
45
|
|
|
@@ -52,7 +53,7 @@ export const getSelectEntityRelationsQuery = (model: EntityModel, relationNames:
|
|
|
52
53
|
(relation) =>
|
|
53
54
|
`$${relation.name}Where: ${relation.targetModel.name}Where, $${relation.name}Limit: Int${
|
|
54
55
|
fieldIsSearchable(model, relation.name) ? `, $${relation.name}Search: String` : ''
|
|
55
|
-
}
|
|
56
|
+
}`,
|
|
56
57
|
)
|
|
57
58
|
.join(', ')}) {
|
|
58
59
|
${relations
|
|
@@ -85,7 +86,7 @@ export const getSelectEntityRelationsQuery = (model: EntityModel, relationNames:
|
|
|
85
86
|
export const getManyToManyRelationsQuery = (
|
|
86
87
|
model: Model,
|
|
87
88
|
action: 'create' | 'update',
|
|
88
|
-
manyToManyRelations: ManyToManyRelation[]
|
|
89
|
+
manyToManyRelations: ManyToManyRelation[],
|
|
89
90
|
) =>
|
|
90
91
|
!!manyToManyRelations.length &&
|
|
91
92
|
(action === 'update'
|
|
@@ -138,14 +139,14 @@ export const getMutationQuery = (model: Model, action: 'create' | 'update' | 'de
|
|
|
138
139
|
}
|
|
139
140
|
`
|
|
140
141
|
: action === 'update'
|
|
141
|
-
|
|
142
|
+
? `
|
|
142
143
|
mutation Update${model.name} ($id: ID!, $data: Update${model.name}!) {
|
|
143
144
|
mutated: update${model.name}(where: { id: $id } data: $data) {
|
|
144
145
|
id
|
|
145
146
|
}
|
|
146
147
|
}
|
|
147
148
|
`
|
|
148
|
-
|
|
149
|
+
: `
|
|
149
150
|
mutation Delete${model.name} ($id: ID!) {
|
|
150
151
|
mutated: delete${model.name}(where: { id: $id }) {
|
|
151
152
|
id
|
|
@@ -162,7 +163,7 @@ export const getEntityListQuery = (
|
|
|
162
163
|
role: string,
|
|
163
164
|
relations?: string[],
|
|
164
165
|
fragment = '',
|
|
165
|
-
reverseRelation?: ReverseRelation
|
|
166
|
+
reverseRelation?: ReverseRelation,
|
|
166
167
|
) => `query ${model.plural}List(
|
|
167
168
|
${reverseRelation ? '$id: ID!,' : ''}
|
|
168
169
|
$limit: Int!,
|
|
@@ -171,14 +172,14 @@ export const getEntityListQuery = (
|
|
|
171
172
|
) {
|
|
172
173
|
${reverseRelation ? `root: ${typeToField(reverseRelation.sourceModel.name)}(where: { id: $id }) {` : ''}
|
|
173
174
|
data: ${reverseRelation ? reverseRelation.name : model.pluralField}(limit: $limit, where: $where, ${
|
|
174
|
-
|
|
175
|
-
}) {
|
|
175
|
+
model.fields.some(({ searchable }) => searchable) ? ', search: $search' : ''
|
|
176
|
+
}) {
|
|
176
177
|
${displayField(model)}
|
|
177
178
|
${model.fields.filter(and(isSimpleField, isQueriableBy(role))).map(({ name }) => name)}
|
|
178
179
|
${fragment}
|
|
179
180
|
${queryRelations(
|
|
180
181
|
model.models,
|
|
181
|
-
model.relations.filter((relation) => !relations || relations.includes(relation.name))
|
|
182
|
+
model.relations.filter((relation) => !relations || relations.includes(relation.name)),
|
|
182
183
|
)}
|
|
183
184
|
${fragment}
|
|
184
185
|
}
|
|
@@ -193,14 +194,14 @@ export const getEntityQuery = (model: EntityModel, role: string, relations?: str
|
|
|
193
194
|
${model.fields.filter(and(isSimpleField, isQueriableBy(role))).map(({ name }) => name)}
|
|
194
195
|
${queryRelations(
|
|
195
196
|
model.models,
|
|
196
|
-
model.relations.filter((relation) => !relations || relations.includes(relation.name))
|
|
197
|
+
model.relations.filter((relation) => !relations || relations.includes(relation.name)),
|
|
197
198
|
)}
|
|
198
199
|
${queryRelations(
|
|
199
200
|
model.models,
|
|
200
201
|
model.reverseRelations.filter(
|
|
201
202
|
(reverseRelation) =>
|
|
202
|
-
isToOneRelation(reverseRelation.field) && (!relations || relations.includes(reverseRelation.name))
|
|
203
|
-
)
|
|
203
|
+
isToOneRelation(reverseRelation.field) && (!relations || relations.includes(reverseRelation.name)),
|
|
204
|
+
),
|
|
204
205
|
)}
|
|
205
206
|
${fragment}
|
|
206
207
|
}
|
|
@@ -220,6 +221,6 @@ export const queryRelations = (models: Models, relations: Relation[]) =>
|
|
|
220
221
|
(relation): string => `${relation.name} {
|
|
221
222
|
id
|
|
222
223
|
${displayField(relation.targetModel)}
|
|
223
|
-
}
|
|
224
|
+
}`,
|
|
224
225
|
)
|
|
225
226
|
.join('\n');
|
package/src/db/generate.ts
CHANGED
|
@@ -15,6 +15,7 @@ const PRIMITIVE_TYPES = {
|
|
|
15
15
|
const OPTIONAL_SEED_FIELDS = ['createdAt', 'createdById', 'updatedAt', 'updatedById', 'deletedAt', 'deletedById'];
|
|
16
16
|
|
|
17
17
|
export const generateDBModels = (models: Models, dateLibrary: DateLibrary) => {
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
18
19
|
const writer: CodeBlockWriter = new CodeBlockWriter['default']({
|
|
19
20
|
useSingleQuote: true,
|
|
20
21
|
indentNumberOfSpaces: 2,
|
|
@@ -52,8 +53,8 @@ export const generateDBModels = (models: Models, dateLibrary: DateLibrary) => {
|
|
|
52
53
|
`'${getColumnName(field)}'${field.nonNull && field.defaultValue === undefined ? '' : '?'}: ${getFieldType(
|
|
53
54
|
field,
|
|
54
55
|
dateLibrary,
|
|
55
|
-
true
|
|
56
|
-
)}${field.list ? ' | string' : ''}${field.nonNull ? '' : ' | null'}
|
|
56
|
+
true,
|
|
57
|
+
)}${field.list ? ' | string' : ''}${field.nonNull ? '' : ' | null'};`,
|
|
57
58
|
)
|
|
58
59
|
.newLine();
|
|
59
60
|
}
|
|
@@ -68,7 +69,7 @@ export const generateDBModels = (models: Models, dateLibrary: DateLibrary) => {
|
|
|
68
69
|
.write(
|
|
69
70
|
`'${getColumnName(field)}'?: ${getFieldType(field, dateLibrary, true)}${field.list ? ' | string' : ''}${
|
|
70
71
|
field.nonNull ? '' : ' | null'
|
|
71
|
-
}
|
|
72
|
+
};`,
|
|
72
73
|
)
|
|
73
74
|
.newLine();
|
|
74
75
|
}
|
|
@@ -90,7 +91,7 @@ export const generateDBModels = (models: Models, dateLibrary: DateLibrary) => {
|
|
|
90
91
|
field.nonNull && field.defaultValue === undefined && !OPTIONAL_SEED_FIELDS.includes(fieldName) ? '' : '?'
|
|
91
92
|
}: ${field.kind === 'enum' ? (field.list ? 'string[]' : 'string') : getFieldType(field, dateLibrary, true)}${
|
|
92
93
|
field.list ? ' | string' : ''
|
|
93
|
-
}${field.nonNull ? '' : ' | null'}
|
|
94
|
+
}${field.nonNull ? '' : ' | null'};`,
|
|
94
95
|
)
|
|
95
96
|
.newLine();
|
|
96
97
|
}
|
|
@@ -126,6 +127,7 @@ const getFieldType = (field: EntityField, dateLibrary: DateLibrary, input?: bool
|
|
|
126
127
|
if (field.type === 'DateTime') {
|
|
127
128
|
return (input ? `(${DATE_CLASS[dateLibrary]} | string)` : DATE_CLASS[dateLibrary]) + (field.list ? '[]' : '');
|
|
128
129
|
}
|
|
130
|
+
|
|
129
131
|
return get(PRIMITIVE_TYPES, field.type) + (field.list ? '[]' : '');
|
|
130
132
|
default: {
|
|
131
133
|
const exhaustiveCheck: never = kind;
|
|
@@ -135,6 +137,7 @@ const getFieldType = (field: EntityField, dateLibrary: DateLibrary, input?: bool
|
|
|
135
137
|
};
|
|
136
138
|
|
|
137
139
|
export const generateKnexTables = (models: Models) => {
|
|
140
|
+
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
138
141
|
const writer: CodeBlockWriter = new CodeBlockWriter['default']({
|
|
139
142
|
useSingleQuote: true,
|
|
140
143
|
indentNumberOfSpaces: 2,
|
|
@@ -145,7 +148,7 @@ export const generateKnexTables = (models: Models) => {
|
|
|
145
148
|
.write(
|
|
146
149
|
`import { ${models.entities
|
|
147
150
|
.map((model) => `${model.name}, ${model.name}Initializer, ${model.name}Mutator`)
|
|
148
|
-
.join(', ')} } from '.'
|
|
151
|
+
.join(', ')} } from '.';`,
|
|
149
152
|
)
|
|
150
153
|
.blankLine();
|
|
151
154
|
|
|
@@ -22,6 +22,7 @@ import { Value } from '../values';
|
|
|
22
22
|
type Callbacks = (() => void)[];
|
|
23
23
|
|
|
24
24
|
export class MigrationGenerator {
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
25
26
|
private writer: CodeBlockWriter = new CodeBlockWriter['default']({
|
|
26
27
|
useSingleQuote: true,
|
|
27
28
|
indentNumberOfSpaces: 2,
|
|
@@ -31,7 +32,10 @@ export class MigrationGenerator {
|
|
|
31
32
|
private uuidUsed?: boolean;
|
|
32
33
|
private nowUsed?: boolean;
|
|
33
34
|
|
|
34
|
-
constructor(
|
|
35
|
+
constructor(
|
|
36
|
+
knex: Knex,
|
|
37
|
+
private models: Models,
|
|
38
|
+
) {
|
|
35
39
|
this.schema = SchemaInspector(knex);
|
|
36
40
|
}
|
|
37
41
|
|
|
@@ -49,7 +53,7 @@ export class MigrationGenerator {
|
|
|
49
53
|
this.createEnums(
|
|
50
54
|
this.models.enums.filter((enm) => !enums.includes(lowerFirst(enm.name))),
|
|
51
55
|
up,
|
|
52
|
-
down
|
|
56
|
+
down,
|
|
53
57
|
);
|
|
54
58
|
|
|
55
59
|
for (const model of models.entities) {
|
|
@@ -81,10 +85,10 @@ export class MigrationGenerator {
|
|
|
81
85
|
if (model.oldName) {
|
|
82
86
|
// Rename table
|
|
83
87
|
up.push(() => {
|
|
84
|
-
this.renameTable(model.oldName
|
|
88
|
+
this.renameTable(model.oldName!, model.name);
|
|
85
89
|
});
|
|
86
90
|
down.push(() => {
|
|
87
|
-
this.renameTable(model.name, model.oldName);
|
|
91
|
+
this.renameTable(model.name, model.oldName!);
|
|
88
92
|
});
|
|
89
93
|
tables[tables.indexOf(model.oldName)] = model.name;
|
|
90
94
|
this.columns[model.name] = this.columns[model.oldName];
|
|
@@ -137,7 +141,7 @@ export class MigrationGenerator {
|
|
|
137
141
|
model,
|
|
138
142
|
model.fields.filter(not(isInherited)).filter(({ oldName }) => oldName),
|
|
139
143
|
up,
|
|
140
|
-
down
|
|
144
|
+
down,
|
|
141
145
|
);
|
|
142
146
|
|
|
143
147
|
// Add missing fields
|
|
@@ -148,10 +152,10 @@ export class MigrationGenerator {
|
|
|
148
152
|
.filter(
|
|
149
153
|
({ name, ...field }) =>
|
|
150
154
|
field.kind !== 'custom' &&
|
|
151
|
-
!this.getColumn(model.name, field.kind === 'relation' ? field.foreignKey || `${name}Id` : name)
|
|
155
|
+
!this.getColumn(model.name, field.kind === 'relation' ? field.foreignKey || `${name}Id` : name),
|
|
152
156
|
),
|
|
153
157
|
up,
|
|
154
|
-
down
|
|
158
|
+
down,
|
|
155
159
|
);
|
|
156
160
|
|
|
157
161
|
// Update fields
|
|
@@ -160,6 +164,7 @@ export class MigrationGenerator {
|
|
|
160
164
|
if (!col) {
|
|
161
165
|
return false;
|
|
162
166
|
}
|
|
167
|
+
|
|
163
168
|
return !nonNull && !col.is_nullable;
|
|
164
169
|
});
|
|
165
170
|
this.updateFields(model, existingFields, up, down);
|
|
@@ -215,7 +220,7 @@ export class MigrationGenerator {
|
|
|
215
220
|
.filter(
|
|
216
221
|
({ name, ...field }) =>
|
|
217
222
|
field.kind !== 'custom' &&
|
|
218
|
-
!this.getColumn(revisionTable, field.kind === 'relation' ? field.foreignKey || `${name}Id` : name)
|
|
223
|
+
!this.getColumn(revisionTable, field.kind === 'relation' ? field.foreignKey || `${name}Id` : name),
|
|
219
224
|
);
|
|
220
225
|
|
|
221
226
|
this.createRevisionFields(model, missingRevisionFields, up, down);
|
|
@@ -226,7 +231,7 @@ export class MigrationGenerator {
|
|
|
226
231
|
field.kind !== 'custom' &&
|
|
227
232
|
!updatable &&
|
|
228
233
|
!(field.kind === 'relation' && field.foreignKey === 'id') &&
|
|
229
|
-
this.getColumn(revisionTable, field.kind === 'relation' ? field.foreignKey || `${name}Id` : name)
|
|
234
|
+
this.getColumn(revisionTable, field.kind === 'relation' ? field.foreignKey || `${name}Id` : name),
|
|
230
235
|
);
|
|
231
236
|
this.createRevisionFields(model, revisionFieldsToRemove, down, up);
|
|
232
237
|
}
|
|
@@ -267,7 +272,7 @@ export class MigrationGenerator {
|
|
|
267
272
|
model,
|
|
268
273
|
model.fields.filter(isUpdatableField).filter(({ deleted }) => deleted),
|
|
269
274
|
down,
|
|
270
|
-
up
|
|
275
|
+
up,
|
|
271
276
|
);
|
|
272
277
|
}
|
|
273
278
|
}
|
|
@@ -276,7 +281,7 @@ export class MigrationGenerator {
|
|
|
276
281
|
this.createEnums(
|
|
277
282
|
this.models.enums.filter((enm) => enm.deleted),
|
|
278
283
|
down,
|
|
279
|
-
up
|
|
284
|
+
up,
|
|
280
285
|
);
|
|
281
286
|
|
|
282
287
|
writer.writeLine(`import { Knex } from 'knex';`);
|
|
@@ -308,7 +313,7 @@ export class MigrationGenerator {
|
|
|
308
313
|
this.alterTable(model.name, () => {
|
|
309
314
|
this.renameColumn(
|
|
310
315
|
field.kind === 'relation' ? `${field.oldName}Id` : get(field, 'oldName'),
|
|
311
|
-
field.kind === 'relation' ? `${field.name}Id` : field.name
|
|
316
|
+
field.kind === 'relation' ? `${field.name}Id` : field.name,
|
|
312
317
|
);
|
|
313
318
|
});
|
|
314
319
|
}
|
|
@@ -319,15 +324,14 @@ export class MigrationGenerator {
|
|
|
319
324
|
this.alterTable(model.name, () => {
|
|
320
325
|
this.renameColumn(
|
|
321
326
|
field.kind === 'relation' ? `${field.name}Id` : field.name,
|
|
322
|
-
field.kind === 'relation' ? `${field.oldName}Id` : get(field, 'oldName')
|
|
327
|
+
field.kind === 'relation' ? `${field.oldName}Id` : get(field, 'oldName'),
|
|
323
328
|
);
|
|
324
329
|
});
|
|
325
330
|
}
|
|
326
331
|
});
|
|
327
332
|
|
|
328
333
|
for (const field of fields) {
|
|
329
|
-
|
|
330
|
-
summonByName(this.columns[model.name]!, field.kind === 'relation' ? `${field.oldName!}Id` : field.oldName!).name =
|
|
334
|
+
summonByName(this.columns[model.name], field.kind === 'relation' ? `${field.oldName!}Id` : field.oldName!).name =
|
|
331
335
|
field.kind === 'relation' ? `${field.name}Id` : field.name;
|
|
332
336
|
}
|
|
333
337
|
}
|
|
@@ -400,7 +404,7 @@ export class MigrationGenerator {
|
|
|
400
404
|
this.column(
|
|
401
405
|
field,
|
|
402
406
|
{ alter: true },
|
|
403
|
-
summonByName(this.columns[model.name], field.kind === 'relation' ? `${field.name}Id` : field.name)
|
|
407
|
+
summonByName(this.columns[model.name], field.kind === 'relation' ? `${field.name}Id` : field.name),
|
|
404
408
|
);
|
|
405
409
|
}
|
|
406
410
|
});
|
|
@@ -426,7 +430,7 @@ export class MigrationGenerator {
|
|
|
426
430
|
this.column(
|
|
427
431
|
field,
|
|
428
432
|
{ alter: true },
|
|
429
|
-
summonByName(this.columns[model.name], field.kind === 'relation' ? `${field.name}Id` : field.name)
|
|
433
|
+
summonByName(this.columns[model.name], field.kind === 'relation' ? `${field.name}Id` : field.name),
|
|
430
434
|
);
|
|
431
435
|
}
|
|
432
436
|
});
|
|
@@ -476,7 +480,7 @@ export class MigrationGenerator {
|
|
|
476
480
|
.write(
|
|
477
481
|
`${col}: knex.raw('(select "${col}" from "${model.name}" where "${model.name}".id = "${
|
|
478
482
|
model.name
|
|
479
|
-
}Revision"."${typeToField(model.name)}Id")')
|
|
483
|
+
}Revision"."${typeToField(model.name)}Id")'),`,
|
|
480
484
|
)
|
|
481
485
|
.newLine();
|
|
482
486
|
}
|
|
@@ -511,9 +515,9 @@ export class MigrationGenerator {
|
|
|
511
515
|
up.push(() =>
|
|
512
516
|
this.writer
|
|
513
517
|
.writeLine(
|
|
514
|
-
`await knex.raw(\`CREATE TYPE "${name}" AS ENUM (${enm.values.map((value) => `'${value}'`).join(',')})\`)
|
|
518
|
+
`await knex.raw(\`CREATE TYPE "${name}" AS ENUM (${enm.values.map((value) => `'${value}'`).join(',')})\`);`,
|
|
515
519
|
)
|
|
516
|
-
.newLine()
|
|
520
|
+
.newLine(),
|
|
517
521
|
);
|
|
518
522
|
down.push(() => this.writer.writeLine(`await knex.raw('DROP TYPE "${name}"');`));
|
|
519
523
|
}
|
|
@@ -575,7 +579,7 @@ export class MigrationGenerator {
|
|
|
575
579
|
private column(
|
|
576
580
|
{ name, primary, list, ...field }: EntityField,
|
|
577
581
|
{ setUnique = true, setNonNull = true, alter = false, foreign = true, setDefault = true } = {},
|
|
578
|
-
toColumn?: Column
|
|
582
|
+
toColumn?: Column,
|
|
579
583
|
) {
|
|
580
584
|
const col = (what?: string) => {
|
|
581
585
|
if (what) {
|
|
@@ -648,7 +652,7 @@ export class MigrationGenerator {
|
|
|
648
652
|
col(`table.uuid('${field.foreignKey}')`);
|
|
649
653
|
if (foreign && !alter) {
|
|
650
654
|
this.writer.writeLine(
|
|
651
|
-
`table.foreign('${field.foreignKey}').references('id').inTable('${field.type}').onDelete('CASCADE')
|
|
655
|
+
`table.foreign('${field.foreignKey}').references('id').inTable('${field.type}').onDelete('CASCADE');`,
|
|
652
656
|
);
|
|
653
657
|
}
|
|
654
658
|
break;
|
package/src/models/models.ts
CHANGED
|
@@ -71,7 +71,7 @@ export class Models {
|
|
|
71
71
|
kind: 'raw-enum',
|
|
72
72
|
name: 'Order',
|
|
73
73
|
values: ['ASC', 'DESC'],
|
|
74
|
-
}
|
|
74
|
+
},
|
|
75
75
|
);
|
|
76
76
|
const entities = this.definitions.filter(isEntityModelDefinition);
|
|
77
77
|
|
|
@@ -204,7 +204,7 @@ export class Models {
|
|
|
204
204
|
}
|
|
205
205
|
|
|
206
206
|
this.models = this.definitions.map(
|
|
207
|
-
(definition) => new (MODEL_KIND_TO_CLASS_MAPPING[definition.kind] as any)(this, definition)
|
|
207
|
+
(definition) => new (MODEL_KIND_TO_CLASS_MAPPING[definition.kind] as any)(this, definition),
|
|
208
208
|
);
|
|
209
209
|
for (const model of this.models) {
|
|
210
210
|
this.modelsByName[model.name] = model;
|
|
@@ -228,6 +228,7 @@ export class Models {
|
|
|
228
228
|
if (!(model instanceof expectedType)) {
|
|
229
229
|
throw new Error(`Model ${name} is not of kind ${kind}.`);
|
|
230
230
|
}
|
|
231
|
+
|
|
231
232
|
return model as ModelKindToClassMapping[K];
|
|
232
233
|
}
|
|
233
234
|
}
|
|
@@ -237,7 +238,10 @@ export abstract class Model {
|
|
|
237
238
|
plural: string;
|
|
238
239
|
description: string;
|
|
239
240
|
|
|
240
|
-
constructor(
|
|
241
|
+
constructor(
|
|
242
|
+
public models: Models,
|
|
243
|
+
definition: ModelDefinition,
|
|
244
|
+
) {
|
|
241
245
|
Object.assign(this, definition);
|
|
242
246
|
this.plural = definition.plural || pluralize(definition.name);
|
|
243
247
|
}
|
|
@@ -358,6 +362,7 @@ export class EntityModel extends Model {
|
|
|
358
362
|
.filter(isRelation)
|
|
359
363
|
.map((relationField) => new NormalRelation(this, relationField, this.models.getModel(relationField.type, 'entity')));
|
|
360
364
|
}
|
|
365
|
+
|
|
361
366
|
return this._relations;
|
|
362
367
|
}
|
|
363
368
|
|
|
@@ -368,6 +373,7 @@ export class EntityModel extends Model {
|
|
|
368
373
|
this._relationsByName[relation.name] = relation;
|
|
369
374
|
}
|
|
370
375
|
}
|
|
376
|
+
|
|
371
377
|
return this._relationsByName;
|
|
372
378
|
}
|
|
373
379
|
|
|
@@ -380,9 +386,10 @@ export class EntityModel extends Model {
|
|
|
380
386
|
this._reverseRelations = this.models.entities.flatMap((model) =>
|
|
381
387
|
model.relations
|
|
382
388
|
.filter((relation) => relation.targetModel.name === this.name || relation.targetModel.name === this.rootModel.name)
|
|
383
|
-
.map((relation) => relation.reverse)
|
|
389
|
+
.map((relation) => relation.reverse),
|
|
384
390
|
);
|
|
385
391
|
}
|
|
392
|
+
|
|
386
393
|
return this._reverseRelations;
|
|
387
394
|
}
|
|
388
395
|
|
|
@@ -393,6 +400,7 @@ export class EntityModel extends Model {
|
|
|
393
400
|
this._reverseRelationsByName[reverseRelation.name] = reverseRelation;
|
|
394
401
|
}
|
|
395
402
|
}
|
|
403
|
+
|
|
396
404
|
return this._reverseRelationsByName;
|
|
397
405
|
}
|
|
398
406
|
|
|
@@ -405,7 +413,7 @@ export class EntityModel extends Model {
|
|
|
405
413
|
this._manyToManyRelations = [];
|
|
406
414
|
for (const relationFromSource of this.reverseRelations) {
|
|
407
415
|
const relationToTarget = relationFromSource.targetModel.relations.find(
|
|
408
|
-
(relation) => !relation.field.generated && relation.field.name !== relationFromSource.field.name
|
|
416
|
+
(relation) => !relation.field.generated && relation.field.name !== relationFromSource.field.name,
|
|
409
417
|
);
|
|
410
418
|
if (!relationToTarget) {
|
|
411
419
|
continue;
|
|
@@ -413,7 +421,7 @@ export class EntityModel extends Model {
|
|
|
413
421
|
|
|
414
422
|
const inapplicableFields = relationFromSource.targetModel.fields.filter(
|
|
415
423
|
(otherField) =>
|
|
416
|
-
!otherField.generated && ![relationFromSource.field.name, relationToTarget.field.name].includes(otherField.name)
|
|
424
|
+
!otherField.generated && ![relationFromSource.field.name, relationToTarget.field.name].includes(otherField.name),
|
|
417
425
|
);
|
|
418
426
|
if (inapplicableFields.length) {
|
|
419
427
|
continue;
|
|
@@ -422,6 +430,7 @@ export class EntityModel extends Model {
|
|
|
422
430
|
this._manyToManyRelations.push(new ManyToManyRelation(relationFromSource, relationToTarget));
|
|
423
431
|
}
|
|
424
432
|
}
|
|
433
|
+
|
|
425
434
|
return this._manyToManyRelations;
|
|
426
435
|
}
|
|
427
436
|
|
|
@@ -432,6 +441,7 @@ export class EntityModel extends Model {
|
|
|
432
441
|
this._manyToManyRelationsByName[manyToManyRelation.name] = manyToManyRelation;
|
|
433
442
|
}
|
|
434
443
|
}
|
|
444
|
+
|
|
435
445
|
return this._manyToManyRelationsByName;
|
|
436
446
|
}
|
|
437
447
|
|
|
@@ -444,6 +454,7 @@ export class EntityModel extends Model {
|
|
|
444
454
|
if (!this._parentModel) {
|
|
445
455
|
this._parentModel = this.models.getModel(this.parent, 'entity');
|
|
446
456
|
}
|
|
457
|
+
|
|
447
458
|
return this._parentModel;
|
|
448
459
|
}
|
|
449
460
|
}
|
|
@@ -472,14 +483,18 @@ export abstract class Relation {
|
|
|
472
483
|
public name: string,
|
|
473
484
|
public sourceModel: EntityModel,
|
|
474
485
|
public field: RelationField,
|
|
475
|
-
public targetModel: EntityModel
|
|
486
|
+
public targetModel: EntityModel,
|
|
476
487
|
) {}
|
|
477
488
|
}
|
|
478
489
|
|
|
479
490
|
export class NormalRelation extends Relation {
|
|
480
491
|
public reverse: ReverseRelation;
|
|
481
492
|
|
|
482
|
-
constructor(
|
|
493
|
+
constructor(
|
|
494
|
+
sourceModel: EntityModel,
|
|
495
|
+
public field: RelationField,
|
|
496
|
+
targetModel: EntityModel,
|
|
497
|
+
) {
|
|
483
498
|
super(field.name, sourceModel, field, targetModel);
|
|
484
499
|
this.reverse = new ReverseRelation(this);
|
|
485
500
|
}
|
|
@@ -492,7 +507,7 @@ export class ReverseRelation extends Relation {
|
|
|
492
507
|
(reverse.field.toOne ? typeToField(reverse.sourceModel.name) : reverse.sourceModel.pluralField),
|
|
493
508
|
reverse.targetModel,
|
|
494
509
|
reverse.field,
|
|
495
|
-
reverse.sourceModel
|
|
510
|
+
reverse.sourceModel,
|
|
496
511
|
);
|
|
497
512
|
}
|
|
498
513
|
}
|
|
@@ -10,5 +10,5 @@ export type MutationHook<DateType extends AnyDateType = AnyDateType> = (
|
|
|
10
10
|
action: Action,
|
|
11
11
|
when: 'before' | 'after',
|
|
12
12
|
data: { prev: Entity; input: Entity; normalizedInput: Entity; next: Entity },
|
|
13
|
-
ctx: Context<DateType
|
|
13
|
+
ctx: Context<DateType>,
|
|
14
14
|
) => Promise<void>;
|