grafast 0.1.1-beta.21 → 0.1.1-beta.22

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.
Files changed (94) hide show
  1. package/README.md +0 -4
  2. package/dist/args.js +3 -3
  3. package/dist/constants.d.ts +79 -0
  4. package/dist/constants.js +79 -0
  5. package/dist/engine/LayerPlan.d.ts +71 -8
  6. package/dist/engine/LayerPlan.js +375 -265
  7. package/dist/engine/OperationPlan.d.ts +77 -14
  8. package/dist/engine/OperationPlan.js +1508 -382
  9. package/dist/engine/OperationPlanTypes.d.ts +66 -0
  10. package/dist/engine/OperationPlanTypes.js +3 -0
  11. package/dist/engine/OutputPlan.d.ts +6 -0
  12. package/dist/engine/OutputPlan.js +138 -82
  13. package/dist/engine/StepTracker.js +76 -17
  14. package/dist/engine/executeBucket.js +327 -166
  15. package/dist/engine/lib/defaultPlanResolver.d.ts +1 -4
  16. package/dist/engine/lib/defaultPlanResolver.js +1 -5
  17. package/dist/engine/lib/withGlobalLayerPlan.d.ts +3 -1
  18. package/dist/engine/lib/withGlobalLayerPlan.js +19 -1
  19. package/dist/envelop.js +14 -3
  20. package/dist/error.d.ts +1 -1
  21. package/dist/error.js +9 -9
  22. package/dist/establishOperationPlan.d.ts +2 -1
  23. package/dist/establishOperationPlan.js +10 -10
  24. package/dist/execute.js +7 -5
  25. package/dist/global.d.ts +10 -0
  26. package/dist/global.js +25 -0
  27. package/dist/grafastGraphql.js +4 -3
  28. package/dist/grafastPrint.js +36 -4
  29. package/dist/index.d.ts +76 -8
  30. package/dist/index.js +37 -33
  31. package/dist/input.js +20 -1
  32. package/dist/inspect.js +1 -0
  33. package/dist/interfaces.d.ts +80 -122
  34. package/dist/interfaces.js +0 -77
  35. package/dist/makeGrafastSchema.d.ts +118 -35
  36. package/dist/makeGrafastSchema.js +197 -29
  37. package/dist/mermaid.js +198 -97
  38. package/dist/operationPlan-input.d.ts +1 -1
  39. package/dist/operationPlan-input.js +15 -5
  40. package/dist/planJSONInterfaces.d.ts +24 -5
  41. package/dist/prepare.d.ts +16 -9
  42. package/dist/prepare.js +54 -51
  43. package/dist/step.d.ts +45 -9
  44. package/dist/step.js +139 -22
  45. package/dist/steps/__flag.d.ts +3 -2
  46. package/dist/steps/__flag.js +31 -29
  47. package/dist/steps/__inputObject.d.ts +1 -1
  48. package/dist/steps/__inputStaticLeaf.d.ts +3 -2
  49. package/dist/steps/__inputStaticLeaf.js +13 -7
  50. package/dist/steps/__item.d.ts +1 -1
  51. package/dist/steps/__item.js +3 -3
  52. package/dist/steps/__trackedValue.d.ts +6 -3
  53. package/dist/steps/__trackedValue.js +25 -9
  54. package/dist/steps/__value.d.ts +2 -1
  55. package/dist/steps/__value.js +5 -0
  56. package/dist/steps/access.d.ts +17 -1
  57. package/dist/steps/access.js +14 -1
  58. package/dist/steps/applyInput.d.ts +1 -1
  59. package/dist/steps/applyInput.js +7 -6
  60. package/dist/steps/applyTransforms.js +9 -7
  61. package/dist/steps/bakedInput.js +2 -2
  62. package/dist/steps/coalesce.d.ts +15 -0
  63. package/dist/steps/coalesce.js +36 -0
  64. package/dist/steps/constant.js +16 -14
  65. package/dist/steps/each.d.ts +2 -2
  66. package/dist/steps/first.d.ts +2 -0
  67. package/dist/steps/first.js +5 -1
  68. package/dist/steps/graphqlResolver.d.ts +2 -2
  69. package/dist/steps/graphqlResolver.js +63 -161
  70. package/dist/steps/index.d.ts +3 -15
  71. package/dist/steps/index.js +6 -41
  72. package/dist/steps/lambda.js +1 -1
  73. package/dist/steps/last.d.ts +2 -0
  74. package/dist/steps/last.js +4 -0
  75. package/dist/steps/listTransform.d.ts +2 -2
  76. package/dist/steps/listTransform.js +11 -13
  77. package/dist/steps/load.d.ts +28 -22
  78. package/dist/steps/load.js +47 -1
  79. package/dist/steps/node.d.ts +10 -7
  80. package/dist/steps/node.js +5 -19
  81. package/dist/steps/object.js +6 -1
  82. package/dist/steps/proxy.d.ts +0 -6
  83. package/dist/steps/proxy.js +3 -3
  84. package/dist/steps/remapKeys.d.ts +1 -1
  85. package/dist/steps/remapKeys.js +0 -1
  86. package/dist/utils.d.ts +27 -5
  87. package/dist/utils.js +235 -15
  88. package/dist/version.d.ts +1 -1
  89. package/dist/version.js +1 -1
  90. package/package.json +6 -6
  91. package/dist/polymorphic.d.ts +0 -14
  92. package/dist/polymorphic.js +0 -72
  93. package/dist/steps/polymorphicBranch.d.ts +0 -27
  94. package/dist/steps/polymorphicBranch.js +0 -62
@@ -0,0 +1,66 @@
1
+ import type { FieldNode, GraphQLFieldMap, GraphQLInterfaceType, GraphQLList, GraphQLObjectType, GraphQLOutputType, GraphQLUnionType, SelectionNode } from "graphql";
2
+ import type { SelectionSetDigest } from "../graphqlCollectFields";
3
+ import type { LocationDetails, Maybe } from "../interfaces";
4
+ import type { Step } from "../step";
5
+ import type { LayerPlan, LayerPlanReasonListItemStream } from "./LayerPlan";
6
+ import type { OutputPlan } from "./OutputPlan";
7
+ export type StreamDetails = {
8
+ if: Step<boolean>;
9
+ initialCount: Step<number>;
10
+ label: Step<Maybe<string>>;
11
+ };
12
+ export interface CommonPlanningDetails<TType extends GraphQLOutputType | GraphQLInterfaceType | GraphQLUnionType = GraphQLOutputType> {
13
+ outputPlan: OutputPlan;
14
+ path: readonly string[];
15
+ planningPath: string;
16
+ polymorphicPaths: ReadonlySet<string> | null;
17
+ parentStep: Step;
18
+ positionType: TType;
19
+ layerPlan: LayerPlan;
20
+ }
21
+ export interface PlanIntoOutputPlanDetails extends CommonPlanningDetails<GraphQLOutputType> {
22
+ resolverEmulation: boolean;
23
+ selections: readonly SelectionNode[] | undefined;
24
+ parentObjectType: GraphQLObjectType | null;
25
+ responseKey: string | null;
26
+ locationDetails: LocationDetails;
27
+ listDepth: number;
28
+ streamDetails: StreamDetails | null;
29
+ }
30
+ export interface PlanFieldReturnTypeDetails extends Omit<PlanIntoOutputPlanDetails, "listDepth"> {
31
+ parentObjectType: GraphQLObjectType;
32
+ }
33
+ export interface ProcessGroupedFieldSetDetails extends CommonPlanningDetails<GraphQLObjectType> {
34
+ objectTypeFields: GraphQLFieldMap<any, any>;
35
+ isMutation: boolean;
36
+ groupedFieldSet: SelectionSetDigest;
37
+ }
38
+ export interface PlanSelectionSetDetails extends CommonPlanningDetails<GraphQLObjectType> {
39
+ resolverEmulation: boolean;
40
+ selections: readonly SelectionNode[];
41
+ isMutation?: boolean;
42
+ }
43
+ export interface PlanListItemDetails extends CommonPlanningDetails<GraphQLList<GraphQLOutputType>> {
44
+ resolverEmulation: boolean;
45
+ selections: readonly SelectionNode[] | undefined;
46
+ listDepth: number;
47
+ stream: LayerPlanReasonListItemStream | undefined;
48
+ locationDetails: LocationDetails;
49
+ }
50
+ export interface PolymorphicResolveTypeDetails extends CommonPlanningDetails<GraphQLInterfaceType | GraphQLUnionType> {
51
+ resolverEmulation: boolean;
52
+ selections: readonly SelectionNode[];
53
+ allPossibleObjectTypes: readonly GraphQLObjectType<any, any>[];
54
+ locationDetails: LocationDetails;
55
+ parentObjectType: GraphQLObjectType | null;
56
+ responseKey: string | null;
57
+ isNonNull: boolean;
58
+ stepForType?: ReadonlyMap<GraphQLObjectType, Step | Error>;
59
+ }
60
+ export interface PolymorphicPlanObjectTypeDetails extends CommonPlanningDetails<GraphQLObjectType> {
61
+ resolverEmulation: boolean;
62
+ fieldNodes: readonly FieldNode[];
63
+ locationDetails: LocationDetails;
64
+ isNonNull: boolean;
65
+ }
66
+ //# sourceMappingURL=OperationPlanTypes.d.ts.map
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=OperationPlanTypes.js.map
@@ -163,6 +163,7 @@ export declare class OutputPlan<TType extends OutputPlanType = OutputPlanType> {
163
163
  rootStep: Step, type: TType, locationDetails: LocationDetails);
164
164
  print(): string;
165
165
  toString(): string;
166
+ expectChild(type: GraphQLObjectType | null, key: string | null): void;
166
167
  addChild(type: GraphQLObjectType | null, key: string | null, child: OutputPlanKeyValue): void;
167
168
  getLayerPlans(layerPlans?: Set<LayerPlan<import("./LayerPlan.js").LayerPlanReason>>): Set<LayerPlan>;
168
169
  makeNextStepByLayerPlan(): Record<number, any[]>;
@@ -173,4 +174,9 @@ export declare class OutputPlan<TType extends OutputPlanType = OutputPlanType> {
173
174
  }
174
175
  export declare function coerceError(error: Error, locationDetails: LocationDetails, path: ReadonlyArray<string | number>): graphql.GraphQLError;
175
176
  export declare function nonNullError(locationDetails: LocationDetails, path: readonly (string | number)[]): graphql.GraphQLError;
177
+ /**
178
+ * Finds the child of `targetParent` that has a path towards `descendent` (by
179
+ * walking backwards from descendent to targetParent).
180
+ */
181
+ export declare function getDirectLayerPlanChild(targetParent: LayerPlan, descendent: LayerPlan): LayerPlan;
176
182
  //# sourceMappingURL=OutputPlan.d.ts.map
@@ -4,17 +4,22 @@ exports.OutputPlan = void 0;
4
4
  exports.coerceError = coerceError;
5
5
  exports.nonNullError = nonNullError;
6
6
  exports.getChildBucketAndIndex = getChildBucketAndIndex;
7
+ exports.getDirectLayerPlanChild = getDirectLayerPlanChild;
7
8
  const tslib_1 = require("tslib");
8
9
  const lru_1 = tslib_1.__importDefault(require("@graphile/lru"));
10
+ const debug_1 = tslib_1.__importDefault(require("debug"));
9
11
  const graphql = tslib_1.__importStar(require("graphql"));
10
12
  const tamedevil_1 = tslib_1.__importStar(require("tamedevil"));
11
13
  const assert = tslib_1.__importStar(require("../assert.js"));
14
+ const constants_js_1 = require("../constants.js");
12
15
  const dev_js_1 = require("../dev.js");
13
16
  const index_js_1 = require("../index.js");
14
17
  const inspect_js_1 = require("../inspect.js");
15
- const interfaces_js_1 = require("../interfaces.js");
16
- const polymorphic_js_1 = require("../polymorphic.js");
17
18
  const access_js_1 = require("../steps/access.js");
19
+ const utils_js_1 = require("../utils.js");
20
+ const LayerPlan_js_1 = require("./LayerPlan.js");
21
+ const debug = (0, debug_1.default)("grafast:OutputPlan");
22
+ const debugVerbose = debug.extend("verbose");
18
23
  const { executeSync, GraphQLBoolean, GraphQLError, GraphQLFloat, GraphQLID, GraphQLInt, GraphQLString, isObjectType, Kind, OperationTypeNode, } = graphql;
19
24
  /**
20
25
  * Defines a way of taking a layerPlan and converting it into an output value.
@@ -105,7 +110,32 @@ class OutputPlan {
105
110
  }
106
111
  }
107
112
  toString() {
108
- return `OutputPlan<${this.type.mode}${this.sideEffectStep ? `^${this.sideEffectStep.id}` : ""}∈${this.layerPlan.id}!${this.rootStep.id}>`;
113
+ let processRootString = "";
114
+ if (this.processRoot != null) {
115
+ const fnBody = this.processRoot.toString();
116
+ const VALUE_ARROW = "value => ";
117
+ if (fnBody.startsWith(VALUE_ARROW)) {
118
+ const sliced = fnBody.slice(VALUE_ARROW.length);
119
+ if (sliced.startsWith("(value") &&
120
+ sliced.endsWith(")") &&
121
+ sliced.replace(/[()]/g, "").length === sliced.length - 2) {
122
+ processRootString = sliced.slice(6, -1);
123
+ }
124
+ else {
125
+ processRootString = `:value=>${sliced}`;
126
+ }
127
+ }
128
+ else {
129
+ processRootString = `:${fnBody}`;
130
+ }
131
+ }
132
+ return `OutputPlan<${this.type.mode}${this.sideEffectStep ? `^${this.sideEffectStep.id}` : ""}∈${this.layerPlan.id}!${this.rootStep.id}${processRootString}>`;
133
+ }
134
+ // HACK: ensure output objects are ordered correctly
135
+ expectChild(type, key) {
136
+ if (this.type.mode === "root" || this.type.mode === "object") {
137
+ this.keys[key] = undefined; // placeholder
138
+ }
109
139
  }
110
140
  addChild(type, key, child) {
111
141
  if (this.type.mode === "root" || this.type.mode === "object") {
@@ -155,7 +185,8 @@ class OutputPlan {
155
185
  assert.ok(type && this.type.typeNames.includes(type.name), "GrafastInternalError<566a34ac-1138-4dbf-943e-f704819431dd>: polymorphic output plan can only addChild for a matching type");
156
186
  assert.strictEqual(key, null, "GrafastInternalError<4346ebda-a02d-4489-b767-7a6d621a73c7>: addChild for polymorphic OutputPlan should not specify a key");
157
187
  assert.ok(child.type === "outputPlan", "GrafastInternalError<b29285da-fb07-4943-9038-708edc785041>: polymorphic OutputPlan child must be an outputPlan");
158
- assert.ok(child.outputPlan.type.mode === "object", "GrafastInternalError<203469c6-4bfa-4cd1-ae82-cc5d0132ca16>: polymorphic OutputPlan child must be an object outputPlan");
188
+ assert.ok(child.outputPlan.type.mode === "object" ||
189
+ child.outputPlan.type.mode === "null", "GrafastInternalError<203469c6-4bfa-4cd1-ae82-cc5d0132ca16>: polymorphic OutputPlan child must be an object outputPlan");
159
190
  }
160
191
  this.childByTypeName[type.name] = child.outputPlan;
161
192
  }
@@ -218,13 +249,16 @@ class OutputPlan {
218
249
  // should be safe aga.
219
250
  const $root = this.layerPlan.operationPlan.dangerouslyGetStep(this.rootStep.id);
220
251
  if ($root instanceof index_js_1.AccessStep &&
252
+ $root.isSyncAndSafe && // Make sure we're not using it for streaming!
221
253
  $root.fallback === undefined &&
222
254
  $root.implicitSideEffectStep === null &&
223
255
  (!this.sideEffectStep || !(0, index_js_1.stepADependsOnStepB)($root, this.sideEffectStep))) {
224
256
  const expressionDetails = $root.unbatchedExecute[access_js_1.expressionSymbol];
225
- if (expressionDetails !== undefined) {
226
- // @ts-ignore
227
- const { step: $parent } = $root.getDepOptions(0);
257
+ // @ts-ignore
258
+ const { step: $parent, onReject, acceptFlags } = $root._getDepOptions(0);
259
+ if (expressionDetails !== undefined &&
260
+ onReject == null &&
261
+ acceptFlags === constants_js_1.DEFAULT_ACCEPT_FLAGS) {
228
262
  this.layerPlan.operationPlan.stepTracker.setOutputPlanRootStep(this, $parent);
229
263
  const [path, fallback] = expressionDetails;
230
264
  withFastExpression(path, fallback, (fn) => {
@@ -292,14 +326,7 @@ class OutputPlan {
292
326
  throw new Error("GrafastInternalError<48fabdc8-ce84-45ec-ac20-35a2af9098e0>: No child output plan for list bucket?");
293
327
  }
294
328
  const childIsNonNull = this.childIsNonNull;
295
- let directLayerPlanChild = this.child.layerPlan;
296
- while (directLayerPlanChild.parentLayerPlan !== this.layerPlan) {
297
- const parent = directLayerPlanChild.parentLayerPlan;
298
- if (!parent) {
299
- throw new Error(`GrafastInternalError<d43e06d8-c533-4e7b-b3e7-af399f19c83f>: Invalid heirarchy - could not find direct layerPlan child of ${this}`);
300
- }
301
- directLayerPlanChild = parent;
302
- }
329
+ const directLayerPlanChild = getDirectLayerPlanChild(this.layerPlan, this.child.layerPlan);
303
330
  const canStream = directLayerPlanChild.reason.type === "listItem" &&
304
331
  !!directLayerPlanChild.reason.stream;
305
332
  if (childIsNonNull) {
@@ -391,63 +418,57 @@ function getChildBucketAndIndex(layerPlan, outputPlan, bucket, bucketIndex, arra
391
418
  (outputPlan != null && outputPlan.type.mode === "array")) {
392
419
  throw new Error("GrafastInternalError<83d0e3cc-7eec-4185-85b4-846540288162>: arrayIndex must be supplied iff outputPlan is an array");
393
420
  }
394
- if (outputPlan != null && layerPlan === bucket.layerPlan) {
395
- // Same layer; straightforward
396
- return [bucket, bucketIndex];
397
- }
398
- const reversePath = [layerPlan];
399
- let current = layerPlan;
400
- while (!bucket.children[current.id]) {
401
- current = current.parentLayerPlan;
402
- if (!current) {
403
- return null;
404
- }
405
- reversePath.push(current);
421
+ const paths = (0, utils_js_1.pathsFromAncestorToTargetLayerPlan)(bucket.layerPlan, layerPlan);
422
+ if (paths.length === 0) {
423
+ return null;
406
424
  }
407
- let currentBucket = bucket;
408
- let currentIndex = bucketIndex;
409
- for (let l = reversePath.length, i = l - 1; i >= 0; i--) {
410
- const layerPlan = reversePath[i];
411
- const child = currentBucket.children[layerPlan.id];
412
- if (!child) {
413
- return null;
414
- }
415
- const out = child.map.get(currentIndex);
416
- if (out == null) {
417
- return null;
418
- }
419
- /*
420
- * TEST: I think this '|| i !== l - 1' check is saying that an array can
421
- * only occur at the furthest ancestor and everything since then must be
422
- * non-array. Presumably in the case of nested arrays there would be an
423
- * intermediary bucket, hence why this check is allowed, but that should be
424
- * tested. Also, are there any confounding factors when it comes to steps
425
- * themselves using arrays for object values - for example pgSelectSingle is
426
- * represented by an array (tuple), but that doesn't make it a list so it should
427
- * be fine. Use tests to validate this is all fine.
428
- */
429
- if (arrayIndex == null || i !== l - 1) {
430
- if (Array.isArray(out)) {
431
- throw new Error("GrafastInternalError<db189d32-bf8f-4e58-b55f-5c5ac3bb2381>: Was expecting an arrayIndex, but none was provided");
425
+ toNextPath: for (const path of paths) {
426
+ let currentBucket = bucket;
427
+ let currentIndex = bucketIndex;
428
+ for (let i = 0, l = path.length; i < l; i++) {
429
+ const layerPlan = path[i];
430
+ const child = currentBucket.children[layerPlan.id];
431
+ if (!child) {
432
+ continue toNextPath;
432
433
  }
433
- currentBucket = child.bucket;
434
- currentIndex = out;
435
- }
436
- else {
437
- if (!Array.isArray(out)) {
438
- throw new Error(`GrafastInternalError<8190d09f-dc75-46ec-8162-b20ad516de41>: Cannot access array index in non-array ${(0, inspect_js_1.inspect)(out)}`);
434
+ const out = child.map.get(currentIndex);
435
+ if (out == null) {
436
+ continue toNextPath;
439
437
  }
440
- if (!(out.length > arrayIndex)) {
441
- throw new Error(`GrafastInternalError<1f596c22-368b-4d0d-94df-fb3df632b064>: Attempted to retrieve array index '${arrayIndex}' which is out of bounds of array with length '${out.length}'`);
438
+ /*
439
+ * TEST: I think this '|| i !== l - 1' check is saying that an array can
440
+ * only occur at the furthest ancestor and everything since then must be
441
+ * non-array. Presumably in the case of nested arrays there would be an
442
+ * intermediary bucket, hence why this check is allowed, but that should be
443
+ * tested. Also, are there any confounding factors when it comes to steps
444
+ * themselves using arrays for object values - for example pgSelectSingle is
445
+ * represented by an array (tuple), but that doesn't make it a list so it should
446
+ * be fine. Use tests to validate this is all fine.
447
+ */
448
+ if (arrayIndex == null || i !== 0) {
449
+ if (Array.isArray(out)) {
450
+ throw new Error("GrafastInternalError<db189d32-bf8f-4e58-b55f-5c5ac3bb2381>: Was expecting an arrayIndex, but none was provided");
451
+ }
452
+ currentBucket = child.bucket;
453
+ currentIndex = out;
454
+ }
455
+ else {
456
+ if (!Array.isArray(out)) {
457
+ throw new Error(`GrafastInternalError<8190d09f-dc75-46ec-8162-b20ad516de41>: Cannot access array index in non-array ${(0, inspect_js_1.inspect)(out)}`);
458
+ }
459
+ if (!(out.length > arrayIndex)) {
460
+ throw new Error(`GrafastInternalError<1f596c22-368b-4d0d-94df-fb3df632b064>: Attempted to retrieve array index '${arrayIndex}' which is out of bounds of array with length '${out.length}'`);
461
+ }
462
+ currentBucket = child.bucket;
463
+ currentIndex = out[arrayIndex];
442
464
  }
443
- currentBucket = child.bucket;
444
- currentIndex = out[arrayIndex];
445
465
  }
466
+ if (currentIndex == null) {
467
+ continue toNextPath;
468
+ }
469
+ return [currentBucket, currentIndex];
446
470
  }
447
- if (currentIndex == null) {
448
- return null;
449
- }
450
- return [currentBucket, currentIndex];
471
+ return null;
451
472
  }
452
473
  function makeExecutor(config) {
453
474
  const { preamble = null, inner, asString, nameExtra, skipNullHandling = false, } = config;
@@ -461,13 +482,13 @@ function makeExecutor(config) {
461
482
  throw new Error(`GrafastInternalError<da9cc5a0-23bf-4af8-a103-92f995795398>: ${(0, index_js_1.stripAnsi)(String(this.sideEffectStep))} has no entry in ${bucket}`);
462
483
  }
463
484
  const seFlags = ev._flagsAt(sideEffectBucketIndex);
464
- if (seFlags & interfaces_js_1.FLAG_ERROR) {
485
+ if (seFlags & constants_js_1.FLAG_ERROR) {
465
486
  const seVal = ev.at(sideEffectBucketIndex);
466
487
  throw coerceError(seVal, this.locationDetails, mutablePath.slice(1));
467
488
  }
468
489
  }
469
490
  }
470
- if (bucketRootFlags & interfaces_js_1.FLAG_ERROR) {
491
+ if (bucketRootFlags & constants_js_1.FLAG_ERROR) {
471
492
  throw coerceError(rawBucketRootValue, this.locationDetails, mutablePath.slice(1));
472
493
  }
473
494
  const bucketRootValue = this.processRoot !== null
@@ -498,7 +519,7 @@ function executeChildPlan(that, locationDetails, childOutputPlan, isNonNull, asS
498
519
  throw new Error(`GrafastInternalError<d18d52b5-f5bf-42df-a2dd-80e522310b8e>: ${(0, index_js_1.stripAnsi)(String($sideEffect))} has no entry in ${bucket}`);
499
520
  }
500
521
  const flags = ev._flagsAt(sideEffectBucketIndex);
501
- if (flags & interfaces_js_1.FLAG_ERROR) {
522
+ if (flags & constants_js_1.FLAG_ERROR) {
502
523
  const e = coerceError(ev.at(sideEffectBucketIndex), locationDetails, mutablePath.slice(1));
503
524
  if (isNonNull) {
504
525
  throw e;
@@ -661,23 +682,19 @@ const stringLeafExecutorString = makeExecutor({
661
682
  }
662
683
  },
663
684
  });
664
- // NOTE: the reference to $$concreteType here is a (temporary) optimization; it
665
- // should be `resolveType(bucketRootValue)` but it's not worth the function
666
- // call overhead. Longer term it should just be read directly from a different
667
- // store.
685
+ // TODO: do we need this or can we skip it?
668
686
  function makePolymorphicExecutor(asString) {
669
687
  return makeExecutor({
670
688
  inner(bucketRootValue, root, mutablePath, bucket, bucketIndex) {
689
+ const typeName = bucketRootValue;
671
690
  if (dev_js_1.isDev) {
672
- if (!(0, polymorphic_js_1.isPolymorphicData)(bucketRootValue)) {
673
- throw coerceError(new Error("GrafastInternalError<db7fcda5-dc39-4568-a7ce-ee8acb88806b>: Expected polymorphic data"), this.locationDetails, mutablePath.slice(1));
674
- }
691
+ assert.ok(typeName, "GrafastInternalError<fd3f3cf0-0789-4c74-a6cd-839c808896ed>: Could not determine concreteType for object");
675
692
  }
676
- const typeName = bucketRootValue[interfaces_js_1.$$concreteType];
677
693
  const childOutputPlan = this.childByTypeName[typeName];
678
- if (dev_js_1.isDev) {
679
- assert.ok(typeName, "GrafastInternalError<fd3f3cf0-0789-4c74-a6cd-839c808896ed>: Could not determine concreteType for object");
680
- assert.ok(childOutputPlan, `GrafastInternalError<a46999ef-41ff-4a22-bae9-fa37ff6e5f7f>: Could not determine the OutputPlan to use for '${typeName}' from '${bucket.layerPlan}'`);
694
+ if (!childOutputPlan) {
695
+ // Search: InvalidConcreteTypeName
696
+ console.warn(`Invalid object type name for this abstract position${this.locationDetails.parentTypeName && this.locationDetails.fieldName ? ` at ${this.locationDetails.parentTypeName}.${this.locationDetails.fieldName}` : ""}; saw %o, but expected one of ${this.type.typeNames.join(", ")}`, typeName);
697
+ return (asString ? "null" : null);
681
698
  }
682
699
  const directChild = bucket.children[childOutputPlan.layerPlan.id];
683
700
  if (directChild !== undefined) {
@@ -686,7 +703,13 @@ function makePolymorphicExecutor(asString) {
686
703
  else {
687
704
  const c = getChildBucketAndIndex(childOutputPlan.layerPlan, this, bucket, bucketIndex);
688
705
  if (!c) {
689
- throw new Error("GrafastInternalError<691509d8-31fa-4cfe-a6df-dcba21bd521f>: polymorphic executor couldn't determine child bucket");
706
+ // TODO: Implies that the bucket didn't run; is this a normal
707
+ // situation? We should be able to detect it and handle it more
708
+ // cleanly.
709
+ if (dev_js_1.isDev) {
710
+ debugVerbose(`GrafastInternalWarning<691509d8-31fa-4cfe-a6df-dcba21bd521f>: polymorphic executor couldn't determine child bucket. childOutputPlan=%c, childOutputPlan.layerPlan=%c, bucket=%c`, childOutputPlan, childOutputPlan.layerPlan, bucket);
711
+ }
712
+ return (asString ? "null" : null);
690
713
  }
691
714
  const [childBucket, childBucketIndex] = c;
692
715
  return childOutputPlan[asString ? "executeString" : "execute"](root, mutablePath, childBucket, childBucketIndex);
@@ -768,7 +791,7 @@ function makeArrayExecutor(childIsNonNull, canStream, asString) {
768
791
  }
769
792
  }
770
793
  if (canStream) {
771
- const stream = bucketRootValue[interfaces_js_1.$$streamMore];
794
+ const stream = bucketRootValue[constants_js_1.$$streamMore];
772
795
  if (stream !== undefined) {
773
796
  const labelStepId = childOutputPlan.layerPlan.reason.stream?.labelStepId;
774
797
  root.streams.push({
@@ -1044,4 +1067,37 @@ function withFastExpression(path, fallback, callback) {
1044
1067
  }
1045
1068
  });
1046
1069
  }
1070
+ /**
1071
+ * Finds the child of `targetParent` that has a path towards `descendent` (by
1072
+ * walking backwards from descendent to targetParent).
1073
+ */
1074
+ function getDirectLayerPlanChild(targetParent, descendent) {
1075
+ const child = _getDirectLayerPlanChild(targetParent, descendent);
1076
+ if (child == null) {
1077
+ throw new Error(`GrafastInternalError<d43e06d8-c533-4e7b-b3e7-af399f19c83f>: Invalid hierarchy - could not find direct layerPlan child of ${targetParent} that leads to ${descendent}`);
1078
+ }
1079
+ return child;
1080
+ }
1081
+ function _getDirectLayerPlanChild(targetParent, descendent) {
1082
+ let directLayerPlanChild = descendent;
1083
+ let parent;
1084
+ while ((0, LayerPlan_js_1.hasParentLayerPlan)(directLayerPlanChild.reason) &&
1085
+ (parent = directLayerPlanChild.reason.parentLayerPlan) !== targetParent) {
1086
+ directLayerPlanChild = parent;
1087
+ }
1088
+ if (directLayerPlanChild.reason.type === "combined") {
1089
+ for (const plp of directLayerPlanChild.reason.parentLayerPlans) {
1090
+ const dlpc = _getDirectLayerPlanChild(targetParent, plp);
1091
+ if (dlpc)
1092
+ return dlpc;
1093
+ }
1094
+ return null;
1095
+ }
1096
+ else if (directLayerPlanChild.reason.type === "root") {
1097
+ return null;
1098
+ }
1099
+ else {
1100
+ return directLayerPlanChild;
1101
+ }
1102
+ }
1047
1103
  //# sourceMappingURL=OutputPlan.js.map
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.StepTracker = void 0;
4
+ const constants_js_1 = require("../constants.js");
4
5
  const dev_js_1 = require("../dev.js");
5
6
  const inspect_js_1 = require("../inspect.js");
6
- const interfaces_js_1 = require("../interfaces.js");
7
7
  const step_js_1 = require("../step.js");
8
8
  const utils_js_1 = require("../utils.js");
9
9
  const lock_js_1 = require("./lock.js");
@@ -40,6 +40,8 @@ class StepTracker {
40
40
  /** @internal */
41
41
  this.layerPlansByParentStep = new Map();
42
42
  /** @internal */
43
+ this.layerPlansByDependentStep = new Map();
44
+ /** @internal */
43
45
  this.layerPlans = [];
44
46
  /**
45
47
  * All the OutputPlans that were created to allow a more efficient
@@ -96,6 +98,7 @@ class StepTracker {
96
98
  case "root":
97
99
  case "subscription":
98
100
  case "mutationField":
101
+ case "polymorphicPartition":
99
102
  case "defer": {
100
103
  break;
101
104
  }
@@ -115,13 +118,16 @@ class StepTracker {
115
118
  }
116
119
  case "subroutine": {
117
120
  const parent = layerPlan.reason.parentStep;
118
- if (parent[interfaces_js_1.$$subroutine] !== null) {
121
+ if (parent[constants_js_1.$$subroutine] !== null) {
119
122
  throw new Error(`Steps may currently only have one subroutine. If you have need for a step with multiple subroutines, please get in touch.`);
120
123
  }
121
- parent[interfaces_js_1.$$subroutine] =
124
+ parent[constants_js_1.$$subroutine] =
122
125
  layerPlan;
123
126
  break;
124
127
  }
128
+ case "combined": {
129
+ break;
130
+ }
125
131
  default: {
126
132
  const never = layerPlan.reason;
127
133
  throw new Error(`Unexpected layerPlan reason ${never.type}`);
@@ -165,10 +171,22 @@ class StepTracker {
165
171
  }
166
172
  this.layerPlans[layerPlan.id] = null;
167
173
  // Remove layerPlan from its parent
168
- if (layerPlan.parentLayerPlan !== null) {
169
- const idx = layerPlan.parentLayerPlan.children.indexOf(layerPlan);
174
+ if (layerPlan.reason.type === "root") {
175
+ // no action
176
+ }
177
+ else if (layerPlan.reason.type === "combined") {
178
+ for (const parentLayerPlan of layerPlan.reason.parentLayerPlans) {
179
+ const idx = parentLayerPlan.children.indexOf(layerPlan);
180
+ if (idx >= 0) {
181
+ parentLayerPlan.children.splice(idx, 1);
182
+ }
183
+ }
184
+ }
185
+ else {
186
+ const parentLayerPlan = layerPlan.reason.parentLayerPlan;
187
+ const idx = parentLayerPlan.children.indexOf(layerPlan);
170
188
  if (idx >= 0) {
171
- layerPlan.parentLayerPlan.children.splice(idx, 1);
189
+ parentLayerPlan.children.splice(idx, 1);
172
190
  }
173
191
  }
174
192
  // Remove references
@@ -184,6 +202,16 @@ class StepTracker {
184
202
  .delete(layerPlan);
185
203
  }
186
204
  }
205
+ if (layerPlan.reason.type === "combined") {
206
+ for (const combo of layerPlan.combinations) {
207
+ for (const source of combo.sources) {
208
+ const step = this.getStepById(source.stepId);
209
+ this.layerPlansByDependentStep
210
+ .get(step)
211
+ .delete(layerPlan);
212
+ }
213
+ }
214
+ }
187
215
  // Remove all plans in this layer
188
216
  const handled = new Set();
189
217
  const handle = (step) => {
@@ -220,16 +248,16 @@ class StepTracker {
220
248
  const $dependent = (0, utils_js_1.sudo)(raw$dependent);
221
249
  const $dependency = (0, utils_js_1.sudo)(options.step);
222
250
  if (!this.activeSteps.has($dependent)) {
223
- throw new Error(`Cannot add ${$dependency} as a dependency of ${$dependent}; the latter is deleted!`);
251
+ throw new Error(`Cannot add ${$dependency} as a dependency of ${$dependent}; the latter is deleted! Explanation: https://err.red/gasdd#phase=${this.operationPlan.phase}&dependency=${encodeURIComponent(String($dependency))}&dependent=${encodeURIComponent(String($dependent))}&deleted=dependent`);
224
252
  }
225
253
  if (!this.activeSteps.has($dependency)) {
226
- throw new Error(`Cannot add ${$dependency} as a dependency of ${$dependent}; the former is deleted!`);
254
+ throw new Error(`Cannot add ${$dependency} as a dependency of ${$dependent}; the former is deleted! Explanation: https://err.red/gasdd#phase=${this.operationPlan.phase}&dependency=${encodeURIComponent(String($dependency))}&dependent=${encodeURIComponent(String($dependent))}&deleted=dependency`);
227
255
  }
228
256
  if ($dependent.isFinalized) {
229
257
  throw new Error("You cannot add a dependency after the step is finalized.");
230
258
  }
231
259
  if (!($dependency instanceof step_js_1.Step)) {
232
- throw new Error(`Error occurred when adding dependency for '${$dependent}', value passed was not a step, it was '${(0, inspect_js_1.inspect)($dependency)}'`);
260
+ throw new Error(`Error occurred when adding dependency for '${$dependent}', value passed was not a step, it was '${(0, inspect_js_1.inspect)($dependency)}' (phase = ${this.operationPlan.phase})`);
233
261
  }
234
262
  if (dev_js_1.isDev) {
235
263
  // Check that we can actually add this as a dependency
@@ -237,19 +265,21 @@ class StepTracker {
237
265
  throw new Error(
238
266
  //console.error(
239
267
  // This is not a GrafastInternalError
240
- `Attempted to add '${$dependency}' (${$dependency.layerPlan}) as a dependency of '${$dependent}' (${$dependent.layerPlan}), but we cannot because that LayerPlan isn't an ancestor`);
268
+ `Attempted to add '${$dependency}' (${$dependency.layerPlan}) as a dependency of '${$dependent}' (${$dependent.layerPlan}), but we cannot because that LayerPlan isn't an ancestor. (phase = ${this.operationPlan.phase})`);
241
269
  }
242
270
  }
243
271
  const dependentDependencies = (0, utils_js_1.writeableArray)($dependent.dependencies);
244
272
  const dependentDependencyForbiddenFlags = (0, utils_js_1.writeableArray)($dependent.dependencyForbiddenFlags);
245
273
  const dependentDependencyOnReject = (0, utils_js_1.writeableArray)($dependent.dependencyOnReject);
246
- const { skipDeduplication, acceptFlags = interfaces_js_1.ALL_FLAGS & ~$dependent.defaultForbiddenFlags, onReject, } = options;
274
+ const dependentDependencyDataOnly = (0, utils_js_1.writeableArray)($dependent.dependencyDataOnly);
275
+ const { skipDeduplication, acceptFlags = constants_js_1.ALL_FLAGS & ~$dependent.defaultForbiddenFlags, onReject, dataOnly = false, } = options;
247
276
  // When copying dependencies between classes, we might not want to
248
277
  // deduplicate because we might refer to the dependency by its index. As
249
278
  // such, we should only dedupe by default but allow opting out.
250
279
  // TODO: change this to `!skipDeduplication`
251
280
  if (skipDeduplication === false) {
252
- const existingIndex = dependentDependencies.indexOf($dependency);
281
+ const $searchForMe = options.step;
282
+ const existingIndex = dependentDependencies.indexOf($searchForMe);
253
283
  if (existingIndex >= 0) {
254
284
  return existingIndex;
255
285
  }
@@ -260,13 +290,14 @@ class StepTracker {
260
290
  }
261
291
  $dependent._isUnary = false;
262
292
  }
263
- const forbiddenFlags = interfaces_js_1.ALL_FLAGS & ~(acceptFlags & interfaces_js_1.TRAPPABLE_FLAGS);
293
+ const forbiddenFlags = constants_js_1.ALL_FLAGS & ~(acceptFlags & $dependent.__trappableFlags);
264
294
  this.stepsWithNoDependenciesByConstructor
265
295
  .get($dependent.constructor)
266
296
  ?.delete($dependent);
267
297
  const dependencyIndex = dependentDependencies.push($dependency) - 1;
268
298
  dependentDependencyForbiddenFlags[dependencyIndex] = forbiddenFlags;
269
299
  dependentDependencyOnReject[dependencyIndex] = onReject;
300
+ dependentDependencyDataOnly[dependencyIndex] = dataOnly;
270
301
  (0, utils_js_1.writeableArray)($dependency.dependents).push({
271
302
  step: $dependent,
272
303
  dependencyIndex,
@@ -274,13 +305,16 @@ class StepTracker {
274
305
  return dependencyIndex;
275
306
  }
276
307
  addStepUnaryDependency($dependent, options) {
308
+ if (options.dataOnly) {
309
+ throw new Error(`${$dependent} attempted to add dataOnly unary dependency; this is not permitted.`);
310
+ }
277
311
  const $dependency = options.step;
312
+ const { nonUnaryMessage = defaultNonUnaryMessage, ...rest } = options;
278
313
  if (!$dependency._isUnary) {
279
- const { nonUnaryMessage = defaultNonUnaryMessage } = options;
280
314
  throw new Error(nonUnaryMessage($dependent, $dependency));
281
315
  }
282
316
  $dependency._isUnaryLocked = true;
283
- return this.addStepDependency($dependent, options);
317
+ return this.addStepDependency($dependent, { ...rest, dataOnly: false });
284
318
  }
285
319
  setOutputPlanRootStep(outputPlan, $dependency) {
286
320
  if (!this.activeSteps.has($dependency)) {
@@ -402,6 +436,28 @@ class StepTracker {
402
436
  layerPlans.clear();
403
437
  }
404
438
  }
439
+ // Update combos
440
+ {
441
+ const layerPlans = this.layerPlansByDependentStep.get($original);
442
+ if (layerPlans?.size) {
443
+ let layerPlansByReplacementDependentStep = this.layerPlansByDependentStep.get($replacement);
444
+ if (!layerPlansByReplacementDependentStep) {
445
+ layerPlansByReplacementDependentStep = new Set();
446
+ this.layerPlansByDependentStep.set($replacement, layerPlansByReplacementDependentStep);
447
+ }
448
+ for (const layerPlan of layerPlans) {
449
+ for (const combo of layerPlan.combinations) {
450
+ for (const source of combo.sources) {
451
+ if (source.stepId === $original.id) {
452
+ source.stepId = $replacement.id;
453
+ }
454
+ }
455
+ }
456
+ layerPlansByReplacementDependentStep.add(layerPlan);
457
+ }
458
+ layerPlans.clear();
459
+ }
460
+ }
405
461
  // NOTE: had to add the code ensuring all the layer plan parentStepId's
406
462
  // existed to fix polymorphism, but it feels wrong. Should we be doing
407
463
  // something different?
@@ -456,6 +512,9 @@ class StepTracker {
456
512
  const s3 = this.layerPlansByParentStep.get($step);
457
513
  if (s3 && s3.size !== 0)
458
514
  return false;
515
+ const s4 = this.layerPlansByDependentStep.get($step);
516
+ if (s4 && s4.size !== 0)
517
+ return false;
459
518
  return true;
460
519
  }
461
520
  /**
@@ -498,8 +557,8 @@ class StepTracker {
498
557
  * then they can also be eradicated _except_ during the 'plan' phase.
499
558
  */
500
559
  eradicate($original) {
501
- if ($original[interfaces_js_1.$$subroutine] !== null) {
502
- this.deleteLayerPlan($original[interfaces_js_1.$$subroutine]);
560
+ if ($original[constants_js_1.$$subroutine] !== null) {
561
+ this.deleteLayerPlan($original[constants_js_1.$$subroutine]);
503
562
  }
504
563
  this.removeStepFromItsLayerPlan($original);
505
564
  const oldAliases = this.aliasesById[$original.id];