@coderich/autograph 0.12.0 → 0.13.1
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 +159 -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 +602 -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,187 @@
|
|
|
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
|
+
model: this.#model.key,
|
|
79
|
+
select: Object.values(this.#model.fields).map(field => field.key),
|
|
80
|
+
input: this.#model.walk(input, node => node.value !== undefined && Object.assign(node, { key: node.field.key })),
|
|
81
|
+
where: isNative ? where : this.#model.walk(where, node => Object.assign(node, { key: node.field.key })),
|
|
82
|
+
sort: this.#model.walk(sort, node => Object.assign(node, { key: node.field.key })),
|
|
83
|
+
before: (!isCursorPaging || !before) ? undefined : JSON.parse(Buffer.from(before, 'base64').toString('ascii')),
|
|
84
|
+
after: (!isCursorPaging || !after) ? undefined : JSON.parse(Buffer.from(after, 'base64').toString('ascii')),
|
|
85
|
+
$schema: this.#schema.resolvePath,
|
|
86
|
+
});
|
|
185
87
|
|
|
186
|
-
|
|
187
|
-
this.props.model = model;
|
|
188
|
-
return this;
|
|
189
|
-
}
|
|
88
|
+
if (!isNative) this.#finalize(query.toObject());
|
|
190
89
|
|
|
191
|
-
|
|
192
|
-
this.props.transaction = transaction;
|
|
193
|
-
return this;
|
|
90
|
+
return query;
|
|
194
91
|
}
|
|
195
92
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
93
|
+
/**
|
|
94
|
+
* Recursive pipeline function
|
|
95
|
+
*/
|
|
96
|
+
#pipeline(query, target, model, data, transformers = [], paths = []) {
|
|
97
|
+
return Util.mapPromise(data, (doc, index) => {
|
|
98
|
+
const path = [...paths];
|
|
99
|
+
if (Array.isArray(data)) path.push(index);
|
|
100
|
+
if (target === 'input') doc = mergeDeep(model.pipelineFields.input, doc);
|
|
101
|
+
else if (target === 'where') doc = mergeDeep(model.pipelineFields.where, doc);
|
|
102
|
+
|
|
103
|
+
return Util.pipeline(Object.entries(doc).map(([key, startValue]) => async (prev) => {
|
|
104
|
+
const field = model.fields[key];
|
|
105
|
+
if (!field) return prev;
|
|
106
|
+
|
|
107
|
+
// Transform value
|
|
108
|
+
let $value = await Util.pipeline(transformers.map(t => async (value) => {
|
|
109
|
+
const v = await t({ query, model, field, value, path: path.concat(key), startValue, resolver: this.#resolver, context: this.#context, schema: this.#schema });
|
|
110
|
+
return v === undefined ? value : v;
|
|
111
|
+
}), startValue);
|
|
112
|
+
|
|
113
|
+
// If it's embedded - delegate
|
|
114
|
+
if (field.isEmbedded) $value = await this.#pipeline(query, target, field.model, $value, transformers, path.concat(key));
|
|
115
|
+
|
|
116
|
+
// Assign it back
|
|
117
|
+
if (target === 'input' && $value === undefined) return prev;
|
|
118
|
+
return Object.assign(prev, { [field.name]: $value });
|
|
119
|
+
}), {});
|
|
120
|
+
});
|
|
199
121
|
}
|
|
200
122
|
|
|
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
|
-
|
|
123
|
+
/**
|
|
124
|
+
* Finalize the query for the driver
|
|
125
|
+
*/
|
|
126
|
+
#finalize(query) {
|
|
127
|
+
const { where = {}, sort = {} } = query;
|
|
128
|
+
const flatSort = Util.flatten(sort, { safe: true });
|
|
129
|
+
const flatWhere = Util.flatten(where, { safe: true });
|
|
130
|
+
const $sort = Util.unflatten(Object.keys(flatSort).reduce((prev, key) => Object.assign(prev, { [key]: {} }), {}));
|
|
131
|
+
|
|
132
|
+
//
|
|
133
|
+
query.sort = this.#model.walk(sort, (node) => {
|
|
134
|
+
if (node.field.isVirtual || node.field.isFKReference) node.key = `join_${node.field.model.key}`;
|
|
135
|
+
return node;
|
|
136
|
+
}, { key: 'key' });
|
|
137
|
+
|
|
138
|
+
// Reconstruct the where clause by pulling out anything that requires a join
|
|
139
|
+
query.where = finalizeWhereClause(Util.unflatten(Object.entries(flatWhere).reduce((prev, [key, value]) => {
|
|
140
|
+
if (this.#model.isJoinPath(key, 'key')) return prev;
|
|
141
|
+
value = Util.map(value, el => (isGlob(el) ? globToRegex(el) : el));
|
|
142
|
+
return Object.assign(prev, { [key]: value });
|
|
143
|
+
}, {}), { safe: true }));
|
|
144
|
+
|
|
145
|
+
// Determine what join data is needed (derived from where + sort)
|
|
146
|
+
const joinData = mergeDeep($sort, Util.unflatten(Object.entries(flatWhere).reduce((prev, [key, value]) => {
|
|
147
|
+
if (this.#model.isJoinPath(key, 'key')) return Object.assign(prev, { [key]: value });
|
|
148
|
+
return prev;
|
|
149
|
+
}, {}), { safe: true }));
|
|
150
|
+
|
|
151
|
+
// Construct joins
|
|
152
|
+
query.joins = [];
|
|
153
|
+
|
|
154
|
+
this.#model.walk(joinData, (node) => {
|
|
155
|
+
const { model, field, key, value, isLeaf, path, run } = node;
|
|
156
|
+
|
|
157
|
+
if (field.join) {
|
|
158
|
+
let isArray;
|
|
159
|
+
const join = { ...field.join, where: {} };
|
|
160
|
+
|
|
161
|
+
if (run.length > 1) {
|
|
162
|
+
join.from = path.reduce((prev, curr, i) => {
|
|
163
|
+
const $field = this.#model.resolvePath(path.slice(0, i + 1).join('.'), 'key');
|
|
164
|
+
if ($field.isArray) isArray = true;
|
|
165
|
+
return prev.concat($field.linkField.key);
|
|
166
|
+
}, []).join('.');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
join.isArray = isArray || model.resolvePath(join.from).isArray;
|
|
170
|
+
|
|
171
|
+
query.joins.push(join);
|
|
238
172
|
}
|
|
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
173
|
|
|
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
|
-
}
|
|
174
|
+
if (isLeaf) {
|
|
175
|
+
const $model = field.model || model;
|
|
176
|
+
const join = query.joins.find(j => j.to === $model.key);
|
|
177
|
+
const $value = Util.map(value, el => (isGlob(el) ? globToRegex(el) : el));
|
|
178
|
+
const $$value = Array.isArray($value) ? { $in: $value } : $value;
|
|
179
|
+
const from = field.model ? join.from : key;
|
|
180
|
+
join.where[from] = $$value;
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
346
183
|
|
|
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
|
-
};
|
|
184
|
+
return node;
|
|
185
|
+
}, { key: 'key' });
|
|
362
186
|
}
|
|
363
187
|
};
|