@coderich/autograph 0.12.0 → 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 +84 -101
- package/src/data/Resolver.js +304 -0
- package/src/data/Transaction.js +49 -0
- package/src/query/Query.js +158 -335
- package/src/query/QueryBuilder.js +228 -114
- package/src/query/QueryResolver.js +110 -205
- 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 -161
- package/src/data/Field.js +0 -83
- package/src/data/Model.js +0 -214
- 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,363 +1,186 @@
|
|
|
1
|
-
const
|
|
1
|
+
const Util = require('@coderich/util');
|
|
2
|
+
const Pipeline = require('../data/Pipeline');
|
|
3
|
+
const { isGlob, globToRegex, mergeDeep, finalizeWhereClause } = require('../service/AppService');
|
|
2
4
|
|
|
3
5
|
module.exports = class Query {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
this.props.match = this.props.match || {};
|
|
11
|
-
this.props.options = this.props.options || {};
|
|
12
|
-
this.props.flags = this.props.flags || {
|
|
13
|
-
debug: false,
|
|
14
|
-
silent: false,
|
|
15
|
-
validate: true, // { externals }
|
|
16
|
-
pipeline: true, // { instruct, construct, destruct, restruct, serialize, deserialize, transform, rekey }
|
|
17
|
-
required: false,
|
|
18
|
-
};
|
|
19
|
-
this.merge(props);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
propCheck(prop, ...checks) {
|
|
23
|
-
checks.forEach((check) => {
|
|
24
|
-
if (this.props[check]) throw Boom.badRequest(`Cannot use "${prop}" while using "${check}"`);
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
id(id) {
|
|
29
|
-
this.propCheck('id', 'where', 'native', 'sort', 'skip', 'limit', 'before', 'after', 'first', 'last');
|
|
30
|
-
this.props.id = id;
|
|
31
|
-
this.props.batch = 'id';
|
|
32
|
-
this.props.where = { id };
|
|
33
|
-
return this.match({ id });
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
batch(batch) {
|
|
37
|
-
this.props.batch = batch;
|
|
38
|
-
return this;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
where(where) {
|
|
42
|
-
this.propCheck('where', 'id', 'native');
|
|
43
|
-
this.props.where = where;
|
|
44
|
-
return this.match(where);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
search(search) {
|
|
48
|
-
this.propCheck('search', 'id');
|
|
49
|
-
this.props.search = search;
|
|
50
|
-
return this;
|
|
51
|
-
}
|
|
6
|
+
#config;
|
|
7
|
+
#resolver;
|
|
8
|
+
#context;
|
|
9
|
+
#schema;
|
|
10
|
+
#model;
|
|
11
|
+
#query;
|
|
52
12
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
this
|
|
56
|
-
|
|
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;
|
|
57
21
|
}
|
|
58
22
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return this;
|
|
23
|
+
clone(query) {
|
|
24
|
+
query = { ...this.#query, ...query }; // NO deepMerge here; must replace fields entirely
|
|
25
|
+
return new Query({ ...this.#config, query });
|
|
62
26
|
}
|
|
63
27
|
|
|
64
|
-
|
|
65
|
-
this
|
|
66
|
-
return this;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
$select(select) {
|
|
70
|
-
this.props.$select = select;
|
|
71
|
-
return this;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
fields(fields) {
|
|
75
|
-
this.props.select = fields;
|
|
76
|
-
return this;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
joins(...joins) {
|
|
80
|
-
this.props.joins.push(...joins);
|
|
81
|
-
return this;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
sort(sort) {
|
|
85
|
-
this.propCheck('sort', 'id');
|
|
86
|
-
this.props.sort = sort;
|
|
87
|
-
return this;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
$sort(sort) {
|
|
91
|
-
this.props.$sort = sort;
|
|
92
|
-
return this;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
sortBy(sort) {
|
|
96
|
-
return this.sort(sort);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
skip(skip) {
|
|
100
|
-
this.propCheck('skip', 'id');
|
|
101
|
-
if (this.isCursorPaging) throw Boom.badRequest('Cannot use "skip" while using Cursor-Style Pagination');
|
|
102
|
-
this.isClassicPaging = true;
|
|
103
|
-
this.props.skip = skip;
|
|
104
|
-
return this;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
limit(limit) {
|
|
108
|
-
this.propCheck('limit', 'id');
|
|
109
|
-
if (this.isCursorPaging) throw Boom.badRequest('Cannot use "limit" while using Cursor-Style Pagination');
|
|
110
|
-
this.isClassicPaging = true;
|
|
111
|
-
this.props.limit = limit;
|
|
112
|
-
return this;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
first(first) {
|
|
116
|
-
this.propCheck('first', 'id', 'last');
|
|
117
|
-
if (this.isClassicPaging) throw Boom.badRequest('Cannot use "first" while using Classic-Style Pagination');
|
|
118
|
-
this.isCursorPaging = true;
|
|
119
|
-
this.props.first = first + 2; // Adding 2 for pagination meta info (hasNext hasPrev)
|
|
120
|
-
return this;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
last(last) {
|
|
124
|
-
this.propCheck('last', 'id', 'first');
|
|
125
|
-
if (this.isClassicPaging) throw Boom.badRequest('Cannot use "last" while using Classic-Style Pagination');
|
|
126
|
-
this.isCursorPaging = true;
|
|
127
|
-
this.props.last = last + 2; // Adding 2 for pagination meta info (hasNext hasPrev)
|
|
128
|
-
return this;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
before(before) {
|
|
132
|
-
this.propCheck('before', 'id');
|
|
133
|
-
if (this.isClassicPaging) throw Boom.badRequest('Cannot use "before" while using Classic-Style Pagination');
|
|
134
|
-
this.isCursorPaging = true;
|
|
135
|
-
this.props.before = before;
|
|
136
|
-
return this;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
after(after) {
|
|
140
|
-
this.propCheck('after', 'id');
|
|
141
|
-
if (this.isClassicPaging) throw Boom.badRequest('Cannot use "after" while using Classic-Style Pagination');
|
|
142
|
-
this.isCursorPaging = true;
|
|
143
|
-
this.props.after = after;
|
|
144
|
-
return this;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
options(options) {
|
|
148
|
-
this.props.options = options;
|
|
149
|
-
return this;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
meta(meta) {
|
|
153
|
-
this.props.meta = meta;
|
|
154
|
-
return this;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
flags(flags) {
|
|
158
|
-
Object.assign(this.props.flags, flags);
|
|
159
|
-
return this;
|
|
28
|
+
toObject() {
|
|
29
|
+
return this.#query;
|
|
160
30
|
}
|
|
161
31
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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
|
+
};
|
|
165
45
|
}
|
|
166
46
|
|
|
167
47
|
/**
|
|
168
|
-
*
|
|
48
|
+
* Run a portion of the pipeline against a data set
|
|
169
49
|
*/
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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]));
|
|
173
58
|
}
|
|
174
59
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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 }));
|
|
179
69
|
}
|
|
180
70
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
+
});
|
|
185
86
|
|
|
186
|
-
|
|
187
|
-
this.props.model = model;
|
|
188
|
-
return this;
|
|
189
|
-
}
|
|
87
|
+
if (!isNative) this.#finalize(query.toObject());
|
|
190
88
|
|
|
191
|
-
|
|
192
|
-
this.props.transaction = transaction;
|
|
193
|
-
return this;
|
|
89
|
+
return query;
|
|
194
90
|
}
|
|
195
91
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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
|
+
});
|
|
199
120
|
}
|
|
200
121
|
|
|
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
|
-
|
|
236
|
-
|
|
237
|
-
|
|
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);
|
|
238
171
|
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
return this;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
crud(crud) {
|
|
245
|
-
this.props.crud = crud;
|
|
246
|
-
return this;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
key(key) {
|
|
250
|
-
this.props.key = key;
|
|
251
|
-
return this;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
input(input = {}) { // Allows .save(/* empty */);
|
|
255
|
-
// delete input.id; // We do not want to allow changing id via input
|
|
256
|
-
this.props.input = input;
|
|
257
|
-
return this;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
$input(input) {
|
|
261
|
-
this.props.$input = input;
|
|
262
|
-
return this;
|
|
263
|
-
}
|
|
264
172
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
payload(payload) {
|
|
276
|
-
this.props.payload = payload;
|
|
277
|
-
return this;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
result(result) {
|
|
281
|
-
this.props.result = result;
|
|
282
|
-
return this;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
$doc($doc) {
|
|
286
|
-
this.props.$doc = $doc;
|
|
287
|
-
return this;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
args(args) {
|
|
291
|
-
this.props.args = args;
|
|
292
|
-
return this;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
clone() {
|
|
296
|
-
const clone = new Query();
|
|
297
|
-
clone.props = { ...this.props };
|
|
298
|
-
return clone;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
toDriver() {
|
|
302
|
-
const self = this;
|
|
303
|
-
const { model } = this.props;
|
|
304
|
-
const isSorted = Boolean(Object.keys(this.props.$sort || {}).length);
|
|
305
|
-
|
|
306
|
-
return {
|
|
307
|
-
isNative: Boolean(this.props.native),
|
|
308
|
-
model: model.getKey(),
|
|
309
|
-
shape: model.getShape(),
|
|
310
|
-
method: this.props.method,
|
|
311
|
-
select: this.props.$select,
|
|
312
|
-
joins: this.props.joins,
|
|
313
|
-
where: this.props.match,
|
|
314
|
-
search: this.props.search,
|
|
315
|
-
sort: this.props.$sort,
|
|
316
|
-
skip: this.props.skip,
|
|
317
|
-
limit: this.props.limit,
|
|
318
|
-
first: isSorted ? this.props.first : undefined,
|
|
319
|
-
last: isSorted ? this.props.last : undefined,
|
|
320
|
-
// before: isSorted && this.props.before ? model.normalize(this, JSON.parse(Buffer.from(this.props.before, 'base64').toString('ascii')), 'serialize') : undefined,
|
|
321
|
-
get before() {
|
|
322
|
-
if (!isSorted || !self.props.before) return undefined;
|
|
323
|
-
const shape = model.getShape('create', 'sort');
|
|
324
|
-
const before = JSON.parse(Buffer.from(self.props.before, 'base64').toString('ascii'));
|
|
325
|
-
const $before = model.shapeObject(shape, before, self);
|
|
326
|
-
return $before;
|
|
327
|
-
},
|
|
328
|
-
get after() {
|
|
329
|
-
if (!isSorted || !self.props.after) return undefined;
|
|
330
|
-
const shape = model.getShape('create', 'sort');
|
|
331
|
-
const after = JSON.parse(Buffer.from(self.props.after, 'base64').toString('ascii'));
|
|
332
|
-
const $after = model.shapeObject(shape, after, self);
|
|
333
|
-
return $after;
|
|
334
|
-
},
|
|
335
|
-
options: this.props.options,
|
|
336
|
-
input: this.props.$input,
|
|
337
|
-
flags: this.props.flags,
|
|
338
|
-
$doc: this.props.$doc,
|
|
339
|
-
doc: this.props.doc,
|
|
340
|
-
};
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
toObject() {
|
|
344
|
-
return this.props;
|
|
345
|
-
}
|
|
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
|
+
}
|
|
346
182
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
cmd: this.props.cmd,
|
|
350
|
-
method: this.props.method,
|
|
351
|
-
where: this.props.match,
|
|
352
|
-
search: this.props.search,
|
|
353
|
-
sort: this.props.sort,
|
|
354
|
-
skip: this.props.skip,
|
|
355
|
-
limit: this.props.limit,
|
|
356
|
-
before: this.props.before,
|
|
357
|
-
after: this.props.after,
|
|
358
|
-
first: this.props.first,
|
|
359
|
-
last: this.props.last,
|
|
360
|
-
options: this.props.options,
|
|
361
|
-
};
|
|
183
|
+
return node;
|
|
184
|
+
}, { key: 'key' });
|
|
362
185
|
}
|
|
363
186
|
};
|