orchid-graphql 0.0.4 → 1.1.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/README.md +6 -9
- package/dist/index.cjs +238 -185
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +130 -72
- package/dist/index.js +238 -185
- package/dist/index.js.map +1 -1
- package/package.json +13 -27
- package/src/index.ts +10 -16
- package/src/orm/orm.ts +117 -0
- package/src/resolvers/graph.ts +6 -80
- package/src/resolvers/table.ts +8 -142
- package/src/filters/filters.ts +0 -93
- package/src/paginators/base.ts +0 -40
- package/src/paginators/cursor.ts +0 -113
- package/src/resolvers/field.ts +0 -46
- package/src/resolvers/page.ts +0 -34
- package/src/resolvers/relation.ts +0 -28
- package/src/utils/is-plain-object.ts +0 -3
- package/src/utils/modifier.ts +0 -3
- package/src/utils/run-after.ts +0 -19
package/README.md
CHANGED
|
@@ -2,10 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
A helper library to resolve GraphQL queries directly with [Orchid ORM](https://orchid-orm.netlify.app) tables and relations.
|
|
4
4
|
|
|
5
|
-
This is a fork of [objection-graphql-resolver](https://github.com/IlyaSemenov/objection-graphql-resolver) which does the same for [Objection.js ORM](https://vincit.github.io/objection.js/).
|
|
6
|
-
|
|
7
|
-
## Features
|
|
8
|
-
|
|
9
5
|
- Highly effective: selects only requested fields and relations.
|
|
10
6
|
- Unlimited nested resolvers.
|
|
11
7
|
- Pagination.
|
|
@@ -13,11 +9,13 @@ This is a fork of [objection-graphql-resolver](https://github.com/IlyaSemenov/ob
|
|
|
13
9
|
- Hook into (sub)queries with query modifiers.
|
|
14
10
|
- Hook into field results to restrict access to sensitive information.
|
|
15
11
|
|
|
12
|
+
_Note that there is a sister project: `objection-graphql-resolver` which does the same for [Objection.js ORM](https://vincit.github.io/objection.js/)._
|
|
13
|
+
|
|
16
14
|
## Status and limitations
|
|
17
15
|
|
|
18
|
-
This is pre-release and not battle tested. `orchid-graphql` is a quick
|
|
16
|
+
This is pre-release and not battle tested. `orchid-graphql` is a quick adaptation of `objection-graphql-resolver`.
|
|
19
17
|
|
|
20
|
-
In particular
|
|
18
|
+
In particular the typings are not ready. The resolver returns a generic `Query` most of the time.
|
|
21
19
|
|
|
22
20
|
## Install
|
|
23
21
|
|
|
@@ -299,8 +297,7 @@ const graph = r.graph(
|
|
|
299
297
|
}),
|
|
300
298
|
preview2: r.field({
|
|
301
299
|
// Modify query
|
|
302
|
-
modify: (
|
|
303
|
-
query.select(raw("substr(text,1,100) as preview2")),
|
|
300
|
+
modify: (q) => q.select({ preview2: q.raw("substr(text,1,100)") }),
|
|
304
301
|
// Post-process selected value
|
|
305
302
|
transform(
|
|
306
303
|
// Selected value
|
|
@@ -390,7 +387,7 @@ const resolvers = {
|
|
|
390
387
|
}
|
|
391
388
|
)
|
|
392
389
|
},
|
|
393
|
-
posts_page: (parent, args, context, info) => {
|
|
390
|
+
posts_page: async (parent, args, context, info) => {
|
|
394
391
|
return await graph.resolvePage(
|
|
395
392
|
// Root query (required)
|
|
396
393
|
db.post,
|
package/dist/index.cjs
CHANGED
|
@@ -35,29 +35,7 @@ __export(src_exports, {
|
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(src_exports);
|
|
37
37
|
|
|
38
|
-
// src/paginators/
|
|
39
|
-
var s = Symbol();
|
|
40
|
-
function set_query_page_result(query, get_page) {
|
|
41
|
-
function _get_page(data) {
|
|
42
|
-
if (!Array.isArray(data)) {
|
|
43
|
-
throw new Error(`Paginator called for single result query.`);
|
|
44
|
-
}
|
|
45
|
-
return get_page(data);
|
|
46
|
-
}
|
|
47
|
-
const _query = query.query;
|
|
48
|
-
const { handleResult } = _query;
|
|
49
|
-
_query.handleResult = (q, result, s2) => {
|
|
50
|
-
const data = handleResult(q, result, s2);
|
|
51
|
-
return s2 ? data : _get_page(data);
|
|
52
|
-
};
|
|
53
|
-
_query[s] = _get_page;
|
|
54
|
-
return query;
|
|
55
|
-
}
|
|
56
|
-
function get_query_pagination_handler(query) {
|
|
57
|
-
return query.query[s];
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// src/paginators/cursor.ts
|
|
38
|
+
// ../graphql-orm/src/paginators/cursor.ts
|
|
61
39
|
function defineCursorPaginator(options = {}) {
|
|
62
40
|
return new CursorPaginator(options);
|
|
63
41
|
}
|
|
@@ -79,18 +57,22 @@ var CursorPaginator = class {
|
|
|
79
57
|
}
|
|
80
58
|
});
|
|
81
59
|
}
|
|
82
|
-
paginate(query,
|
|
60
|
+
paginate(query, context) {
|
|
61
|
+
const { orm: orm2 } = context.graph;
|
|
62
|
+
const { args } = context.tree;
|
|
83
63
|
const take = args.take ?? this.options.take;
|
|
84
|
-
const
|
|
85
|
-
query =
|
|
64
|
+
const cursor = args.cursor;
|
|
65
|
+
query = orm2.reset_query_order(query);
|
|
86
66
|
for (const field of this.fields) {
|
|
87
|
-
query =
|
|
67
|
+
query = orm2.select_field(query, { field: field.name, as: field.name });
|
|
68
|
+
query = orm2.add_query_order(query, field.name, field.desc);
|
|
88
69
|
}
|
|
89
70
|
if (cursor) {
|
|
90
|
-
|
|
71
|
+
const { expression, bindings } = this._parse_cursor(cursor);
|
|
72
|
+
query = orm2.where_raw(query, expression, bindings);
|
|
91
73
|
}
|
|
92
|
-
query =
|
|
93
|
-
query = set_query_page_result(query, (nodes) => {
|
|
74
|
+
query = orm2.set_query_limit(query, take + 1);
|
|
75
|
+
query = orm2.set_query_page_result(query, (nodes) => {
|
|
94
76
|
let cursor2;
|
|
95
77
|
if (nodes.length > take) {
|
|
96
78
|
cursor2 = this._create_cursor(nodes[take - 1]);
|
|
@@ -113,29 +95,29 @@ var CursorPaginator = class {
|
|
|
113
95
|
})
|
|
114
96
|
);
|
|
115
97
|
}
|
|
116
|
-
|
|
98
|
+
_parse_cursor(cursor) {
|
|
117
99
|
const values = JSON.parse(cursor);
|
|
118
100
|
const left = [];
|
|
119
101
|
const right = [];
|
|
120
|
-
const
|
|
102
|
+
const bindings = {};
|
|
121
103
|
for (let i = 0; i < this.fields.length; ++i) {
|
|
122
104
|
const field = this.fields[i];
|
|
123
105
|
const expressions = field.desc ? right : left;
|
|
124
106
|
const placeholders = field.desc ? left : right;
|
|
125
107
|
expressions.push(`"${field.name}"`);
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
expr_values[placeholder] = values[i];
|
|
108
|
+
placeholders.push("$" + field.name);
|
|
109
|
+
bindings[field.name] = values[i];
|
|
129
110
|
}
|
|
130
|
-
return
|
|
131
|
-
|
|
132
|
-
|
|
111
|
+
return {
|
|
112
|
+
expression: `(${left.join(",")}) > (${right.join(",")})`,
|
|
113
|
+
bindings
|
|
114
|
+
};
|
|
133
115
|
}
|
|
134
116
|
};
|
|
135
117
|
|
|
136
|
-
// src/utils/run-after.ts
|
|
137
|
-
function run_after_query(query, transform) {
|
|
138
|
-
return
|
|
118
|
+
// ../graphql-orm/src/utils/run-after.ts
|
|
119
|
+
function run_after_query(orm2, query, transform) {
|
|
120
|
+
return orm2.run_after_query(query, async (result) => {
|
|
139
121
|
if (Array.isArray(result)) {
|
|
140
122
|
const result1 = await Promise.all(result.map(transform));
|
|
141
123
|
return result1.filter(Boolean);
|
|
@@ -147,7 +129,7 @@ function run_after_query(query, transform) {
|
|
|
147
129
|
});
|
|
148
130
|
}
|
|
149
131
|
|
|
150
|
-
// src/resolvers/field.ts
|
|
132
|
+
// ../graphql-orm/src/resolvers/field.ts
|
|
151
133
|
function defineFieldResolver(options = {}) {
|
|
152
134
|
const { tableField, modify, transform } = options;
|
|
153
135
|
return function resolve(query, context) {
|
|
@@ -155,10 +137,13 @@ function defineFieldResolver(options = {}) {
|
|
|
155
137
|
if (modify) {
|
|
156
138
|
query = modify(query, context);
|
|
157
139
|
} else {
|
|
158
|
-
query =
|
|
140
|
+
query = context.graph.orm.select_field(query, {
|
|
141
|
+
field: tableField || field,
|
|
142
|
+
as: field
|
|
143
|
+
});
|
|
159
144
|
}
|
|
160
145
|
if (transform) {
|
|
161
|
-
query = run_after_query(query, async (instance) => {
|
|
146
|
+
query = run_after_query(context.graph.orm, query, async (instance) => {
|
|
162
147
|
instance[field] = await transform(instance[field], instance, context);
|
|
163
148
|
return instance;
|
|
164
149
|
});
|
|
@@ -167,14 +152,12 @@ function defineFieldResolver(options = {}) {
|
|
|
167
152
|
};
|
|
168
153
|
}
|
|
169
154
|
|
|
170
|
-
// src/resolvers/graph.ts
|
|
155
|
+
// ../graphql-orm/src/resolvers/graph.ts
|
|
171
156
|
var import_graphql_parse_resolve_info = require("graphql-parse-resolve-info");
|
|
172
|
-
function createGraphResolver(types, options) {
|
|
173
|
-
return new GraphResolver(types, options);
|
|
174
|
-
}
|
|
175
157
|
var GraphResolver = class {
|
|
176
|
-
constructor(
|
|
177
|
-
this.
|
|
158
|
+
constructor(orm2, type_resolvers, options = {}) {
|
|
159
|
+
this.orm = orm2;
|
|
160
|
+
this.type_resolvers = type_resolvers;
|
|
178
161
|
this.options = options;
|
|
179
162
|
}
|
|
180
163
|
resolve(query, { info, context, filters }) {
|
|
@@ -191,87 +174,81 @@ var GraphResolver = class {
|
|
|
191
174
|
_resolve_type(query, context) {
|
|
192
175
|
const { tree } = context;
|
|
193
176
|
const type = Object.keys(tree.fieldsByTypeName)[0];
|
|
194
|
-
const
|
|
195
|
-
if (!
|
|
196
|
-
throw new Error(`
|
|
177
|
+
const type_resolver = this.type_resolvers[type];
|
|
178
|
+
if (!type_resolver) {
|
|
179
|
+
throw new Error(`Resolver not found for type ${type}.`);
|
|
197
180
|
}
|
|
198
|
-
return
|
|
181
|
+
return type_resolver.resolve(query, {
|
|
182
|
+
...context,
|
|
183
|
+
graph: this,
|
|
184
|
+
tree,
|
|
185
|
+
type
|
|
186
|
+
});
|
|
199
187
|
}
|
|
200
188
|
_resolve_page(query, paginator, context) {
|
|
201
189
|
let { tree } = context;
|
|
202
|
-
const { args } = tree;
|
|
203
190
|
for (const field of paginator.path) {
|
|
204
191
|
const type = Object.keys(tree.fieldsByTypeName)[0];
|
|
205
192
|
tree = tree.fieldsByTypeName[type][field];
|
|
206
193
|
}
|
|
207
194
|
query = this._resolve_type(query, { ...context, tree });
|
|
208
|
-
return paginator.paginate(query,
|
|
195
|
+
return paginator.paginate(query, {
|
|
196
|
+
...context,
|
|
197
|
+
graph: this
|
|
198
|
+
});
|
|
209
199
|
}
|
|
210
200
|
};
|
|
211
201
|
|
|
212
|
-
// src/resolvers/page.ts
|
|
213
|
-
var import_orchid_core = require("orchid-core");
|
|
202
|
+
// ../graphql-orm/src/resolvers/page.ts
|
|
214
203
|
function definePageResolver(paginator, options = {}) {
|
|
215
204
|
const { tableField, modify } = options;
|
|
216
|
-
return
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
});
|
|
205
|
+
return function resolve(query, context) {
|
|
206
|
+
const { graph, field } = context;
|
|
207
|
+
const pagination_context = {};
|
|
208
|
+
query = graph.orm.select_relation(query, {
|
|
209
|
+
relation: tableField || field,
|
|
210
|
+
as: field,
|
|
211
|
+
modify(subquery) {
|
|
212
|
+
subquery = graph._resolve_page(subquery, paginator, context);
|
|
213
|
+
subquery = graph.orm.modify_subquery_pagination(
|
|
214
|
+
subquery,
|
|
215
|
+
pagination_context
|
|
216
|
+
);
|
|
217
|
+
return modify ? modify(subquery, context) : subquery;
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
query = graph.orm.finish_query_pagination(query, field, pagination_context);
|
|
221
|
+
return query;
|
|
222
|
+
};
|
|
235
223
|
}
|
|
236
224
|
|
|
237
|
-
// src/resolvers/relation.ts
|
|
225
|
+
// ../graphql-orm/src/resolvers/relation.ts
|
|
238
226
|
function defineRelationResolver(options = {}) {
|
|
239
227
|
const { tableField, filters, modify } = options;
|
|
240
|
-
return
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
});
|
|
228
|
+
return function resolve(query, context) {
|
|
229
|
+
const { graph, field } = context;
|
|
230
|
+
return graph.orm.select_relation(query, {
|
|
231
|
+
relation: tableField || field,
|
|
232
|
+
as: field,
|
|
233
|
+
modify(subquery) {
|
|
234
|
+
subquery = graph._resolve_type(subquery, { ...context, filters });
|
|
235
|
+
return modify ? modify(subquery, context) : subquery;
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
};
|
|
254
239
|
}
|
|
255
240
|
|
|
256
|
-
// src/utils/is-plain-object.ts
|
|
241
|
+
// ../graphql-orm/src/utils/is-plain-object.ts
|
|
257
242
|
function is_plain_object(obj) {
|
|
258
243
|
return typeof obj === "object" && !Array.isArray(obj);
|
|
259
244
|
}
|
|
260
245
|
|
|
261
|
-
// src/filters/filters.ts
|
|
262
|
-
function
|
|
263
|
-
return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
264
|
-
}
|
|
265
|
-
function apply_filters({
|
|
266
|
-
query,
|
|
267
|
-
filters,
|
|
268
|
-
args,
|
|
269
|
-
modifiers
|
|
270
|
-
}) {
|
|
246
|
+
// ../graphql-orm/src/filters/filters.ts
|
|
247
|
+
function apply_filters(query, { filters, modifiers, context }) {
|
|
271
248
|
if (!filters) {
|
|
272
249
|
return query;
|
|
273
250
|
}
|
|
274
|
-
const filter_obj = args?.filter;
|
|
251
|
+
const filter_obj = context.tree.args?.filter;
|
|
275
252
|
if (!filter_obj) {
|
|
276
253
|
return query;
|
|
277
254
|
}
|
|
@@ -283,90 +260,60 @@ function apply_filters({
|
|
|
283
260
|
continue;
|
|
284
261
|
}
|
|
285
262
|
if (modifiers?.[field]) {
|
|
286
|
-
query = modifiers[field](query, value);
|
|
263
|
+
query = modifiers[field](query, value, context);
|
|
287
264
|
} else {
|
|
288
|
-
const [
|
|
289
|
-
const op = op0?.toLowerCase()
|
|
290
|
-
|
|
291
|
-
// TODO: add the rest of orchid ops (or allow all of them?)
|
|
292
|
-
[
|
|
293
|
-
"exact",
|
|
294
|
-
"lt",
|
|
295
|
-
"lte",
|
|
296
|
-
"gt",
|
|
297
|
-
"gte",
|
|
298
|
-
"like",
|
|
299
|
-
"ilike",
|
|
300
|
-
"contains"
|
|
301
|
-
].includes(op)
|
|
302
|
-
) {
|
|
303
|
-
if (!is_scalar(value)) {
|
|
304
|
-
throw new Error(
|
|
305
|
-
`Unsupported filter value for ${query.table}.${field}: must be scalar.`
|
|
306
|
-
);
|
|
307
|
-
}
|
|
308
|
-
if (op === "exact") {
|
|
309
|
-
query = query.where({ [dbfield]: value });
|
|
310
|
-
} else {
|
|
311
|
-
const query_op = { like: "contains" }[op] || op;
|
|
312
|
-
query = query.where({ [dbfield]: { [query_op]: value } });
|
|
313
|
-
}
|
|
314
|
-
} else if (op === "in") {
|
|
315
|
-
if (!(Array.isArray(value) && value.every(is_scalar))) {
|
|
316
|
-
throw new Error(
|
|
317
|
-
`Invalid filter value for ${query.table}.${field}: must be an array of scalars.`
|
|
318
|
-
);
|
|
319
|
-
}
|
|
320
|
-
query = query.whereIn(dbfield, value);
|
|
321
|
-
} else {
|
|
322
|
-
throw new Error(
|
|
323
|
-
`Invalid filter ${query.table}.${field}: unsupported operator ${op}.`
|
|
324
|
-
);
|
|
325
|
-
}
|
|
265
|
+
const [table_field, op0] = field.split("__");
|
|
266
|
+
const op = op0?.toLowerCase();
|
|
267
|
+
query = context.graph.orm.where(query, table_field, op, value);
|
|
326
268
|
}
|
|
327
269
|
}
|
|
328
270
|
return query;
|
|
329
271
|
}
|
|
330
272
|
|
|
331
|
-
// src/resolvers/table.ts
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
273
|
+
// ../graphql-orm/src/resolvers/table.ts
|
|
274
|
+
var TableResolver = class {
|
|
275
|
+
constructor(orm2, table, options = {}) {
|
|
276
|
+
this.orm = orm2;
|
|
277
|
+
this.table = table;
|
|
278
|
+
this.options = options;
|
|
279
|
+
this.relations = new Set(orm2.get_table_relations(table));
|
|
280
|
+
this.virtual_fields = new Set(orm2.get_table_virtual_fields(table));
|
|
281
|
+
this.modifiers = { ...orm2.get_table_modifiers(table), ...options.modifiers };
|
|
282
|
+
const { fields } = options;
|
|
283
|
+
if (fields) {
|
|
284
|
+
this.table_field_resolvers = Object.keys(fields).reduce((resolvers, field) => {
|
|
285
|
+
const r0 = fields[field];
|
|
286
|
+
const r = typeof r0 === "function" ? r0 : r0 === true ? this._get_default_field_resolver(field) : typeof r0 === "string" ? this._get_default_field_resolver(field, r0) : void 0;
|
|
287
|
+
if (r === void 0) {
|
|
288
|
+
throw new Error(
|
|
289
|
+
`Field resolver must be a function, string, or true; found ${typeof r0}.`
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
resolvers[field] = r;
|
|
293
|
+
return resolvers;
|
|
294
|
+
}, {});
|
|
341
295
|
}
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
resolvers[field] = r;
|
|
354
|
-
return resolvers;
|
|
355
|
-
},
|
|
356
|
-
{}
|
|
357
|
-
) : void 0;
|
|
358
|
-
const { modify, transform } = options;
|
|
359
|
-
return function resolve(query, context) {
|
|
296
|
+
}
|
|
297
|
+
// Introspection results
|
|
298
|
+
relations;
|
|
299
|
+
virtual_fields;
|
|
300
|
+
modifiers;
|
|
301
|
+
table_field_resolvers;
|
|
302
|
+
/** Modify query to select fields/relations and filter the result set. */
|
|
303
|
+
resolve(query, context) {
|
|
304
|
+
const { modify, transform } = this.options;
|
|
360
305
|
const { graph, tree, type, filters } = context;
|
|
361
|
-
|
|
306
|
+
const query_table = this.orm.get_query_table(query);
|
|
307
|
+
const table_table = this.orm.get_table_table(this.table);
|
|
308
|
+
if (query_table !== table_table) {
|
|
362
309
|
throw new Error(
|
|
363
|
-
`Mismatching query type
|
|
310
|
+
`Mismatching query table for type ${type}: expected ${table_table}, received ${query_table}.`
|
|
364
311
|
);
|
|
365
312
|
}
|
|
366
|
-
const allow_all_fields = options.allowAllFields ?? graph.options.allowAllFields ??
|
|
367
|
-
if (!allow_all_fields && !table_field_resolvers) {
|
|
313
|
+
const allow_all_fields = this.options.allowAllFields ?? graph.options.allowAllFields ?? !this.options.fields;
|
|
314
|
+
if (!allow_all_fields && !this.table_field_resolvers) {
|
|
368
315
|
throw new Error(
|
|
369
|
-
`
|
|
316
|
+
`Resolver for type ${type} must either allow all fields or specify options.fields.`
|
|
370
317
|
);
|
|
371
318
|
}
|
|
372
319
|
if (modify) {
|
|
@@ -374,31 +321,137 @@ function defineTableResolver(table, options = {}) {
|
|
|
374
321
|
}
|
|
375
322
|
for (const subtree of Object.values(tree.fieldsByTypeName[type])) {
|
|
376
323
|
const field = subtree.name;
|
|
377
|
-
const r = table_field_resolvers?.[field] || (allow_all_fields ?
|
|
324
|
+
const r = this.table_field_resolvers?.[field] || (allow_all_fields ? this._get_default_field_resolver(field) : void 0);
|
|
378
325
|
if (!r) {
|
|
379
|
-
throw new Error(`No field resolver defined for field ${type}.${field}
|
|
326
|
+
throw new Error(`No field resolver defined for field ${type}.${field}.`);
|
|
380
327
|
}
|
|
381
328
|
if (r) {
|
|
382
329
|
query = r(query, { ...context, tree: subtree, field });
|
|
383
330
|
}
|
|
384
331
|
}
|
|
385
|
-
const allow_all_filters = options.allowAllFilters ?? graph.options.allowAllFilters;
|
|
332
|
+
const allow_all_filters = this.options.allowAllFilters ?? graph.options.allowAllFilters;
|
|
386
333
|
const effective_filters = allow_all_filters ? true : filters;
|
|
387
334
|
if (effective_filters) {
|
|
388
|
-
query = apply_filters({
|
|
389
|
-
query,
|
|
335
|
+
query = apply_filters(query, {
|
|
390
336
|
filters: effective_filters,
|
|
391
|
-
|
|
392
|
-
|
|
337
|
+
modifiers: this.modifiers,
|
|
338
|
+
context
|
|
393
339
|
});
|
|
394
340
|
}
|
|
395
341
|
if (transform) {
|
|
396
|
-
query = run_after_query(query, (instance) => {
|
|
342
|
+
query = run_after_query(this.orm, query, (instance) => {
|
|
397
343
|
return transform(instance, context);
|
|
398
344
|
});
|
|
399
345
|
}
|
|
346
|
+
query = this.orm.prevent_select_all(query);
|
|
400
347
|
return query;
|
|
401
|
-
}
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Create field resolver which will modify query to resolve GraphQL field.
|
|
351
|
+
*/
|
|
352
|
+
_get_default_field_resolver(field, tableField) {
|
|
353
|
+
const table_field_lookup = tableField || field;
|
|
354
|
+
if (this.options.modifiers?.[table_field_lookup] || this.virtual_fields.has(table_field_lookup)) {
|
|
355
|
+
return (query) => query;
|
|
356
|
+
} else if (this.relations.has(table_field_lookup)) {
|
|
357
|
+
return defineRelationResolver({ tableField });
|
|
358
|
+
} else {
|
|
359
|
+
return defineFieldResolver({ tableField });
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
// src/orm/orm.ts
|
|
365
|
+
var import_orchid_core = require("orchid-core");
|
|
366
|
+
var orm = {
|
|
367
|
+
Table: void 0,
|
|
368
|
+
Query: void 0,
|
|
369
|
+
// Reflection
|
|
370
|
+
get_table_table(table) {
|
|
371
|
+
return table.table;
|
|
372
|
+
},
|
|
373
|
+
get_table_relations(table) {
|
|
374
|
+
return Object.keys(table.relations);
|
|
375
|
+
},
|
|
376
|
+
get_table_virtual_fields() {
|
|
377
|
+
return [];
|
|
378
|
+
},
|
|
379
|
+
get_table_modifiers() {
|
|
380
|
+
return void 0;
|
|
381
|
+
},
|
|
382
|
+
get_query_table(query) {
|
|
383
|
+
if (!query.table) {
|
|
384
|
+
throw new Error("Query must have table.");
|
|
385
|
+
}
|
|
386
|
+
return query.table;
|
|
387
|
+
},
|
|
388
|
+
// Select
|
|
389
|
+
select_field(query, { field, as }) {
|
|
390
|
+
return query.select({ [as]: field });
|
|
391
|
+
},
|
|
392
|
+
select_relation(query, { relation, as, modify }) {
|
|
393
|
+
return query.select({
|
|
394
|
+
[as]: (q) => modify(q[relation])
|
|
395
|
+
});
|
|
396
|
+
},
|
|
397
|
+
// Find
|
|
398
|
+
where(query, field, op, value) {
|
|
399
|
+
return query.where({ [field]: op ? { [op]: value } : value });
|
|
400
|
+
},
|
|
401
|
+
where_raw(query, expression, bindings) {
|
|
402
|
+
return query.where(query.raw(expression, bindings));
|
|
403
|
+
},
|
|
404
|
+
// Order & Limit
|
|
405
|
+
reset_query_order(query) {
|
|
406
|
+
return query.clear("order");
|
|
407
|
+
},
|
|
408
|
+
add_query_order(query, field, desc) {
|
|
409
|
+
return query.order({ [field]: desc ? "DESC" : "ASC" });
|
|
410
|
+
},
|
|
411
|
+
set_query_limit(query, limit) {
|
|
412
|
+
return query.limit(limit);
|
|
413
|
+
},
|
|
414
|
+
// Pagination helpers
|
|
415
|
+
set_query_page_result(query, get_page) {
|
|
416
|
+
const _query = query.query;
|
|
417
|
+
const { handleResult } = _query;
|
|
418
|
+
_query.handleResult = (q, result, s2) => {
|
|
419
|
+
const data = handleResult(q, result, s2);
|
|
420
|
+
return s2 ? data : get_page(data);
|
|
421
|
+
};
|
|
422
|
+
_query[s] = get_page;
|
|
423
|
+
return query;
|
|
424
|
+
},
|
|
425
|
+
modify_subquery_pagination(subquery, context) {
|
|
426
|
+
context.get_page = subquery.query[s];
|
|
427
|
+
return subquery;
|
|
428
|
+
},
|
|
429
|
+
finish_query_pagination(query, field, context) {
|
|
430
|
+
const { get_page } = context;
|
|
431
|
+
if (!get_page) {
|
|
432
|
+
throw new Error(`Internal error: paginator didn't provide page callback.`);
|
|
433
|
+
}
|
|
434
|
+
(0, import_orchid_core.overrideParserInQuery)(query.query, field, get_page);
|
|
435
|
+
return query;
|
|
436
|
+
},
|
|
437
|
+
// Misc
|
|
438
|
+
run_after_query(query, fn) {
|
|
439
|
+
return query.afterQuery(async (_, result) => fn(result));
|
|
440
|
+
},
|
|
441
|
+
prevent_select_all(query) {
|
|
442
|
+
return query;
|
|
443
|
+
}
|
|
444
|
+
};
|
|
445
|
+
var s = Symbol("subquery_pagination_handler");
|
|
446
|
+
|
|
447
|
+
// src/resolvers/graph.ts
|
|
448
|
+
function createGraphResolver(types, options) {
|
|
449
|
+
return new GraphResolver(orm, types, options);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// src/resolvers/table.ts
|
|
453
|
+
function defineTableResolver(table, options = {}) {
|
|
454
|
+
return new TableResolver(orm, table, options);
|
|
402
455
|
}
|
|
403
456
|
// Annotate the CommonJS export names for ESM import in node:
|
|
404
457
|
0 && (module.exports = {
|