grafast 0.1.1-beta.11 → 0.1.1-beta.13
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 +0 -3
- package/dist/args.js +8 -2
- package/dist/constraints.d.ts +15 -1
- package/dist/constraints.js +40 -1
- package/dist/engine/LayerPlan.d.ts +1 -0
- package/dist/engine/LayerPlan.js +62 -9
- package/dist/engine/OperationPlan.js +372 -274
- package/dist/engine/OutputPlan.d.ts +6 -5
- package/dist/engine/OutputPlan.js +423 -444
- package/dist/engine/executeBucket.js +36 -77
- package/dist/error.d.ts +13 -0
- package/dist/grafastGraphql.d.ts +5 -5
- package/dist/graphqlCollectFields.d.ts +6 -0
- package/dist/graphqlCollectFields.js +14 -8
- package/dist/interfaces.d.ts +18 -0
- package/dist/interfaces.js +0 -2
- package/dist/mermaid.js +20 -11
- package/dist/operationPlan-input.js +8 -1
- package/dist/planJSONInterfaces.d.ts +2 -0
- package/dist/prepare.js +3 -3
- package/dist/step.d.ts +5 -5
- package/dist/step.js +53 -2
- package/dist/steps/__flag.d.ts +3 -2
- package/dist/steps/__inputObject.d.ts +1 -0
- package/dist/steps/__inputObject.js +36 -0
- package/dist/steps/__item.d.ts +3 -3
- package/dist/steps/__trackedValue.d.ts +8 -0
- package/dist/steps/__trackedValue.js +40 -0
- package/dist/steps/__value.d.ts +2 -1
- package/dist/steps/constant.d.ts +2 -0
- package/dist/steps/constant.js +12 -0
- package/dist/steps/graphqlResolver.js +8 -5
- package/dist/steps/listen.d.ts +2 -2
- package/dist/steps/object.d.ts +1 -1
- package/dist/steps/sideEffect.d.ts +0 -1
- package/dist/thereCanBeOnlyOne.js +1 -1
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +7 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -11,8 +11,6 @@ const interfaces_js_1 = require("../interfaces.js");
|
|
|
11
11
|
const step_js_1 = require("../step.js");
|
|
12
12
|
const timeSource_js_1 = require("../timeSource.js");
|
|
13
13
|
const utils_js_1 = require("../utils.js");
|
|
14
|
-
/** Path to use when there's no polymorphic paths. */
|
|
15
|
-
const NO_POLY_PATH = "";
|
|
16
14
|
const timeoutError = Object.freeze(new error_js_1.SafeError("Execution timeout exceeded, please simplify or add limits to your request.", Object.freeze({ [interfaces_js_1.$$timeout]: true })));
|
|
17
15
|
function noop() {
|
|
18
16
|
/*noop*/
|
|
@@ -66,7 +64,6 @@ function executeBucket(bucket, requestContext) {
|
|
|
66
64
|
const { middleware } = args;
|
|
67
65
|
const { metaByMetaKey, size, store, layerPlan: { phases, children: childLayerPlans }, } = bucket;
|
|
68
66
|
const phaseCount = phases.length;
|
|
69
|
-
let sideEffectStepsWithErrors = null;
|
|
70
67
|
// Like a `for(i = 0; i < phaseCount; i++)` loop with some `await`s in it, except it does promise
|
|
71
68
|
// handling manually so that it can complete synchronously (no promises) if
|
|
72
69
|
// possible.
|
|
@@ -83,7 +80,6 @@ function executeBucket(bucket, requestContext) {
|
|
|
83
80
|
*/
|
|
84
81
|
let indexesPendingLoopOver = [];
|
|
85
82
|
let executePromises = null;
|
|
86
|
-
let sideEffectSteps = null;
|
|
87
83
|
let executePromiseResultIndex = null;
|
|
88
84
|
const resultList = [];
|
|
89
85
|
if (phase.checkTimeout &&
|
|
@@ -107,14 +103,6 @@ function executeBucket(bucket, requestContext) {
|
|
|
107
103
|
const normalSteps = phase.normalSteps;
|
|
108
104
|
for (let normalStepIndex = 0, l = normalSteps.length; normalStepIndex < l; normalStepIndex++) {
|
|
109
105
|
const step = normalSteps[normalStepIndex].step;
|
|
110
|
-
if (step.hasSideEffects) {
|
|
111
|
-
if (sideEffectSteps === null) {
|
|
112
|
-
sideEffectSteps = [step];
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
sideEffectSteps.push(step);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
106
|
try {
|
|
119
107
|
const r = executeStep(step);
|
|
120
108
|
if ((0, utils_js_1.isPromiseLike)(r)) {
|
|
@@ -144,24 +132,6 @@ function executeBucket(bucket, requestContext) {
|
|
|
144
132
|
}
|
|
145
133
|
}
|
|
146
134
|
}
|
|
147
|
-
const handleSideEffectSteps = () => {
|
|
148
|
-
if (!sideEffectStepsWithErrors) {
|
|
149
|
-
sideEffectStepsWithErrors = bucket.polymorphicPathList.reduce((memo, path) => {
|
|
150
|
-
memo[path ?? NO_POLY_PATH] = [];
|
|
151
|
-
return memo;
|
|
152
|
-
}, Object.create(null));
|
|
153
|
-
}
|
|
154
|
-
for (const step of sideEffectSteps) {
|
|
155
|
-
if (step.polymorphicPaths) {
|
|
156
|
-
for (const path of step.polymorphicPaths) {
|
|
157
|
-
sideEffectStepsWithErrors[path].push(step);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
sideEffectStepsWithErrors[NO_POLY_PATH].push(step);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
135
|
const next = () => {
|
|
166
136
|
return nextPhase(phaseIndex + 1);
|
|
167
137
|
};
|
|
@@ -340,10 +310,6 @@ function executeBucket(bucket, requestContext) {
|
|
|
340
310
|
bucket.setResult(finishedStep, dataIndex, error, interfaces_js_1.FLAG_ERROR);
|
|
341
311
|
}
|
|
342
312
|
}
|
|
343
|
-
if ((bucket.flagUnion & interfaces_js_1.FLAG_ERROR) === interfaces_js_1.FLAG_ERROR &&
|
|
344
|
-
sideEffectSteps) {
|
|
345
|
-
handleSideEffectSteps();
|
|
346
|
-
}
|
|
347
313
|
return promises ? Promise.all(promises) : undefined;
|
|
348
314
|
})
|
|
349
315
|
.then(null, (e) => {
|
|
@@ -359,9 +325,6 @@ function executeBucket(bucket, requestContext) {
|
|
|
359
325
|
});
|
|
360
326
|
}
|
|
361
327
|
else {
|
|
362
|
-
if ((bucket.flagUnion & interfaces_js_1.FLAG_ERROR) === interfaces_js_1.FLAG_ERROR && sideEffectSteps) {
|
|
363
|
-
handleSideEffectSteps();
|
|
364
|
-
}
|
|
365
328
|
return promises ? Promise.all(promises) : undefined;
|
|
366
329
|
}
|
|
367
330
|
};
|
|
@@ -392,18 +355,30 @@ function executeBucket(bucket, requestContext) {
|
|
|
392
355
|
bucket.store.set(step.id, batchExecutionValue((0, utils_js_1.arrayOfLength)(size)));
|
|
393
356
|
}
|
|
394
357
|
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
const
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
358
|
+
for (let dataIndex = 0; dataIndex < size; dataIndex++) {
|
|
359
|
+
stepLoop: for (let allStepsIndex = executedLength; allStepsIndex < allStepsLength; allStepsIndex++) {
|
|
360
|
+
const step = (0, utils_js_1.sudo)(_allSteps[allStepsIndex]);
|
|
361
|
+
// Unary steps only need to be processed once
|
|
362
|
+
if (step._isUnary && dataIndex !== 0) {
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
365
|
+
// Check if the side effect errored
|
|
366
|
+
const $sideEffect = step.implicitSideEffectStep;
|
|
367
|
+
if ($sideEffect) {
|
|
368
|
+
let currentPolymorphicPath;
|
|
369
|
+
if ($sideEffect.polymorphicPaths === null ||
|
|
370
|
+
(currentPolymorphicPath =
|
|
371
|
+
bucket.polymorphicPathList[dataIndex]) === null ||
|
|
372
|
+
$sideEffect.polymorphicPaths.has(currentPolymorphicPath)) {
|
|
373
|
+
const depExecutionValue = bucket.store.get($sideEffect.id);
|
|
374
|
+
if (depExecutionValue === undefined) {
|
|
375
|
+
throw new Error(`GrafastInternalError<fcc8d302-ac66-40e8-aaea-ee2c7e2b30b2>: failed to get result for side effect ${$sideEffect} which impacts ${step}`);
|
|
376
|
+
}
|
|
377
|
+
const depFlags = depExecutionValue._flagsAt(dataIndex);
|
|
378
|
+
if (depFlags & interfaces_js_1.FLAG_POLY_SKIPPED) {
|
|
379
|
+
/* noop */
|
|
380
|
+
}
|
|
381
|
+
else if (depFlags & interfaces_js_1.FLAG_ERROR) {
|
|
407
382
|
if (step._isUnary) {
|
|
408
383
|
// COPY the unary value
|
|
409
384
|
bucket.store.set(step.id, depExecutionValue);
|
|
@@ -413,17 +388,10 @@ function executeBucket(bucket, requestContext) {
|
|
|
413
388
|
const depVal = depExecutionValue.at(dataIndex);
|
|
414
389
|
bucket.setResult(step, dataIndex, depVal, depFlags);
|
|
415
390
|
}
|
|
391
|
+
continue stepLoop;
|
|
416
392
|
}
|
|
417
|
-
continue outerLoop;
|
|
418
393
|
}
|
|
419
394
|
}
|
|
420
|
-
}
|
|
421
|
-
stepLoop: for (let allStepsIndex = executedLength; allStepsIndex < allStepsLength; allStepsIndex++) {
|
|
422
|
-
const step = (0, utils_js_1.sudo)(_allSteps[allStepsIndex]);
|
|
423
|
-
// Unary steps only need to be processed once
|
|
424
|
-
if (step._isUnary && dataIndex !== 0) {
|
|
425
|
-
continue;
|
|
426
|
-
}
|
|
427
395
|
try {
|
|
428
396
|
const deps = [];
|
|
429
397
|
const extra = extras[allStepsIndex];
|
|
@@ -630,7 +598,7 @@ function executeBucket(bucket, requestContext) {
|
|
|
630
598
|
let newSize = 0;
|
|
631
599
|
const stepPolymorphicPaths = step.polymorphicPaths;
|
|
632
600
|
const legitDepsCount = (0, utils_js_1.sudo)(step).dependencies.length;
|
|
633
|
-
let dependencies =
|
|
601
|
+
let dependencies = step.implicitSideEffectStep
|
|
634
602
|
? dependenciesIncludingSideEffects.slice(0, legitDepsCount)
|
|
635
603
|
: dependenciesIncludingSideEffects;
|
|
636
604
|
// OPTIM: if unariesIncludingSideEffects.some(isGrafastError) then shortcut execution because everything fails
|
|
@@ -762,8 +730,11 @@ function executeBucket(bucket, requestContext) {
|
|
|
762
730
|
const dependencies = _rawDependencies;
|
|
763
731
|
let needsFiltering = false;
|
|
764
732
|
const defaultForbiddenFlags = (0, utils_js_1.sudo)(step).defaultForbiddenFlags;
|
|
765
|
-
const addDependency = (
|
|
766
|
-
const executionValue = store.get(
|
|
733
|
+
const addDependency = ($dep, forbiddenFlags, onReject) => {
|
|
734
|
+
const executionValue = store.get($dep.id);
|
|
735
|
+
if (executionValue === undefined) {
|
|
736
|
+
throw new Error(`GrafastInternalError<d9e9eb37-4251-4659-a545-4730826ecf0e>: ${$dep} data couldn't be found, but required by ${step} (with side effect ${step.implicitSideEffectStep})!`);
|
|
737
|
+
}
|
|
767
738
|
_rawDependencies.push(executionValue);
|
|
768
739
|
_rawForbiddenFlags.push(forbiddenFlags);
|
|
769
740
|
_rawOnReject.push(onReject);
|
|
@@ -774,27 +745,15 @@ function executeBucket(bucket, requestContext) {
|
|
|
774
745
|
};
|
|
775
746
|
const sstep = (0, utils_js_1.sudo)(step);
|
|
776
747
|
const depCount = sstep.dependencies.length;
|
|
777
|
-
if (depCount > 0
|
|
748
|
+
if (depCount > 0) {
|
|
778
749
|
for (let i = 0, l = depCount; i < l; i++) {
|
|
779
750
|
const $dep = sstep.dependencies[i];
|
|
780
751
|
addDependency($dep, sstep.dependencyForbiddenFlags[i], sstep.dependencyOnReject[i]);
|
|
781
752
|
}
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
// TODO: revisit this, feels like we might be adding the same
|
|
787
|
-
// effect multiple times if it matches multiple paths.
|
|
788
|
-
addDependency(sideEffectStep, defaultForbiddenFlags, undefined);
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
else {
|
|
793
|
-
for (const sideEffectStep of sideEffectStepsWithErrors[NO_POLY_PATH]) {
|
|
794
|
-
addDependency(sideEffectStep, defaultForbiddenFlags, undefined);
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
}
|
|
753
|
+
}
|
|
754
|
+
const $sideEffect = step.implicitSideEffectStep;
|
|
755
|
+
if ($sideEffect) {
|
|
756
|
+
addDependency($sideEffect, defaultForbiddenFlags, undefined);
|
|
798
757
|
}
|
|
799
758
|
if (dev_js_1.isDev &&
|
|
800
759
|
step.layerPlan.reason.type === "polymorphic" &&
|
package/dist/error.d.ts
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
|
+
import type { ExecutionEntryFlags } from "./interfaces.js";
|
|
1
2
|
import { $$safeError } from "./interfaces.js";
|
|
3
|
+
declare const $$flagged: unique symbol;
|
|
4
|
+
/**
|
|
5
|
+
* Wrapper for errors to return (rather than throw or reject) from user code.
|
|
6
|
+
*/
|
|
7
|
+
export interface FlaggedValue<TValue = any> {
|
|
8
|
+
[$$flagged]: true;
|
|
9
|
+
flags: ExecutionEntryFlags;
|
|
10
|
+
value: TValue;
|
|
11
|
+
planId: number | null;
|
|
12
|
+
toString(): string;
|
|
13
|
+
}
|
|
2
14
|
export declare const $$inhibit: FlaggedValue<null>;
|
|
3
15
|
/**
|
|
4
16
|
* Used to wrap error values to have Grafast treat them as if they were
|
|
@@ -15,4 +27,5 @@ export declare class SafeError<TExtensions extends Record<string, any> | undefin
|
|
|
15
27
|
constructor(message: string, extensions?: TExtensions, errorOptions?: ErrorOptions);
|
|
16
28
|
}
|
|
17
29
|
export declare function isSafeError(error: Error): error is SafeError;
|
|
30
|
+
export {};
|
|
18
31
|
//# sourceMappingURL=error.d.ts.map
|
package/dist/grafastGraphql.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import type { AsyncExecutionResult, ExecutionResult } from "graphql";
|
|
2
2
|
import type { PromiseOrValue } from "graphql/jsutils/PromiseOrValue";
|
|
3
3
|
import type { GrafastArgs } from "./interfaces.js";
|
|
4
|
-
/**
|
|
5
|
-
* @deprecated Second and third parameters should be passed as part of args,
|
|
6
|
-
* specifically `resolvedPreset` and `requestContext`.
|
|
7
|
-
*/
|
|
8
|
-
export declare function grafast(args: GrafastArgs, legacyResolvedPreset?: GraphileConfig.ResolvedPreset, legacyCtx?: Partial<Grafast.RequestContext>): PromiseOrValue<ExecutionResult | AsyncGenerator<AsyncExecutionResult, void, undefined>>;
|
|
9
4
|
/**
|
|
10
5
|
* A replacement for GraphQL.js' `graphql` method that calls Grafast's
|
|
11
6
|
* execute instead
|
|
12
7
|
*/
|
|
13
8
|
export declare function grafast(args: GrafastArgs): PromiseOrValue<ExecutionResult | AsyncGenerator<AsyncExecutionResult, void, undefined>>;
|
|
9
|
+
/**
|
|
10
|
+
* @deprecated Second and third parameters should be passed as part of args,
|
|
11
|
+
* specifically `resolvedPreset` and `requestContext`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function grafast(args: GrafastArgs, legacyResolvedPreset?: GraphileConfig.ResolvedPreset | undefined, legacyCtx?: Partial<Grafast.RequestContext> | undefined): PromiseOrValue<ExecutionResult | AsyncGenerator<AsyncExecutionResult, void, undefined>>;
|
|
14
14
|
export declare function grafastSync(args: GrafastArgs, legacyResolvedPreset?: GraphileConfig.ResolvedPreset, legacyRequestContext?: Partial<Grafast.RequestContext>): ExecutionResult;
|
|
15
15
|
//# sourceMappingURL=grafastGraphql.d.ts.map
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type { DirectiveNode } from "graphql";
|
|
2
2
|
import type { __TrackedValueStep } from "./steps/index.js";
|
|
3
3
|
export declare function evalDirectiveArgDirect<T = unknown>(directive: DirectiveNode, argumentName: string, variableValuesStep: __TrackedValueStep, defaultValue: T): T | undefined;
|
|
4
|
+
export declare function newSelectionSetDigest(resolverEmulation: boolean): {
|
|
5
|
+
label: undefined;
|
|
6
|
+
fields: Map<any, any>;
|
|
7
|
+
deferred: undefined;
|
|
8
|
+
resolverEmulation: boolean;
|
|
9
|
+
};
|
|
4
10
|
//# sourceMappingURL=graphqlCollectFields.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.graphqlCollectFields = exports.evalDirectiveArgDirect = exports.evalDirectiveArg = void 0;
|
|
3
|
+
exports.graphqlCollectFields = exports.newSelectionSetDigest = exports.evalDirectiveArgDirect = exports.evalDirectiveArg = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const graphql = tslib_1.__importStar(require("graphql"));
|
|
6
6
|
const error_js_1 = require("./error.js");
|
|
@@ -100,6 +100,7 @@ const processFragment = (operationPlan, parentStepId, objectType, isMutation, se
|
|
|
100
100
|
label,
|
|
101
101
|
fields: new Map(),
|
|
102
102
|
deferred: undefined,
|
|
103
|
+
resolverEmulation: selectionSetDigest.resolverEmulation,
|
|
103
104
|
}
|
|
104
105
|
: null;
|
|
105
106
|
if (deferredDigest !== null) {
|
|
@@ -110,8 +111,17 @@ const processFragment = (operationPlan, parentStepId, objectType, isMutation, se
|
|
|
110
111
|
selectionSetDigest.deferred.push(deferredDigest);
|
|
111
112
|
}
|
|
112
113
|
}
|
|
113
|
-
graphqlCollectFields(operationPlan, parentStepId, objectType, fragmentSelectionSet.selections,
|
|
114
|
+
graphqlCollectFields(operationPlan, parentStepId, objectType, fragmentSelectionSet.selections, deferredDigest ?? selectionSetDigest, isMutation, visitedFragments);
|
|
114
115
|
};
|
|
116
|
+
function newSelectionSetDigest(resolverEmulation) {
|
|
117
|
+
return {
|
|
118
|
+
label: undefined,
|
|
119
|
+
fields: new Map(),
|
|
120
|
+
deferred: undefined,
|
|
121
|
+
resolverEmulation,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
exports.newSelectionSetDigest = newSelectionSetDigest;
|
|
115
125
|
/**
|
|
116
126
|
* Implements the `GraphQLCollectFields` algorithm - like `CollectFields` the
|
|
117
127
|
* GraphQL spec, but modified such that access to variables is tracked.
|
|
@@ -120,13 +130,9 @@ const processFragment = (operationPlan, parentStepId, objectType, isMutation, se
|
|
|
120
130
|
*
|
|
121
131
|
* @internal
|
|
122
132
|
*/
|
|
123
|
-
function graphqlCollectFields(operationPlan, parentStepId, objectType, selections, isMutation = false,
|
|
133
|
+
function graphqlCollectFields(operationPlan, parentStepId, objectType, selections, selectionSetDigest, isMutation = false,
|
|
124
134
|
// This is significantly faster than an array or a Set
|
|
125
|
-
visitedFragments = Object.create(null)
|
|
126
|
-
label: undefined,
|
|
127
|
-
fields: new Map(),
|
|
128
|
-
deferred: undefined,
|
|
129
|
-
}) {
|
|
135
|
+
visitedFragments = Object.create(null)) {
|
|
130
136
|
// const objectTypeFields = objectType.getFields();
|
|
131
137
|
const trackedVariableValuesStep = operationPlan.trackedVariableValuesStep;
|
|
132
138
|
for (let i = 0, l = selections.length; i < l; i++) {
|
package/dist/interfaces.d.ts
CHANGED
|
@@ -83,6 +83,10 @@ export declare const $$data: unique symbol;
|
|
|
83
83
|
* example details of the plan or SQL queries or similar that were executed.
|
|
84
84
|
*/
|
|
85
85
|
export declare const $$extensions: unique symbol;
|
|
86
|
+
/**
|
|
87
|
+
* The "GraphQLObjectType" type name, useful when dealing with polymorphism.
|
|
88
|
+
*/
|
|
89
|
+
export declare const $$concreteType: unique symbol;
|
|
86
90
|
/**
|
|
87
91
|
* Set this key on a type if that type's serialization is idempotent (that is
|
|
88
92
|
* to say `serialize(serialize(thing)) === serialize(thing)`). This means we
|
|
@@ -399,6 +403,20 @@ export interface ExecutionExtra extends ExecutionExtraBase {
|
|
|
399
403
|
}
|
|
400
404
|
export interface UnbatchedExecutionExtra extends ExecutionExtraBase {
|
|
401
405
|
}
|
|
406
|
+
/**
|
|
407
|
+
* A bitwise number representing a number of flags:
|
|
408
|
+
*
|
|
409
|
+
* - 0: normal execution value
|
|
410
|
+
* - 1: errored (trappable)
|
|
411
|
+
* - 2: null (trappable)
|
|
412
|
+
* - 4: inhibited (trappable)
|
|
413
|
+
* - 8: disabled due to polymorphism (untrappable)
|
|
414
|
+
* - 16: stopped (untrappable) - e.g. due to fatal (unrecoverable) error
|
|
415
|
+
* - 32: ...
|
|
416
|
+
*/
|
|
417
|
+
export type ExecutionEntryFlags = number & {
|
|
418
|
+
readonly tsBrand?: unique symbol;
|
|
419
|
+
};
|
|
402
420
|
export declare const NO_FLAGS: ExecutionEntryFlags;
|
|
403
421
|
export declare const FLAG_ERROR: ExecutionEntryFlags;
|
|
404
422
|
export declare const FLAG_NULL: ExecutionEntryFlags;
|
package/dist/interfaces.js
CHANGED
package/dist/mermaid.js
CHANGED
|
@@ -137,7 +137,7 @@ concise = false, skipBuckets = global.grafastExplainMermaidSkipBuckets ?? false,
|
|
|
137
137
|
pp(stepById[plan.dependencyIds[0]].polymorphicPaths) === polyPaths
|
|
138
138
|
? ""
|
|
139
139
|
: `\n${polyPaths}`;
|
|
140
|
-
const planString = `${planName}[${plan.id}${`∈${plan.bucketId}`}]${meta ? `\n<${meta}>` : ""}${polyPathsIfDifferent}`;
|
|
140
|
+
const planString = `${planName}[${plan.id}${`∈${plan.bucketId}`}]${plan.isUnary ? " ➊" : ""}${meta ? `\n<${meta}>` : ""}${polyPathsIfDifferent}`;
|
|
141
141
|
const [lBrace, rBrace] = plan.stepClass === "__ItemStep"
|
|
142
142
|
? ["[/", "\\]"]
|
|
143
143
|
: plan.isSyncAndSafe
|
|
@@ -267,6 +267,18 @@ concise = false, skipBuckets = global.grafastExplainMermaidSkipBuckets ?? false,
|
|
|
267
267
|
const stepToString = (step) => {
|
|
268
268
|
return `${step.stepClass.replace(/Step$/, "")}${step.bucketId === 0 ? "" : `{${step.bucketId}}`}${step.metaString ? `<${step.metaString}>` : ""}[${step.id}]`;
|
|
269
269
|
};
|
|
270
|
+
let firstSideEffect = true;
|
|
271
|
+
sortedSteps.forEach((step) => {
|
|
272
|
+
if (step.implicitSideEffectStepId) {
|
|
273
|
+
if (firstSideEffect) {
|
|
274
|
+
graph.push("");
|
|
275
|
+
graph.push(" %% implicit side effects");
|
|
276
|
+
firstSideEffect = false;
|
|
277
|
+
}
|
|
278
|
+
const sideEffectStep = stepById[step.implicitSideEffectStepId];
|
|
279
|
+
graph.push(` ${planId(sideEffectStep)} -.-o ${planId(step)}`);
|
|
280
|
+
}
|
|
281
|
+
});
|
|
270
282
|
graph.push("");
|
|
271
283
|
if (!concise && !skipBuckets)
|
|
272
284
|
graph.push(" subgraph Buckets");
|
|
@@ -278,17 +290,18 @@ concise = false, skipBuckets = global.grafastExplainMermaidSkipBuckets ?? false,
|
|
|
278
290
|
(layerPlan.reason.type === "polymorphic"
|
|
279
291
|
? `\n${layerPlan.reason.typeNames}`
|
|
280
292
|
: ``);
|
|
281
|
-
const outputMapStuff = [];
|
|
282
293
|
if (!skipBuckets) {
|
|
283
|
-
graph.push(` Bucket${layerPlan.id}(${(0, exports.mermaidEscape)(`Bucket ${layerPlan.id}${raisonDEtre}${layerPlan.
|
|
294
|
+
graph.push(` Bucket${layerPlan.id}(${(0, exports.mermaidEscape)(`Bucket ${layerPlan.id}${raisonDEtre}${layerPlan.parentSideEffectStepId != null
|
|
295
|
+
? `\nParent side effect step: ${stepById[layerPlan.parentSideEffectStepId].id}`
|
|
296
|
+
: ""}${layerPlan.copyStepIds.length > 0
|
|
284
297
|
? `\nDeps: ${layerPlan.copyStepIds
|
|
285
298
|
.map((pId) => stepById[pId].id)
|
|
286
|
-
.join(", ")}
|
|
299
|
+
.join(", ")}`
|
|
287
300
|
: ""}${layerPlan.reason.type === "polymorphic"
|
|
288
|
-
? pp(layerPlan.reason.polymorphicPaths)
|
|
289
|
-
: ""}${layerPlan.rootStepId != null && layerPlan.reason.type !== "root"
|
|
301
|
+
? "\n" + pp(layerPlan.reason.polymorphicPaths)
|
|
302
|
+
: ""}\n${layerPlan.rootStepId != null && layerPlan.reason.type !== "root"
|
|
290
303
|
? `\nROOT ${stepToString(stepById[layerPlan.rootStepId])}`
|
|
291
|
-
: ""}${startSteps(layerPlan)}
|
|
304
|
+
: ""}${startSteps(layerPlan)}`)}):::bucket`);
|
|
292
305
|
}
|
|
293
306
|
graph.push(` classDef bucket${layerPlan.id} stroke:${color(layerPlan.id)}`);
|
|
294
307
|
graph.push(` class ${[`Bucket${layerPlan.id}`, ...steps.map(planId)].join(",")} bucket${layerPlan.id}`);
|
|
@@ -302,10 +315,6 @@ concise = false, skipBuckets = global.grafastExplainMermaidSkipBuckets ?? false,
|
|
|
302
315
|
}
|
|
303
316
|
}
|
|
304
317
|
}
|
|
305
|
-
const isUnary = (step) => step.isUnary;
|
|
306
|
-
graph.push(`\
|
|
307
|
-
classDef unary fill:#fafffa,borderWidth:8px
|
|
308
|
-
class ${sortedSteps.filter(isUnary).map(planId)} unary`);
|
|
309
318
|
if (!concise && !skipBuckets)
|
|
310
319
|
graph.push(" end");
|
|
311
320
|
const graphString = graph.join("\n");
|
|
@@ -310,7 +310,14 @@ function withFieldArgsForArguments(operationPlan, $parent, $all, field, applyAft
|
|
|
310
310
|
if (mode === "apply" &&
|
|
311
311
|
(!subpath || (Array.isArray(subpath) && subpath.length === 0))) {
|
|
312
312
|
if (isInputObjectType(nullableEntityType)) {
|
|
313
|
-
|
|
313
|
+
if (!("evalKeys" in $input)) {
|
|
314
|
+
throw new Error(`GrafastInternalError<d782160e-7a99-4a12-b690-435c1ab7b676>: Expected ${$input} to be a __InputObjectStep or __TrackedValueStep (i.e. to have 'evalKeys')`);
|
|
315
|
+
}
|
|
316
|
+
const keys = $input.evalKeys();
|
|
317
|
+
if (keys == null) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
for (const fieldName of keys) {
|
|
314
321
|
const $target = typeof targetStepOrCallback === "function"
|
|
315
322
|
? targetStepOrCallback()
|
|
316
323
|
: targetStepOrCallback;
|
|
@@ -8,6 +8,7 @@ export interface GrafastPlanStepJSONv1 {
|
|
|
8
8
|
metaString: string | null;
|
|
9
9
|
isUnary: boolean;
|
|
10
10
|
bucketId: string | number;
|
|
11
|
+
implicitSideEffectStepId: string | number | null;
|
|
11
12
|
dependencyIds: ReadonlyArray<string | number>;
|
|
12
13
|
dependencyForbiddenFlags: ReadonlyArray<ExecutionEntryFlags>;
|
|
13
14
|
dependencyOnReject: ReadonlyArray<string | null | undefined>;
|
|
@@ -69,6 +70,7 @@ export interface GrafastPlanBucketReasonSubroutineJSONv1 {
|
|
|
69
70
|
export interface GrafastPlanBucketJSONv1 {
|
|
70
71
|
id: number;
|
|
71
72
|
reason: GrafastPlanBucketReasonJSONv1;
|
|
73
|
+
parentSideEffectStepId: string | number | null;
|
|
72
74
|
copyStepIds: ReadonlyArray<string | number>;
|
|
73
75
|
steps: ReadonlyArray<GrafastPlanStepJSONv1>;
|
|
74
76
|
rootStepId: string | number | null;
|
package/dist/prepare.js
CHANGED
|
@@ -152,7 +152,7 @@ function outputBucket(outputPlan, rootBucket, rootBucketIndex, requestContext, p
|
|
|
152
152
|
childBucketIndex = rootBucketIndex;
|
|
153
153
|
}
|
|
154
154
|
else {
|
|
155
|
-
const c = (0, OutputPlan_js_1.getChildBucketAndIndex)(outputPlan, null, rootBucket, rootBucketIndex, null);
|
|
155
|
+
const c = (0, OutputPlan_js_1.getChildBucketAndIndex)(outputPlan.layerPlan, null, rootBucket, rootBucketIndex, null);
|
|
156
156
|
if (!c) {
|
|
157
157
|
throw new Error(`GrafastInternalError<8bbf56c1-8e2a-4ee9-b5fc-724fd0ee222b>: could not find relevant bucket for output plan`);
|
|
158
158
|
}
|
|
@@ -250,11 +250,11 @@ function executePreemptive(args, operationPlan, variableValues, context, rootVal
|
|
|
250
250
|
releaseUnusedIterators(rootBucket, rootBucketIndex, null);
|
|
251
251
|
// Something major went wrong!
|
|
252
252
|
const errors = [
|
|
253
|
-
new GraphQLError(bucketRootValue.
|
|
253
|
+
new GraphQLError(bucketRootValue.message, operationPlan.rootOutputPlan.locationDetails.node, // node
|
|
254
254
|
undefined, // source
|
|
255
255
|
null, // positions
|
|
256
256
|
null, // path
|
|
257
|
-
bucketRootValue
|
|
257
|
+
bucketRootValue, // originalError
|
|
258
258
|
null),
|
|
259
259
|
];
|
|
260
260
|
const payload = Object.create(null);
|
package/dist/step.d.ts
CHANGED
|
@@ -27,11 +27,6 @@ export declare abstract class BaseStep {
|
|
|
27
27
|
isArgumentsFinalized: boolean;
|
|
28
28
|
isFinalized: boolean;
|
|
29
29
|
debug: boolean;
|
|
30
|
-
/**
|
|
31
|
-
* Set this true for plans that implement mutations; this will prevent them
|
|
32
|
-
* from being tree-shaken.
|
|
33
|
-
*/
|
|
34
|
-
hasSideEffects: boolean;
|
|
35
30
|
constructor();
|
|
36
31
|
toString(): string;
|
|
37
32
|
/**
|
|
@@ -113,6 +108,11 @@ export declare class ExecutableStep<TData = any> extends BaseStep {
|
|
|
113
108
|
* Like `metaKey` but for the optimize phase
|
|
114
109
|
*/
|
|
115
110
|
optimizeMetaKey: number | string | symbol | undefined;
|
|
111
|
+
/**
|
|
112
|
+
* Set this true for plans that implement mutations; this will prevent them
|
|
113
|
+
* from being tree-shaken.
|
|
114
|
+
*/
|
|
115
|
+
hasSideEffects: boolean;
|
|
116
116
|
constructor();
|
|
117
117
|
protected withMyLayerPlan<T>(callback: () => T): T;
|
|
118
118
|
protected getStep(id: number): ExecutableStep;
|
package/dist/step.js
CHANGED
|
@@ -63,7 +63,6 @@ class BaseStep {
|
|
|
63
63
|
this.isArgumentsFinalized = false;
|
|
64
64
|
this.isFinalized = false;
|
|
65
65
|
this.debug = (0, global_js_1.getDebug)();
|
|
66
|
-
this.hasSideEffects = false;
|
|
67
66
|
const layerPlan = (0, withGlobalLayerPlan_js_1.currentLayerPlan)();
|
|
68
67
|
this.layerPlan = layerPlan;
|
|
69
68
|
this.operationPlan = layerPlan.operationPlan;
|
|
@@ -108,6 +107,57 @@ class ExecutableStep extends BaseStep {
|
|
|
108
107
|
* (default = ALL_FLAGS & ~FLAG_NULL)
|
|
109
108
|
*/
|
|
110
109
|
this.defaultForbiddenFlags = interfaces_js_1.DEFAULT_FORBIDDEN_FLAGS;
|
|
110
|
+
this.implicitSideEffectStep = null;
|
|
111
|
+
this.hasSideEffects ??= false;
|
|
112
|
+
let hasSideEffects = false;
|
|
113
|
+
const stepTracker = this.layerPlan.operationPlan.stepTracker;
|
|
114
|
+
Object.defineProperty(this, "hasSideEffects", {
|
|
115
|
+
get() {
|
|
116
|
+
return hasSideEffects;
|
|
117
|
+
},
|
|
118
|
+
set(value) {
|
|
119
|
+
/**
|
|
120
|
+
* If steps were created after this step, an this step doesn't depend
|
|
121
|
+
* on them, then it's no longer safe to change hasSideEffects.
|
|
122
|
+
*/
|
|
123
|
+
let nonDependentSteps = null;
|
|
124
|
+
const maxStepId = stepTracker.stepCount - 1;
|
|
125
|
+
if (this.id === maxStepId) {
|
|
126
|
+
// All good - no more steps were created
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// If the step created them during initialization and is dependent on
|
|
130
|
+
// them, that's fine too.
|
|
131
|
+
for (let id = this.id + 1; id <= maxStepId; id++) {
|
|
132
|
+
const step = stepTracker.getStepById(id);
|
|
133
|
+
if ((0, utils_js_1.stepADependsOnStepB)(this, step))
|
|
134
|
+
continue;
|
|
135
|
+
if (nonDependentSteps === null) {
|
|
136
|
+
nonDependentSteps = [step];
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
nonDependentSteps.push(step);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (nonDependentSteps === null) {
|
|
144
|
+
hasSideEffects = value;
|
|
145
|
+
if (value === true) {
|
|
146
|
+
this.layerPlan.latestSideEffectStep = this;
|
|
147
|
+
}
|
|
148
|
+
else if (value !== true && hasSideEffects === true) {
|
|
149
|
+
throw new Error(`Cannot mark ${this} as having no side effects after having set it to have side effects.`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
throw new Error(`Attempted to mark ${this} as having side effects, but other non-dependent steps (${nonDependentSteps
|
|
154
|
+
.map(String)
|
|
155
|
+
.join(", ")}) have already been created.`);
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
enumerable: true,
|
|
159
|
+
configurable: false,
|
|
160
|
+
});
|
|
111
161
|
this.dependencies = [];
|
|
112
162
|
this.dependencyForbiddenFlags = [];
|
|
113
163
|
this.dependencyOnReject = [];
|
|
@@ -117,6 +167,7 @@ class ExecutableStep extends BaseStep {
|
|
|
117
167
|
this._stepOptions = { stream: null };
|
|
118
168
|
this.store = true;
|
|
119
169
|
this.polymorphicPaths = (0, withGlobalLayerPlan_js_1.currentPolymorphicPaths)();
|
|
170
|
+
// Important: MUST come after `this.layerPlan = ...`
|
|
120
171
|
this.id = this.layerPlan._addStep(this);
|
|
121
172
|
}
|
|
122
173
|
withMyLayerPlan(callback) {
|
|
@@ -163,7 +214,7 @@ class ExecutableStep extends BaseStep {
|
|
|
163
214
|
catch (e) {
|
|
164
215
|
// Ignore
|
|
165
216
|
}
|
|
166
|
-
return chalk_1.default.bold.blue(`${this.constructor.name.replace(/Step$/, "")}${this.layerPlan.id === 0 ? "" : chalk_1.default.grey(`{${this.layerPlan.id}}`)}${meta != null && meta.length ? chalk_1.default.grey(`<${meta}>`) : ""}[${(0, inspect_js_1.inspect)(this.id, {
|
|
217
|
+
return chalk_1.default.bold.blue(`${this.constructor.name.replace(/Step$/, "")}${this.layerPlan.id === 0 ? "" : chalk_1.default.grey(`{${this.layerPlan.id}}`)}${this._isUnary ? "➊" : ""}${meta != null && meta.length ? chalk_1.default.grey(`<${meta}>`) : ""}[${(0, inspect_js_1.inspect)(this.id, {
|
|
167
218
|
colors: true,
|
|
168
219
|
})}]`);
|
|
169
220
|
}
|
package/dist/steps/__flag.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ExecutionDetails, ExecutionEntryFlags, GrafastResultsList } from "../interfaces.js";
|
|
2
2
|
import { $$deepDepSkip } from "../interfaces.js";
|
|
3
|
+
import type { ListCapableStep } from "../step.js";
|
|
3
4
|
import { ExecutableStep } from "../step.js";
|
|
4
5
|
import type { __ItemStep } from "./__item.js";
|
|
5
6
|
export declare const TRAP_ERROR: ExecutionEntryFlags;
|
|
@@ -32,8 +33,8 @@ export declare class __FlagStep<TData> extends ExecutableStep<TData> {
|
|
|
32
33
|
constructor(step: ExecutableStep, options: FlagStepOptions);
|
|
33
34
|
toStringMeta(): string | null;
|
|
34
35
|
[$$deepDepSkip](): ExecutableStep;
|
|
35
|
-
listItem?: ($item: __ItemStep<
|
|
36
|
-
_listItem($item: __ItemStep<
|
|
36
|
+
listItem?: ($item: __ItemStep<ListCapableStep<unknown, ExecutableStep<unknown>>>) => ExecutableStep;
|
|
37
|
+
_listItem($item: __ItemStep<ListCapableStep<unknown, ExecutableStep<unknown>>>): ExecutableStep<unknown>;
|
|
37
38
|
deduplicate(_peers: readonly ExecutableStep<any>[]): readonly ExecutableStep<any>[];
|
|
38
39
|
execute(_details: ExecutionDetails<[data: TData, cond?: boolean]>): GrafastResultsList<TData>;
|
|
39
40
|
finalize(): void;
|
|
@@ -22,6 +22,7 @@ export declare class __InputObjectStep<TInputType extends GraphQLInputObjectType
|
|
|
22
22
|
evalIs(value: null | undefined | 0): boolean;
|
|
23
23
|
evalIsEmpty(): boolean;
|
|
24
24
|
evalHas(attrName: string): boolean;
|
|
25
|
+
evalKeys(): ReadonlyArray<keyof TInputType & string> | null;
|
|
25
26
|
}
|
|
26
27
|
export type __InputObjectStepWithDollars<TInputType extends GraphQLInputObjectType = GraphQLInputObjectType> = __InputObjectStep<TInputType> & {
|
|
27
28
|
[key in keyof ReturnType<TInputType["getFields"]> & string as `$${key}`]: InputStep<ReturnType<TInputType["getFields"]>[key]["type"]>;
|