grafast 0.1.1-beta.2 → 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/README.md +2 -3
- package/dist/args.d.ts +4 -7
- package/dist/args.js +53 -38
- package/dist/assert.js +2 -3
- package/dist/bucket.d.ts +1 -89
- package/dist/config.d.ts +0 -17
- package/dist/config.js +1 -95
- package/dist/constraints.d.ts +15 -1
- package/dist/constraints.js +41 -3
- package/dist/deferred.js +1 -2
- package/dist/dev.d.ts +1 -4
- package/dist/dev.js +18 -3
- package/dist/engine/LayerPlan.d.ts +21 -111
- package/dist/engine/LayerPlan.js +196 -78
- package/dist/engine/OperationPlan.d.ts +30 -104
- package/dist/engine/OperationPlan.js +763 -471
- package/dist/engine/OutputPlan.d.ts +9 -20
- package/dist/engine/OutputPlan.js +432 -444
- package/dist/engine/StepTracker.d.ts +1 -95
- package/dist/engine/StepTracker.js +94 -20
- package/dist/engine/executeBucket.d.ts +5 -7
- package/dist/engine/executeBucket.js +646 -244
- package/dist/engine/executeOutputPlan.d.ts +0 -53
- package/dist/engine/executeOutputPlan.js +7 -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 -0
- package/dist/engine/lib/withGlobalLayerPlan.js +7 -4
- package/dist/engine/lock.d.ts +4 -0
- package/dist/engine/lock.js +82 -0
- package/dist/envelop.js +5 -4
- package/dist/error.d.ts +18 -49
- package/dist/error.js +50 -39
- package/dist/establishOperationPlan.js +57 -42
- package/dist/execute.d.ts +5 -4
- package/dist/execute.js +31 -15
- package/dist/exportAs.d.ts +1 -18
- package/dist/exportAs.js +2 -3
- package/dist/global.js +2 -3
- package/dist/grafastGraphql.d.ts +6 -1
- package/dist/grafastGraphql.js +35 -16
- package/dist/grafastPrint.d.ts +3 -0
- package/dist/grafastPrint.js +67 -6
- package/dist/graphqlCollectFields.d.ts +7 -34
- package/dist/graphqlCollectFields.js +24 -13
- package/dist/graphqlMergeSelectionSets.js +1 -2
- package/dist/index.d.ts +44 -29
- package/dist/index.js +91 -18
- package/dist/input.d.ts +1 -9
- package/dist/input.js +75 -28
- package/dist/inspect.d.ts +9 -3
- package/dist/inspect.js +3 -3
- package/dist/interfaces.d.ts +238 -93
- package/dist/interfaces.js +20 -3
- package/dist/makeGrafastSchema.d.ts +21 -9
- package/dist/makeGrafastSchema.js +353 -133
- package/dist/mermaid.d.ts +0 -17
- package/dist/mermaid.js +131 -19
- package/dist/middleware.d.ts +7 -0
- package/dist/middleware.js +24 -0
- package/dist/multistep.d.ts +19 -0
- package/dist/multistep.js +54 -0
- package/dist/operationPlan-input.d.ts +5 -4
- package/dist/operationPlan-input.js +140 -368
- package/dist/planJSONInterfaces.d.ts +12 -2
- package/dist/polymorphic.js +4 -5
- package/dist/prepare.d.ts +1 -7
- package/dist/prepare.js +100 -74
- package/dist/step.d.ts +118 -172
- package/dist/step.js +262 -183
- package/dist/steps/__flag.d.ts +65 -0
- package/dist/steps/__flag.js +261 -0
- package/dist/steps/__inputDefault.d.ts +14 -0
- package/dist/steps/__inputDefault.js +48 -0
- package/dist/steps/__inputDynamicScalar.d.ts +4 -6
- 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 +7 -11
- package/dist/steps/__inputObject.js +49 -3
- package/dist/steps/__inputStaticLeaf.d.ts +2 -4
- package/dist/steps/__inputStaticLeaf.js +3 -1
- package/dist/steps/__item.d.ts +10 -12
- package/dist/steps/__item.js +8 -2
- package/dist/steps/__trackedValue.d.ts +7 -55
- package/dist/steps/__trackedValue.js +69 -8
- package/dist/steps/__value.d.ts +5 -4
- package/dist/steps/__value.js +5 -4
- package/dist/steps/access.d.ts +10 -10
- package/dist/steps/access.js +50 -17
- package/dist/steps/applyInput.d.ts +44 -0
- package/dist/steps/applyInput.js +206 -0
- package/dist/steps/applyTransforms.d.ts +2 -25
- package/dist/steps/applyTransforms.js +53 -31
- package/dist/steps/bakedInput.d.ts +23 -0
- package/dist/steps/bakedInput.js +90 -0
- package/dist/steps/condition.d.ts +31 -0
- package/dist/steps/condition.js +94 -0
- package/dist/steps/connection.d.ts +56 -42
- package/dist/steps/connection.js +97 -44
- package/dist/steps/constant.d.ts +7 -7
- package/dist/steps/constant.js +86 -7
- package/dist/steps/each.d.ts +3 -3
- package/dist/steps/each.js +2 -3
- package/dist/steps/error.d.ts +4 -4
- package/dist/steps/error.js +7 -6
- package/dist/steps/filter.d.ts +3 -2
- package/dist/steps/filter.js +1 -2
- package/dist/steps/first.d.ts +10 -9
- package/dist/steps/first.js +9 -13
- package/dist/steps/graphqlResolver.d.ts +3 -76
- package/dist/steps/graphqlResolver.js +89 -72
- package/dist/steps/groupBy.d.ts +3 -2
- package/dist/steps/groupBy.js +1 -2
- package/dist/steps/index.d.ts +12 -3
- package/dist/steps/index.js +48 -6
- package/dist/steps/lambda.d.ts +9 -9
- package/dist/steps/lambda.js +18 -9
- package/dist/steps/last.d.ts +9 -8
- package/dist/steps/last.js +7 -6
- package/dist/steps/list.d.ts +20 -9
- package/dist/steps/list.js +56 -13
- package/dist/steps/listTransform.d.ts +18 -22
- package/dist/steps/listTransform.js +58 -27
- package/dist/steps/listen.d.ts +6 -11
- package/dist/steps/listen.js +14 -16
- package/dist/steps/load.d.ts +42 -33
- package/dist/steps/load.js +60 -27
- package/dist/steps/node.d.ts +17 -10
- package/dist/steps/node.js +18 -6
- package/dist/steps/object.d.ts +33 -27
- package/dist/steps/object.js +53 -32
- package/dist/steps/partitionByIndex.d.ts +3 -2
- package/dist/steps/partitionByIndex.js +1 -2
- package/dist/steps/polymorphicBranch.d.ts +27 -0
- package/dist/steps/polymorphicBranch.js +62 -0
- package/dist/steps/proxy.d.ts +11 -12
- package/dist/steps/proxy.js +8 -5
- package/dist/steps/remapKeys.d.ts +10 -10
- package/dist/steps/remapKeys.js +14 -7
- package/dist/steps/reverse.d.ts +8 -8
- package/dist/steps/reverse.js +10 -7
- package/dist/steps/setter.d.ts +9 -18
- package/dist/steps/setter.js +24 -14
- package/dist/steps/sideEffect.d.ts +28 -0
- package/dist/steps/sideEffect.js +44 -0
- package/dist/stringifyPayload.js +1 -2
- package/dist/stripAnsi.js +2 -2
- package/dist/subscribe.d.ts +7 -1
- package/dist/subscribe.js +24 -9
- package/dist/thereCanBeOnlyOne.js +1 -1
- package/dist/timeSource.d.ts +0 -1
- package/dist/utils.d.ts +56 -55
- package/dist/utils.js +179 -59
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +5 -8
package/dist/step.js
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var _a;
|
|
2
|
+
var _a, _b;
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.
|
|
4
|
+
exports.isExecutableStep = exports.UnbatchedExecutableStep = exports.ExecutableStep = exports.UnbatchedStep = exports.Step = exports.assertFinalized = exports.$$noExec = void 0;
|
|
5
|
+
exports.isStep = isStep;
|
|
6
|
+
exports.assertStep = assertStep;
|
|
7
|
+
exports.isUnbatchedStep = isUnbatchedStep;
|
|
8
|
+
exports.isObjectLikeStep = isObjectLikeStep;
|
|
9
|
+
exports.isListLikeStep = isListLikeStep;
|
|
10
|
+
exports.isPolymorphicStep = isPolymorphicStep;
|
|
11
|
+
exports.isListCapableStep = isListCapableStep;
|
|
12
|
+
exports.assertListCapableStep = assertListCapableStep;
|
|
13
|
+
exports.assertExecutableStep = assertExecutableStep;
|
|
5
14
|
const tslib_1 = require("tslib");
|
|
6
15
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
7
16
|
const tamedevil_1 = tslib_1.__importDefault(require("tamedevil"));
|
|
8
17
|
const dev_js_1 = require("./dev.js");
|
|
9
18
|
const withGlobalLayerPlan_js_1 = require("./engine/lib/withGlobalLayerPlan.js");
|
|
19
|
+
const lock_js_1 = require("./engine/lock.js");
|
|
20
|
+
const error_js_1 = require("./error.js");
|
|
10
21
|
const global_js_1 = require("./global.js");
|
|
11
22
|
const inspect_js_1 = require("./inspect.js");
|
|
12
23
|
const interfaces_js_1 = require("./interfaces.js");
|
|
13
|
-
|
|
14
|
-
* @internal
|
|
15
|
-
*/
|
|
16
|
-
exports.$$deepDepSkip = Symbol("deepDepSkip_experimental");
|
|
24
|
+
const utils_js_1 = require("./utils.js");
|
|
17
25
|
/**
|
|
18
26
|
* This indicates that a step never executes (e.g. __ItemStep and __ValueStep)
|
|
19
27
|
* and thus when executed skips direct to reallyCompletedStep.
|
|
@@ -21,6 +29,7 @@ exports.$$deepDepSkip = Symbol("deepDepSkip_experimental");
|
|
|
21
29
|
* @internal
|
|
22
30
|
*/
|
|
23
31
|
exports.$$noExec = Symbol("noExec");
|
|
32
|
+
const ref_flagError = tamedevil_1.default.ref(error_js_1.flagError, "flagError");
|
|
24
33
|
function throwDestroyed() {
|
|
25
34
|
let message;
|
|
26
35
|
try {
|
|
@@ -32,7 +41,7 @@ function throwDestroyed() {
|
|
|
32
41
|
throw new Error(message);
|
|
33
42
|
}
|
|
34
43
|
function isDeepDepSkippable($dep) {
|
|
35
|
-
return
|
|
44
|
+
return interfaces_js_1.$$deepDepSkip in $dep && typeof $dep[interfaces_js_1.$$deepDepSkip] === "function";
|
|
36
45
|
}
|
|
37
46
|
function reallyAssertFinalized(plan) {
|
|
38
47
|
if (!plan.isFinalized) {
|
|
@@ -42,80 +51,154 @@ function reallyAssertFinalized(plan) {
|
|
|
42
51
|
// Optimise this away in production.
|
|
43
52
|
exports.assertFinalized = !dev_js_1.isDev ? dev_js_1.noop : reallyAssertFinalized;
|
|
44
53
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* ModifierStep (for use when planning arguments/input fields).
|
|
48
|
-
*
|
|
49
|
-
* @remarks
|
|
50
|
-
*
|
|
51
|
-
* Though it might seem that ModifierStep should be used for all inputs
|
|
52
|
-
* (arguments, input objects), this is not the case. When planning an output
|
|
53
|
-
* field, all inputs to it (including arguments, parent plan, context, etc)
|
|
54
|
-
* should be other executable plans. The only time that ModifierStep is used is
|
|
55
|
-
* when writing specific plans as part of the argument or input field
|
|
56
|
-
* definitions themself; even in these cases the inputs to these plan resolvers
|
|
57
|
-
* will be ExecutablePlans.
|
|
54
|
+
* Executable plans are the plans associated with leaves on the GraphQL tree,
|
|
55
|
+
* they must be able to execute to return values.
|
|
58
56
|
*/
|
|
59
|
-
class
|
|
60
|
-
static { _a = interfaces_js_1.$$subroutine; }
|
|
57
|
+
class Step {
|
|
58
|
+
static { _a = interfaces_js_1.$$subroutine, _b = lock_js_1.$$unlock; }
|
|
61
59
|
constructor() {
|
|
62
60
|
this[_a] = null;
|
|
61
|
+
/**
|
|
62
|
+
* For input values, set `true` if it comes from variables/arguments since
|
|
63
|
+
* they cannot be modified (even by mutations), set `false` otherwise.
|
|
64
|
+
*
|
|
65
|
+
* @internal
|
|
66
|
+
*/
|
|
67
|
+
this._isImmutable = false;
|
|
68
|
+
/** @internal */
|
|
69
|
+
this[_b] = undefined;
|
|
70
|
+
/**
|
|
71
|
+
* (default = ALL_FLAGS & ~FLAG_NULL)
|
|
72
|
+
*/
|
|
73
|
+
this.defaultForbiddenFlags = interfaces_js_1.DEFAULT_FORBIDDEN_FLAGS;
|
|
74
|
+
/**
|
|
75
|
+
* If the peerKey of two steps do not match, then they are definitely not
|
|
76
|
+
* peers. Use this to reduce the load on deduplicate by more quickly
|
|
77
|
+
* eradicating definitely-not-peers.
|
|
78
|
+
*
|
|
79
|
+
* Note: we may well change this to be a function in future, so it's advised
|
|
80
|
+
* that you don't use this unless you're working inside the graphile/crystal
|
|
81
|
+
* core codebase.
|
|
82
|
+
*
|
|
83
|
+
* @experimental
|
|
84
|
+
*/
|
|
85
|
+
this.peerKey = null;
|
|
63
86
|
this.isArgumentsFinalized = false;
|
|
64
87
|
this.isFinalized = false;
|
|
65
88
|
this.debug = (0, global_js_1.getDebug)();
|
|
66
|
-
this.hasSideEffects = false;
|
|
67
89
|
const layerPlan = (0, withGlobalLayerPlan_js_1.currentLayerPlan)();
|
|
68
90
|
this.layerPlan = layerPlan;
|
|
69
91
|
this.operationPlan = layerPlan.operationPlan;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
92
|
+
this._isUnary = true;
|
|
93
|
+
this._isUnaryLocked = false;
|
|
94
|
+
this.implicitSideEffectStep = null;
|
|
95
|
+
this.hasSideEffects ??= false;
|
|
96
|
+
let hasSideEffects = false;
|
|
97
|
+
const stepTracker = this.layerPlan.operationPlan.stepTracker;
|
|
98
|
+
Object.defineProperty(this, "hasSideEffects", {
|
|
99
|
+
get() {
|
|
100
|
+
return hasSideEffects;
|
|
101
|
+
},
|
|
102
|
+
set(value) {
|
|
103
|
+
/**
|
|
104
|
+
* If steps were created after this step, an this step doesn't depend
|
|
105
|
+
* on them, then it's no longer safe to change hasSideEffects.
|
|
106
|
+
*/
|
|
107
|
+
let nonDependentSteps = null;
|
|
108
|
+
const maxStepId = stepTracker.stepCount - 1;
|
|
109
|
+
if (this.id === maxStepId) {
|
|
110
|
+
// All good - no more steps were created
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
// If the step created them during initialization and is dependent on
|
|
114
|
+
// them, that's fine too.
|
|
115
|
+
for (let id = this.id + 1; id <= maxStepId; id++) {
|
|
116
|
+
const step = stepTracker.getStepById(id);
|
|
117
|
+
if ((0, utils_js_1.stepADependsOnStepB)(this, step))
|
|
118
|
+
continue;
|
|
119
|
+
if (nonDependentSteps === null) {
|
|
120
|
+
nonDependentSteps = [step];
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
nonDependentSteps.push(step);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (nonDependentSteps === null) {
|
|
128
|
+
hasSideEffects = value;
|
|
129
|
+
if (value === true) {
|
|
130
|
+
this.layerPlan.latestSideEffectStep = this;
|
|
131
|
+
this.operationPlan.resetCache();
|
|
132
|
+
}
|
|
133
|
+
else if (value !== true && hasSideEffects === true) {
|
|
134
|
+
throw new Error(`Cannot mark ${this} as having no side effects after having set it to have side effects.`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
throw new Error(`Attempted to mark ${this} as having side effects, but other non-dependent steps (${nonDependentSteps
|
|
139
|
+
.map(String)
|
|
140
|
+
.join(", ")}) have already been created.`);
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
enumerable: true,
|
|
144
|
+
configurable: false,
|
|
145
|
+
});
|
|
102
146
|
this.dependencies = [];
|
|
147
|
+
this.dependencyForbiddenFlags = [];
|
|
148
|
+
this.dependencyOnReject = [];
|
|
103
149
|
this.dependents = [];
|
|
104
150
|
this.isOptimized = false;
|
|
105
151
|
this.allowMultipleOptimizations = false;
|
|
106
|
-
this._stepOptions = { stream: null };
|
|
152
|
+
this._stepOptions = { stream: null, walkIterable: false };
|
|
107
153
|
this.store = true;
|
|
108
154
|
this.polymorphicPaths = (0, withGlobalLayerPlan_js_1.currentPolymorphicPaths)();
|
|
155
|
+
// Important: MUST come after `this.layerPlan = ...`
|
|
109
156
|
this.id = this.layerPlan._addStep(this);
|
|
110
157
|
}
|
|
158
|
+
/**
|
|
159
|
+
* Generally you should only use this once the dependencies of a step are
|
|
160
|
+
* established, if you use it beforehand and it returns `true` then adding a
|
|
161
|
+
* non-unary dependency later will result in an error.
|
|
162
|
+
*/
|
|
163
|
+
getAndFreezeIsUnary() {
|
|
164
|
+
this._isUnaryLocked = true;
|
|
165
|
+
return this._isUnary;
|
|
166
|
+
}
|
|
111
167
|
withMyLayerPlan(callback) {
|
|
112
168
|
return (0, withGlobalLayerPlan_js_1.withGlobalLayerPlan)(this.layerPlan, this.polymorphicPaths, callback);
|
|
113
169
|
}
|
|
170
|
+
/** @experimental */
|
|
171
|
+
withLayerPlan(callback) {
|
|
172
|
+
return (0, withGlobalLayerPlan_js_1.withGlobalLayerPlan)(this.layerPlan, this.polymorphicPaths, callback);
|
|
173
|
+
}
|
|
114
174
|
getStep(id) {
|
|
115
175
|
return this.layerPlan.getStep(id, this);
|
|
116
176
|
}
|
|
117
|
-
|
|
118
|
-
|
|
177
|
+
getDepOptions(depId) {
|
|
178
|
+
const step = this.dependencies[depId];
|
|
179
|
+
const forbiddenFlags = this.dependencyForbiddenFlags[depId];
|
|
180
|
+
const onReject = this.dependencyOnReject[depId];
|
|
181
|
+
const acceptFlags = interfaces_js_1.ALL_FLAGS & ~forbiddenFlags;
|
|
182
|
+
return { step, acceptFlags, onReject };
|
|
183
|
+
}
|
|
184
|
+
getDep(_depId, _throwOnFlagged = false) {
|
|
185
|
+
// This gets replaced when `__FlagStep` is loaded. Were we on ESM we could
|
|
186
|
+
// just put the code here, but since we're not we have to avoid the
|
|
187
|
+
// circular dependency.
|
|
188
|
+
throw new Error(`Grafast failed to load correctly`);
|
|
189
|
+
}
|
|
190
|
+
maybeGetDep(depId, throwOnFlagged = false) {
|
|
191
|
+
return depId == null
|
|
192
|
+
? null
|
|
193
|
+
: throwOnFlagged
|
|
194
|
+
? this.getDep(depId, true)
|
|
195
|
+
: this.getDep(depId);
|
|
196
|
+
}
|
|
197
|
+
getDepOrConstant(_depId, _fallback) {
|
|
198
|
+
// This gets replaced when `constant` is loaded. Were we on ESM we could
|
|
199
|
+
// just put the code here, but since we're not we have to avoid the
|
|
200
|
+
// circular dependency.
|
|
201
|
+
throw new Error(`Grafast failed to load correctly`);
|
|
119
202
|
}
|
|
120
203
|
/**
|
|
121
204
|
* Like getDep, except it skips over __ItemStep and similar steps to get to
|
|
@@ -129,48 +212,72 @@ class ExecutableStep extends BaseStep {
|
|
|
129
212
|
// __ItemStep and __ListTransformStep are safe to walk through, but other
|
|
130
213
|
// classes may not be.
|
|
131
214
|
while (isDeepDepSkippable($dep)) {
|
|
132
|
-
$dep = $dep[
|
|
215
|
+
$dep = $dep[interfaces_js_1.$$deepDepSkip]();
|
|
133
216
|
}
|
|
134
217
|
return $dep;
|
|
135
218
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
219
|
+
/**
|
|
220
|
+
* Cache a generated step by a given identifier (cacheKey) such that we don't
|
|
221
|
+
* need to regenerate it on future calls, significantly reducing the load on
|
|
222
|
+
* deduplication later.
|
|
223
|
+
*
|
|
224
|
+
* @experimental
|
|
225
|
+
*/
|
|
226
|
+
cacheStep(actionKey, cacheKey, cb) {
|
|
227
|
+
return this.operationPlan.cacheStep(this, actionKey, cacheKey, cb);
|
|
141
228
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
229
|
+
toString() {
|
|
230
|
+
let meta;
|
|
231
|
+
try {
|
|
232
|
+
// If we log out too early, the meta function might fail.
|
|
233
|
+
meta = this.toStringMeta();
|
|
145
234
|
}
|
|
146
|
-
|
|
147
|
-
|
|
235
|
+
catch (e) {
|
|
236
|
+
// Ignore
|
|
148
237
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
238
|
+
return chalk_1.default.bold.blue(`${this.constructor.name.replace(/Step$/, "")}${this.layerPlan.id === 0 ? "" : chalk_1.default.grey(`{${this.layerPlan.id}}`)}${this._isUnary ? "➊" : ""}${this._stepOptions.stream != null ? "@s" : ""}${meta != null && meta.length ? chalk_1.default.grey(`<${meta}>`) : ""}[${(0, inspect_js_1.inspect)(this.id, { colors: true })}]`);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* This metadata will be merged into toString when referencing this plan.
|
|
242
|
+
*/
|
|
243
|
+
toStringMeta() {
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
planJSONExtra() {
|
|
247
|
+
return undefined;
|
|
248
|
+
}
|
|
249
|
+
canAddDependency(step) {
|
|
250
|
+
return (0, utils_js_1.stepAMayDependOnStepB)(this, step);
|
|
251
|
+
}
|
|
252
|
+
addDependency(stepOrOptions) {
|
|
253
|
+
const options = stepOrOptions instanceof Step
|
|
254
|
+
? { step: stepOrOptions, skipDeduplication: false }
|
|
255
|
+
: stepOrOptions;
|
|
256
|
+
if (options.step.layerPlan.id > this.layerPlan.id) {
|
|
257
|
+
throw new Error(`Cannot add dependency ${options.step} to ${this} since the former is in a deeper layerPlan (creates a catch-22)`);
|
|
157
258
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
259
|
+
return this.operationPlan.stepTracker.addStepDependency(this, options);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Adds "unary" dependencies; in `execute({count, values})` you'll receive a
|
|
263
|
+
* `values[index]` (where `index` is the return value of this function) with
|
|
264
|
+
* `isBatch = false` so you can use the `values[index].value` property
|
|
265
|
+
* directly.
|
|
266
|
+
*/
|
|
267
|
+
addUnaryDependency(stepOrOptions) {
|
|
268
|
+
const options = stepOrOptions instanceof Step ? { step: stepOrOptions } : stepOrOptions;
|
|
269
|
+
if (options.step.layerPlan.id > this.layerPlan.id) {
|
|
270
|
+
throw new Error(`Cannot add dependency ${options.step} to ${this} since the former is in a deeper layerPlan (creates a catch-22)`);
|
|
166
271
|
}
|
|
167
|
-
return this.operationPlan.stepTracker.
|
|
272
|
+
return this.operationPlan.stepTracker.addStepUnaryDependency(this, options);
|
|
168
273
|
}
|
|
169
274
|
finalize() {
|
|
170
275
|
if (typeof this.isSyncAndSafe !== "boolean") {
|
|
171
276
|
// Take a guess
|
|
172
|
-
|
|
173
|
-
|
|
277
|
+
if (!dev_js_1.isDev) {
|
|
278
|
+
this.isSyncAndSafe = false;
|
|
279
|
+
}
|
|
280
|
+
else if (this.execute.constructor.name === "AsyncFunction") {
|
|
174
281
|
this.isSyncAndSafe = false;
|
|
175
282
|
}
|
|
176
283
|
else {
|
|
@@ -182,17 +289,29 @@ class ExecutableStep extends BaseStep {
|
|
|
182
289
|
this.execute.constructor.name === "AsyncFunction") {
|
|
183
290
|
throw new Error(`${this} claims to be synchronous, however the execute method is asynchronous`);
|
|
184
291
|
}
|
|
185
|
-
|
|
292
|
+
if (!this.isFinalized) {
|
|
293
|
+
this.isFinalized = true;
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
throw new Error(`Step ${this} has already been finalized - do not call \`finalize()\` from user code!`);
|
|
297
|
+
}
|
|
186
298
|
}
|
|
187
299
|
/**
|
|
188
|
-
* This function will be called with
|
|
189
|
-
* each incoming grafast object, where each entry in the array is a list of
|
|
190
|
-
* the values retrieved from executing the plans in `this.dependencies` for
|
|
191
|
-
* that grafast object.
|
|
300
|
+
* This function will be called with 'execution details', an object containing:
|
|
192
301
|
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
302
|
+
* - `count`: the number of entries in the batch that's being executed
|
|
303
|
+
* - `values`: a tuple representing the runtime values of the steps
|
|
304
|
+
* dependencies; each value in the tuple is an object, either a batch object
|
|
305
|
+
* containing a list of size `count` containing the values, or a unary
|
|
306
|
+
* object containing the single value common to all entries.
|
|
307
|
+
* - `indexMap`: helper function to map over each index from `0` to `count-1`,
|
|
308
|
+
* returning the resulting array.
|
|
309
|
+
* - `indexForEach`: as `indexMap`, but without the array result.
|
|
310
|
+
* - `meta`: [experimental]
|
|
311
|
+
*
|
|
312
|
+
* `execute` must return a list with `count` entries, where each value in the
|
|
313
|
+
* list relates to the result of executing this plan for the corresponding
|
|
314
|
+
* entry in each of the entries in the `values` tuple.
|
|
196
315
|
*
|
|
197
316
|
* IMPORTANT: it is up to the execute function to cache/memoize results as
|
|
198
317
|
* appropriate for performance, this can be done via the `meta` object.
|
|
@@ -202,13 +321,10 @@ class ExecutableStep extends BaseStep {
|
|
|
202
321
|
* add attributes to meta for each purpose (e.g. use `meta.cache` for
|
|
203
322
|
* memoizing results) so that you can expand your usage of meta in future.
|
|
204
323
|
*/
|
|
205
|
-
/* abstract */
|
|
206
|
-
|
|
207
|
-
extra) {
|
|
324
|
+
/* abstract */
|
|
325
|
+
execute(details) {
|
|
208
326
|
// ESLint/TS: ignore not used.
|
|
209
|
-
|
|
210
|
-
values;
|
|
211
|
-
extra;
|
|
327
|
+
details;
|
|
212
328
|
throw new Error(`${this} has not implemented an 'execute' method`);
|
|
213
329
|
}
|
|
214
330
|
destroy() {
|
|
@@ -221,14 +337,14 @@ class ExecutableStep extends BaseStep {
|
|
|
221
337
|
this.optimize = throwDestroyed;
|
|
222
338
|
this.finalize = throwDestroyed;
|
|
223
339
|
this.execute = throwDestroyed;
|
|
224
|
-
super.destroy();
|
|
225
340
|
}
|
|
226
341
|
}
|
|
227
|
-
exports.
|
|
228
|
-
|
|
229
|
-
|
|
342
|
+
exports.Step = Step;
|
|
343
|
+
exports.ExecutableStep = Step;
|
|
344
|
+
function _buildOptimizedExecuteV2Expression(depCount, isSyncAndSafe) {
|
|
345
|
+
const identifiers = [];
|
|
230
346
|
for (let i = 0; i < depCount; i++) {
|
|
231
|
-
|
|
347
|
+
identifiers.push(tamedevil_1.default.identifier(`value${i}`));
|
|
232
348
|
}
|
|
233
349
|
const tryOrNot = (inFrag) => {
|
|
234
350
|
if (isSyncAndSafe) {
|
|
@@ -239,20 +355,21 @@ function _buildOptimizedExecuteExpression(depCount, isSyncAndSafe) {
|
|
|
239
355
|
try {
|
|
240
356
|
${tamedevil_1.default.indent(inFrag)}
|
|
241
357
|
} catch (e) {
|
|
242
|
-
results[i] =
|
|
358
|
+
results[i] = ${ref_flagError}(e);
|
|
243
359
|
}\
|
|
244
360
|
`;
|
|
245
361
|
}
|
|
246
362
|
};
|
|
247
363
|
return (0, tamedevil_1.default) `\
|
|
248
|
-
(function execute(
|
|
249
|
-
|
|
250
|
-
${tamedevil_1.default.join(
|
|
251
|
-
|
|
364
|
+
(function execute({
|
|
365
|
+
count,
|
|
366
|
+
values: [${tamedevil_1.default.join(identifiers, ", ")}],
|
|
367
|
+
extra,
|
|
368
|
+
}) {
|
|
252
369
|
const results = [];
|
|
253
370
|
for (let i = 0; i < count; i++) {
|
|
254
371
|
${tryOrNot((0, tamedevil_1.default) `\
|
|
255
|
-
results[i] = this.unbatchedExecute(extra, ${tamedevil_1.default.join(
|
|
372
|
+
results[i] = this.unbatchedExecute(extra, ${tamedevil_1.default.join(identifiers.map((identifier) => (0, tamedevil_1.default) `${identifier}.at(i)`), ", ")});\
|
|
256
373
|
`)}
|
|
257
374
|
}
|
|
258
375
|
return results;
|
|
@@ -264,11 +381,11 @@ const safeCache = [];
|
|
|
264
381
|
tamedevil_1.default.batch(() => {
|
|
265
382
|
for (let i = 0; i <= MAX_DEPENDENCIES_TO_CACHE; i++) {
|
|
266
383
|
const depCount = i;
|
|
267
|
-
const unsafeExpression =
|
|
384
|
+
const unsafeExpression = _buildOptimizedExecuteV2Expression(depCount, false);
|
|
268
385
|
tamedevil_1.default.runInBatch(unsafeExpression, (fn) => {
|
|
269
386
|
unsafeCache[depCount] = fn;
|
|
270
387
|
});
|
|
271
|
-
const safeExpression =
|
|
388
|
+
const safeExpression = _buildOptimizedExecuteV2Expression(depCount, true);
|
|
272
389
|
tamedevil_1.default.runInBatch(safeExpression, (fn) => {
|
|
273
390
|
safeCache[depCount] = fn;
|
|
274
391
|
});
|
|
@@ -282,115 +399,77 @@ function buildOptimizedExecute(depCount, isSyncAndSafe, callback) {
|
|
|
282
399
|
return;
|
|
283
400
|
}
|
|
284
401
|
// Build it
|
|
285
|
-
const expression =
|
|
402
|
+
const expression = _buildOptimizedExecuteV2Expression(depCount, isSyncAndSafe);
|
|
286
403
|
tamedevil_1.default.runInBatch(expression, (fn) => {
|
|
287
404
|
callback(fn);
|
|
288
405
|
});
|
|
289
406
|
}
|
|
290
|
-
class
|
|
407
|
+
class UnbatchedStep extends Step {
|
|
291
408
|
static { this.$$export = {
|
|
292
409
|
moduleName: "grafast",
|
|
293
|
-
exportName: "
|
|
410
|
+
exportName: "UnbatchedStep",
|
|
294
411
|
}; }
|
|
295
412
|
finalize() {
|
|
296
|
-
|
|
297
|
-
|
|
413
|
+
if (this.execute === UnbatchedStep.prototype.execute) {
|
|
414
|
+
// If they've not replaced 'execute', use our optimized form
|
|
298
415
|
buildOptimizedExecute(this.dependencies.length, this.isSyncAndSafe, (fn) => {
|
|
299
416
|
this.execute = fn;
|
|
300
417
|
});
|
|
301
418
|
}
|
|
302
419
|
super.finalize();
|
|
303
420
|
}
|
|
304
|
-
execute(
|
|
421
|
+
execute({ indexMap, values, extra, }) {
|
|
305
422
|
console.warn(`${this} didn't call 'super.finalize()' in the finalize method.`);
|
|
306
|
-
const
|
|
307
|
-
|
|
423
|
+
const depCount = this.dependencies.length;
|
|
424
|
+
return indexMap((i) => {
|
|
308
425
|
try {
|
|
309
|
-
const tuple =
|
|
310
|
-
|
|
426
|
+
const tuple = [];
|
|
427
|
+
for (let j = 0; j < depCount; j++) {
|
|
428
|
+
tuple[j] = values[j].at(i);
|
|
429
|
+
}
|
|
430
|
+
return this.unbatchedExecute(extra, ...tuple);
|
|
311
431
|
}
|
|
312
432
|
catch (e) {
|
|
313
|
-
|
|
433
|
+
return (0, error_js_1.flagError)(e);
|
|
314
434
|
}
|
|
315
|
-
}
|
|
316
|
-
return results;
|
|
435
|
+
});
|
|
317
436
|
}
|
|
318
437
|
}
|
|
319
|
-
exports.
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
typeof step.execute === "function");
|
|
438
|
+
exports.UnbatchedStep = UnbatchedStep;
|
|
439
|
+
exports.UnbatchedExecutableStep = UnbatchedStep;
|
|
440
|
+
function isStep(step) {
|
|
441
|
+
return step instanceof Step;
|
|
324
442
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
throw new Error(`Expected an executable step, but received something else: ${(0, inspect_js_1.inspect)(step)}`);
|
|
443
|
+
function assertStep(step) {
|
|
444
|
+
if (!isStep(step)) {
|
|
445
|
+
throw new Error(`Expected a step, but received something else: ${(0, inspect_js_1.inspect)(step)}`);
|
|
329
446
|
}
|
|
330
447
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
return (isExecutableStep(step) &&
|
|
334
|
-
typeof step.unbatchedExecute === "function");
|
|
448
|
+
function isUnbatchedStep(step) {
|
|
449
|
+
return isStep(step) && typeof step.unbatchedExecute === "function";
|
|
335
450
|
}
|
|
336
|
-
exports.isUnbatchedExecutableStep = isUnbatchedExecutableStep;
|
|
337
451
|
function isObjectLikeStep(plan) {
|
|
338
452
|
return "get" in plan && typeof plan.get === "function";
|
|
339
453
|
}
|
|
340
|
-
exports.isObjectLikeStep = isObjectLikeStep;
|
|
341
454
|
function isListLikeStep(plan) {
|
|
342
455
|
return "at" in plan && typeof plan.at === "function";
|
|
343
456
|
}
|
|
344
|
-
exports.isListLikeStep = isListLikeStep;
|
|
345
|
-
function isStreamableStep(plan) {
|
|
346
|
-
return typeof plan.stream === "function";
|
|
347
|
-
}
|
|
348
|
-
exports.isStreamableStep = isStreamableStep;
|
|
349
457
|
function isPolymorphicStep(s) {
|
|
350
458
|
return ("planForType" in s &&
|
|
351
459
|
typeof s.planForType === "function");
|
|
352
460
|
}
|
|
353
|
-
exports.isPolymorphicStep = isPolymorphicStep;
|
|
354
|
-
/**
|
|
355
|
-
* Modifier plans modify their parent plan (which may be another ModifierStep
|
|
356
|
-
* or an ExecutableStep). First they gather all the requirements from their
|
|
357
|
-
* children (if any) being applied to them, then they apply themselves to their
|
|
358
|
-
* parent plan. This application is done through the `apply()` method.
|
|
359
|
-
*
|
|
360
|
-
* Modifier plans do not use dependencies.
|
|
361
|
-
*/
|
|
362
|
-
class ModifierStep extends BaseStep {
|
|
363
|
-
constructor($parent) {
|
|
364
|
-
super();
|
|
365
|
-
this.$parent = $parent;
|
|
366
|
-
this.id = this.layerPlan._addModifierStep(this);
|
|
367
|
-
}
|
|
368
|
-
toString() {
|
|
369
|
-
const meta = this.toStringMeta();
|
|
370
|
-
return chalk_1.default.bold.blue(`${this.constructor.name.replace(/Step$/, "")}${meta != null && meta.length ? chalk_1.default.grey(`<${meta}>`) : ""}[${(0, inspect_js_1.inspect)(this.id, {
|
|
371
|
-
colors: true,
|
|
372
|
-
})}]`);
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
exports.ModifierStep = ModifierStep;
|
|
376
|
-
function isModifierStep(plan) {
|
|
377
|
-
return "apply" in plan && typeof plan.apply === "function";
|
|
378
|
-
}
|
|
379
|
-
exports.isModifierStep = isModifierStep;
|
|
380
|
-
function assertModifierStep(plan, pathDescription) {
|
|
381
|
-
if (!isModifierStep(plan)) {
|
|
382
|
-
throw new Error(`The plan returned from '${pathDescription}' should be a modifier plan, but it does not implement the 'apply' method.`);
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
exports.assertModifierStep = assertModifierStep;
|
|
386
461
|
function isListCapableStep(plan) {
|
|
387
462
|
return "listItem" in plan && typeof plan.listItem === "function";
|
|
388
463
|
}
|
|
389
|
-
exports.isListCapableStep = isListCapableStep;
|
|
390
464
|
function assertListCapableStep(plan, pathDescription) {
|
|
391
465
|
if (!isListCapableStep(plan)) {
|
|
392
466
|
throw new Error(`The plan returned from '${pathDescription}' should be a list capable plan, but ${plan} does not implement the 'listItem' method.`);
|
|
393
467
|
}
|
|
394
468
|
}
|
|
395
|
-
|
|
469
|
+
/** @deprecated Use isStep instead */
|
|
470
|
+
exports.isExecutableStep = isStep;
|
|
471
|
+
/** @deprecated Use isStep instead */
|
|
472
|
+
function assertExecutableStep(step) {
|
|
473
|
+
return assertStep(step);
|
|
474
|
+
}
|
|
396
475
|
//# sourceMappingURL=step.js.map
|