@coderich/autograph 0.13.38 → 0.13.39
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/package.json +3 -3
- package/src/data/DataLoader.js +52 -5
- package/src/query/Query.js +7 -4
- package/src/service/AppService.js +0 -8
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coderich/autograph",
|
|
3
3
|
"main": "index.js",
|
|
4
|
-
"version": "0.13.
|
|
4
|
+
"version": "0.13.39",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"dev": "coderich-dev"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@coderich/util": "1.0.
|
|
18
|
+
"@coderich/util": "1.0.4",
|
|
19
19
|
"@graphql-tools/merge": "9.0.0",
|
|
20
20
|
"@graphql-tools/resolvers-composition": "7.0.0",
|
|
21
21
|
"@hapi/boom": "10.0.1",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@apollo/server": "4.9.5",
|
|
35
|
-
"@coderich/autograph-mongodb": "0.0.
|
|
35
|
+
"@coderich/autograph-mongodb": "0.0.4",
|
|
36
36
|
"@coderich/dev": "0.2.1",
|
|
37
37
|
"@graphql-tools/schema": "10.0.0",
|
|
38
38
|
"graphql": "16.8.1",
|
package/src/data/DataLoader.js
CHANGED
|
@@ -24,16 +24,63 @@ module.exports = class Loader {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
#resolve(queries) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Batch queries can save resources and network round-trip latency. However, we have to be careful to
|
|
29
|
+
* preserve the order and adhere to the DataLoader API. This step simply creates a map of batch
|
|
30
|
+
* queries to run; saving the order ("i") along with useful query information
|
|
31
|
+
*/
|
|
32
|
+
const batchesByKey = queries.reduce((prev, query, i) => {
|
|
33
|
+
const $query = query.toDriver().toObject();
|
|
34
|
+
const key = $query.batch ?? '__default__';
|
|
35
|
+
const [values] = key === '__default__' ? [] : Object.values(Util.flatten($query.where, { safe: true }));
|
|
36
|
+
const $values = Util.ensureArray(values).map(value => (value instanceof RegExp ? value : new RegExp(`${value}`, 'i')));
|
|
37
|
+
prev[key] = prev[key] || [];
|
|
38
|
+
prev[key].push({ query, $query, values, $values, i });
|
|
39
|
+
return prev;
|
|
40
|
+
}, {});
|
|
30
41
|
|
|
31
|
-
|
|
42
|
+
return Promise.all(Object.entries(batchesByKey).map(([key, batches]) => {
|
|
43
|
+
switch (key) {
|
|
44
|
+
case '__default__': {
|
|
45
|
+
return batches.map(batch => this.#model.source.client.resolve(batch.$query).then(data => ({ data, ...batch })));
|
|
46
|
+
}
|
|
47
|
+
default: {
|
|
48
|
+
const values = Array.from(new Set(batches.map(batch => batch.values).flat()));
|
|
49
|
+
const $query = { ...batches[0].$query, op: 'findMany', where: { [key]: values } };
|
|
50
|
+
return this.#model.source.client.resolve($query).then((docs) => {
|
|
51
|
+
return batches.map((batch) => {
|
|
52
|
+
const matches = docs.filter((doc) => {
|
|
53
|
+
let match = false;
|
|
54
|
+
Util.pathmap(key, doc, (mixed) => {
|
|
55
|
+
match = match || Util.ensureArray(mixed).some(value => batch.$values.some($value => `${value}`.match($value)));
|
|
56
|
+
return mixed;
|
|
57
|
+
});
|
|
58
|
+
return match;
|
|
59
|
+
});
|
|
60
|
+
const data = batch.$query.op === 'findOne' ? matches[0] : matches;
|
|
61
|
+
return { data, ...batch };
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}).flat()).then((results) => {
|
|
67
|
+
return results.flat().sort((a, b) => a.i - b.i).map(({ query, $query, data }) => {
|
|
32
68
|
if (data == null) return null; // Explicit return null;
|
|
33
69
|
if ($query.isCursorPaging && Array.isArray(data)) data = Loader.#paginateResults(data, query.toObject());
|
|
34
70
|
return this.#resolver.toResultSet(this.#model, data);
|
|
35
71
|
});
|
|
36
|
-
})
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// return Promise.all(queries.map((query, i) => {
|
|
75
|
+
// const dquery = query.toDriver();
|
|
76
|
+
// const $query = dquery.toObject();
|
|
77
|
+
|
|
78
|
+
// return this.#model.source.client.resolve($query).then((data) => {
|
|
79
|
+
// if (data == null) return null; // Explicit return null;
|
|
80
|
+
// if ($query.isCursorPaging && Array.isArray(data)) data = Loader.#paginateResults(data, query.toObject());
|
|
81
|
+
// return this.#resolver.toResultSet(this.#model, data);
|
|
82
|
+
// });
|
|
83
|
+
// }));
|
|
37
84
|
}
|
|
38
85
|
|
|
39
86
|
static #paginateResults(rs, query) {
|
package/src/query/Query.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const Util = require('@coderich/util');
|
|
2
|
-
const { isGlob, globToRegex, mergeDeep,
|
|
2
|
+
const { isGlob, globToRegex, mergeDeep, JSONParse } = require('../service/AppService');
|
|
3
3
|
|
|
4
4
|
module.exports = class Query {
|
|
5
5
|
#config;
|
|
@@ -89,7 +89,7 @@ module.exports = class Query {
|
|
|
89
89
|
* Finalize the query for the driver
|
|
90
90
|
*/
|
|
91
91
|
#finalize(query) {
|
|
92
|
-
const { where = {}, sort = {} } = query;
|
|
92
|
+
const { where = {}, sort = {}, op } = query;
|
|
93
93
|
const flatSort = Util.flatten(sort, { safe: true });
|
|
94
94
|
const flatWhere = Util.flatten(where, { safe: true });
|
|
95
95
|
const $sort = Util.unflatten(Object.keys(flatSort).reduce((prev, key) => Object.assign(prev, { [key]: {} }), {}), { safe: true });
|
|
@@ -101,11 +101,11 @@ module.exports = class Query {
|
|
|
101
101
|
}, { key: 'key' });
|
|
102
102
|
|
|
103
103
|
// Reconstruct the where clause by pulling out anything that requires a join
|
|
104
|
-
query.where =
|
|
104
|
+
query.where = Object.entries(flatWhere).reduce((prev, [key, value]) => {
|
|
105
105
|
if (this.#model.isJoinPath(key, 'key')) return prev;
|
|
106
106
|
value = Util.map(value, el => (isGlob(el) ? globToRegex(el) : el));
|
|
107
107
|
return Object.assign(prev, { [key]: value });
|
|
108
|
-
}, {})
|
|
108
|
+
}, {});
|
|
109
109
|
|
|
110
110
|
// Determine what join data is needed (derived from where + sort)
|
|
111
111
|
const joinData = mergeDeep($sort, Util.unflatten(Object.entries(flatWhere).reduce((prev, [key, value]) => {
|
|
@@ -113,6 +113,9 @@ module.exports = class Query {
|
|
|
113
113
|
return prev;
|
|
114
114
|
}, {}), { safe: true }));
|
|
115
115
|
|
|
116
|
+
// If we have 1 field in where clause this is a candidate for batching
|
|
117
|
+
query.batch = (op === 'findOne' || op === 'findMany') && Object.keys(query.where).length === 1 ? Object.keys(query.where)[0] : '__default__';
|
|
118
|
+
|
|
116
119
|
// Construct joins
|
|
117
120
|
query.joins = [];
|
|
118
121
|
|
|
@@ -17,14 +17,6 @@ exports.hashObject = obj => ObjectHash(obj, { respectType: false, respectFunctio
|
|
|
17
17
|
exports.fromGUID = guid => Buffer.from(`${guid}`, 'base64').toString('ascii').split(',');
|
|
18
18
|
exports.guidToId = (autograph, guid) => (autograph.legacyMode ? guid : exports.uvl(exports.fromGUID(guid)[1], guid));
|
|
19
19
|
|
|
20
|
-
exports.finalizeWhereClause = (obj, arrayOp = '$in') => {
|
|
21
|
-
return Object.entries(Util.flatten(obj, { safe: true })).reduce((prev, [key, value]) => {
|
|
22
|
-
const isArray = Array.isArray(value);
|
|
23
|
-
if (isArray) return Object.assign(prev, { [key]: { [arrayOp]: value } });
|
|
24
|
-
return Object.assign(prev, { [key]: value });
|
|
25
|
-
}, {});
|
|
26
|
-
};
|
|
27
|
-
|
|
28
20
|
exports.getGQLReturnType = (info) => {
|
|
29
21
|
const returnType = `${info.returnType}`;
|
|
30
22
|
const typeMap = { array: /^\[.+\].?$/, connection: /.+Connection!?$/, number: /^(Int|Float)!?$/, scalar: /.*/ };
|