grafast 0.1.1-beta.6 → 0.1.1-beta.7
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 +1 -0
- package/dist/dev.d.ts +1 -0
- package/dist/dev.js +5 -5
- package/dist/engine/LayerPlan.js +140 -67
- package/dist/engine/OperationPlan.d.ts +1 -0
- package/dist/engine/OperationPlan.js +86 -11
- package/dist/engine/OutputPlan.js +14 -8
- package/dist/engine/StepTracker.js +55 -15
- package/dist/engine/executeBucket.d.ts +5 -1
- package/dist/engine/executeBucket.js +545 -167
- package/dist/engine/executeOutputPlan.js +6 -0
- package/dist/engine/lib/withGlobalLayerPlan.d.ts +2 -0
- package/dist/engine/lib/withGlobalLayerPlan.js +5 -1
- package/dist/error.d.ts +4 -4
- package/dist/error.js +45 -38
- package/dist/execute.d.ts +7 -1
- package/dist/execute.js +2 -6
- package/dist/grafastPrint.d.ts +3 -0
- package/dist/grafastPrint.js +63 -1
- package/dist/index.d.ts +7 -5
- package/dist/index.js +29 -5
- package/dist/inspect.d.ts +2 -1
- package/dist/interfaces.d.ts +65 -5
- package/dist/interfaces.js +20 -1
- package/dist/makeGrafastSchema.d.ts +4 -1
- package/dist/makeGrafastSchema.js +317 -156
- package/dist/mermaid.js +69 -5
- package/dist/operationPlan-input.js +1 -1
- package/dist/planJSONInterfaces.d.ts +4 -0
- package/dist/prepare.js +68 -60
- package/dist/step.d.ts +41 -22
- package/dist/step.js +95 -72
- package/dist/steps/__flag.d.ts +61 -0
- package/dist/steps/__flag.js +257 -0
- package/dist/steps/__inputDynamicScalar.d.ts +2 -2
- package/dist/steps/__inputObject.d.ts +2 -2
- package/dist/steps/__item.d.ts +2 -1
- package/dist/steps/__item.js +4 -1
- package/dist/steps/__trackedValue.d.ts +3 -3
- package/dist/steps/__trackedValue.js +5 -2
- package/dist/steps/access.d.ts +3 -3
- package/dist/steps/access.js +1 -1
- package/dist/steps/applyTransforms.js +46 -26
- package/dist/steps/condition.d.ts +31 -0
- package/dist/steps/condition.js +94 -0
- package/dist/steps/connection.d.ts +23 -12
- package/dist/steps/connection.js +46 -9
- package/dist/steps/constant.d.ts +4 -2
- package/dist/steps/constant.js +13 -1
- package/dist/steps/error.d.ts +2 -2
- package/dist/steps/error.js +4 -3
- package/dist/steps/first.d.ts +3 -3
- package/dist/steps/first.js +2 -7
- package/dist/steps/graphqlResolver.js +51 -25
- package/dist/steps/index.d.ts +2 -0
- package/dist/steps/index.js +13 -2
- package/dist/steps/lambda.d.ts +2 -2
- package/dist/steps/last.d.ts +2 -2
- package/dist/steps/list.d.ts +3 -3
- package/dist/steps/list.js +3 -7
- package/dist/steps/listTransform.d.ts +5 -5
- package/dist/steps/listTransform.js +45 -21
- package/dist/steps/listen.d.ts +2 -5
- package/dist/steps/listen.js +8 -10
- package/dist/steps/load.d.ts +37 -22
- package/dist/steps/load.js +43 -15
- package/dist/steps/node.d.ts +2 -2
- package/dist/steps/object.d.ts +12 -13
- package/dist/steps/object.js +7 -11
- package/dist/steps/polymorphicBranch.d.ts +2 -2
- package/dist/steps/polymorphicBranch.js +5 -8
- package/dist/steps/proxy.d.ts +3 -4
- package/dist/steps/proxy.js +5 -2
- package/dist/steps/remapKeys.d.ts +3 -3
- package/dist/steps/remapKeys.js +4 -2
- package/dist/steps/reverse.d.ts +3 -3
- package/dist/steps/reverse.js +5 -2
- package/dist/steps/sideEffect.d.ts +2 -2
- package/dist/subscribe.d.ts +7 -1
- package/dist/subscribe.js +2 -6
- package/dist/utils.js +22 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -55,6 +55,7 @@ And please give some love to our featured sponsors 🤩:
|
|
|
55
55
|
<td align="center"><a href="https://stellate.co/"><img src="https://graphile.org/images/sponsors/Stellate.png" width="90" height="90" alt="Stellate" /><br />Stellate</a> *</td>
|
|
56
56
|
</tr><tr>
|
|
57
57
|
<td align="center"><a href="https://gosteelhead.com/"><img src="https://graphile.org/images/sponsors/steelhead.svg" width="90" height="90" alt="Steelhead" /><br />Steelhead</a> *</td>
|
|
58
|
+
<td align="center"><a href="https://www.sylvera.com/"><img src="https://graphile.org/images/sponsors/sylvera.svg" width="90" height="90" alt="Sylvera" /><br />Sylvera</a> *</td>
|
|
58
59
|
</tr></table>
|
|
59
60
|
|
|
60
61
|
<em>\* Sponsors the entire Graphile suite</em>
|
package/dist/dev.d.ts
CHANGED
package/dist/dev.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.noop = exports.isDev = void 0;
|
|
3
|
+
exports.noop = exports.isTest = exports.isDev = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* @internal
|
|
6
6
|
*/
|
|
7
7
|
const graphileEnv = typeof process !== "undefined" ? process.env.GRAPHILE_ENV : undefined;
|
|
8
8
|
const nodeEnv = typeof process !== "undefined" ? process.env.NODE_ENV : undefined;
|
|
9
|
+
const mode = graphileEnv !== undefined ? graphileEnv : nodeEnv;
|
|
9
10
|
/**
|
|
10
11
|
* @internal
|
|
11
12
|
*/
|
|
12
|
-
exports.isDev =
|
|
13
|
-
|
|
14
|
-
: nodeEnv === "development" || nodeEnv === "test";
|
|
13
|
+
exports.isDev = mode === "development" || mode === "test";
|
|
14
|
+
exports.isTest = mode === "test";
|
|
15
15
|
function noop() { }
|
|
16
16
|
exports.noop = noop;
|
|
17
17
|
if (typeof process !== "undefined" &&
|
|
@@ -19,7 +19,7 @@ if (typeof process !== "undefined" &&
|
|
|
19
19
|
typeof nodeEnv === "undefined") {
|
|
20
20
|
console.warn(`The GRAPHILE_ENV environmental variable is not set; Grafast will run in production mode. In your development environments, it's recommended that you set \`GRAPHILE_ENV=development\` to opt in to additional checks that will provide guidance and help you to catch issues in your code earlier, and other changes such as formatting to improve your development experience.`);
|
|
21
21
|
}
|
|
22
|
-
else if (exports.isDev) {
|
|
22
|
+
else if (exports.isDev && !exports.isTest) {
|
|
23
23
|
console.warn(`Grafast is running in development mode due to \`${graphileEnv !== undefined
|
|
24
24
|
? `GRAPHILE_ENV=${graphileEnv}`
|
|
25
25
|
: `NODE_ENV=${nodeEnv}`}\`; this is recommended for development environments (and strongly discouraged in production), but will impact on performance - in particular, planning will be significantly more expensive.`);
|
package/dist/engine/LayerPlan.js
CHANGED
|
@@ -5,8 +5,8 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const lru_1 = tslib_1.__importDefault(require("@graphile/lru"));
|
|
6
6
|
const tamedevil_1 = tslib_1.__importDefault(require("tamedevil"));
|
|
7
7
|
const assert = tslib_1.__importStar(require("../assert.js"));
|
|
8
|
-
const error_js_1 = require("../error.js");
|
|
9
8
|
const inspect_js_1 = require("../inspect.js");
|
|
9
|
+
const interfaces_js_1 = require("../interfaces.js");
|
|
10
10
|
const polymorphic_js_1 = require("../polymorphic.js");
|
|
11
11
|
const executeBucket_js_1 = require("./executeBucket.js");
|
|
12
12
|
function isBranchingLayerPlan(layerPlan) {
|
|
@@ -76,8 +76,8 @@ class LayerPlan {
|
|
|
76
76
|
*/
|
|
77
77
|
this.rootStep = null;
|
|
78
78
|
/**
|
|
79
|
-
* Which
|
|
80
|
-
* be "copied across" to this bucket because
|
|
79
|
+
* Which steps the results for which are available in a parent bucket need to
|
|
80
|
+
* be "copied across" to this bucket because steps in this bucket still
|
|
81
81
|
* reference them?
|
|
82
82
|
*
|
|
83
83
|
* @internal
|
|
@@ -132,7 +132,7 @@ class LayerPlan {
|
|
|
132
132
|
const reasonExtra = this.reason.type === "polymorphic"
|
|
133
133
|
? `{${this.reason.typeNames.join(",")}}`
|
|
134
134
|
: "";
|
|
135
|
-
const deps = this.copyStepIds.length > 0 ?
|
|
135
|
+
const deps = this.copyStepIds.length > 0 ? `/${this.copyStepIds}` : "";
|
|
136
136
|
return `LayerPlan<${this.id}${chain}?${this.reason.type}${reasonExtra}!${this.rootStep?.id ?? "x"}${deps}>`;
|
|
137
137
|
}
|
|
138
138
|
print(depth = 0) {
|
|
@@ -158,17 +158,18 @@ class LayerPlan {
|
|
|
158
158
|
return this.operationPlan._addModifierStep(step);
|
|
159
159
|
}
|
|
160
160
|
finalize() {
|
|
161
|
-
if (
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const
|
|
165
|
-
|
|
161
|
+
if (
|
|
162
|
+
// this.reason.type === "nullableBoundary" ||
|
|
163
|
+
this.reason.type === "listItem") {
|
|
164
|
+
const u = this.copyStepIds.length;
|
|
165
|
+
const signature = `${this.reason.type[0]}_${u}`;
|
|
166
|
+
withNewBucketFactory(signature, u, this.reason.type, (fn) => {
|
|
166
167
|
this.newBucket = fn(this.copyStepIds);
|
|
167
168
|
});
|
|
168
169
|
}
|
|
169
170
|
}
|
|
170
171
|
newBucket(parentBucket) {
|
|
171
|
-
const copyStepIds = this
|
|
172
|
+
const { copyStepIds } = this;
|
|
172
173
|
const store = new Map();
|
|
173
174
|
const polymorphicPathList = this.reason.type === "mutationField"
|
|
174
175
|
? parentBucket.polymorphicPathList
|
|
@@ -178,20 +179,41 @@ class LayerPlan {
|
|
|
178
179
|
let size = 0;
|
|
179
180
|
switch (this.reason.type) {
|
|
180
181
|
case "nullableBoundary": {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const nullableStepStore = parentBucket.store.get(itemStepId);
|
|
184
|
-
if (!nullableStepStore) {
|
|
185
|
-
throw new Error(`GrafastInternalError<017dc8bf-1db1-4983-a41e-e69c6652e4c7>: could not find entry '${itemStepId}' (${parentBucket.layerPlan.operationPlan.dangerouslyGetStep(itemStepId)}) in store for ${parentBucket.layerPlan}`);
|
|
182
|
+
if (this.rootStep == null) {
|
|
183
|
+
throw new Error("GrafastInternalError<f8136364-46c7-4886-b2ae-51319826f97d>: nullableStepStore layer plan has no rootStepId");
|
|
186
184
|
}
|
|
185
|
+
const itemStepId = this.rootStep.id;
|
|
187
186
|
// PERF: if parent bucket has no nulls/errors in `itemStepId`
|
|
188
187
|
// then we can just copy everything wholesale rather than building
|
|
189
188
|
// new arrays and looping.
|
|
190
189
|
const hasNoNullsOrErrors = false;
|
|
191
|
-
if (
|
|
190
|
+
if (this.rootStep._isUnary) {
|
|
191
|
+
const fieldValue = parentBucket.store.get(itemStepId);
|
|
192
|
+
const forbiddenFlags = fieldValue._entryFlags & interfaces_js_1.FORBIDDEN_BY_NULLABLE_BOUNDARY_FLAGS;
|
|
193
|
+
if (forbiddenFlags) {
|
|
194
|
+
size = 0;
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
size = parentBucket.size;
|
|
198
|
+
store.set(itemStepId, fieldValue);
|
|
199
|
+
for (const stepId of copyStepIds) {
|
|
200
|
+
store.set(stepId, parentBucket.store.get(stepId));
|
|
201
|
+
}
|
|
202
|
+
for (let i = 0; i < size; i++) {
|
|
203
|
+
map.set(i, i);
|
|
204
|
+
polymorphicPathList[i] = parentBucket.polymorphicPathList[i];
|
|
205
|
+
iterators[i] = parentBucket.iterators[i];
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
else if (hasNoNullsOrErrors) {
|
|
210
|
+
const nullableStepStore = parentBucket.store.get(itemStepId);
|
|
211
|
+
if (!nullableStepStore) {
|
|
212
|
+
throw new Error(`GrafastInternalError<017dc8bf-1db1-4983-a41e-e69c6652e4c7>: could not find entry '${itemStepId}' (${parentBucket.layerPlan.operationPlan.dangerouslyGetStep(itemStepId)}) in store for ${parentBucket.layerPlan}`);
|
|
213
|
+
}
|
|
192
214
|
store.set(itemStepId, nullableStepStore);
|
|
193
|
-
for (const
|
|
194
|
-
store.set(
|
|
215
|
+
for (const stepId of copyStepIds) {
|
|
216
|
+
store.set(stepId, parentBucket.store.get(stepId));
|
|
195
217
|
}
|
|
196
218
|
for (let originalIndex = 0; originalIndex < parentBucket.size; originalIndex++) {
|
|
197
219
|
const newIndex = size++;
|
|
@@ -203,16 +225,26 @@ class LayerPlan {
|
|
|
203
225
|
}
|
|
204
226
|
else {
|
|
205
227
|
const itemStepIdList = [];
|
|
206
|
-
store.set(itemStepId, itemStepIdList);
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
228
|
+
store.set(itemStepId, (0, executeBucket_js_1.batchExecutionValue)(itemStepIdList));
|
|
229
|
+
for (const stepId of copyStepIds) {
|
|
230
|
+
const ev = parentBucket.store.get(stepId);
|
|
231
|
+
if (ev.isBatch) {
|
|
232
|
+
// Prepare store with an empty list for each copyPlanId
|
|
233
|
+
store.set(stepId, (0, executeBucket_js_1.batchExecutionValue)([]));
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
store.set(stepId, ev);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
const nullableStepStore = parentBucket.store.get(itemStepId);
|
|
240
|
+
if (!nullableStepStore) {
|
|
241
|
+
throw new Error(`GrafastInternalError<017dc8bf-1db1-4983-a41e-e69c6652e4c7>: could not find entry '${itemStepId}' (${parentBucket.layerPlan.operationPlan.dangerouslyGetStep(itemStepId)}) in store for ${parentBucket.layerPlan}`);
|
|
210
242
|
}
|
|
211
243
|
// We'll typically be creating fewer nullableBoundary bucket entries
|
|
212
244
|
// than we have parent bucket entries (because we exclude nulls), so
|
|
213
245
|
// we must "multiply up" (down) the store entries.
|
|
214
246
|
for (let originalIndex = 0; originalIndex < parentBucket.size; originalIndex++) {
|
|
215
|
-
const fieldValue = nullableStepStore
|
|
247
|
+
const fieldValue = nullableStepStore.at(originalIndex);
|
|
216
248
|
if (fieldValue != null) {
|
|
217
249
|
const newIndex = size++;
|
|
218
250
|
map.set(originalIndex, newIndex);
|
|
@@ -220,9 +252,12 @@ class LayerPlan {
|
|
|
220
252
|
polymorphicPathList[newIndex] =
|
|
221
253
|
parentBucket.polymorphicPathList[originalIndex];
|
|
222
254
|
iterators[newIndex] = parentBucket.iterators[originalIndex];
|
|
223
|
-
for (const
|
|
224
|
-
store.get(
|
|
225
|
-
|
|
255
|
+
for (const stepId of copyStepIds) {
|
|
256
|
+
const ev = store.get(stepId);
|
|
257
|
+
if (ev.isBatch) {
|
|
258
|
+
const orig = parentBucket.store.get(stepId);
|
|
259
|
+
ev._copyResult(newIndex, orig, originalIndex);
|
|
260
|
+
}
|
|
226
261
|
}
|
|
227
262
|
}
|
|
228
263
|
}
|
|
@@ -235,32 +270,52 @@ class LayerPlan {
|
|
|
235
270
|
if (!listStepStore) {
|
|
236
271
|
throw new Error(`GrafastInternalError<314865b0-f7e8-4e81-b966-56e5a0de562e>: could not find entry '${listStepId}' (${parentBucket.layerPlan.operationPlan.dangerouslyGetStep(listStepId)}) in store for layerPlan ${parentBucket.layerPlan}`);
|
|
237
272
|
}
|
|
238
|
-
|
|
239
|
-
if (itemStepId == null) {
|
|
273
|
+
if (this.rootStep == null) {
|
|
240
274
|
throw new Error("GrafastInternalError<b3a2bff9-15c6-47e2-aa82-19c862324f1a>: listItem layer plan has no rootStepId");
|
|
241
275
|
}
|
|
242
|
-
|
|
243
|
-
//
|
|
244
|
-
|
|
245
|
-
|
|
276
|
+
const itemStepId = this.rootStep.id;
|
|
277
|
+
// Item steps are **NOT** unary
|
|
278
|
+
const itemStepIdList = this.rootStep._isUnary ? null : [];
|
|
279
|
+
if (this.rootStep._isUnary) {
|
|
280
|
+
// handled later
|
|
281
|
+
const list = listStepStore.at(0);
|
|
282
|
+
store.set(itemStepId, (0, executeBucket_js_1.unaryExecutionValue)(Array.isArray(list) ? list[0] : list));
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
store.set(itemStepId, (0, executeBucket_js_1.batchExecutionValue)(itemStepIdList));
|
|
286
|
+
}
|
|
287
|
+
for (const stepId of copyStepIds) {
|
|
288
|
+
const ev = parentBucket.store.get(stepId);
|
|
289
|
+
if (ev.isBatch) {
|
|
290
|
+
// Prepare store with an empty list for each copyPlanId
|
|
291
|
+
store.set(stepId, (0, executeBucket_js_1.batchExecutionValue)([]));
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
store.set(stepId, ev);
|
|
295
|
+
}
|
|
246
296
|
}
|
|
247
297
|
// We'll typically be creating more listItem bucket entries than we
|
|
248
298
|
// have parent buckets, so we must "multiply up" the store entries.
|
|
249
299
|
for (let originalIndex = 0; originalIndex < parentBucket.size; originalIndex++) {
|
|
250
|
-
const list = listStepStore
|
|
300
|
+
const list = listStepStore.at(originalIndex);
|
|
251
301
|
if (Array.isArray(list)) {
|
|
252
302
|
const newIndexes = [];
|
|
253
303
|
map.set(originalIndex, newIndexes);
|
|
254
304
|
for (let j = 0, l = list.length; j < l; j++) {
|
|
255
305
|
const newIndex = size++;
|
|
256
306
|
newIndexes.push(newIndex);
|
|
257
|
-
|
|
307
|
+
if (itemStepIdList !== null) {
|
|
308
|
+
itemStepIdList[newIndex] = list[j];
|
|
309
|
+
}
|
|
258
310
|
polymorphicPathList[newIndex] =
|
|
259
311
|
parentBucket.polymorphicPathList[originalIndex];
|
|
260
312
|
iterators[newIndex] = parentBucket.iterators[originalIndex];
|
|
261
|
-
for (const
|
|
262
|
-
store.get(
|
|
263
|
-
|
|
313
|
+
for (const stepId of copyStepIds) {
|
|
314
|
+
const ev = store.get(stepId);
|
|
315
|
+
if (ev.isBatch) {
|
|
316
|
+
const orig = parentBucket.store.get(stepId);
|
|
317
|
+
ev._copyResult(newIndex, orig, originalIndex);
|
|
318
|
+
}
|
|
264
319
|
}
|
|
265
320
|
}
|
|
266
321
|
}
|
|
@@ -273,8 +328,8 @@ class LayerPlan {
|
|
|
273
328
|
for (let i = 0; i < parentBucket.size; i++) {
|
|
274
329
|
map.set(i, i);
|
|
275
330
|
}
|
|
276
|
-
for (const
|
|
277
|
-
store.set(
|
|
331
|
+
for (const stepId of copyStepIds) {
|
|
332
|
+
store.set(stepId, parentBucket.store.get(stepId));
|
|
278
333
|
}
|
|
279
334
|
break;
|
|
280
335
|
}
|
|
@@ -287,20 +342,24 @@ class LayerPlan {
|
|
|
287
342
|
// We're only copying over the entries that match this type (note:
|
|
288
343
|
// they may end up being null, but that's okay)
|
|
289
344
|
const targetTypeNames = this.reason.typeNames;
|
|
290
|
-
for (const
|
|
291
|
-
store.
|
|
292
|
-
if (!
|
|
293
|
-
throw new Error(`GrafastInternalError<548f0d84-4556-4189-8655-fb16aa3345a6>: new bucket for ${this} wants to copy ${this.operationPlan.dangerouslyGetStep(
|
|
345
|
+
for (const stepId of copyStepIds) {
|
|
346
|
+
const ev = parentBucket.store.get(stepId);
|
|
347
|
+
if (!ev) {
|
|
348
|
+
throw new Error(`GrafastInternalError<548f0d84-4556-4189-8655-fb16aa3345a6>: new bucket for ${this} wants to copy ${this.operationPlan.dangerouslyGetStep(stepId)}, but bucket for ${parentBucket.layerPlan} doesn't contain that plan`);
|
|
349
|
+
}
|
|
350
|
+
if (ev.isBatch) {
|
|
351
|
+
store.set(stepId, (0, executeBucket_js_1.batchExecutionValue)([]));
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
store.set(stepId, ev);
|
|
294
355
|
}
|
|
295
356
|
}
|
|
296
357
|
for (let originalIndex = 0; originalIndex < parentBucket.size; originalIndex++) {
|
|
297
|
-
const
|
|
298
|
-
if (
|
|
299
|
-
continue;
|
|
300
|
-
}
|
|
301
|
-
if ((0, error_js_1.isGrafastError)(value)) {
|
|
358
|
+
const flags = polymorphicPlanStore._flagsAt(originalIndex);
|
|
359
|
+
if (flags & (interfaces_js_1.FLAG_ERROR | interfaces_js_1.FLAG_INHIBITED | interfaces_js_1.FLAG_NULL)) {
|
|
302
360
|
continue;
|
|
303
361
|
}
|
|
362
|
+
const value = polymorphicPlanStore.at(originalIndex);
|
|
304
363
|
const typeName = (0, polymorphic_js_1.resolveType)(value);
|
|
305
364
|
if (!targetTypeNames.includes(typeName)) {
|
|
306
365
|
continue;
|
|
@@ -314,8 +373,11 @@ class LayerPlan {
|
|
|
314
373
|
polymorphicPathList[newIndex] = newPolymorphicPath;
|
|
315
374
|
iterators[newIndex] = parentBucket.iterators[originalIndex];
|
|
316
375
|
for (const planId of copyStepIds) {
|
|
317
|
-
store.get(planId)
|
|
318
|
-
|
|
376
|
+
const ev = store.get(planId);
|
|
377
|
+
if (ev.isBatch) {
|
|
378
|
+
const orig = parentBucket.store.get(planId);
|
|
379
|
+
ev._copyResult(newIndex, orig, originalIndex);
|
|
380
|
+
}
|
|
319
381
|
}
|
|
320
382
|
}
|
|
321
383
|
break;
|
|
@@ -345,7 +407,7 @@ class LayerPlan {
|
|
|
345
407
|
size,
|
|
346
408
|
store,
|
|
347
409
|
// PERF: not necessarily, if we don't copy the errors, we don't have the errors.
|
|
348
|
-
|
|
410
|
+
flagUnion: parentBucket.flagUnion,
|
|
349
411
|
polymorphicPathList,
|
|
350
412
|
iterators,
|
|
351
413
|
}, parentBucket.metaByMetaKey);
|
|
@@ -369,8 +431,9 @@ const te_parentBucketDotPolymorphicPathList = (0, tamedevil_1.default) `parentBu
|
|
|
369
431
|
const te_parentBucketDotIterators = (0, tamedevil_1.default) `parentBucket.iterators`;
|
|
370
432
|
const te_emptyArray = (0, tamedevil_1.default) `[]`;
|
|
371
433
|
const ref_newBucket = tamedevil_1.default.ref(executeBucket_js_1.newBucket, "newBucket");
|
|
434
|
+
const ref_batchExecutionValue = tamedevil_1.default.ref(executeBucket_js_1.batchExecutionValue, "batchExecutionValue");
|
|
372
435
|
function makeNewBucketExpression(signature, reasonType, inner) {
|
|
373
|
-
|
|
436
|
+
const expr = (0, tamedevil_1.default) `\
|
|
374
437
|
(function ${tamedevil_1.default.identifier(`newBucket_${signature}`)}(parentBucket) {
|
|
375
438
|
const store = new Map();
|
|
376
439
|
const polymorphicPathList = ${reasonType === "mutationField"
|
|
@@ -389,7 +452,7 @@ ${inner}
|
|
|
389
452
|
size,
|
|
390
453
|
store,
|
|
391
454
|
// PERF: not necessarily, if we don't copy the errors, we don't have the errors.
|
|
392
|
-
|
|
455
|
+
flagUnion: parentBucket.flagUnion,
|
|
393
456
|
polymorphicPathList,
|
|
394
457
|
iterators,
|
|
395
458
|
}, parentBucket.metaByMetaKey);
|
|
@@ -401,9 +464,14 @@ ${inner}
|
|
|
401
464
|
return null;
|
|
402
465
|
}
|
|
403
466
|
})`;
|
|
467
|
+
// te.debug(expr);
|
|
468
|
+
return expr;
|
|
404
469
|
}
|
|
405
470
|
function newBucketFactoryInnerExpression(signature, copyCount, reasonType) {
|
|
406
471
|
if (reasonType === "nullableBoundary") {
|
|
472
|
+
if (Math.random() < 2) {
|
|
473
|
+
throw new Error("This code no longer works since we added unary steps.");
|
|
474
|
+
}
|
|
407
475
|
// PERF: if parent bucket has no nulls/errors in itemStepId
|
|
408
476
|
// then we can just copy everything wholesale rather than building
|
|
409
477
|
// new arrays and looping.
|
|
@@ -414,12 +482,14 @@ function newBucketFactoryInnerExpression(signature, copyCount, reasonType) {
|
|
|
414
482
|
const te_target = tamedevil_1.default.identifier(`target${i}`);
|
|
415
483
|
const te_i = tamedevil_1.default.lit(i);
|
|
416
484
|
blocks.push((0, tamedevil_1.default) `\
|
|
417
|
-
const ${te_source} = parentBucket.store.get(
|
|
418
|
-
const ${te_target} = [];
|
|
419
|
-
store.set(
|
|
485
|
+
const ${te_source} = parentBucket.store.get(copyStepIds[${te_i}]);
|
|
486
|
+
const ${te_target} = ${te_source}.isBatch ? ${ref_batchExecutionValue}([]) : ${te_source};
|
|
487
|
+
store.set(copyStepIds[${te_i}], ${te_target});
|
|
420
488
|
`);
|
|
421
489
|
copyBlocks.push((0, tamedevil_1.default) `\
|
|
422
|
-
${te_target}
|
|
490
|
+
if(${te_target}.isBatch) {
|
|
491
|
+
${te_target}.entries[newIndex] = ${te_source}.at(originalIndex);
|
|
492
|
+
}
|
|
423
493
|
`);
|
|
424
494
|
}
|
|
425
495
|
return makeNewBucketExpression(signature, reasonType, (0, tamedevil_1.default) `\
|
|
@@ -427,7 +497,7 @@ function newBucketFactoryInnerExpression(signature, copyCount, reasonType) {
|
|
|
427
497
|
const nullableStepStore = parentBucket.store.get(itemStepId);
|
|
428
498
|
|
|
429
499
|
const itemStepIdList = [];
|
|
430
|
-
store.set(itemStepId, itemStepIdList);
|
|
500
|
+
store.set(itemStepId, ${ref_batchExecutionValue}(itemStepIdList));
|
|
431
501
|
|
|
432
502
|
// Prepare store with an empty list for each copyPlanId
|
|
433
503
|
${tamedevil_1.default.join(blocks, "")}
|
|
@@ -440,7 +510,7 @@ ${tamedevil_1.default.join(blocks, "")}
|
|
|
440
510
|
originalIndex < parentBucket.size;
|
|
441
511
|
originalIndex++
|
|
442
512
|
) {
|
|
443
|
-
const fieldValue = nullableStepStore
|
|
513
|
+
const fieldValue = nullableStepStore.at(originalIndex);
|
|
444
514
|
if (fieldValue != null) {
|
|
445
515
|
const newIndex = size++;
|
|
446
516
|
map.set(originalIndex, newIndex);
|
|
@@ -461,19 +531,22 @@ ${tamedevil_1.default.join(copyBlocks, "")}
|
|
|
461
531
|
const te_target = tamedevil_1.default.identifier(`target${i}`);
|
|
462
532
|
const te_i = tamedevil_1.default.lit(i);
|
|
463
533
|
blocks.push((0, tamedevil_1.default) `\
|
|
464
|
-
const ${te_source} = parentBucket.store.get(
|
|
465
|
-
const ${te_target} = [];
|
|
466
|
-
store.set(
|
|
534
|
+
const ${te_source} = parentBucket.store.get(copyStepIds[${te_i}]);
|
|
535
|
+
const ${te_target} = ${te_source}.isBatch ? ${ref_batchExecutionValue}([]) : ${te_source};
|
|
536
|
+
store.set(copyStepIds[${te_i}], ${te_target});
|
|
467
537
|
`);
|
|
468
538
|
copyBlocks.push((0, tamedevil_1.default) `\
|
|
469
|
-
${te_target}
|
|
539
|
+
if (${te_target}.isBatch) {
|
|
540
|
+
${te_target}.entries[newIndex] = ${te_source}.at(originalIndex);
|
|
541
|
+
}
|
|
470
542
|
`);
|
|
471
543
|
}
|
|
472
544
|
return makeNewBucketExpression(signature, reasonType, (0, tamedevil_1.default) `\
|
|
473
|
-
const
|
|
545
|
+
const listStepId = this.reason.parentStep.id;
|
|
546
|
+
const listStepStore = parentBucket.store.get(listStepId);
|
|
474
547
|
|
|
475
548
|
const itemStepIdList = [];
|
|
476
|
-
store.set(this.rootStep.id, itemStepIdList);
|
|
549
|
+
store.set(this.rootStep.id, ${ref_batchExecutionValue}(itemStepIdList));
|
|
477
550
|
|
|
478
551
|
// Prepare store with an empty list for each copyPlanId
|
|
479
552
|
${tamedevil_1.default.join(blocks, "")}
|
|
@@ -485,7 +558,7 @@ ${tamedevil_1.default.join(copyBlocks, "")}
|
|
|
485
558
|
originalIndex < parentBucket.size;
|
|
486
559
|
originalIndex++
|
|
487
560
|
) {
|
|
488
|
-
const list = listStepStore
|
|
561
|
+
const list = listStepStore.at(originalIndex);
|
|
489
562
|
if (Array.isArray(list)) {
|
|
490
563
|
const newIndexes = [];
|
|
491
564
|
map.set(originalIndex, newIndexes);
|
|
@@ -522,7 +595,7 @@ function withNewBucketFactory(signature, copyCount, reasonType, callback) {
|
|
|
522
595
|
makingNewBucketCallbacks.set(signature, callbacks);
|
|
523
596
|
const executorExpression = newBucketFactoryInnerExpression(signature, copyCount, reasonType);
|
|
524
597
|
const factoryExpression = (0, tamedevil_1.default) `\
|
|
525
|
-
function ${tamedevil_1.default.identifier(`layerPlanNewBucketFactory_${signature}`)}(
|
|
598
|
+
function ${tamedevil_1.default.identifier(`layerPlanNewBucketFactory_${signature}`)}(copyStepIds) {
|
|
526
599
|
return ${executorExpression};
|
|
527
600
|
}`;
|
|
528
601
|
tamedevil_1.default.runInBatch(factoryExpression, (factory) => {
|
|
@@ -208,6 +208,9 @@ class OperationPlan {
|
|
|
208
208
|
});
|
|
209
209
|
this.checkTimeout();
|
|
210
210
|
this.lap("optimizeSteps");
|
|
211
|
+
this.inlineSteps();
|
|
212
|
+
this.checkTimeout();
|
|
213
|
+
this.lap("inlineSteps");
|
|
211
214
|
this.phase = "finalize";
|
|
212
215
|
this.stepTracker.finalizeSteps();
|
|
213
216
|
// Get rid of steps that are no longer needed after optimising outputPlans
|
|
@@ -810,7 +813,7 @@ class OperationPlan {
|
|
|
810
813
|
});
|
|
811
814
|
const $__item = this.itemStepForListStep(parentLayerPlan, $step, listDepth);
|
|
812
815
|
const $item = (0, step_js_1.isListCapableStep)($step)
|
|
813
|
-
? (0, withGlobalLayerPlan_js_1.withGlobalLayerPlan)($__item.layerPlan, polymorphicPaths, $step.listItem, $step, $__item)
|
|
816
|
+
? (0, withGlobalLayerPlan_js_1.withGlobalLayerPlan)($__item.layerPlan, $__item.polymorphicPaths, $step.listItem, $step, $__item)
|
|
814
817
|
: $__item;
|
|
815
818
|
this.planIntoOutputPlan(listOutputPlan, $item.layerPlan, path, polymorphicPath, polymorphicPaths, selections, null, null, nullableFieldType.ofType, $item, locationDetails, listDepth + 1);
|
|
816
819
|
}
|
|
@@ -862,7 +865,7 @@ class OperationPlan {
|
|
|
862
865
|
}
|
|
863
866
|
}
|
|
864
867
|
catch (e) {
|
|
865
|
-
throw new Error(`The step returned by '${path.join(".")}' is not compatible with the GraphQL object type '${nullableFieldType.name}': ${e.message}`, { cause: e });
|
|
868
|
+
throw new Error(`The step returned by '${path.join(".")}${"[]".repeat(listDepth)}' is not compatible with the GraphQL object type '${nullableFieldType.name}': ${e.message}`, { cause: e });
|
|
866
869
|
}
|
|
867
870
|
}
|
|
868
871
|
if (!selections) {
|
|
@@ -1353,7 +1356,7 @@ class OperationPlan {
|
|
|
1353
1356
|
if (step.hasSideEffects) {
|
|
1354
1357
|
return EMPTY_ARRAY;
|
|
1355
1358
|
}
|
|
1356
|
-
const { dependencies: deps, layerPlan: layerPlan, constructor: stepConstructor, } = (0, utils_js_1.sudo)(step);
|
|
1359
|
+
const { dependencies: deps, dependencyForbiddenFlags: flags, dependencyOnReject: onReject, layerPlan: layerPlan, constructor: stepConstructor, } = (0, utils_js_1.sudo)(step);
|
|
1357
1360
|
const dependencyCount = deps.length;
|
|
1358
1361
|
if (dependencyCount === 0) {
|
|
1359
1362
|
let allPeers = null;
|
|
@@ -1384,15 +1387,18 @@ class OperationPlan {
|
|
|
1384
1387
|
}
|
|
1385
1388
|
const minDepth = Math.max(deferBoundaryDepth, dep.layerPlan.depth);
|
|
1386
1389
|
let allPeers = null;
|
|
1387
|
-
for (const { dependencyIndex: peerDependencyIndex, step:
|
|
1388
|
-
const
|
|
1390
|
+
for (const { dependencyIndex: peerDependencyIndex, step: rawPossiblyPeer, } of dep.dependents) {
|
|
1391
|
+
const possiblyPeer = (0, utils_js_1.sudo)(rawPossiblyPeer);
|
|
1392
|
+
const { layerPlan: peerLayerPlan, dependencyForbiddenFlags: peerFlags, dependencyOnReject: peerOnReject, } = possiblyPeer;
|
|
1389
1393
|
if (possiblyPeer !== step &&
|
|
1390
1394
|
peerDependencyIndex === 0 &&
|
|
1391
1395
|
!possiblyPeer.hasSideEffects &&
|
|
1392
1396
|
possiblyPeer.constructor === stepConstructor &&
|
|
1393
1397
|
peerLayerPlan.depth >= minDepth &&
|
|
1394
1398
|
(0, utils_js_1.sudo)(possiblyPeer).dependencies.length === dependencyCount &&
|
|
1395
|
-
peerLayerPlan === ancestry[peerLayerPlan.depth]
|
|
1399
|
+
peerLayerPlan === ancestry[peerLayerPlan.depth] &&
|
|
1400
|
+
peerFlags[0] === flags[0] &&
|
|
1401
|
+
peerOnReject[0] === onReject[0]) {
|
|
1396
1402
|
if (allPeers === null) {
|
|
1397
1403
|
allPeers = [possiblyPeer];
|
|
1398
1404
|
}
|
|
@@ -1428,13 +1434,17 @@ class OperationPlan {
|
|
|
1428
1434
|
// Check the final dependency - this is likely to have the fewest
|
|
1429
1435
|
// dependents (since it was added last it's more likely to be
|
|
1430
1436
|
// unique).
|
|
1431
|
-
for (const { dependencyIndex: peerDependencyIndex, step:
|
|
1437
|
+
for (const { dependencyIndex: peerDependencyIndex, step: rawPossiblyPeer, } of dep.dependents) {
|
|
1438
|
+
const possiblyPeer = (0, utils_js_1.sudo)(rawPossiblyPeer);
|
|
1439
|
+
const { layerPlan: peerLayerPlan, dependencyForbiddenFlags: peerFlags, dependencyOnReject: peerOnReject, dependencies: peerDependencies, } = possiblyPeer;
|
|
1432
1440
|
if (possiblyPeer !== step &&
|
|
1433
1441
|
peerDependencyIndex === dependencyIndex &&
|
|
1434
1442
|
!possiblyPeer.hasSideEffects &&
|
|
1435
1443
|
possiblyPeer.constructor === stepConstructor &&
|
|
1436
|
-
|
|
1437
|
-
|
|
1444
|
+
peerDependencies.length === dependencyCount &&
|
|
1445
|
+
peerLayerPlan === ancestry[peerLayerPlan.depth] &&
|
|
1446
|
+
peerFlags[0] === flags[0] &&
|
|
1447
|
+
peerOnReject[0] === onReject[0]) {
|
|
1438
1448
|
possiblePeers.push(possiblyPeer);
|
|
1439
1449
|
}
|
|
1440
1450
|
}
|
|
@@ -1533,6 +1543,9 @@ class OperationPlan {
|
|
|
1533
1543
|
// unsafe. Should we do so, we should remove this.
|
|
1534
1544
|
break;
|
|
1535
1545
|
}
|
|
1546
|
+
else if (step instanceof index_js_1.__FlagStep) {
|
|
1547
|
+
break;
|
|
1548
|
+
}
|
|
1536
1549
|
else {
|
|
1537
1550
|
return;
|
|
1538
1551
|
}
|
|
@@ -1570,6 +1583,9 @@ class OperationPlan {
|
|
|
1570
1583
|
// break;
|
|
1571
1584
|
return;
|
|
1572
1585
|
}
|
|
1586
|
+
else if (step instanceof index_js_1.__FlagStep) {
|
|
1587
|
+
break;
|
|
1588
|
+
}
|
|
1573
1589
|
else {
|
|
1574
1590
|
// Plans that rely on external state shouldn't be hoisted because
|
|
1575
1591
|
// their results may change after a mutation, so the mutation should
|
|
@@ -2066,6 +2082,57 @@ class OperationPlan {
|
|
|
2066
2082
|
.slice(0, 10)
|
|
2067
2083
|
.join(", ")}`);
|
|
2068
2084
|
}
|
|
2085
|
+
inlineSteps() {
|
|
2086
|
+
flagLoop: for (const $flag of this.stepTracker.activeSteps) {
|
|
2087
|
+
if ($flag instanceof index_js_1.__FlagStep) {
|
|
2088
|
+
// We can only inline it if it's not used by an output plan or layer plan
|
|
2089
|
+
{
|
|
2090
|
+
const usages = this.stepTracker.outputPlansByRootStep.get($flag);
|
|
2091
|
+
if (usages?.size) {
|
|
2092
|
+
continue;
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
{
|
|
2096
|
+
const usages = this.stepTracker.layerPlansByRootStep.get($flag);
|
|
2097
|
+
if (usages?.size) {
|
|
2098
|
+
continue;
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
{
|
|
2102
|
+
const usages = this.stepTracker.layerPlansByParentStep.get($flag);
|
|
2103
|
+
if (usages?.size) {
|
|
2104
|
+
continue;
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
// We're only going to inline one if we can inline all.
|
|
2108
|
+
const toInline = [];
|
|
2109
|
+
for (const dependent of $flag.dependents) {
|
|
2110
|
+
const { step, dependencyIndex } = dependent;
|
|
2111
|
+
const $dependent = (0, utils_js_1.sudo)(step);
|
|
2112
|
+
const inlineDetails = $flag.inline($dependent.getDepOptions(dependencyIndex));
|
|
2113
|
+
if (inlineDetails === null) {
|
|
2114
|
+
continue flagLoop;
|
|
2115
|
+
}
|
|
2116
|
+
toInline.push({
|
|
2117
|
+
$dependent,
|
|
2118
|
+
dependencyIndex,
|
|
2119
|
+
inlineDetails,
|
|
2120
|
+
dependent,
|
|
2121
|
+
});
|
|
2122
|
+
}
|
|
2123
|
+
// All of them pass the check, let's inline them
|
|
2124
|
+
for (const todo of toInline) {
|
|
2125
|
+
const { $dependent, dependencyIndex, inlineDetails: { onReject, acceptFlags = interfaces_js_1.DEFAULT_ACCEPT_FLAGS }, } = todo;
|
|
2126
|
+
(0, utils_js_1.writeableArray)($dependent.dependencyOnReject)[dependencyIndex] =
|
|
2127
|
+
onReject;
|
|
2128
|
+
(0, utils_js_1.writeableArray)($dependent.dependencyForbiddenFlags)[dependencyIndex] =
|
|
2129
|
+
interfaces_js_1.ALL_FLAGS & ~acceptFlags;
|
|
2130
|
+
}
|
|
2131
|
+
const $flagDep = (0, utils_js_1.sudo)($flag).dependencies[0];
|
|
2132
|
+
this.stepTracker.replaceStep($flag, $flagDep);
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2069
2136
|
/** Finalizes each step */
|
|
2070
2137
|
finalizeSteps() {
|
|
2071
2138
|
const initialStepCount = this.stepTracker.stepCount;
|
|
@@ -2092,9 +2159,13 @@ class OperationPlan {
|
|
|
2092
2159
|
if (currentLayerPlan.copyStepIds.includes(dep.id)) {
|
|
2093
2160
|
break;
|
|
2094
2161
|
}
|
|
2095
|
-
|
|
2162
|
+
const targetStep = this.stepTracker.getStepById(dep.id);
|
|
2163
|
+
if (index_js_1.isDev && targetStep !== dep) {
|
|
2096
2164
|
throw new Error(`GrafastInternalError<b291b110-396a-4c9c-814a-5466af3c50e8>: Plan mismatch; are we using a replaced step? Step ID: ${dep.id}; step: ${dep}; stepById: ${this.stepTracker.getStepById(dep.id)}`);
|
|
2097
2165
|
}
|
|
2166
|
+
if (targetStep._isUnary) {
|
|
2167
|
+
targetStep._isUnaryLocked = true;
|
|
2168
|
+
}
|
|
2098
2169
|
currentLayerPlan.copyStepIds.push(dep.id);
|
|
2099
2170
|
currentLayerPlan = currentLayerPlan.parentLayerPlan;
|
|
2100
2171
|
if (!currentLayerPlan) {
|
|
@@ -2312,12 +2383,16 @@ class OperationPlan {
|
|
|
2312
2383
|
generatePlanJSON() {
|
|
2313
2384
|
function printStep(step) {
|
|
2314
2385
|
const metaString = step.toStringMeta();
|
|
2386
|
+
const sstep = (0, utils_js_1.sudo)(step);
|
|
2315
2387
|
return {
|
|
2316
2388
|
id: step.id,
|
|
2317
2389
|
stepClass: step.constructor.name,
|
|
2318
2390
|
metaString: metaString ? (0, index_js_1.stripAnsi)(metaString) : metaString,
|
|
2391
|
+
isUnary: step._isUnary,
|
|
2319
2392
|
bucketId: step.layerPlan.id,
|
|
2320
|
-
dependencyIds:
|
|
2393
|
+
dependencyIds: sstep.dependencies.map((d) => d.id),
|
|
2394
|
+
dependencyForbiddenFlags: sstep.dependencyForbiddenFlags.slice(),
|
|
2395
|
+
dependencyOnReject: sstep.dependencyOnReject.map((or) => or ? String(or) : or),
|
|
2321
2396
|
polymorphicPaths: step.polymorphicPaths
|
|
2322
2397
|
? [...step.polymorphicPaths]
|
|
2323
2398
|
: undefined,
|