@coderich/autograph 0.11.1 → 0.13.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/index.js +4 -6
- package/package.json +30 -44
- package/src/data/DataLoader.js +77 -70
- package/src/data/Emitter.js +89 -0
- package/src/data/Loader.js +33 -0
- package/src/data/Pipeline.js +88 -96
- package/src/data/Resolver.js +304 -0
- package/src/data/Transaction.js +49 -0
- package/src/query/Query.js +159 -334
- package/src/query/QueryBuilder.js +228 -114
- package/src/query/QueryResolver.js +110 -216
- package/src/query/QueryResolverTransaction.js +16 -0
- package/src/schema/Schema.js +593 -0
- package/src/service/AppService.js +38 -0
- package/src/service/ErrorService.js +7 -0
- package/CHANGELOG.md +0 -41
- package/LICENSE +0 -21
- package/README.md +0 -76
- package/src/.DS_Store +0 -0
- package/src/core/.DS_Store +0 -0
- package/src/core/Boom.js +0 -9
- package/src/core/EventEmitter.js +0 -95
- package/src/core/Resolver.js +0 -124
- package/src/core/Schema.js +0 -55
- package/src/core/ServerResolver.js +0 -15
- package/src/data/.DS_Store +0 -0
- package/src/data/DataService.js +0 -120
- package/src/data/DataTransaction.js +0 -96
- package/src/data/Field.js +0 -83
- package/src/data/Model.js +0 -223
- package/src/data/TreeMap.js +0 -78
- package/src/data/Type.js +0 -50
- package/src/driver/.DS_Store +0 -0
- package/src/driver/MongoDriver.js +0 -227
- package/src/driver/index.js +0 -11
- package/src/graphql/.DS_Store +0 -0
- package/src/graphql/ast/.DS_Store +0 -0
- package/src/graphql/ast/Field.js +0 -206
- package/src/graphql/ast/Model.js +0 -145
- package/src/graphql/ast/Node.js +0 -291
- package/src/graphql/ast/Schema.js +0 -133
- package/src/graphql/ast/Type.js +0 -26
- package/src/graphql/ast/TypeDefApi.js +0 -93
- package/src/graphql/extension/.DS_Store +0 -0
- package/src/graphql/extension/api.js +0 -193
- package/src/graphql/extension/framework.js +0 -71
- package/src/graphql/extension/type.js +0 -34
- package/src/query/.DS_Store +0 -0
- package/src/query/QueryBuilderTransaction.js +0 -26
- package/src/query/QueryService.js +0 -111
- package/src/service/.DS_Store +0 -0
- package/src/service/app.service.js +0 -319
- package/src/service/decorator.service.js +0 -114
- package/src/service/event.service.js +0 -66
- package/src/service/graphql.service.js +0 -92
- package/src/service/schema.service.js +0 -95
package/src/query/Query.js
CHANGED
|
@@ -1,361 +1,186 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
this.timers = {};
|
|
5
|
-
this.isCursorPaging = false;
|
|
6
|
-
this.isClassicPaging = false;
|
|
7
|
-
this.props.joins = this.props.joins || [];
|
|
8
|
-
this.props.match = this.props.match || {};
|
|
9
|
-
this.props.options = this.props.options || {};
|
|
10
|
-
this.props.flags = this.props.flags || {
|
|
11
|
-
debug: false,
|
|
12
|
-
silent: false,
|
|
13
|
-
validate: true, // { externals }
|
|
14
|
-
pipeline: true, // { instruct, construct, destruct, restruct, serialize, deserialize, transform, rekey }
|
|
15
|
-
required: false,
|
|
16
|
-
};
|
|
17
|
-
this.merge(props);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
propCheck(prop, ...checks) {
|
|
21
|
-
checks.forEach((check) => {
|
|
22
|
-
if (this.props[check]) throw new Error(`Cannot use "${prop}" while using "${check}"`);
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
id(id) {
|
|
27
|
-
this.propCheck('id', 'where', 'native', 'sort', 'skip', 'limit', 'before', 'after', 'first', 'last');
|
|
28
|
-
this.props.id = id;
|
|
29
|
-
this.props.batch = 'id';
|
|
30
|
-
this.props.where = { id };
|
|
31
|
-
return this.match({ id });
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
batch(batch) {
|
|
35
|
-
this.props.batch = batch;
|
|
36
|
-
return this;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
where(where) {
|
|
40
|
-
this.propCheck('where', 'id', 'native');
|
|
41
|
-
this.props.where = where;
|
|
42
|
-
return this.match(where);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
search(search) {
|
|
46
|
-
this.propCheck('search', 'id');
|
|
47
|
-
this.props.search = search;
|
|
48
|
-
return this;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
native(native) {
|
|
52
|
-
this.propCheck('native', 'id', 'where');
|
|
53
|
-
this.props.native = native;
|
|
54
|
-
return this.match(native);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
match(match) {
|
|
58
|
-
this.props.match = match;
|
|
59
|
-
return this;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
select(select) {
|
|
63
|
-
this.props.select = select;
|
|
64
|
-
return this;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
$select(select) {
|
|
68
|
-
this.props.$select = select;
|
|
69
|
-
return this;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
fields(fields) {
|
|
73
|
-
this.props.select = fields;
|
|
74
|
-
return this;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
joins(...joins) {
|
|
78
|
-
this.props.joins.push(...joins);
|
|
79
|
-
return this;
|
|
80
|
-
}
|
|
1
|
+
const Util = require('@coderich/util');
|
|
2
|
+
const Pipeline = require('../data/Pipeline');
|
|
3
|
+
const { isGlob, globToRegex, mergeDeep, finalizeWhereClause } = require('../service/AppService');
|
|
81
4
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
this.props.$sort = sort;
|
|
90
|
-
return this;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
sortBy(sort) {
|
|
94
|
-
return this.sort(sort);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
skip(skip) {
|
|
98
|
-
this.propCheck('skip', 'id');
|
|
99
|
-
if (this.isCursorPaging) throw new Error('Cannot use "skip" while using Cursor-Style Pagination');
|
|
100
|
-
this.isClassicPaging = true;
|
|
101
|
-
this.props.skip = skip;
|
|
102
|
-
return this;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
limit(limit) {
|
|
106
|
-
this.propCheck('limit', 'id');
|
|
107
|
-
if (this.isCursorPaging) throw new Error('Cannot use "limit" while using Cursor-Style Pagination');
|
|
108
|
-
this.isClassicPaging = true;
|
|
109
|
-
this.props.limit = limit;
|
|
110
|
-
return this;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
first(first) {
|
|
114
|
-
this.propCheck('first', 'id', 'last');
|
|
115
|
-
if (this.isClassicPaging) throw new Error('Cannot use "first" while using Classic-Style Pagination');
|
|
116
|
-
this.isCursorPaging = true;
|
|
117
|
-
this.props.first = first + 2; // Adding 2 for pagination meta info (hasNext hasPrev)
|
|
118
|
-
return this;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
last(last) {
|
|
122
|
-
this.propCheck('last', 'id', 'first');
|
|
123
|
-
if (this.isClassicPaging) throw new Error('Cannot use "last" while using Classic-Style Pagination');
|
|
124
|
-
this.isCursorPaging = true;
|
|
125
|
-
this.props.last = last + 2; // Adding 2 for pagination meta info (hasNext hasPrev)
|
|
126
|
-
return this;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
before(before) {
|
|
130
|
-
this.propCheck('before', 'id');
|
|
131
|
-
if (this.isClassicPaging) throw new Error('Cannot use "before" while using Classic-Style Pagination');
|
|
132
|
-
this.isCursorPaging = true;
|
|
133
|
-
this.props.before = before;
|
|
134
|
-
return this;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
after(after) {
|
|
138
|
-
this.propCheck('after', 'id');
|
|
139
|
-
if (this.isClassicPaging) throw new Error('Cannot use "after" while using Classic-Style Pagination');
|
|
140
|
-
this.isCursorPaging = true;
|
|
141
|
-
this.props.after = after;
|
|
142
|
-
return this;
|
|
143
|
-
}
|
|
5
|
+
module.exports = class Query {
|
|
6
|
+
#config;
|
|
7
|
+
#resolver;
|
|
8
|
+
#context;
|
|
9
|
+
#schema;
|
|
10
|
+
#model;
|
|
11
|
+
#query;
|
|
144
12
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
13
|
+
constructor(config) {
|
|
14
|
+
const { schema, context, resolver, query } = config;
|
|
15
|
+
this.#config = config;
|
|
16
|
+
this.#resolver = resolver;
|
|
17
|
+
this.#context = context;
|
|
18
|
+
this.#schema = schema;
|
|
19
|
+
this.#model = schema.models[query.model];
|
|
20
|
+
this.#query = query;
|
|
148
21
|
}
|
|
149
22
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
return this;
|
|
23
|
+
clone(query) {
|
|
24
|
+
query = { ...this.#query, ...query }; // NO deepMerge here; must replace fields entirely
|
|
25
|
+
return new Query({ ...this.#config, query });
|
|
153
26
|
}
|
|
154
27
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return this;
|
|
28
|
+
toObject() {
|
|
29
|
+
return this.#query;
|
|
158
30
|
}
|
|
159
31
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
32
|
+
toCacheKey() {
|
|
33
|
+
return {
|
|
34
|
+
op: this.#query.op,
|
|
35
|
+
where: this.#query.where,
|
|
36
|
+
sort: this.#query.sort,
|
|
37
|
+
joins: this.#query.joins,
|
|
38
|
+
skip: this.#query.skip,
|
|
39
|
+
limit: this.#query.limit,
|
|
40
|
+
before: this.#query.before,
|
|
41
|
+
after: this.#query.after,
|
|
42
|
+
first: this.#query.first,
|
|
43
|
+
last: this.#query.last,
|
|
44
|
+
};
|
|
163
45
|
}
|
|
164
46
|
|
|
165
47
|
/**
|
|
166
|
-
*
|
|
48
|
+
* Run a portion of the pipeline against a data set
|
|
167
49
|
*/
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
50
|
+
pipeline(target, data, transformers) {
|
|
51
|
+
data = Util.unflatten(data);
|
|
52
|
+
const crudMap = { create: ['$construct', '$serialize'], update: ['$restruct', '$serialize'] };
|
|
53
|
+
const crudLines = crudMap[this.#query.crud] || [];
|
|
54
|
+
const transformerMap = { where: ['$cast', '$instruct', '$serialize'], sort: [], input: [] };
|
|
55
|
+
if (this.#query.isMutation) transformerMap.input = ['$default', '$cast', '$normalize', '$instruct', ...crudLines];
|
|
56
|
+
transformers = transformers || transformerMap[target];
|
|
57
|
+
return this.#pipeline(this.#query, target, this.#model, data, transformers.map(el => Pipeline[el]));
|
|
171
58
|
}
|
|
172
59
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Transform entire query via pipeline. At minimum, pipeline is needed to unflatten the data...
|
|
62
|
+
*/
|
|
63
|
+
transform() {
|
|
64
|
+
return Promise.all([
|
|
65
|
+
this.pipeline('input', this.#query.input),
|
|
66
|
+
this.#query.isNative ? this.#query.where : this.pipeline('where', this.#query.where),
|
|
67
|
+
this.pipeline('sort', this.#query.sort),
|
|
68
|
+
]).then(([input, where, sort]) => this.clone({ input, where, sort }));
|
|
177
69
|
}
|
|
178
70
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Transform entire query for driver
|
|
73
|
+
*/
|
|
74
|
+
toDriver() {
|
|
75
|
+
const { input, where, sort, before, after, isNative, isCursorPaging } = this.#query;
|
|
76
|
+
|
|
77
|
+
const query = this.clone({
|
|
78
|
+
select: Object.values(this.#model.fields).map(field => field.key),
|
|
79
|
+
input: this.#model.walk(input, node => node.value !== undefined && Object.assign(node, { key: node.field.key })),
|
|
80
|
+
where: isNative ? where : this.#model.walk(where, node => Object.assign(node, { key: node.field.key })),
|
|
81
|
+
sort: this.#model.walk(sort, node => Object.assign(node, { key: node.field.key })),
|
|
82
|
+
before: (!isCursorPaging || !before) ? undefined : JSON.parse(Buffer.from(before, 'base64').toString('ascii')),
|
|
83
|
+
after: (!isCursorPaging || !after) ? undefined : JSON.parse(Buffer.from(after, 'base64').toString('ascii')),
|
|
84
|
+
$schema: this.#schema.resolvePath,
|
|
85
|
+
});
|
|
183
86
|
|
|
184
|
-
|
|
185
|
-
this.props.model = model;
|
|
186
|
-
return this;
|
|
187
|
-
}
|
|
87
|
+
if (!isNative) this.#finalize(query.toObject());
|
|
188
88
|
|
|
189
|
-
|
|
190
|
-
this.props.transaction = transaction;
|
|
191
|
-
return this;
|
|
89
|
+
return query;
|
|
192
90
|
}
|
|
193
91
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Recursive pipeline function
|
|
94
|
+
*/
|
|
95
|
+
#pipeline(query, target, model, data, transformers = [], paths = []) {
|
|
96
|
+
return Util.mapPromise(data, (doc, index) => {
|
|
97
|
+
const path = [...paths];
|
|
98
|
+
if (Array.isArray(data)) path.push(index);
|
|
99
|
+
if (target === 'input') doc = mergeDeep(model.pipelineFields.input, doc);
|
|
100
|
+
else if (target === 'where') doc = mergeDeep(model.pipelineFields.where, doc);
|
|
101
|
+
|
|
102
|
+
return Util.pipeline(Object.entries(doc).map(([key, startValue]) => async (prev) => {
|
|
103
|
+
const field = model.fields[key];
|
|
104
|
+
if (!field) return prev;
|
|
105
|
+
|
|
106
|
+
// Transform value
|
|
107
|
+
let $value = await Util.pipeline(transformers.map(t => async (value) => {
|
|
108
|
+
const v = await t({ query, model, field, value, path: path.concat(key), startValue, resolver: this.#resolver, context: this.#context, schema: this.#schema });
|
|
109
|
+
return v === undefined ? value : v;
|
|
110
|
+
}), startValue);
|
|
111
|
+
|
|
112
|
+
// If it's embedded - delegate
|
|
113
|
+
if (field.isEmbedded) $value = await this.#pipeline(query, target, field.model, $value, transformers, path.concat(key));
|
|
114
|
+
|
|
115
|
+
// Assign it back
|
|
116
|
+
if (target === 'input' && $value === undefined) return prev;
|
|
117
|
+
return Object.assign(prev, { [field.name]: $value });
|
|
118
|
+
}), {});
|
|
119
|
+
});
|
|
197
120
|
}
|
|
198
121
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
122
|
+
/**
|
|
123
|
+
* Finalize the query for the driver
|
|
124
|
+
*/
|
|
125
|
+
#finalize(query) {
|
|
126
|
+
const { where = {}, sort = {} } = query;
|
|
127
|
+
const flatSort = Util.flatten(sort, { safe: true });
|
|
128
|
+
const flatWhere = Util.flatten(where, { safe: true });
|
|
129
|
+
const $sort = Util.unflatten(Object.keys(flatSort).reduce((prev, key) => Object.assign(prev, { [key]: {} }), {}));
|
|
130
|
+
|
|
131
|
+
//
|
|
132
|
+
query.sort = this.#model.walk(sort, (node) => {
|
|
133
|
+
if (node.field.isVirtual || node.field.isFKReference) node.key = `join_${node.field.model.key}`;
|
|
134
|
+
return node;
|
|
135
|
+
}, { key: 'key' });
|
|
136
|
+
|
|
137
|
+
// Reconstruct the where clause by pulling out anything that requires a join
|
|
138
|
+
query.where = finalizeWhereClause(Util.unflatten(Object.entries(flatWhere).reduce((prev, [key, value]) => {
|
|
139
|
+
if (this.#model.isJoinPath(key, 'key')) return prev;
|
|
140
|
+
value = Util.map(value, el => (isGlob(el) ? globToRegex(el) : el));
|
|
141
|
+
return Object.assign(prev, { [key]: value });
|
|
142
|
+
}, {}), { safe: true }));
|
|
143
|
+
|
|
144
|
+
// Determine what join data is needed (derived from where + sort)
|
|
145
|
+
const joinData = mergeDeep($sort, Util.unflatten(Object.entries(flatWhere).reduce((prev, [key, value]) => {
|
|
146
|
+
if (this.#model.isJoinPath(key, 'key')) return Object.assign(prev, { [key]: value });
|
|
147
|
+
return prev;
|
|
148
|
+
}, {}), { safe: true }));
|
|
149
|
+
|
|
150
|
+
// Construct joins
|
|
151
|
+
query.joins = [];
|
|
152
|
+
|
|
153
|
+
this.#model.walk(joinData, (node) => {
|
|
154
|
+
const { model, field, key, value, isLeaf, path, run } = node;
|
|
155
|
+
|
|
156
|
+
if (field.join) {
|
|
157
|
+
let isArray;
|
|
158
|
+
const join = { ...field.join, where: {} };
|
|
159
|
+
|
|
160
|
+
if (run.length > 1) {
|
|
161
|
+
join.from = path.reduce((prev, curr, i) => {
|
|
162
|
+
const $field = this.#model.resolvePath(path.slice(0, i + 1).join('.'), 'key');
|
|
163
|
+
if ($field.isArray) isArray = true;
|
|
164
|
+
return prev.concat($field.linkField.key);
|
|
165
|
+
}, []).join('.');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
join.isArray = isArray || model.resolvePath(join.from).isArray;
|
|
169
|
+
|
|
170
|
+
query.joins.push(join);
|
|
236
171
|
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
return this;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
crud(crud) {
|
|
243
|
-
this.props.crud = crud;
|
|
244
|
-
return this;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
key(key) {
|
|
248
|
-
this.props.key = key;
|
|
249
|
-
return this;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
input(input = {}) { // Allows .save(/* empty */);
|
|
253
|
-
// delete input.id; // We do not want to allow changing id via input
|
|
254
|
-
this.props.input = input;
|
|
255
|
-
return this;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
$input(input) {
|
|
259
|
-
this.props.$input = input;
|
|
260
|
-
return this;
|
|
261
|
-
}
|
|
262
172
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
payload(payload) {
|
|
274
|
-
this.props.payload = payload;
|
|
275
|
-
return this;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
result(result) {
|
|
279
|
-
this.props.result = result;
|
|
280
|
-
return this;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
$doc($doc) {
|
|
284
|
-
this.props.$doc = $doc;
|
|
285
|
-
return this;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
args(args) {
|
|
289
|
-
this.props.args = args;
|
|
290
|
-
return this;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
clone() {
|
|
294
|
-
const clone = new Query();
|
|
295
|
-
clone.props = { ...this.props };
|
|
296
|
-
return clone;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
toDriver() {
|
|
300
|
-
const self = this;
|
|
301
|
-
const { model } = this.props;
|
|
302
|
-
const isSorted = Boolean(Object.keys(this.props.$sort || {}).length);
|
|
303
|
-
|
|
304
|
-
return {
|
|
305
|
-
isNative: Boolean(this.props.native),
|
|
306
|
-
model: model.getKey(),
|
|
307
|
-
shape: model.getShape(),
|
|
308
|
-
method: this.props.method,
|
|
309
|
-
select: this.props.$select,
|
|
310
|
-
joins: this.props.joins,
|
|
311
|
-
where: this.props.match,
|
|
312
|
-
search: this.props.search,
|
|
313
|
-
sort: this.props.$sort,
|
|
314
|
-
skip: this.props.skip,
|
|
315
|
-
limit: this.props.limit,
|
|
316
|
-
first: isSorted ? this.props.first : undefined,
|
|
317
|
-
last: isSorted ? this.props.last : undefined,
|
|
318
|
-
// before: isSorted && this.props.before ? model.normalize(this, JSON.parse(Buffer.from(this.props.before, 'base64').toString('ascii')), 'serialize') : undefined,
|
|
319
|
-
get before() {
|
|
320
|
-
if (!isSorted || !self.props.before) return undefined;
|
|
321
|
-
const shape = model.getShape('create', 'sort');
|
|
322
|
-
const before = JSON.parse(Buffer.from(self.props.before, 'base64').toString('ascii'));
|
|
323
|
-
const $before = model.shapeObject(shape, before, self);
|
|
324
|
-
return $before;
|
|
325
|
-
},
|
|
326
|
-
get after() {
|
|
327
|
-
if (!isSorted || !self.props.after) return undefined;
|
|
328
|
-
const shape = model.getShape('create', 'sort');
|
|
329
|
-
const after = JSON.parse(Buffer.from(self.props.after, 'base64').toString('ascii'));
|
|
330
|
-
const $after = model.shapeObject(shape, after, self);
|
|
331
|
-
return $after;
|
|
332
|
-
},
|
|
333
|
-
options: this.props.options,
|
|
334
|
-
input: this.props.$input,
|
|
335
|
-
flags: this.props.flags,
|
|
336
|
-
$doc: this.props.$doc,
|
|
337
|
-
doc: this.props.doc,
|
|
338
|
-
};
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
toObject() {
|
|
342
|
-
return this.props;
|
|
343
|
-
}
|
|
173
|
+
if (isLeaf) {
|
|
174
|
+
const $model = field.model || model;
|
|
175
|
+
const join = query.joins.find(j => j.to === $model.key);
|
|
176
|
+
const $value = Util.map(value, el => (isGlob(el) ? globToRegex(el) : el));
|
|
177
|
+
const $$value = Array.isArray($value) ? { $in: $value } : $value;
|
|
178
|
+
const from = field.model ? join.from : key;
|
|
179
|
+
join.where[from] = $$value;
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
344
182
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
cmd: this.props.cmd,
|
|
348
|
-
method: this.props.method,
|
|
349
|
-
where: this.props.match,
|
|
350
|
-
search: this.props.search,
|
|
351
|
-
sort: this.props.sort,
|
|
352
|
-
skip: this.props.skip,
|
|
353
|
-
limit: this.props.limit,
|
|
354
|
-
before: this.props.before,
|
|
355
|
-
after: this.props.after,
|
|
356
|
-
first: this.props.first,
|
|
357
|
-
last: this.props.last,
|
|
358
|
-
options: this.props.options,
|
|
359
|
-
};
|
|
183
|
+
return node;
|
|
184
|
+
}, { key: 'key' });
|
|
360
185
|
}
|
|
361
186
|
};
|