grafast 0.1.1-beta.20 → 0.1.1-beta.21
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/dist/args.js +2 -3
- package/dist/assert.js +2 -3
- package/dist/constraints.js +1 -2
- package/dist/deferred.js +1 -2
- package/dist/dev.js +2 -2
- package/dist/engine/LayerPlan.d.ts +20 -16
- package/dist/engine/LayerPlan.js +5 -10
- package/dist/engine/OperationPlan.d.ts +12 -13
- package/dist/engine/OperationPlan.js +210 -146
- package/dist/engine/OutputPlan.d.ts +4 -4
- package/dist/engine/OutputPlan.js +13 -10
- package/dist/engine/StepTracker.js +11 -2
- package/dist/engine/executeBucket.js +135 -94
- package/dist/engine/executeOutputPlan.js +1 -2
- package/dist/engine/lib/defaultPlanResolver.d.ts +6 -0
- package/dist/engine/lib/defaultPlanResolver.js +11 -0
- package/dist/engine/lib/withGlobalLayerPlan.d.ts +2 -2
- package/dist/engine/lib/withGlobalLayerPlan.js +4 -5
- package/dist/engine/lock.d.ts +3 -3
- package/dist/engine/lock.js +3 -3
- package/dist/error.js +4 -4
- package/dist/establishOperationPlan.js +2 -3
- package/dist/execute.js +3 -4
- package/dist/exportAs.js +2 -3
- package/dist/global.js +2 -3
- package/dist/grafastGraphql.js +2 -3
- package/dist/grafastPrint.js +7 -8
- package/dist/graphqlCollectFields.js +6 -7
- package/dist/graphqlMergeSelectionSets.js +1 -2
- package/dist/index.d.ts +22 -18
- package/dist/index.js +41 -16
- package/dist/input.js +75 -28
- package/dist/inspect.d.ts +9 -4
- package/dist/inspect.js +2 -2
- package/dist/interfaces.d.ts +110 -89
- package/dist/makeGrafastSchema.d.ts +18 -9
- package/dist/makeGrafastSchema.js +64 -30
- package/dist/mermaid.js +53 -14
- package/dist/middleware.js +1 -2
- package/dist/multistep.d.ts +6 -6
- package/dist/multistep.js +6 -7
- package/dist/operationPlan-input.d.ts +5 -4
- package/dist/operationPlan-input.js +131 -399
- package/dist/planJSONInterfaces.d.ts +6 -2
- package/dist/polymorphic.js +4 -5
- package/dist/prepare.js +6 -6
- package/dist/step.d.ts +67 -99
- package/dist/step.js +99 -127
- package/dist/steps/__flag.d.ts +16 -16
- package/dist/steps/__flag.js +9 -6
- package/dist/steps/__inputDefault.d.ts +14 -0
- package/dist/steps/__inputDefault.js +48 -0
- package/dist/steps/__inputDynamicScalar.d.ts +2 -4
- package/dist/steps/__inputDynamicScalar.js +4 -2
- package/dist/steps/__inputList.d.ts +5 -9
- package/dist/steps/__inputList.js +4 -1
- package/dist/steps/__inputObject.d.ts +6 -11
- package/dist/steps/__inputObject.js +13 -3
- package/dist/steps/__inputStaticLeaf.d.ts +2 -4
- package/dist/steps/__inputStaticLeaf.js +3 -1
- package/dist/steps/__item.d.ts +6 -6
- package/dist/steps/__item.js +1 -1
- package/dist/steps/__trackedValue.d.ts +4 -49
- package/dist/steps/__trackedValue.js +24 -6
- package/dist/steps/__value.d.ts +3 -3
- package/dist/steps/__value.js +3 -2
- package/dist/steps/access.d.ts +7 -6
- package/dist/steps/access.js +14 -7
- package/dist/steps/applyInput.d.ts +44 -0
- package/dist/steps/applyInput.js +206 -0
- package/dist/steps/applyTransforms.d.ts +2 -2
- package/dist/steps/applyTransforms.js +7 -5
- package/dist/steps/bakedInput.d.ts +23 -0
- package/dist/steps/bakedInput.js +90 -0
- package/dist/steps/condition.d.ts +5 -5
- package/dist/steps/condition.js +3 -3
- package/dist/steps/connection.d.ts +42 -39
- package/dist/steps/connection.js +51 -35
- package/dist/steps/constant.d.ts +4 -8
- package/dist/steps/constant.js +54 -6
- package/dist/steps/each.d.ts +3 -3
- package/dist/steps/each.js +1 -2
- package/dist/steps/error.d.ts +2 -2
- package/dist/steps/error.js +3 -3
- package/dist/steps/filter.d.ts +3 -2
- package/dist/steps/filter.js +1 -2
- package/dist/steps/first.d.ts +6 -5
- package/dist/steps/first.js +5 -4
- package/dist/steps/graphqlResolver.d.ts +2 -2
- package/dist/steps/graphqlResolver.js +44 -56
- package/dist/steps/groupBy.d.ts +3 -2
- package/dist/steps/groupBy.js +1 -2
- package/dist/steps/index.d.ts +4 -2
- package/dist/steps/index.js +21 -9
- package/dist/steps/lambda.d.ts +5 -5
- package/dist/steps/lambda.js +4 -4
- package/dist/steps/last.d.ts +6 -5
- package/dist/steps/last.js +5 -4
- package/dist/steps/list.d.ts +7 -7
- package/dist/steps/list.js +3 -3
- package/dist/steps/listTransform.d.ts +14 -12
- package/dist/steps/listTransform.js +14 -7
- package/dist/steps/listen.d.ts +6 -8
- package/dist/steps/listen.js +7 -7
- package/dist/steps/load.d.ts +6 -6
- package/dist/steps/load.js +7 -7
- package/dist/steps/node.d.ts +16 -10
- package/dist/steps/node.js +14 -7
- package/dist/steps/object.d.ts +11 -11
- package/dist/steps/object.js +5 -5
- package/dist/steps/partitionByIndex.d.ts +3 -2
- package/dist/steps/partitionByIndex.js +1 -2
- package/dist/steps/polymorphicBranch.d.ts +8 -8
- package/dist/steps/polymorphicBranch.js +4 -4
- package/dist/steps/proxy.d.ts +8 -8
- package/dist/steps/proxy.js +3 -3
- package/dist/steps/remapKeys.d.ts +6 -6
- package/dist/steps/remapKeys.js +3 -3
- package/dist/steps/reverse.d.ts +5 -5
- package/dist/steps/reverse.js +4 -4
- package/dist/steps/setter.d.ts +9 -18
- package/dist/steps/setter.js +24 -14
- package/dist/steps/sideEffect.d.ts +4 -4
- package/dist/steps/sideEffect.js +3 -3
- package/dist/stringifyPayload.js +1 -2
- package/dist/stripAnsi.js +2 -2
- package/dist/subscribe.js +2 -3
- package/dist/timeSource.d.ts +0 -1
- package/dist/utils.d.ts +43 -31
- package/dist/utils.js +97 -61
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
|
@@ -14,12 +14,13 @@ const inspect_js_1 = require("../inspect.js");
|
|
|
14
14
|
const interfaces_js_1 = require("../interfaces.js");
|
|
15
15
|
const operationPlan_input_js_1 = require("../operationPlan-input.js");
|
|
16
16
|
const step_js_1 = require("../step.js");
|
|
17
|
-
const
|
|
17
|
+
const connection_js_1 = require("../steps/connection.js");
|
|
18
18
|
const constant_js_1 = require("../steps/constant.js");
|
|
19
19
|
const graphqlResolver_js_1 = require("../steps/graphqlResolver.js");
|
|
20
20
|
const timeSource_js_1 = require("../timeSource.js");
|
|
21
21
|
const utils_js_1 = require("../utils.js");
|
|
22
22
|
const LayerPlan_js_1 = require("./LayerPlan.js");
|
|
23
|
+
const defaultPlanResolver_js_1 = require("./lib/defaultPlanResolver.js");
|
|
23
24
|
const withGlobalLayerPlan_js_1 = require("./lib/withGlobalLayerPlan.js");
|
|
24
25
|
const lock_js_1 = require("./lock.js");
|
|
25
26
|
const OutputPlan_js_1 = require("./OutputPlan.js");
|
|
@@ -55,7 +56,7 @@ const MAX_OPTIMIZATION_LOOPS = 10;
|
|
|
55
56
|
const REASON_ROOT = Object.freeze({ type: "root" });
|
|
56
57
|
const OUTPUT_PLAN_TYPE_NULL = Object.freeze({ mode: "null" });
|
|
57
58
|
const OUTPUT_PLAN_TYPE_ARRAY = Object.freeze({ mode: "array" });
|
|
58
|
-
const newValueStepCallback = () => new index_js_1.__ValueStep();
|
|
59
|
+
const newValueStepCallback = (isImmutable) => new index_js_1.__ValueStep(isImmutable);
|
|
59
60
|
const NO_ARGS = {
|
|
60
61
|
get() {
|
|
61
62
|
throw new Error(`This field doesn't have any arguments`);
|
|
@@ -89,13 +90,8 @@ class OperationPlan {
|
|
|
89
90
|
this.loc = index_js_1.isDev
|
|
90
91
|
? []
|
|
91
92
|
: null /* forbid loc in production */;
|
|
92
|
-
this.modifierStepCount = 0;
|
|
93
|
-
this.modifierDepthCount = 0;
|
|
94
|
-
this.modifierSteps = [];
|
|
95
93
|
/** @internal */
|
|
96
94
|
this.stepTracker = new StepTracker_js_1.StepTracker(this);
|
|
97
|
-
this.maxDeduplicatedStepId = -1;
|
|
98
|
-
this.maxValidatedStepId = -1;
|
|
99
95
|
/**
|
|
100
96
|
* @internal
|
|
101
97
|
*/
|
|
@@ -108,6 +104,8 @@ class OperationPlan {
|
|
|
108
104
|
this.previousLap = this.startTime;
|
|
109
105
|
this.laps = [];
|
|
110
106
|
this.optimizeMeta = new Map();
|
|
107
|
+
/** @internal */
|
|
108
|
+
this.valueNodeToStaticValueCache = new Map();
|
|
111
109
|
/** @internal Use plan.getStep(id) instead. */
|
|
112
110
|
this.getStep = index_js_1.isDev
|
|
113
111
|
? (id, requestingStep) => {
|
|
@@ -320,21 +318,6 @@ class OperationPlan {
|
|
|
320
318
|
}
|
|
321
319
|
return this.stepTracker.addStep(plan);
|
|
322
320
|
}
|
|
323
|
-
/**
|
|
324
|
-
* Adds a plan to the known steps and returns the number to use as the plan
|
|
325
|
-
* id. ONLY to be used from Step, user code should never call this directly.
|
|
326
|
-
*
|
|
327
|
-
* @internal
|
|
328
|
-
*/
|
|
329
|
-
_addModifierStep(step) {
|
|
330
|
-
if (!["plan", "validate", "optimize"].includes(this.phase)) {
|
|
331
|
-
throw new Error(`Creating a step during the '${this.phase}' phase is forbidden.`);
|
|
332
|
-
}
|
|
333
|
-
const modifierStepId = `${this.modifierDepthCount}-${this
|
|
334
|
-
.modifierStepCount++}`;
|
|
335
|
-
this.modifierSteps.push(step);
|
|
336
|
-
return modifierStepId;
|
|
337
|
-
}
|
|
338
321
|
/**
|
|
339
322
|
* Get a plan without specifying who requested it; this disables all the
|
|
340
323
|
* caller checks. Only intended to be called from internal code.
|
|
@@ -473,14 +456,10 @@ class OperationPlan {
|
|
|
473
456
|
: NO_ARGS;
|
|
474
457
|
if (subscriptionPlanResolver !== undefined) {
|
|
475
458
|
// PERF: optimize this
|
|
476
|
-
const { haltTree, step: subscribeStep } = this.planField(this.rootLayerPlan, path, exports.POLYMORPHIC_ROOT_PATHS,
|
|
459
|
+
const { haltTree, step: subscribeStep } = this.planField(rootType.name, fieldName, this.rootLayerPlan, path, exports.POLYMORPHIC_ROOT_PATHS, subscriptionPlanResolver, "subscribePlan", this.trackedRootValueStep, fieldSpec, trackedArguments, true);
|
|
477
460
|
if (haltTree) {
|
|
478
461
|
throw new index_js_1.SafeError("Failed to setup subscription");
|
|
479
462
|
}
|
|
480
|
-
const stepOptions = {
|
|
481
|
-
stream: { initialCount: 0 },
|
|
482
|
-
};
|
|
483
|
-
subscribeStep._stepOptions = stepOptions;
|
|
484
463
|
this.rootLayerPlan.setRootStep(subscribeStep);
|
|
485
464
|
const subscriptionEventLayerPlan = new LayerPlan_js_1.LayerPlan(this, this.rootLayerPlan, {
|
|
486
465
|
type: "subscription",
|
|
@@ -521,10 +500,8 @@ class OperationPlan {
|
|
|
521
500
|
},
|
|
522
501
|
});
|
|
523
502
|
});
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
};
|
|
527
|
-
subscribeStep._stepOptions = stepOptions;
|
|
503
|
+
subscribeStep._stepOptions.stream = {};
|
|
504
|
+
subscribeStep._stepOptions.walkIterable = true;
|
|
528
505
|
this.rootLayerPlan.setRootStep(subscribeStep);
|
|
529
506
|
const subscriptionEventLayerPlan = new LayerPlan_js_1.LayerPlan(this, this.rootLayerPlan, {
|
|
530
507
|
type: "subscription",
|
|
@@ -548,7 +525,7 @@ class OperationPlan {
|
|
|
548
525
|
* Gets the item plan for a given parent list plan - this ensures we only
|
|
549
526
|
* create one item plan per parent plan.
|
|
550
527
|
*/
|
|
551
|
-
itemStepForListStep(parentLayerPlan, listStep, depth
|
|
528
|
+
itemStepForListStep(parentLayerPlan, listStep, depth, stream) {
|
|
552
529
|
const itemStepId = this.itemStepIdByListStepId[listStep.id];
|
|
553
530
|
if (itemStepId !== undefined) {
|
|
554
531
|
return this.stepTracker.getStepById(itemStepId);
|
|
@@ -557,7 +534,7 @@ class OperationPlan {
|
|
|
557
534
|
const layerPlan = new LayerPlan_js_1.LayerPlan(this, parentLayerPlan, {
|
|
558
535
|
type: "listItem",
|
|
559
536
|
parentStep: listStep,
|
|
560
|
-
stream
|
|
537
|
+
stream,
|
|
561
538
|
});
|
|
562
539
|
const itemPlan = (0, withGlobalLayerPlan_js_1.withGlobalLayerPlan)(layerPlan, listStep.polymorphicPaths, () => new index_js_1.__ItemStep(listStep, depth));
|
|
563
540
|
layerPlan.setRootStep(itemPlan);
|
|
@@ -633,8 +610,7 @@ class OperationPlan {
|
|
|
633
610
|
? defaultFieldResolver
|
|
634
611
|
: null;
|
|
635
612
|
// Apply a default plan to fields that do not have a plan nor a resolver.
|
|
636
|
-
const planResolver = rawPlanResolver ??
|
|
637
|
-
(resolver ? undefined : makeDefaultPlan(fieldName));
|
|
613
|
+
const planResolver = rawPlanResolver ?? (resolver ? undefined : defaultPlanResolver_js_1.defaultPlanResolver);
|
|
638
614
|
/*
|
|
639
615
|
* When considering resolvers on fields, there's three booleans to
|
|
640
616
|
* consider:
|
|
@@ -717,8 +693,49 @@ class OperationPlan {
|
|
|
717
693
|
? (0, withGlobalLayerPlan_js_1.withGlobalLayerPlan)(this.rootLayerPlan, exports.POLYMORPHIC_ROOT_PATHS, this.getTrackedArguments, this, objectFieldArgs, field)
|
|
718
694
|
: NO_ARGS;
|
|
719
695
|
const fieldPath = [...path, responseKey];
|
|
696
|
+
let streamDetails = null;
|
|
697
|
+
const isList = isListType(getNullableType(fieldType));
|
|
698
|
+
if (isList) {
|
|
699
|
+
// read the @stream directive, if present
|
|
700
|
+
// TODO: Check SameStreamDirective still exists in @stream spec at release.
|
|
701
|
+
/*
|
|
702
|
+
* `SameStreamDirective`
|
|
703
|
+
* (https://github.com/graphql/graphql-spec/blob/26fd78c4a89a79552dcc0c7e0140a975ce654400/spec/Section%205%20--%20Validation.md#L450-L458)
|
|
704
|
+
* ensures that every field that has `@stream` must have the same
|
|
705
|
+
* `@stream` arguments; so we can just check the first node in the
|
|
706
|
+
* merged set to see our stream options. NOTE: if this changes before
|
|
707
|
+
* release then we may need to find the stream with the largest
|
|
708
|
+
* `initialCount` to figure what to do; something like:
|
|
709
|
+
*
|
|
710
|
+
* const streamDirective = firstField.directives?.filter(
|
|
711
|
+
* (d) => d.name.value === "stream",
|
|
712
|
+
* ).sort(
|
|
713
|
+
* (a, z) => getArg(z, 'initialCount', 0) - getArg(a, 'initialCount', 0)
|
|
714
|
+
* )[0]
|
|
715
|
+
*/
|
|
716
|
+
for (const n of fieldNodes) {
|
|
717
|
+
const streamDirective = n.directives?.find((d) => d.name.value === "stream");
|
|
718
|
+
if (streamDirective === undefined) {
|
|
719
|
+
// Undo any previous stream details; the non-@stream wins.
|
|
720
|
+
streamDetails = null;
|
|
721
|
+
break;
|
|
722
|
+
}
|
|
723
|
+
else if (streamDetails !== null) {
|
|
724
|
+
// Validation promises the values are the same
|
|
725
|
+
continue;
|
|
726
|
+
}
|
|
727
|
+
else {
|
|
728
|
+
// Create streamDetails
|
|
729
|
+
streamDetails = this.withRootLayerPlan(() => ({
|
|
730
|
+
initialCount: this.internalDependency((0, utils_js_1.directiveArgument)(this, streamDirective, "initialCount", graphql.Kind.INT) ?? (0, constant_js_1.constant)(0)),
|
|
731
|
+
if: this.internalDependency((0, utils_js_1.directiveArgument)(this, streamDirective, "if", graphql.Kind.BOOLEAN) ?? (0, constant_js_1.constant)(true)),
|
|
732
|
+
label: this.internalDependency((0, utils_js_1.directiveArgument)(this, streamDirective, "label", graphql.Kind.STRING) ?? (0, constant_js_1.constant)(undefined)),
|
|
733
|
+
}));
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
}
|
|
720
737
|
if (typeof planResolver === "function") {
|
|
721
|
-
({ step, haltTree } = this.planField(fieldLayerPlan, fieldPath, polymorphicPaths,
|
|
738
|
+
({ step, haltTree } = this.planField(objectType.name, fieldName, fieldLayerPlan, fieldPath, polymorphicPaths, planResolver, "plan", parentStep, objectField, trackedArguments, isList ? (streamDetails ?? false) : null));
|
|
722
739
|
}
|
|
723
740
|
else {
|
|
724
741
|
// No plan resolver (or plan resolver fallback) so there must be a
|
|
@@ -764,7 +781,7 @@ class OperationPlan {
|
|
|
764
781
|
// If one field has a selection set, they all have a selection set (guaranteed by validation).
|
|
765
782
|
field.selectionSet != null
|
|
766
783
|
? fieldNodes.flatMap((n) => n.selectionSet.selections)
|
|
767
|
-
: undefined, objectType, responseKey, fieldType, step, locationDetails, resolverEmulation);
|
|
784
|
+
: undefined, objectType, responseKey, fieldType, step, locationDetails, resolverEmulation, 0, streamDetails);
|
|
768
785
|
}
|
|
769
786
|
}
|
|
770
787
|
finally {
|
|
@@ -818,29 +835,54 @@ class OperationPlan {
|
|
|
818
835
|
if (this.loc !== null)
|
|
819
836
|
this.loc.pop();
|
|
820
837
|
}
|
|
838
|
+
internalDependency($step) {
|
|
839
|
+
this.stepTracker.internalDependencies.add($step);
|
|
840
|
+
return $step;
|
|
841
|
+
}
|
|
821
842
|
// Similar to the old 'planFieldReturnType'
|
|
822
843
|
planIntoOutputPlan(parentOutputPlan,
|
|
823
844
|
// Typically this is parentOutputPlan.layerPlan; but in the case of mutationFields it isn't.
|
|
824
845
|
parentLayerPlan,
|
|
825
846
|
// This is the LAYER-RELATIVE path, not the absolute path! It resets!
|
|
826
|
-
path, polymorphicPath, polymorphicPaths, selections, parentObjectType, responseKey, fieldType, $step, locationDetails, resolverEmulation, listDepth
|
|
847
|
+
path, polymorphicPath, polymorphicPaths, selections, parentObjectType, responseKey, fieldType, $step, locationDetails, resolverEmulation, listDepth, streamDetails) {
|
|
827
848
|
const nullableFieldType = getNullableType(fieldType);
|
|
828
849
|
const isNonNull = nullableFieldType !== fieldType;
|
|
829
850
|
if (isListType(nullableFieldType)) {
|
|
830
|
-
const
|
|
851
|
+
const $list = (0, withGlobalLayerPlan_js_1.withGlobalLayerPlan)(parentLayerPlan, polymorphicPaths, connection_js_1.itemsOrStep, null, $step);
|
|
852
|
+
if ($list !== $step) {
|
|
853
|
+
$list._stepOptions.stream = $step._stepOptions.stream;
|
|
854
|
+
}
|
|
855
|
+
$list._stepOptions.walkIterable = true;
|
|
856
|
+
const listOutputPlan = new OutputPlan_js_1.OutputPlan(parentLayerPlan, $list, OUTPUT_PLAN_TYPE_ARRAY, locationDetails);
|
|
831
857
|
parentOutputPlan.addChild(parentObjectType, responseKey, {
|
|
832
858
|
type: "outputPlan",
|
|
833
859
|
outputPlan: listOutputPlan,
|
|
834
860
|
isNonNull,
|
|
835
861
|
locationDetails,
|
|
836
862
|
});
|
|
837
|
-
const
|
|
863
|
+
const stream = streamDetails
|
|
864
|
+
? {
|
|
865
|
+
// These are already marked as internal dependencies
|
|
866
|
+
initialCountStepId: streamDetails.initialCount.id,
|
|
867
|
+
ifStepId: streamDetails.if.id,
|
|
868
|
+
labelStepId: streamDetails.label.id,
|
|
869
|
+
}
|
|
870
|
+
: undefined;
|
|
871
|
+
let $__item = this.itemStepForListStep(parentLayerPlan, $list, listDepth, stream);
|
|
838
872
|
const $sideEffect = $__item.layerPlan.latestSideEffectStep;
|
|
839
873
|
try {
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
874
|
+
let $item;
|
|
875
|
+
if ((0, step_js_1.isListCapableStep)($list)) {
|
|
876
|
+
$item = (0, withGlobalLayerPlan_js_1.withGlobalLayerPlan)($__item.layerPlan, $__item.polymorphicPaths, $list.listItem, $list, $__item);
|
|
877
|
+
this.deduplicateSteps();
|
|
878
|
+
// Refetch steps following deduplicate
|
|
879
|
+
$__item = this.stepTracker.getStepById($__item.id);
|
|
880
|
+
$item = this.stepTracker.getStepById($item.id);
|
|
881
|
+
}
|
|
882
|
+
else {
|
|
883
|
+
$item = $__item;
|
|
884
|
+
}
|
|
885
|
+
this.planIntoOutputPlan(listOutputPlan, $item.layerPlan, path, polymorphicPath, polymorphicPaths, selections, null, null, nullableFieldType.ofType, $item, locationDetails, resolverEmulation, listDepth + 1, null);
|
|
844
886
|
}
|
|
845
887
|
finally {
|
|
846
888
|
$__item.layerPlan.latestSideEffectStep = $sideEffect;
|
|
@@ -894,8 +936,8 @@ class OperationPlan {
|
|
|
894
936
|
const stepAssertion = nullableFieldType.extensions?.grafast?.assertStep;
|
|
895
937
|
if (stepAssertion != null) {
|
|
896
938
|
try {
|
|
897
|
-
if (stepAssertion === index_js_1.
|
|
898
|
-
stepAssertion.prototype instanceof index_js_1.
|
|
939
|
+
if (stepAssertion === index_js_1.Step ||
|
|
940
|
+
stepAssertion.prototype instanceof index_js_1.Step) {
|
|
899
941
|
if (!($step instanceof stepAssertion)) {
|
|
900
942
|
throw new Error(`Step mis-match: expected ${stepAssertion.name}, but instead found ${$step.constructor.name} (${$step})`);
|
|
901
943
|
}
|
|
@@ -1112,7 +1154,13 @@ class OperationPlan {
|
|
|
1112
1154
|
return layerPlan;
|
|
1113
1155
|
}
|
|
1114
1156
|
}
|
|
1115
|
-
planField(layerPlan, path, polymorphicPaths,
|
|
1157
|
+
planField(typeName, fieldName, layerPlan, path, polymorphicPaths, planResolver, applyAfterMode, rawParentStep, field, trackedArguments,
|
|
1158
|
+
// If 'true' this is a subscription rather than a stream
|
|
1159
|
+
// If 'false' this is a list but it will never stream
|
|
1160
|
+
// If 'null' this is neither subscribe field nor list field
|
|
1161
|
+
// Otherwise, it's a list field that has the `@stream` directive applied
|
|
1162
|
+
streamDetails, deduplicate = true) {
|
|
1163
|
+
const coordinate = `${typeName}.${fieldName}`;
|
|
1116
1164
|
// The step may have been de-duped whilst sibling steps were planned
|
|
1117
1165
|
// PERF: this should be handled in the parent?
|
|
1118
1166
|
const parentStep = this.stepTracker.getStepById(rawParentStep.id);
|
|
@@ -1121,7 +1169,8 @@ class OperationPlan {
|
|
|
1121
1169
|
if (this.loc !== null)
|
|
1122
1170
|
this.loc.push(`planField(${path.join(".")})`);
|
|
1123
1171
|
try {
|
|
1124
|
-
let step = (0, withGlobalLayerPlan_js_1.withGlobalLayerPlan)(layerPlan, polymorphicPaths, operationPlan_input_js_1.withFieldArgsForArguments, null, this,
|
|
1172
|
+
let step = (0, withGlobalLayerPlan_js_1.withGlobalLayerPlan)(layerPlan, polymorphicPaths, operationPlan_input_js_1.withFieldArgsForArguments, null, this, trackedArguments, field, parentStep, applyAfterMode, coordinate, (fieldArgs) => planResolver(parentStep, fieldArgs, {
|
|
1173
|
+
fieldName,
|
|
1125
1174
|
field,
|
|
1126
1175
|
schema: this.schema,
|
|
1127
1176
|
}));
|
|
@@ -1135,31 +1184,22 @@ class OperationPlan {
|
|
|
1135
1184
|
haltTree = true;
|
|
1136
1185
|
}
|
|
1137
1186
|
(0, step_js_1.assertExecutableStep)(step);
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
const streamDirective = fieldNodes[0].directives?.find((d) => d.name.value === "stream");
|
|
1155
|
-
const stepOptions = {
|
|
1156
|
-
stream: !haltTree && streamDirective
|
|
1157
|
-
? {
|
|
1158
|
-
initialCount: Number((0, graphqlCollectFields_js_1.evalDirectiveArg)(fieldNodes[0], "stream", "initialCount", this.trackedVariableValuesStep, null)) || 0,
|
|
1159
|
-
}
|
|
1160
|
-
: null,
|
|
1161
|
-
};
|
|
1162
|
-
step._stepOptions = stepOptions;
|
|
1187
|
+
if (streamDetails === true) {
|
|
1188
|
+
// subscription
|
|
1189
|
+
step._stepOptions.stream = {};
|
|
1190
|
+
step._stepOptions.walkIterable = true;
|
|
1191
|
+
}
|
|
1192
|
+
else if (streamDetails === false) {
|
|
1193
|
+
step._stepOptions.walkIterable = true;
|
|
1194
|
+
}
|
|
1195
|
+
else if (streamDetails != null) {
|
|
1196
|
+
step._stepOptions.stream = {
|
|
1197
|
+
initialCountStepId: streamDetails.initialCount.id,
|
|
1198
|
+
ifStepId: streamDetails.if.id,
|
|
1199
|
+
labelStepId: streamDetails.label.id,
|
|
1200
|
+
};
|
|
1201
|
+
step._stepOptions.walkIterable = true;
|
|
1202
|
+
}
|
|
1163
1203
|
if (deduplicate) {
|
|
1164
1204
|
// Now that the field has been planned (including arguments, but NOT
|
|
1165
1205
|
// including selection set) we can deduplicate it to see if any of its
|
|
@@ -1193,7 +1233,6 @@ class OperationPlan {
|
|
|
1193
1233
|
}
|
|
1194
1234
|
const step = (0, withGlobalLayerPlan_js_1.withGlobalLayerPlan)(layerPlan, polymorphicPaths, index_js_1.error, null, e);
|
|
1195
1235
|
const haltTree = true;
|
|
1196
|
-
this.modifierSteps = [];
|
|
1197
1236
|
// PERF: consider deleting all steps that were allocated during this. For
|
|
1198
1237
|
// now we'll just rely on tree-shaking.
|
|
1199
1238
|
return { step, haltTree };
|
|
@@ -1231,42 +1270,12 @@ class OperationPlan {
|
|
|
1231
1270
|
},
|
|
1232
1271
|
};
|
|
1233
1272
|
}
|
|
1234
|
-
withModifiers(cb) {
|
|
1235
|
-
// Stash previous modifiers
|
|
1236
|
-
const previousModifierDepthCount = this.modifierDepthCount++;
|
|
1237
|
-
const previousCount = this.modifierStepCount;
|
|
1238
|
-
const previousStack = this.modifierSteps.splice(0, this.modifierSteps.length);
|
|
1239
|
-
this.modifierStepCount = 0;
|
|
1240
|
-
let result;
|
|
1241
|
-
let plansToApply;
|
|
1242
|
-
try {
|
|
1243
|
-
result = cb();
|
|
1244
|
-
}
|
|
1245
|
-
finally {
|
|
1246
|
-
// Remove the modifier plans from operationPlan and sort them ready for application.
|
|
1247
|
-
plansToApply = this.modifierSteps
|
|
1248
|
-
.splice(0, this.modifierSteps.length)
|
|
1249
|
-
.reverse();
|
|
1250
|
-
// Restore previous modifiers
|
|
1251
|
-
this.modifierStepCount = previousCount;
|
|
1252
|
-
for (const mod of previousStack) {
|
|
1253
|
-
this.modifierSteps.push(mod);
|
|
1254
|
-
}
|
|
1255
|
-
// Restore previous depth
|
|
1256
|
-
this.modifierDepthCount = previousModifierDepthCount;
|
|
1257
|
-
}
|
|
1258
|
-
// Apply the plans.
|
|
1259
|
-
for (let i = 0, l = plansToApply.length; i < l; i++) {
|
|
1260
|
-
plansToApply[i].apply();
|
|
1261
|
-
}
|
|
1262
|
-
return result;
|
|
1263
|
-
}
|
|
1264
1273
|
/**
|
|
1265
1274
|
* Sets up tracking for the given value (variableValues, context, rootValue).
|
|
1266
1275
|
*/
|
|
1267
1276
|
track(value, constraints, variableDefinitions) {
|
|
1268
|
-
const valueStep = (0, withGlobalLayerPlan_js_1.withGlobalLayerPlan)(this.rootLayerPlan, exports.POLYMORPHIC_ROOT_PATHS, newValueStepCallback);
|
|
1269
|
-
const trackedObjectStep = (0, withGlobalLayerPlan_js_1.withGlobalLayerPlan)(this.rootLayerPlan, exports.POLYMORPHIC_ROOT_PATHS, () => new index_js_1.__TrackedValueStep(value, valueStep, constraints, [], variableDefinitions));
|
|
1277
|
+
const valueStep = (0, withGlobalLayerPlan_js_1.withGlobalLayerPlan)(this.rootLayerPlan, exports.POLYMORPHIC_ROOT_PATHS, newValueStepCallback, null, variableDefinitions != null);
|
|
1278
|
+
const trackedObjectStep = (0, withGlobalLayerPlan_js_1.withGlobalLayerPlan)(this.rootLayerPlan, exports.POLYMORPHIC_ROOT_PATHS, () => new index_js_1.__TrackedValueStep(value, valueStep, constraints, [], variableDefinitions != null, variableDefinitions));
|
|
1270
1279
|
return [valueStep, trackedObjectStep];
|
|
1271
1280
|
}
|
|
1272
1281
|
/**
|
|
@@ -1280,8 +1289,8 @@ class OperationPlan {
|
|
|
1280
1289
|
continue;
|
|
1281
1290
|
for (const key in step) {
|
|
1282
1291
|
const val = step[key];
|
|
1283
|
-
if (key !==
|
|
1284
|
-
val instanceof index_js_1.
|
|
1292
|
+
if (key !== "implicitSideEffectStep" &&
|
|
1293
|
+
val instanceof index_js_1.Step) {
|
|
1285
1294
|
errors.push(new Error(`ERROR: ExecutableStep ${step} has illegal reference via property '${key}' to step ${val}. You must not reference steps directly, instead add the step as a dependency (\`depId = this.addDependency($step)\`) and use \`this.getDep(depId)\` to look the step up (or, if the step is not a dependency, store the step ID and use \`this.getStep(stepId)\` each time you need to reference it). Failure to comply could result in subtle breakage during optimisation.`));
|
|
1286
1295
|
}
|
|
1287
1296
|
}
|
|
@@ -1421,7 +1430,24 @@ class OperationPlan {
|
|
|
1421
1430
|
// call the function with an empty array; ignore the result.
|
|
1422
1431
|
return EMPTY_ARRAY;
|
|
1423
1432
|
}
|
|
1424
|
-
|
|
1433
|
+
// NOTE: Streams have no peers - we cannot reference the stream more than
|
|
1434
|
+
// once (and we aim to not cache the stream because we want its entries to
|
|
1435
|
+
// be garbage collected) - however if we're already fetching the list then
|
|
1436
|
+
// we shouldn't fetch it again via stream... We should deduplicate a stream
|
|
1437
|
+
// to return a non-stream.
|
|
1438
|
+
if (step._stepOptions.stream != null) {
|
|
1439
|
+
// TODO: remove this if block when we implement the new stream/defer -
|
|
1440
|
+
// deduplicating a stream should be fine. (Not subscriptions though - may
|
|
1441
|
+
// need a check for that!)
|
|
1442
|
+
return EMPTY_ARRAY;
|
|
1443
|
+
}
|
|
1444
|
+
if (this.stepTracker.internalDependencies.has(step)) {
|
|
1445
|
+
// PERF: we need to set up correct tracking, then internal deps can be deduped
|
|
1446
|
+
return EMPTY_ARRAY;
|
|
1447
|
+
}
|
|
1448
|
+
const sstep = (0, utils_js_1.sudo)(step);
|
|
1449
|
+
const { dependencies: deps, dependencyForbiddenFlags: flags, dependencyOnReject: onReject, layerPlan: layerPlan, constructor: stepConstructor, peerKey, } = sstep;
|
|
1450
|
+
// const streamInitialCount = sstep._stepOptions.stream?.initialCount;
|
|
1425
1451
|
const dependencyCount = deps.length;
|
|
1426
1452
|
if (dependencyCount === 0) {
|
|
1427
1453
|
let allPeers = null;
|
|
@@ -1430,7 +1456,10 @@ class OperationPlan {
|
|
|
1430
1456
|
if (possiblyPeer !== step &&
|
|
1431
1457
|
!possiblyPeer.hasSideEffects &&
|
|
1432
1458
|
possiblyPeer.layerPlan === layerPlan &&
|
|
1433
|
-
possiblyPeer.
|
|
1459
|
+
possiblyPeer._stepOptions.stream == null &&
|
|
1460
|
+
possiblyPeer.peerKey === peerKey
|
|
1461
|
+
// && possiblyPeer._stepOptions.stream?.initialCount === streamInitialCount
|
|
1462
|
+
) {
|
|
1434
1463
|
if (allPeers === null) {
|
|
1435
1464
|
allPeers = [possiblyPeer];
|
|
1436
1465
|
}
|
|
@@ -1457,8 +1486,11 @@ class OperationPlan {
|
|
|
1457
1486
|
if (peerDependencyIndex !== 0 ||
|
|
1458
1487
|
rawPossiblyPeer === step ||
|
|
1459
1488
|
rawPossiblyPeer.hasSideEffects ||
|
|
1489
|
+
rawPossiblyPeer._stepOptions.stream != null ||
|
|
1460
1490
|
rawPossiblyPeer.constructor !== stepConstructor ||
|
|
1461
|
-
rawPossiblyPeer.peerKey !== peerKey
|
|
1491
|
+
rawPossiblyPeer.peerKey !== peerKey
|
|
1492
|
+
// || rawPossiblyPeer._stepOptions.stream?.initialCount !== streamInitialCount
|
|
1493
|
+
) {
|
|
1462
1494
|
continue;
|
|
1463
1495
|
}
|
|
1464
1496
|
const possiblyPeer = (0, utils_js_1.sudo)(rawPossiblyPeer);
|
|
@@ -1508,8 +1540,11 @@ class OperationPlan {
|
|
|
1508
1540
|
if (peerDependencyIndex !== dependencyIndex ||
|
|
1509
1541
|
rawPossiblyPeer === step ||
|
|
1510
1542
|
rawPossiblyPeer.hasSideEffects ||
|
|
1543
|
+
rawPossiblyPeer._stepOptions.stream != null ||
|
|
1511
1544
|
rawPossiblyPeer.constructor !== stepConstructor ||
|
|
1512
|
-
rawPossiblyPeer.peerKey !== peerKey
|
|
1545
|
+
rawPossiblyPeer.peerKey !== peerKey
|
|
1546
|
+
// || rawPossiblyPeer._stepOptions.stream?.initialCount !== streamInitialCount
|
|
1547
|
+
) {
|
|
1513
1548
|
continue;
|
|
1514
1549
|
}
|
|
1515
1550
|
const possiblyPeer = (0, utils_js_1.sudo)(rawPossiblyPeer);
|
|
@@ -1738,6 +1773,11 @@ class OperationPlan {
|
|
|
1738
1773
|
if (this.isImmoveable(step)) {
|
|
1739
1774
|
return step;
|
|
1740
1775
|
}
|
|
1776
|
+
if (step._isUnary) {
|
|
1777
|
+
step._isUnaryLocked = true;
|
|
1778
|
+
// Don't push unary steps down
|
|
1779
|
+
return step;
|
|
1780
|
+
}
|
|
1741
1781
|
switch (step.layerPlan.reason.type) {
|
|
1742
1782
|
case "root":
|
|
1743
1783
|
case "subscription":
|
|
@@ -1915,7 +1955,14 @@ class OperationPlan {
|
|
|
1915
1955
|
return { stepsAtMinDepth, equivalentSteps };
|
|
1916
1956
|
}
|
|
1917
1957
|
deduplicateStep(step) {
|
|
1958
|
+
// Conditions applied to this step are now finalized, though we may still
|
|
1959
|
+
// tell the step to do more stuff (like fetch extra data), it can no longer
|
|
1960
|
+
// change its order, conditions, etc.
|
|
1918
1961
|
step.isArgumentsFinalized = true;
|
|
1962
|
+
// If a step is unary at this point, it must always remain unary.
|
|
1963
|
+
if (step._isUnary) {
|
|
1964
|
+
step._isUnaryLocked = true;
|
|
1965
|
+
}
|
|
1919
1966
|
if (step.deduplicate == null)
|
|
1920
1967
|
return step;
|
|
1921
1968
|
const result = this._deduplicateInnerLogic(step);
|
|
@@ -1934,6 +1981,10 @@ class OperationPlan {
|
|
|
1934
1981
|
}
|
|
1935
1982
|
winner.polymorphicPaths = polymorphicPaths;
|
|
1936
1983
|
}
|
|
1984
|
+
// Equivalent steps cannot be streaming; so we can no longer stream either.
|
|
1985
|
+
if (equivalentSteps.length > 0) {
|
|
1986
|
+
winner._stepOptions.stream = null;
|
|
1987
|
+
}
|
|
1937
1988
|
// Give the steps a chance to pass their responsibilities to the winner.
|
|
1938
1989
|
if (winner !== step) {
|
|
1939
1990
|
const wasLocked = index_js_1.isDev && (0, lock_js_1.unlock)(step);
|
|
@@ -1990,7 +2041,7 @@ class OperationPlan {
|
|
|
1990
2041
|
this.deduplicateStepsProcess(processed, start, dep);
|
|
1991
2042
|
}
|
|
1992
2043
|
}
|
|
1993
|
-
(0, withGlobalLayerPlan_js_1.withGlobalLayerPlan)(step.layerPlan, step.polymorphicPaths, this.deduplicateStep, this, step);
|
|
2044
|
+
(0, withGlobalLayerPlan_js_1.withGlobalLayerPlan)(step.layerPlan, step.polymorphicPaths, this.phase === "plan" ? this.deduplicateStep : this.hoistAndDeduplicate, this, step);
|
|
1994
2045
|
}
|
|
1995
2046
|
/**
|
|
1996
2047
|
* Gives us a chance to replace nearly-duplicate plans with other existing
|
|
@@ -2044,27 +2095,6 @@ class OperationPlan {
|
|
|
2044
2095
|
pushDownSteps() {
|
|
2045
2096
|
this.processSteps("pushDown", "dependents-first", false, this.pushDown);
|
|
2046
2097
|
}
|
|
2047
|
-
getStepOptionsForStep(step) {
|
|
2048
|
-
return step._stepOptions;
|
|
2049
|
-
/*
|
|
2050
|
-
// NOTE: streams can only be merged if their parameters are compatible
|
|
2051
|
-
// (namely they need to have equivalent `initialCount`)
|
|
2052
|
-
const streamLayerPlan = step.childLayerPlans.find(
|
|
2053
|
-
(lp) => lp.reason.type === "stream",
|
|
2054
|
-
);
|
|
2055
|
-
|
|
2056
|
-
// PERF: if step isn't streamable, don't create a streamLayerPlan because
|
|
2057
|
-
// there's no point (and then we can leverage better optimisations).
|
|
2058
|
-
|
|
2059
|
-
return {
|
|
2060
|
-
stream:
|
|
2061
|
-
streamLayerPlan && isStreamableStep(step)
|
|
2062
|
-
? // && streamLayerPlan.parentStep === step
|
|
2063
|
-
{ initialCount: streamLayerPlan.reason.initialCount }
|
|
2064
|
-
: null,
|
|
2065
|
-
};
|
|
2066
|
-
*/
|
|
2067
|
-
}
|
|
2068
2098
|
/**
|
|
2069
2099
|
* Calls the 'optimize' method on a plan, which may cause the plan to
|
|
2070
2100
|
* communicate with its (deep) dependencies, and even to replace itself with
|
|
@@ -2082,7 +2112,7 @@ class OperationPlan {
|
|
|
2082
2112
|
return step;
|
|
2083
2113
|
}
|
|
2084
2114
|
// We know if it's streaming or not based on the LayerPlan it's contained within.
|
|
2085
|
-
const stepOptions =
|
|
2115
|
+
// const stepOptions = step._stepOptions;
|
|
2086
2116
|
let meta;
|
|
2087
2117
|
if (step.optimizeMetaKey !== undefined) {
|
|
2088
2118
|
meta = this.optimizeMeta.get(step.optimizeMetaKey);
|
|
@@ -2093,7 +2123,11 @@ class OperationPlan {
|
|
|
2093
2123
|
}
|
|
2094
2124
|
const wasLocked = index_js_1.isDev && (0, lock_js_1.unlock)(step);
|
|
2095
2125
|
const replacementStep = step.optimize({
|
|
2096
|
-
|
|
2126
|
+
stream: step._stepOptions.stream
|
|
2127
|
+
? {
|
|
2128
|
+
// We could add more details here, but for now we don't really need them?
|
|
2129
|
+
}
|
|
2130
|
+
: null,
|
|
2097
2131
|
meta,
|
|
2098
2132
|
});
|
|
2099
2133
|
if (wasLocked)
|
|
@@ -2197,7 +2231,6 @@ class OperationPlan {
|
|
|
2197
2231
|
/** Finalizes each step */
|
|
2198
2232
|
finalizeSteps() {
|
|
2199
2233
|
const initialStepCount = this.stepTracker.stepCount;
|
|
2200
|
-
assert.strictEqual(this.modifierSteps.length, 0, "No modifier steps expected when performing finalizeSteps");
|
|
2201
2234
|
for (const step of this.stepTracker.activeSteps) {
|
|
2202
2235
|
const wasLocked = index_js_1.isDev && (0, lock_js_1.unlock)(step);
|
|
2203
2236
|
step.finalize();
|
|
@@ -2330,7 +2363,7 @@ class OperationPlan {
|
|
|
2330
2363
|
!(0, utils_js_1.stepADependsOnStepB)(sstep, latestSideEffectStep)) {
|
|
2331
2364
|
sstep.implicitSideEffectStep = latestSideEffectStep;
|
|
2332
2365
|
}
|
|
2333
|
-
if (step.isSyncAndSafe && (0, step_js_1.
|
|
2366
|
+
if (step.isSyncAndSafe && (0, step_js_1.isUnbatchedStep)(step)) {
|
|
2334
2367
|
if (phase.unbatchedSyncAndSafeSteps !== undefined) {
|
|
2335
2368
|
phase.unbatchedSyncAndSafeSteps.push({
|
|
2336
2369
|
step,
|
|
@@ -2360,7 +2393,7 @@ class OperationPlan {
|
|
|
2360
2393
|
do {
|
|
2361
2394
|
foundOne = false;
|
|
2362
2395
|
for (const step of pending) {
|
|
2363
|
-
if (step.isSyncAndSafe && (0, step_js_1.
|
|
2396
|
+
if (step.isSyncAndSafe && (0, step_js_1.isUnbatchedStep)(step)) {
|
|
2364
2397
|
if (readyToExecute(step)) {
|
|
2365
2398
|
processed.add(step);
|
|
2366
2399
|
pending.delete(step);
|
|
@@ -2442,6 +2475,18 @@ class OperationPlan {
|
|
|
2442
2475
|
if (layerPlan.reason.type === "listItem") {
|
|
2443
2476
|
const parentStep = layerPlan.reason.parentStep;
|
|
2444
2477
|
ensurePlanAvailableInLayer(parentStep, layerPlan.parentLayerPlan);
|
|
2478
|
+
const stream = layerPlan.reason.stream;
|
|
2479
|
+
if (stream != null) {
|
|
2480
|
+
if (stream.initialCountStepId) {
|
|
2481
|
+
ensurePlanAvailableInLayer(this.stepTracker.getStepById(stream.initialCountStepId), layerPlan.parentLayerPlan);
|
|
2482
|
+
}
|
|
2483
|
+
if (stream.ifStepId) {
|
|
2484
|
+
ensurePlanAvailableInLayer(this.stepTracker.getStepById(stream.ifStepId), layerPlan.parentLayerPlan);
|
|
2485
|
+
}
|
|
2486
|
+
if (stream.labelStepId) {
|
|
2487
|
+
ensurePlanAvailableInLayer(this.stepTracker.getStepById(stream.labelStepId), layerPlan.parentLayerPlan);
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2445
2490
|
}
|
|
2446
2491
|
}
|
|
2447
2492
|
// Populate copyPlanIds for output plans' rootStepId
|
|
@@ -2501,6 +2546,9 @@ class OperationPlan {
|
|
|
2501
2546
|
isSyncAndSafe: step.isSyncAndSafe || undefined,
|
|
2502
2547
|
supportsUnbatched: typeof step.unbatchedExecute === "function" || undefined,
|
|
2503
2548
|
hasSideEffects: step.hasSideEffects || undefined,
|
|
2549
|
+
stream: step._stepOptions.stream
|
|
2550
|
+
? { initialCountStepId: step._stepOptions.stream.initialCountStepId }
|
|
2551
|
+
: undefined,
|
|
2504
2552
|
extra: step.planJSONExtra(),
|
|
2505
2553
|
};
|
|
2506
2554
|
}
|
|
@@ -2624,14 +2672,19 @@ class OperationPlan {
|
|
|
2624
2672
|
* need to regenerate it on future calls, significantly reducing the load on
|
|
2625
2673
|
* deduplication later.
|
|
2626
2674
|
*
|
|
2675
|
+
* Note: automatically extends the cached step into other (relevant)
|
|
2676
|
+
* polymorphic paths; if this shouldn't be the case then don't use cacheStep
|
|
2677
|
+
* and instead rely on deduplication as usual.
|
|
2678
|
+
*
|
|
2627
2679
|
* @experimental
|
|
2628
2680
|
*/
|
|
2629
2681
|
cacheStep(ownerStep, actionKey, cacheKey, cb) {
|
|
2630
2682
|
const layerPlan = (0, withGlobalLayerPlan_js_1.currentLayerPlan)();
|
|
2683
|
+
const paths = (0, withGlobalLayerPlan_js_1.currentPolymorphicPaths)();
|
|
2631
2684
|
const cache = (this._cacheStepStoreByLayerPlanAndActionKey[`${actionKey}|${layerPlan.id}|${ownerStep.id}`] ??= new Map());
|
|
2632
2685
|
const cacheIt = () => {
|
|
2633
2686
|
const stepToCache = cb();
|
|
2634
|
-
if (!(stepToCache instanceof index_js_1.
|
|
2687
|
+
if (!(stepToCache instanceof index_js_1.Step)) {
|
|
2635
2688
|
throw new Error(`The callback passed to cacheStep must always return an ExecutableStep; but this call from ${ownerStep} returned instead ${(0, inspect_js_1.inspect)(stepToCache)}`);
|
|
2636
2689
|
}
|
|
2637
2690
|
cache.set(cacheKey, stepToCache.id);
|
|
@@ -2642,7 +2695,20 @@ class OperationPlan {
|
|
|
2642
2695
|
}
|
|
2643
2696
|
const cachedStepId = cache.get(cacheKey);
|
|
2644
2697
|
const cachedStep = this.stepTracker.stepById[cachedStepId];
|
|
2645
|
-
|
|
2698
|
+
if (cachedStep) {
|
|
2699
|
+
// Fix poly paths
|
|
2700
|
+
if (paths && cachedStep.polymorphicPaths) {
|
|
2701
|
+
const polymorphicPaths = new Set([
|
|
2702
|
+
...cachedStep.polymorphicPaths,
|
|
2703
|
+
...paths,
|
|
2704
|
+
]);
|
|
2705
|
+
cachedStep.polymorphicPaths = polymorphicPaths;
|
|
2706
|
+
}
|
|
2707
|
+
return cachedStep;
|
|
2708
|
+
}
|
|
2709
|
+
else {
|
|
2710
|
+
return cacheIt();
|
|
2711
|
+
}
|
|
2646
2712
|
}
|
|
2647
2713
|
/**
|
|
2648
2714
|
* Clears the cache, typically due to side effects having taken place. Called
|
|
@@ -2651,13 +2717,11 @@ class OperationPlan {
|
|
|
2651
2717
|
resetCache() {
|
|
2652
2718
|
this._cacheStepStoreByLayerPlanAndActionKey = Object.create(null);
|
|
2653
2719
|
}
|
|
2720
|
+
withRootLayerPlan(cb) {
|
|
2721
|
+
return (0, withGlobalLayerPlan_js_1.withGlobalLayerPlan)(this.rootLayerPlan, exports.POLYMORPHIC_ROOT_PATHS, cb);
|
|
2722
|
+
}
|
|
2654
2723
|
}
|
|
2655
2724
|
exports.OperationPlan = OperationPlan;
|
|
2656
|
-
function makeDefaultPlan(fieldName) {
|
|
2657
|
-
return ($step) => typeof $step.get === "function"
|
|
2658
|
-
? $step.get(fieldName)
|
|
2659
|
-
: (0, access_js_1.access)($step, [fieldName]);
|
|
2660
|
-
}
|
|
2661
2725
|
function makeMetaByMetaKeysFactory(allMetaKeysList) {
|
|
2662
2726
|
const l = allMetaKeysList.length;
|
|
2663
2727
|
// Optimize the common cases
|