@constructive-io/graphql-query 2.4.6 → 2.5.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/ast.d.ts +10 -38
- package/ast.js +287 -336
- package/custom-ast.d.ts +20 -3
- package/custom-ast.js +115 -15
- package/esm/ast.js +286 -336
- package/esm/custom-ast.js +111 -15
- package/esm/index.js +2 -341
- package/esm/meta-object/convert.js +14 -9
- package/esm/meta-object/format.json +56 -16
- package/esm/meta-object/validate.js +1 -1
- package/esm/query-builder.js +379 -0
- package/esm/types.js +24 -0
- package/index.d.ts +2 -21
- package/index.js +7 -346
- package/meta-object/convert.d.ts +62 -3
- package/meta-object/convert.js +14 -9
- package/meta-object/format.json +56 -16
- package/meta-object/validate.js +1 -1
- package/package.json +4 -4
- package/query-builder.d.ts +47 -0
- package/query-builder.js +419 -0
- package/types.d.ts +139 -0
- package/types.js +28 -0
package/esm/ast.js
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
import * as t from 'gql-ast';
|
|
3
2
|
import inflection from 'inflection';
|
|
4
|
-
import { getCustomAst
|
|
5
|
-
const isObject = val => val !== null && typeof val === 'object';
|
|
3
|
+
import { getCustomAst } from './custom-ast';
|
|
6
4
|
const NON_MUTABLE_PROPS = ['createdAt', 'createdBy', 'updatedAt', 'updatedBy'];
|
|
7
|
-
const objectToArray = (obj) => Object.keys(obj).map((k) => ({
|
|
8
|
-
|
|
5
|
+
const objectToArray = (obj) => Object.keys(obj).map((k) => ({
|
|
6
|
+
key: k,
|
|
7
|
+
name: obj[k].name || k,
|
|
8
|
+
type: obj[k].type,
|
|
9
|
+
isNotNull: obj[k].isNotNull,
|
|
10
|
+
isArray: obj[k].isArray,
|
|
11
|
+
isArrayNotNull: obj[k].isArrayNotNull,
|
|
12
|
+
properties: obj[k].properties,
|
|
13
|
+
}));
|
|
14
|
+
const createGqlMutation = ({ operationName, mutationName, selectArgs, selections, variableDefinitions, modelName, useModel = true, }) => {
|
|
9
15
|
const opSel = !modelName
|
|
10
16
|
? [
|
|
11
17
|
t.field({
|
|
12
18
|
name: operationName,
|
|
13
19
|
args: selectArgs,
|
|
14
|
-
selectionSet: t.selectionSet({ selections })
|
|
15
|
-
})
|
|
20
|
+
selectionSet: t.selectionSet({ selections }),
|
|
21
|
+
}),
|
|
16
22
|
]
|
|
17
23
|
: [
|
|
18
24
|
t.field({
|
|
@@ -23,12 +29,12 @@ const createGqlMutation = ({ operationName, mutationName, selectArgs, selections
|
|
|
23
29
|
? [
|
|
24
30
|
t.field({
|
|
25
31
|
name: modelName,
|
|
26
|
-
selectionSet: t.selectionSet({ selections })
|
|
27
|
-
})
|
|
32
|
+
selectionSet: t.selectionSet({ selections }),
|
|
33
|
+
}),
|
|
28
34
|
]
|
|
29
|
-
: selections
|
|
30
|
-
})
|
|
31
|
-
})
|
|
35
|
+
: selections,
|
|
36
|
+
}),
|
|
37
|
+
}),
|
|
32
38
|
];
|
|
33
39
|
return t.document({
|
|
34
40
|
definitions: [
|
|
@@ -36,225 +42,194 @@ const createGqlMutation = ({ operationName, mutationName, selectArgs, selections
|
|
|
36
42
|
operation: 'mutation',
|
|
37
43
|
name: mutationName,
|
|
38
44
|
variableDefinitions,
|
|
39
|
-
selectionSet: t.selectionSet({ selections: opSel })
|
|
40
|
-
})
|
|
41
|
-
]
|
|
45
|
+
selectionSet: t.selectionSet({ selections: opSel }),
|
|
46
|
+
}),
|
|
47
|
+
],
|
|
42
48
|
});
|
|
43
49
|
};
|
|
44
|
-
export const getAll = ({ queryName, operationName, query, selection }) => {
|
|
50
|
+
export const getAll = ({ queryName, operationName, query: _query, selection, }) => {
|
|
45
51
|
const selections = getSelections(selection);
|
|
46
52
|
const opSel = [
|
|
47
53
|
t.field({
|
|
48
54
|
name: operationName,
|
|
49
|
-
selectionSet: t.
|
|
50
|
-
|
|
55
|
+
selectionSet: t.selectionSet({
|
|
56
|
+
selections: [
|
|
51
57
|
t.field({
|
|
52
|
-
name: 'totalCount'
|
|
58
|
+
name: 'totalCount',
|
|
53
59
|
}),
|
|
54
60
|
t.field({
|
|
55
61
|
name: 'nodes',
|
|
56
|
-
selectionSet: t.selectionSet({ selections })
|
|
57
|
-
})
|
|
58
|
-
]
|
|
59
|
-
})
|
|
60
|
-
})
|
|
62
|
+
selectionSet: t.selectionSet({ selections }),
|
|
63
|
+
}),
|
|
64
|
+
],
|
|
65
|
+
}),
|
|
66
|
+
}),
|
|
61
67
|
];
|
|
62
68
|
const ast = t.document({
|
|
63
69
|
definitions: [
|
|
64
70
|
t.operationDefinition({
|
|
65
71
|
operation: 'query',
|
|
66
72
|
name: queryName,
|
|
67
|
-
selectionSet: t.selectionSet({ selections: opSel })
|
|
68
|
-
})
|
|
69
|
-
]
|
|
73
|
+
selectionSet: t.selectionSet({ selections: opSel }),
|
|
74
|
+
}),
|
|
75
|
+
],
|
|
76
|
+
});
|
|
77
|
+
return ast;
|
|
78
|
+
};
|
|
79
|
+
export const getCount = ({ queryName, operationName, query, }) => {
|
|
80
|
+
const Singular = query.model;
|
|
81
|
+
const Filter = `${Singular}Filter`;
|
|
82
|
+
const Condition = `${Singular}Condition`;
|
|
83
|
+
const variableDefinitions = [
|
|
84
|
+
t.variableDefinition({
|
|
85
|
+
variable: t.variable({ name: 'condition' }),
|
|
86
|
+
type: t.namedType({ type: Condition }),
|
|
87
|
+
}),
|
|
88
|
+
t.variableDefinition({
|
|
89
|
+
variable: t.variable({ name: 'filter' }),
|
|
90
|
+
type: t.namedType({ type: Filter }),
|
|
91
|
+
}),
|
|
92
|
+
];
|
|
93
|
+
const args = [
|
|
94
|
+
t.argument({ name: 'condition', value: t.variable({ name: 'condition' }) }),
|
|
95
|
+
t.argument({ name: 'filter', value: t.variable({ name: 'filter' }) }),
|
|
96
|
+
];
|
|
97
|
+
// PostGraphile supports totalCount through connections
|
|
98
|
+
const opSel = [
|
|
99
|
+
t.field({
|
|
100
|
+
name: operationName,
|
|
101
|
+
args,
|
|
102
|
+
selectionSet: t.selectionSet({
|
|
103
|
+
selections: [
|
|
104
|
+
t.field({
|
|
105
|
+
name: 'totalCount',
|
|
106
|
+
}),
|
|
107
|
+
],
|
|
108
|
+
}),
|
|
109
|
+
}),
|
|
110
|
+
];
|
|
111
|
+
const ast = t.document({
|
|
112
|
+
definitions: [
|
|
113
|
+
t.operationDefinition({
|
|
114
|
+
operation: 'query',
|
|
115
|
+
name: queryName,
|
|
116
|
+
variableDefinitions,
|
|
117
|
+
selectionSet: t.selectionSet({ selections: opSel }),
|
|
118
|
+
}),
|
|
119
|
+
],
|
|
70
120
|
});
|
|
71
121
|
return ast;
|
|
72
122
|
};
|
|
73
|
-
export const getMany = ({ builder,
|
|
74
|
-
queryName, operationName, query, selection }) => {
|
|
123
|
+
export const getMany = ({ builder, queryName, operationName, query, selection, }) => {
|
|
75
124
|
const Singular = query.model;
|
|
76
125
|
const Plural = operationName.charAt(0).toUpperCase() + operationName.slice(1);
|
|
77
126
|
const Condition = `${Singular}Condition`;
|
|
78
127
|
const Filter = `${Singular}Filter`;
|
|
79
128
|
const OrderBy = `${Plural}OrderBy`;
|
|
80
129
|
const selections = getSelections(selection);
|
|
130
|
+
const variableDefinitions = [
|
|
131
|
+
t.variableDefinition({
|
|
132
|
+
variable: t.variable({ name: 'first' }),
|
|
133
|
+
type: t.namedType({ type: 'Int' }),
|
|
134
|
+
}),
|
|
135
|
+
t.variableDefinition({
|
|
136
|
+
variable: t.variable({ name: 'last' }),
|
|
137
|
+
type: t.namedType({ type: 'Int' }),
|
|
138
|
+
}),
|
|
139
|
+
t.variableDefinition({
|
|
140
|
+
variable: t.variable({ name: 'after' }),
|
|
141
|
+
type: t.namedType({ type: 'Cursor' }),
|
|
142
|
+
}),
|
|
143
|
+
t.variableDefinition({
|
|
144
|
+
variable: t.variable({ name: 'before' }),
|
|
145
|
+
type: t.namedType({ type: 'Cursor' }),
|
|
146
|
+
}),
|
|
147
|
+
t.variableDefinition({
|
|
148
|
+
variable: t.variable({ name: 'offset' }),
|
|
149
|
+
type: t.namedType({ type: 'Int' }),
|
|
150
|
+
}),
|
|
151
|
+
t.variableDefinition({
|
|
152
|
+
variable: t.variable({ name: 'condition' }),
|
|
153
|
+
type: t.namedType({ type: Condition }),
|
|
154
|
+
}),
|
|
155
|
+
t.variableDefinition({
|
|
156
|
+
variable: t.variable({ name: 'filter' }),
|
|
157
|
+
type: t.namedType({ type: Filter }),
|
|
158
|
+
}),
|
|
159
|
+
t.variableDefinition({
|
|
160
|
+
variable: t.variable({ name: 'orderBy' }),
|
|
161
|
+
type: t.listType({
|
|
162
|
+
type: t.nonNullType({ type: t.namedType({ type: OrderBy }) }),
|
|
163
|
+
}),
|
|
164
|
+
}),
|
|
165
|
+
];
|
|
166
|
+
const args = [
|
|
167
|
+
t.argument({ name: 'first', value: t.variable({ name: 'first' }) }),
|
|
168
|
+
t.argument({ name: 'last', value: t.variable({ name: 'last' }) }),
|
|
169
|
+
t.argument({ name: 'offset', value: t.variable({ name: 'offset' }) }),
|
|
170
|
+
t.argument({ name: 'after', value: t.variable({ name: 'after' }) }),
|
|
171
|
+
t.argument({ name: 'before', value: t.variable({ name: 'before' }) }),
|
|
172
|
+
t.argument({ name: 'condition', value: t.variable({ name: 'condition' }) }),
|
|
173
|
+
t.argument({ name: 'filter', value: t.variable({ name: 'filter' }) }),
|
|
174
|
+
t.argument({ name: 'orderBy', value: t.variable({ name: 'orderBy' }) }),
|
|
175
|
+
];
|
|
176
|
+
const pageInfoFields = [
|
|
177
|
+
t.field({ name: 'hasNextPage' }),
|
|
178
|
+
t.field({ name: 'hasPreviousPage' }),
|
|
179
|
+
t.field({ name: 'endCursor' }),
|
|
180
|
+
t.field({ name: 'startCursor' }),
|
|
181
|
+
];
|
|
182
|
+
const dataField = builder?._edges
|
|
183
|
+
? t.field({
|
|
184
|
+
name: 'edges',
|
|
185
|
+
selectionSet: t.selectionSet({
|
|
186
|
+
selections: [
|
|
187
|
+
t.field({ name: 'cursor' }),
|
|
188
|
+
t.field({
|
|
189
|
+
name: 'node',
|
|
190
|
+
selectionSet: t.selectionSet({ selections }),
|
|
191
|
+
}),
|
|
192
|
+
],
|
|
193
|
+
}),
|
|
194
|
+
})
|
|
195
|
+
: t.field({
|
|
196
|
+
name: 'nodes',
|
|
197
|
+
selectionSet: t.selectionSet({ selections }),
|
|
198
|
+
});
|
|
199
|
+
const connectionFields = [
|
|
200
|
+
t.field({ name: 'totalCount' }),
|
|
201
|
+
t.field({
|
|
202
|
+
name: 'pageInfo',
|
|
203
|
+
selectionSet: t.selectionSet({ selections: pageInfoFields }),
|
|
204
|
+
}),
|
|
205
|
+
dataField,
|
|
206
|
+
];
|
|
81
207
|
const ast = t.document({
|
|
82
208
|
definitions: [
|
|
83
209
|
t.operationDefinition({
|
|
84
210
|
operation: 'query',
|
|
85
211
|
name: queryName,
|
|
86
|
-
variableDefinitions
|
|
87
|
-
t.variableDefinition({
|
|
88
|
-
variable: t.variable({
|
|
89
|
-
name: 'first'
|
|
90
|
-
}),
|
|
91
|
-
type: t.namedType({
|
|
92
|
-
type: 'Int'
|
|
93
|
-
})
|
|
94
|
-
}),
|
|
95
|
-
t.variableDefinition({
|
|
96
|
-
variable: t.variable({
|
|
97
|
-
name: 'last'
|
|
98
|
-
}),
|
|
99
|
-
type: t.namedType({
|
|
100
|
-
type: 'Int'
|
|
101
|
-
})
|
|
102
|
-
}),
|
|
103
|
-
t.variableDefinition({
|
|
104
|
-
variable: t.variable({
|
|
105
|
-
name: 'after'
|
|
106
|
-
}),
|
|
107
|
-
type: t.namedType({
|
|
108
|
-
type: 'Cursor'
|
|
109
|
-
})
|
|
110
|
-
}),
|
|
111
|
-
t.variableDefinition({
|
|
112
|
-
variable: t.variable({
|
|
113
|
-
name: 'before'
|
|
114
|
-
}),
|
|
115
|
-
type: t.namedType({
|
|
116
|
-
type: 'Cursor'
|
|
117
|
-
})
|
|
118
|
-
}),
|
|
119
|
-
t.variableDefinition({
|
|
120
|
-
variable: t.variable({
|
|
121
|
-
name: 'offset'
|
|
122
|
-
}),
|
|
123
|
-
type: t.namedType({
|
|
124
|
-
type: 'Int'
|
|
125
|
-
})
|
|
126
|
-
}),
|
|
127
|
-
t.variableDefinition({
|
|
128
|
-
variable: t.variable({
|
|
129
|
-
name: 'condition'
|
|
130
|
-
}),
|
|
131
|
-
type: t.namedType({
|
|
132
|
-
type: Condition
|
|
133
|
-
})
|
|
134
|
-
}),
|
|
135
|
-
t.variableDefinition({
|
|
136
|
-
variable: t.variable({
|
|
137
|
-
name: 'filter'
|
|
138
|
-
}),
|
|
139
|
-
type: t.namedType({
|
|
140
|
-
type: Filter
|
|
141
|
-
})
|
|
142
|
-
}),
|
|
143
|
-
t.variableDefinition({
|
|
144
|
-
variable: t.variable({
|
|
145
|
-
name: 'orderBy'
|
|
146
|
-
}),
|
|
147
|
-
type: t.listType({
|
|
148
|
-
type: t.nonNullType({ type: t.namedType({ type: OrderBy }) })
|
|
149
|
-
})
|
|
150
|
-
})
|
|
151
|
-
],
|
|
212
|
+
variableDefinitions,
|
|
152
213
|
selectionSet: t.selectionSet({
|
|
153
214
|
selections: [
|
|
154
215
|
t.field({
|
|
155
216
|
name: operationName,
|
|
156
|
-
args
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
t.argument({
|
|
164
|
-
name: 'last',
|
|
165
|
-
value: t.variable({
|
|
166
|
-
name: 'last'
|
|
167
|
-
})
|
|
168
|
-
}),
|
|
169
|
-
t.argument({
|
|
170
|
-
name: 'offset',
|
|
171
|
-
value: t.variable({
|
|
172
|
-
name: 'offset'
|
|
173
|
-
})
|
|
174
|
-
}),
|
|
175
|
-
t.argument({
|
|
176
|
-
name: 'after',
|
|
177
|
-
value: t.variable({
|
|
178
|
-
name: 'after'
|
|
179
|
-
})
|
|
180
|
-
}),
|
|
181
|
-
t.argument({
|
|
182
|
-
name: 'before',
|
|
183
|
-
value: t.variable({
|
|
184
|
-
name: 'before'
|
|
185
|
-
})
|
|
186
|
-
}),
|
|
187
|
-
t.argument({
|
|
188
|
-
name: 'condition',
|
|
189
|
-
value: t.variable({
|
|
190
|
-
name: 'condition'
|
|
191
|
-
})
|
|
192
|
-
}),
|
|
193
|
-
t.argument({
|
|
194
|
-
name: 'filter',
|
|
195
|
-
value: t.variable({
|
|
196
|
-
name: 'filter'
|
|
197
|
-
})
|
|
198
|
-
}),
|
|
199
|
-
t.argument({
|
|
200
|
-
name: 'orderBy',
|
|
201
|
-
value: t.variable({
|
|
202
|
-
name: 'orderBy'
|
|
203
|
-
})
|
|
204
|
-
})
|
|
205
|
-
],
|
|
206
|
-
selectionSet: t.objectValue({
|
|
207
|
-
fields: [
|
|
208
|
-
t.field({
|
|
209
|
-
name: 'totalCount'
|
|
210
|
-
}),
|
|
211
|
-
t.field({
|
|
212
|
-
name: 'pageInfo',
|
|
213
|
-
selectionSet: t.selectionSet({
|
|
214
|
-
selections: [
|
|
215
|
-
t.field({ name: 'hasNextPage' }),
|
|
216
|
-
t.field({ name: 'hasPreviousPage' }),
|
|
217
|
-
t.field({ name: 'endCursor' }),
|
|
218
|
-
t.field({ name: 'startCursor' })
|
|
219
|
-
]
|
|
220
|
-
})
|
|
221
|
-
}),
|
|
222
|
-
builder._edges
|
|
223
|
-
? t.field({
|
|
224
|
-
name: 'edges',
|
|
225
|
-
selectionSet: t.selectionSet({
|
|
226
|
-
selections: [
|
|
227
|
-
t.field({ name: 'cursor' }),
|
|
228
|
-
t.field({
|
|
229
|
-
name: 'node',
|
|
230
|
-
selectionSet: t.selectionSet({ selections })
|
|
231
|
-
})
|
|
232
|
-
]
|
|
233
|
-
})
|
|
234
|
-
})
|
|
235
|
-
: t.field({
|
|
236
|
-
name: 'nodes',
|
|
237
|
-
selectionSet: t.selectionSet({
|
|
238
|
-
selections
|
|
239
|
-
})
|
|
240
|
-
})
|
|
241
|
-
]
|
|
242
|
-
})
|
|
243
|
-
})
|
|
244
|
-
]
|
|
245
|
-
})
|
|
246
|
-
})
|
|
247
|
-
]
|
|
217
|
+
args,
|
|
218
|
+
selectionSet: t.selectionSet({ selections: connectionFields }),
|
|
219
|
+
}),
|
|
220
|
+
],
|
|
221
|
+
}),
|
|
222
|
+
}),
|
|
223
|
+
],
|
|
248
224
|
});
|
|
249
225
|
return ast;
|
|
250
226
|
};
|
|
251
|
-
export const getOne = ({
|
|
252
|
-
queryName, operationName, query, selection }) => {
|
|
227
|
+
export const getOne = ({ queryName, operationName, query, selection, }) => {
|
|
253
228
|
const variableDefinitions = Object.keys(query.properties)
|
|
254
|
-
.map((key) => ({
|
|
229
|
+
.map((key) => ({ key, ...query.properties[key] }))
|
|
255
230
|
.filter((field) => field.isNotNull)
|
|
256
231
|
.map((field) => {
|
|
257
|
-
const {
|
|
232
|
+
const { key: fieldName, type: fieldType, isNotNull, isArray, isArrayNotNull, } = field;
|
|
258
233
|
let type = t.namedType({ type: fieldType });
|
|
259
234
|
if (isNotNull)
|
|
260
235
|
type = t.nonNullType({ type });
|
|
@@ -265,7 +240,7 @@ queryName, operationName, query, selection }) => {
|
|
|
265
240
|
}
|
|
266
241
|
return t.variableDefinition({
|
|
267
242
|
variable: t.variable({ name: fieldName }),
|
|
268
|
-
type
|
|
243
|
+
type,
|
|
269
244
|
});
|
|
270
245
|
});
|
|
271
246
|
const props = objectToArray(query.properties);
|
|
@@ -274,7 +249,7 @@ queryName, operationName, query, selection }) => {
|
|
|
274
249
|
.map((field) => {
|
|
275
250
|
return t.argument({
|
|
276
251
|
name: field.name,
|
|
277
|
-
value: t.variable({ name: field.name })
|
|
252
|
+
value: t.variable({ name: field.name }),
|
|
278
253
|
});
|
|
279
254
|
});
|
|
280
255
|
const selections = getSelections(selection);
|
|
@@ -282,8 +257,8 @@ queryName, operationName, query, selection }) => {
|
|
|
282
257
|
t.field({
|
|
283
258
|
name: operationName,
|
|
284
259
|
args: selectArgs,
|
|
285
|
-
selectionSet: t.selectionSet({ selections })
|
|
286
|
-
})
|
|
260
|
+
selectionSet: t.selectionSet({ selections }),
|
|
261
|
+
}),
|
|
287
262
|
];
|
|
288
263
|
const ast = t.document({
|
|
289
264
|
definitions: [
|
|
@@ -291,19 +266,24 @@ queryName, operationName, query, selection }) => {
|
|
|
291
266
|
operation: 'query',
|
|
292
267
|
name: queryName,
|
|
293
268
|
variableDefinitions,
|
|
294
|
-
selectionSet: t.selectionSet({ selections: opSel })
|
|
295
|
-
})
|
|
296
|
-
]
|
|
269
|
+
selectionSet: t.selectionSet({ selections: opSel }),
|
|
270
|
+
}),
|
|
271
|
+
],
|
|
297
272
|
});
|
|
298
273
|
return ast;
|
|
299
274
|
};
|
|
300
|
-
export const createOne = ({ mutationName, operationName, mutation, selection }) => {
|
|
275
|
+
export const createOne = ({ mutationName, operationName, mutation, selection, }) => {
|
|
301
276
|
if (!mutation.properties?.input?.properties) {
|
|
302
|
-
|
|
303
|
-
return;
|
|
277
|
+
throw new Error(`No input field for mutation: ${mutationName}`);
|
|
304
278
|
}
|
|
305
279
|
const modelName = inflection.camelize([inflection.singularize(mutation.model)].join('_'), true);
|
|
306
|
-
const
|
|
280
|
+
const inputProperties = mutation.properties.input
|
|
281
|
+
.properties;
|
|
282
|
+
const modelProperties = inputProperties[modelName];
|
|
283
|
+
if (!modelProperties.properties) {
|
|
284
|
+
throw new Error(`No properties found for model: ${modelName}`);
|
|
285
|
+
}
|
|
286
|
+
const allAttrs = objectToArray(modelProperties.properties);
|
|
307
287
|
const attrs = allAttrs.filter((field) => !NON_MUTABLE_PROPS.includes(field.name));
|
|
308
288
|
const variableDefinitions = getCreateVariablesAst(attrs);
|
|
309
289
|
const selectArgs = [
|
|
@@ -316,15 +296,13 @@ export const createOne = ({ mutationName, operationName, mutation, selection })
|
|
|
316
296
|
value: t.objectValue({
|
|
317
297
|
fields: attrs.map((field) => t.objectField({
|
|
318
298
|
name: field.name,
|
|
319
|
-
value: t.variable({
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
})
|
|
327
|
-
})
|
|
299
|
+
value: t.variable({ name: field.name }),
|
|
300
|
+
})),
|
|
301
|
+
}),
|
|
302
|
+
}),
|
|
303
|
+
],
|
|
304
|
+
}),
|
|
305
|
+
}),
|
|
328
306
|
];
|
|
329
307
|
const selections = selection
|
|
330
308
|
? getSelections(selection)
|
|
@@ -335,19 +313,23 @@ export const createOne = ({ mutationName, operationName, mutation, selection })
|
|
|
335
313
|
selectArgs,
|
|
336
314
|
selections,
|
|
337
315
|
variableDefinitions,
|
|
338
|
-
modelName
|
|
316
|
+
modelName,
|
|
339
317
|
});
|
|
340
318
|
return ast;
|
|
341
319
|
};
|
|
342
|
-
export const patchOne = ({ mutationName, operationName, mutation, selection }) => {
|
|
320
|
+
export const patchOne = ({ mutationName, operationName, mutation, selection, }) => {
|
|
343
321
|
if (!mutation.properties?.input?.properties) {
|
|
344
|
-
|
|
345
|
-
return;
|
|
322
|
+
throw new Error(`No input field for mutation: ${mutationName}`);
|
|
346
323
|
}
|
|
347
324
|
const modelName = inflection.camelize([inflection.singularize(mutation.model)].join('_'), true);
|
|
348
|
-
const
|
|
325
|
+
const inputProperties = mutation.properties.input
|
|
326
|
+
.properties;
|
|
327
|
+
const patchProperties = inputProperties['patch'];
|
|
328
|
+
const allAttrs = patchProperties?.properties
|
|
329
|
+
? objectToArray(patchProperties.properties)
|
|
330
|
+
: [];
|
|
349
331
|
const patchAttrs = allAttrs.filter((prop) => !NON_MUTABLE_PROPS.includes(prop.name));
|
|
350
|
-
const patchByAttrs = objectToArray(
|
|
332
|
+
const patchByAttrs = objectToArray(inputProperties).filter((n) => n.name !== 'patch');
|
|
351
333
|
const patchers = patchByAttrs.map((p) => p.name);
|
|
352
334
|
const variableDefinitions = getUpdateVariablesAst(patchAttrs, patchers);
|
|
353
335
|
const selectArgs = [
|
|
@@ -357,7 +339,7 @@ export const patchOne = ({ mutationName, operationName, mutation, selection }) =
|
|
|
357
339
|
fields: [
|
|
358
340
|
...patchByAttrs.map((field) => t.objectField({
|
|
359
341
|
name: field.name,
|
|
360
|
-
value: t.variable({ name: field.name })
|
|
342
|
+
value: t.variable({ name: field.name }),
|
|
361
343
|
})),
|
|
362
344
|
t.objectField({
|
|
363
345
|
name: 'patch',
|
|
@@ -366,15 +348,13 @@ export const patchOne = ({ mutationName, operationName, mutation, selection }) =
|
|
|
366
348
|
.filter((field) => !patchers.includes(field.name))
|
|
367
349
|
.map((field) => t.objectField({
|
|
368
350
|
name: field.name,
|
|
369
|
-
value: t.variable({
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
})
|
|
377
|
-
})
|
|
351
|
+
value: t.variable({ name: field.name }),
|
|
352
|
+
})),
|
|
353
|
+
}),
|
|
354
|
+
}),
|
|
355
|
+
],
|
|
356
|
+
}),
|
|
357
|
+
}),
|
|
378
358
|
];
|
|
379
359
|
const selections = selection
|
|
380
360
|
? getSelections(selection)
|
|
@@ -385,19 +365,20 @@ export const patchOne = ({ mutationName, operationName, mutation, selection }) =
|
|
|
385
365
|
selectArgs,
|
|
386
366
|
selections,
|
|
387
367
|
variableDefinitions,
|
|
388
|
-
modelName
|
|
368
|
+
modelName,
|
|
389
369
|
});
|
|
390
370
|
return ast;
|
|
391
371
|
};
|
|
392
|
-
export const deleteOne = ({ mutationName, operationName, mutation }) => {
|
|
372
|
+
export const deleteOne = ({ mutationName, operationName, mutation, }) => {
|
|
393
373
|
if (!mutation.properties?.input?.properties) {
|
|
394
|
-
|
|
395
|
-
return;
|
|
374
|
+
throw new Error(`No input field for mutation: ${mutationName}`);
|
|
396
375
|
}
|
|
397
376
|
const modelName = inflection.camelize([inflection.singularize(mutation.model)].join('_'), true);
|
|
398
|
-
const
|
|
377
|
+
const inputProperties = mutation.properties.input
|
|
378
|
+
.properties;
|
|
379
|
+
const deleteAttrs = objectToArray(inputProperties);
|
|
399
380
|
const variableDefinitions = deleteAttrs.map((field) => {
|
|
400
|
-
const { name: fieldName, type: fieldType, isNotNull, isArray
|
|
381
|
+
const { name: fieldName, type: fieldType, isNotNull, isArray } = field;
|
|
401
382
|
let type = t.namedType({ type: fieldType });
|
|
402
383
|
if (isNotNull)
|
|
403
384
|
type = t.nonNullType({ type });
|
|
@@ -408,7 +389,7 @@ export const deleteOne = ({ mutationName, operationName, mutation }) => {
|
|
|
408
389
|
}
|
|
409
390
|
return t.variableDefinition({
|
|
410
391
|
variable: t.variable({ name: fieldName }),
|
|
411
|
-
type
|
|
392
|
+
type,
|
|
412
393
|
});
|
|
413
394
|
});
|
|
414
395
|
const selectArgs = [
|
|
@@ -417,10 +398,10 @@ export const deleteOne = ({ mutationName, operationName, mutation }) => {
|
|
|
417
398
|
value: t.objectValue({
|
|
418
399
|
fields: deleteAttrs.map((f) => t.objectField({
|
|
419
400
|
name: f.name,
|
|
420
|
-
value: t.variable({ name: f.name })
|
|
421
|
-
}))
|
|
422
|
-
})
|
|
423
|
-
})
|
|
401
|
+
value: t.variable({ name: f.name }),
|
|
402
|
+
})),
|
|
403
|
+
}),
|
|
404
|
+
}),
|
|
424
405
|
];
|
|
425
406
|
// so we can support column select grants plugin
|
|
426
407
|
const selections = [t.field({ name: 'clientMutationId' })];
|
|
@@ -431,117 +412,89 @@ export const deleteOne = ({ mutationName, operationName, mutation }) => {
|
|
|
431
412
|
selections,
|
|
432
413
|
useModel: false,
|
|
433
414
|
variableDefinitions,
|
|
434
|
-
modelName
|
|
415
|
+
modelName,
|
|
435
416
|
});
|
|
436
417
|
return ast;
|
|
437
418
|
};
|
|
438
419
|
export function getSelections(selection = []) {
|
|
439
420
|
const selectionAst = (field) => {
|
|
440
421
|
return typeof field === 'string'
|
|
441
|
-
? t.field({
|
|
442
|
-
|
|
443
|
-
})
|
|
444
|
-
: getCustomAst(field.fieldDefn);
|
|
422
|
+
? t.field({ name: field })
|
|
423
|
+
: getCustomAst(field.fieldDefn) || t.field({ name: field.name });
|
|
445
424
|
};
|
|
446
425
|
return selection
|
|
447
426
|
.map((selectionDefn) => {
|
|
448
427
|
if (selectionDefn.isObject) {
|
|
449
428
|
const { name, selection, variables = {}, isBelongTo } = selectionDefn;
|
|
429
|
+
const args = Object.entries(variables).reduce((acc, variable) => {
|
|
430
|
+
const [argName, argValue] = variable;
|
|
431
|
+
const argAst = t.argument({
|
|
432
|
+
name: argName,
|
|
433
|
+
value: getComplexValueAst(argValue),
|
|
434
|
+
});
|
|
435
|
+
return argAst ? [...acc, argAst] : acc;
|
|
436
|
+
}, []);
|
|
437
|
+
const subSelections = selection?.map((field) => selectionAst(field)) || [];
|
|
438
|
+
const selectionSet = isBelongTo
|
|
439
|
+
? t.selectionSet({ selections: subSelections })
|
|
440
|
+
: t.selectionSet({
|
|
441
|
+
selections: [
|
|
442
|
+
t.field({ name: 'totalCount' }),
|
|
443
|
+
t.field({
|
|
444
|
+
name: 'nodes',
|
|
445
|
+
selectionSet: t.selectionSet({ selections: subSelections }),
|
|
446
|
+
}),
|
|
447
|
+
],
|
|
448
|
+
});
|
|
450
449
|
return t.field({
|
|
451
450
|
name,
|
|
452
|
-
args
|
|
453
|
-
|
|
454
|
-
const argAst = t.argument({
|
|
455
|
-
name: argName,
|
|
456
|
-
value: getValueAst(argValue)
|
|
457
|
-
});
|
|
458
|
-
args = argAst ? [...args, argAst] : args;
|
|
459
|
-
return args;
|
|
460
|
-
}, []),
|
|
461
|
-
selectionSet: isBelongTo
|
|
462
|
-
? t.selectionSet({
|
|
463
|
-
selections: selection.map((field) => selectionAst(field))
|
|
464
|
-
})
|
|
465
|
-
: t.objectValue({
|
|
466
|
-
fields: [
|
|
467
|
-
t.field({
|
|
468
|
-
name: 'totalCount'
|
|
469
|
-
}),
|
|
470
|
-
t.field({
|
|
471
|
-
name: 'nodes',
|
|
472
|
-
selectionSet: t.selectionSet({
|
|
473
|
-
selections: selection.map((field) => selectionAst(field))
|
|
474
|
-
})
|
|
475
|
-
})
|
|
476
|
-
]
|
|
477
|
-
})
|
|
451
|
+
args,
|
|
452
|
+
selectionSet,
|
|
478
453
|
});
|
|
479
454
|
}
|
|
480
455
|
else {
|
|
481
|
-
|
|
482
|
-
// Field is not found in model meta, do nothing
|
|
483
|
-
if (!fieldDefn)
|
|
484
|
-
return null;
|
|
485
|
-
return getCustomAst(fieldDefn);
|
|
456
|
+
return selectionAst(selectionDefn);
|
|
486
457
|
}
|
|
487
458
|
})
|
|
488
|
-
.filter(
|
|
459
|
+
.filter((node) => node !== null);
|
|
489
460
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
* @returns {Object} AST for the argument
|
|
494
|
-
*/
|
|
495
|
-
function getValueAst(value) {
|
|
496
|
-
if (value == null) {
|
|
461
|
+
function getComplexValueAst(value) {
|
|
462
|
+
// Handle null
|
|
463
|
+
if (value === null) {
|
|
497
464
|
return t.nullValue();
|
|
498
465
|
}
|
|
466
|
+
// Handle primitives
|
|
467
|
+
if (typeof value === 'boolean') {
|
|
468
|
+
return t.booleanValue({ value });
|
|
469
|
+
}
|
|
499
470
|
if (typeof value === 'number') {
|
|
500
|
-
return t.intValue({ value });
|
|
471
|
+
return t.intValue({ value: value.toString() });
|
|
501
472
|
}
|
|
502
473
|
if (typeof value === 'string') {
|
|
503
474
|
return t.stringValue({ value });
|
|
504
475
|
}
|
|
505
|
-
|
|
506
|
-
return t.booleanValue({ value });
|
|
507
|
-
}
|
|
476
|
+
// Handle arrays
|
|
508
477
|
if (Array.isArray(value)) {
|
|
509
|
-
return t.listValue({
|
|
478
|
+
return t.listValue({
|
|
479
|
+
values: value.map((item) => getComplexValueAst(item)),
|
|
480
|
+
});
|
|
510
481
|
}
|
|
511
|
-
|
|
482
|
+
// Handle objects
|
|
483
|
+
if (typeof value === 'object' && value !== null) {
|
|
484
|
+
const obj = value;
|
|
512
485
|
return t.objectValue({
|
|
513
|
-
fields: Object.entries(
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
t.objectField({
|
|
518
|
-
name: objKey,
|
|
519
|
-
value: getValueAst(objValue)
|
|
520
|
-
})
|
|
521
|
-
];
|
|
522
|
-
return fields;
|
|
523
|
-
}, [])
|
|
486
|
+
fields: Object.entries(obj).map(([key, val]) => t.objectField({
|
|
487
|
+
name: key,
|
|
488
|
+
value: getComplexValueAst(val),
|
|
489
|
+
})),
|
|
524
490
|
});
|
|
525
491
|
}
|
|
492
|
+
throw new Error(`Unsupported value type: ${typeof value}`);
|
|
526
493
|
}
|
|
527
|
-
const CustomInputTypes = {
|
|
528
|
-
interval: 'IntervalInput'
|
|
529
|
-
};
|
|
530
|
-
/**
|
|
531
|
-
* Get mutation variables AST from attributes array
|
|
532
|
-
* @param {Array} attrs
|
|
533
|
-
* @returns {Object} AST for the variables
|
|
534
|
-
*/
|
|
535
494
|
function getCreateVariablesAst(attrs) {
|
|
536
495
|
return attrs.map((field) => {
|
|
537
|
-
const { name: fieldName, type: fieldType, isNotNull, isArray, isArrayNotNull,
|
|
538
|
-
let type;
|
|
539
|
-
if (properties == null) {
|
|
540
|
-
type = t.namedType({ type: fieldType });
|
|
541
|
-
}
|
|
542
|
-
else if (isIntervalType(properties)) {
|
|
543
|
-
type = t.namedType({ type: CustomInputTypes.interval });
|
|
544
|
-
}
|
|
496
|
+
const { name: fieldName, type: fieldType, isNotNull, isArray, isArrayNotNull, } = field;
|
|
497
|
+
let type = t.namedType({ type: fieldType });
|
|
545
498
|
if (isNotNull)
|
|
546
499
|
type = t.nonNullType({ type });
|
|
547
500
|
if (isArray) {
|
|
@@ -551,34 +504,31 @@ function getCreateVariablesAst(attrs) {
|
|
|
551
504
|
}
|
|
552
505
|
return t.variableDefinition({
|
|
553
506
|
variable: t.variable({ name: fieldName }),
|
|
554
|
-
type
|
|
507
|
+
type,
|
|
555
508
|
});
|
|
556
509
|
});
|
|
557
510
|
}
|
|
558
|
-
/**
|
|
559
|
-
* Get mutation variables AST from attributes array
|
|
560
|
-
* @param {Array} attrs
|
|
561
|
-
* @returns {Object} AST for the variables
|
|
562
|
-
*/
|
|
563
511
|
function getUpdateVariablesAst(attrs, patchers) {
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
else if (isIntervalType(properties)) {
|
|
571
|
-
type = t.namedType({ type: CustomInputTypes.interval });
|
|
572
|
-
}
|
|
573
|
-
if (isNotNull)
|
|
574
|
-
type = t.nonNullType({ type });
|
|
575
|
-
if (isArray)
|
|
512
|
+
const patchVariables = attrs
|
|
513
|
+
.filter((field) => !patchers.includes(field.name))
|
|
514
|
+
.map((field) => {
|
|
515
|
+
const { name: fieldName, type: fieldType, isArray, isArrayNotNull, } = field;
|
|
516
|
+
let type = t.namedType({ type: fieldType });
|
|
517
|
+
if (isArray) {
|
|
576
518
|
type = t.listType({ type });
|
|
577
|
-
|
|
578
|
-
|
|
519
|
+
if (isArrayNotNull)
|
|
520
|
+
type = t.nonNullType({ type });
|
|
521
|
+
}
|
|
579
522
|
return t.variableDefinition({
|
|
580
523
|
variable: t.variable({ name: fieldName }),
|
|
581
|
-
type
|
|
524
|
+
type,
|
|
525
|
+
});
|
|
526
|
+
});
|
|
527
|
+
const patcherVariables = patchers.map((patcher) => {
|
|
528
|
+
return t.variableDefinition({
|
|
529
|
+
variable: t.variable({ name: patcher }),
|
|
530
|
+
type: t.nonNullType({ type: t.namedType({ type: 'String' }) }),
|
|
582
531
|
});
|
|
583
532
|
});
|
|
533
|
+
return [...patchVariables, ...patcherVariables];
|
|
584
534
|
}
|