grafast 0.1.1-beta.20 → 0.1.1-beta.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/dist/args.js +2 -3
  2. package/dist/assert.js +2 -3
  3. package/dist/constraints.js +1 -2
  4. package/dist/deferred.js +1 -2
  5. package/dist/dev.js +2 -2
  6. package/dist/engine/LayerPlan.d.ts +20 -16
  7. package/dist/engine/LayerPlan.js +5 -10
  8. package/dist/engine/OperationPlan.d.ts +12 -13
  9. package/dist/engine/OperationPlan.js +210 -146
  10. package/dist/engine/OutputPlan.d.ts +4 -4
  11. package/dist/engine/OutputPlan.js +13 -10
  12. package/dist/engine/StepTracker.js +11 -2
  13. package/dist/engine/executeBucket.js +135 -94
  14. package/dist/engine/executeOutputPlan.js +1 -2
  15. package/dist/engine/lib/defaultPlanResolver.d.ts +6 -0
  16. package/dist/engine/lib/defaultPlanResolver.js +11 -0
  17. package/dist/engine/lib/withGlobalLayerPlan.d.ts +2 -2
  18. package/dist/engine/lib/withGlobalLayerPlan.js +4 -5
  19. package/dist/engine/lock.d.ts +3 -3
  20. package/dist/engine/lock.js +3 -3
  21. package/dist/error.js +4 -4
  22. package/dist/establishOperationPlan.js +2 -3
  23. package/dist/execute.js +3 -4
  24. package/dist/exportAs.js +2 -3
  25. package/dist/global.js +2 -3
  26. package/dist/grafastGraphql.js +2 -3
  27. package/dist/grafastPrint.js +7 -8
  28. package/dist/graphqlCollectFields.js +6 -7
  29. package/dist/graphqlMergeSelectionSets.js +1 -2
  30. package/dist/index.d.ts +22 -18
  31. package/dist/index.js +41 -16
  32. package/dist/input.js +75 -28
  33. package/dist/inspect.d.ts +9 -4
  34. package/dist/inspect.js +2 -2
  35. package/dist/interfaces.d.ts +110 -89
  36. package/dist/makeGrafastSchema.d.ts +18 -9
  37. package/dist/makeGrafastSchema.js +64 -30
  38. package/dist/mermaid.js +53 -14
  39. package/dist/middleware.js +1 -2
  40. package/dist/multistep.d.ts +6 -6
  41. package/dist/multistep.js +6 -7
  42. package/dist/operationPlan-input.d.ts +5 -4
  43. package/dist/operationPlan-input.js +131 -399
  44. package/dist/planJSONInterfaces.d.ts +6 -2
  45. package/dist/polymorphic.js +4 -5
  46. package/dist/prepare.js +6 -6
  47. package/dist/step.d.ts +67 -99
  48. package/dist/step.js +99 -127
  49. package/dist/steps/__flag.d.ts +16 -16
  50. package/dist/steps/__flag.js +9 -6
  51. package/dist/steps/__inputDefault.d.ts +14 -0
  52. package/dist/steps/__inputDefault.js +48 -0
  53. package/dist/steps/__inputDynamicScalar.d.ts +2 -4
  54. package/dist/steps/__inputDynamicScalar.js +4 -2
  55. package/dist/steps/__inputList.d.ts +5 -9
  56. package/dist/steps/__inputList.js +4 -1
  57. package/dist/steps/__inputObject.d.ts +6 -11
  58. package/dist/steps/__inputObject.js +13 -3
  59. package/dist/steps/__inputStaticLeaf.d.ts +2 -4
  60. package/dist/steps/__inputStaticLeaf.js +3 -1
  61. package/dist/steps/__item.d.ts +6 -6
  62. package/dist/steps/__item.js +1 -1
  63. package/dist/steps/__trackedValue.d.ts +4 -49
  64. package/dist/steps/__trackedValue.js +24 -6
  65. package/dist/steps/__value.d.ts +3 -3
  66. package/dist/steps/__value.js +3 -2
  67. package/dist/steps/access.d.ts +7 -6
  68. package/dist/steps/access.js +14 -7
  69. package/dist/steps/applyInput.d.ts +44 -0
  70. package/dist/steps/applyInput.js +206 -0
  71. package/dist/steps/applyTransforms.d.ts +2 -2
  72. package/dist/steps/applyTransforms.js +7 -5
  73. package/dist/steps/bakedInput.d.ts +23 -0
  74. package/dist/steps/bakedInput.js +90 -0
  75. package/dist/steps/condition.d.ts +5 -5
  76. package/dist/steps/condition.js +3 -3
  77. package/dist/steps/connection.d.ts +42 -39
  78. package/dist/steps/connection.js +51 -35
  79. package/dist/steps/constant.d.ts +4 -8
  80. package/dist/steps/constant.js +54 -6
  81. package/dist/steps/each.d.ts +3 -3
  82. package/dist/steps/each.js +1 -2
  83. package/dist/steps/error.d.ts +2 -2
  84. package/dist/steps/error.js +3 -3
  85. package/dist/steps/filter.d.ts +3 -2
  86. package/dist/steps/filter.js +1 -2
  87. package/dist/steps/first.d.ts +6 -5
  88. package/dist/steps/first.js +5 -4
  89. package/dist/steps/graphqlResolver.d.ts +2 -2
  90. package/dist/steps/graphqlResolver.js +44 -56
  91. package/dist/steps/groupBy.d.ts +3 -2
  92. package/dist/steps/groupBy.js +1 -2
  93. package/dist/steps/index.d.ts +4 -2
  94. package/dist/steps/index.js +21 -9
  95. package/dist/steps/lambda.d.ts +5 -5
  96. package/dist/steps/lambda.js +4 -4
  97. package/dist/steps/last.d.ts +6 -5
  98. package/dist/steps/last.js +5 -4
  99. package/dist/steps/list.d.ts +7 -7
  100. package/dist/steps/list.js +3 -3
  101. package/dist/steps/listTransform.d.ts +14 -12
  102. package/dist/steps/listTransform.js +14 -7
  103. package/dist/steps/listen.d.ts +6 -8
  104. package/dist/steps/listen.js +7 -7
  105. package/dist/steps/load.d.ts +6 -6
  106. package/dist/steps/load.js +7 -7
  107. package/dist/steps/node.d.ts +16 -10
  108. package/dist/steps/node.js +14 -7
  109. package/dist/steps/object.d.ts +11 -11
  110. package/dist/steps/object.js +5 -5
  111. package/dist/steps/partitionByIndex.d.ts +3 -2
  112. package/dist/steps/partitionByIndex.js +1 -2
  113. package/dist/steps/polymorphicBranch.d.ts +8 -8
  114. package/dist/steps/polymorphicBranch.js +4 -4
  115. package/dist/steps/proxy.d.ts +8 -8
  116. package/dist/steps/proxy.js +3 -3
  117. package/dist/steps/remapKeys.d.ts +6 -6
  118. package/dist/steps/remapKeys.js +3 -3
  119. package/dist/steps/reverse.d.ts +5 -5
  120. package/dist/steps/reverse.js +4 -4
  121. package/dist/steps/setter.d.ts +9 -18
  122. package/dist/steps/setter.js +24 -14
  123. package/dist/steps/sideEffect.d.ts +4 -4
  124. package/dist/steps/sideEffect.js +3 -3
  125. package/dist/stringifyPayload.js +1 -2
  126. package/dist/stripAnsi.js +2 -2
  127. package/dist/subscribe.js +2 -3
  128. package/dist/timeSource.d.ts +0 -1
  129. package/dist/utils.d.ts +43 -31
  130. package/dist/utils.js +97 -61
  131. package/dist/version.d.ts +1 -1
  132. package/dist/version.js +1 -1
  133. package/package.json +2 -2
@@ -3,7 +3,7 @@ import type { FieldNode, GraphQLEnumType, GraphQLObjectType, GraphQLScalarType }
3
3
  import * as graphql from "graphql";
4
4
  import type { Bucket } from "../bucket.js";
5
5
  import type { ExecutionEntryFlags, JSONValue, LocationDetails } from "../interfaces.js";
6
- import type { ExecutableStep } from "../step.js";
6
+ import type { Step } from "../step.js";
7
7
  import type { PayloadRoot } from "./executeOutputPlan.js";
8
8
  import type { LayerPlan } from "./LayerPlan.js";
9
9
  export type OutputPlanTypeIntrospection = {
@@ -115,12 +115,12 @@ export declare class OutputPlan<TType extends OutputPlanType = OutputPlanType> {
115
115
  * The step that represents the root value. How this is used depends on the
116
116
  * OutputPlanMode.
117
117
  */
118
- readonly rootStep: ExecutableStep;
118
+ readonly rootStep: Step;
119
119
  /**
120
120
  * If this output plan should resolve to an error if a side effect step
121
121
  * raises an error, this is that side effect.
122
122
  */
123
- readonly sideEffectStep: ExecutableStep | null;
123
+ readonly sideEffectStep: Step | null;
124
124
  /**
125
125
  * For root/object output plans, the keys to set on the resulting object
126
126
  * grouped by the concrete object type name.
@@ -160,7 +160,7 @@ export declare class OutputPlan<TType extends OutputPlanType = OutputPlanType> {
160
160
  *
161
161
  * For `introspection`, `null` it's irrelevant. Use `constant(null)` or whatever.
162
162
  */
163
- rootStep: ExecutableStep, type: TType, locationDetails: LocationDetails);
163
+ rootStep: Step, type: TType, locationDetails: LocationDetails);
164
164
  print(): string;
165
165
  toString(): string;
166
166
  addChild(type: GraphQLObjectType | null, key: string | null, child: OutputPlanKeyValue): void;
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getChildBucketAndIndex = exports.nonNullError = exports.coerceError = exports.OutputPlan = void 0;
3
+ exports.OutputPlan = void 0;
4
+ exports.coerceError = coerceError;
5
+ exports.nonNullError = nonNullError;
6
+ exports.getChildBucketAndIndex = getChildBucketAndIndex;
4
7
  const tslib_1 = require("tslib");
5
8
  const lru_1 = tslib_1.__importDefault(require("@graphile/lru"));
6
9
  const graphql = tslib_1.__importStar(require("graphql"));
@@ -221,7 +224,7 @@ class OutputPlan {
221
224
  const expressionDetails = $root.unbatchedExecute[access_js_1.expressionSymbol];
222
225
  if (expressionDetails !== undefined) {
223
226
  // @ts-ignore
224
- const $parent = $root.getDep(0);
227
+ const { step: $parent } = $root.getDepOptions(0);
225
228
  this.layerPlan.operationPlan.stepTracker.setOutputPlanRootStep(this, $parent);
226
229
  const [path, fallback] = expressionDetails;
227
230
  withFastExpression(path, fallback, (fn) => {
@@ -359,10 +362,9 @@ function coerceError(error, locationDetails, path) {
359
362
  }
360
363
  }
361
364
  else {
362
- return new GraphQLError(error.message, locationDetails.node, null, null, path, error, null);
365
+ return new GraphQLError(error?.message ?? String(error), locationDetails.node, null, null, path, error, null);
363
366
  }
364
367
  }
365
- exports.coerceError = coerceError;
366
368
  function nonNullError(locationDetails, path) {
367
369
  const { parentTypeName, fieldName, node } = locationDetails;
368
370
  if (!parentTypeName || !fieldName) {
@@ -370,7 +372,6 @@ function nonNullError(locationDetails, path) {
370
372
  }
371
373
  return new GraphQLError(`Cannot return null for non-nullable field ${parentTypeName}.${fieldName}.`, node, null, null, path, null, null);
372
374
  }
373
- exports.nonNullError = nonNullError;
374
375
  /**
375
376
  * We're currently running OutputPlan `outputPlan` in bucket `bucket` at index
376
377
  * `bucketIndex`. If this is an array OutputPlan then we're looping over the
@@ -448,7 +449,6 @@ function getChildBucketAndIndex(layerPlan, outputPlan, bucket, bucketIndex, arra
448
449
  }
449
450
  return [currentBucket, currentIndex];
450
451
  }
451
- exports.getChildBucketAndIndex = getChildBucketAndIndex;
452
452
  function makeExecutor(config) {
453
453
  const { preamble = null, inner, asString, nameExtra, skipNullHandling = false, } = config;
454
454
  const fn = function (root, mutablePath, bucket, bucketIndex, rawBucketRootValue = bucket.store.get(this.rootStep.id).at(bucketIndex), bucketRootFlags = bucket.store.get(this.rootStep.id)._flagsAt(bucketIndex)) {
@@ -467,6 +467,9 @@ function makeExecutor(config) {
467
467
  }
468
468
  }
469
469
  }
470
+ if (bucketRootFlags & interfaces_js_1.FLAG_ERROR) {
471
+ throw coerceError(rawBucketRootValue, this.locationDetails, mutablePath.slice(1));
472
+ }
470
473
  const bucketRootValue = this.processRoot !== null
471
474
  ? this.processRoot(rawBucketRootValue, bucketRootFlags)
472
475
  : rawBucketRootValue;
@@ -474,9 +477,6 @@ function makeExecutor(config) {
474
477
  if (earlyReturn !== undefined) {
475
478
  return earlyReturn;
476
479
  }
477
- if (bucketRootFlags & interfaces_js_1.FLAG_ERROR) {
478
- throw coerceError(bucketRootValue, this.locationDetails, mutablePath.slice(1));
479
- }
480
480
  if (!skipNullHandling) {
481
481
  if (bucketRootValue == null)
482
482
  return (asString ? "null" : null);
@@ -770,13 +770,16 @@ function makeArrayExecutor(childIsNonNull, canStream, asString) {
770
770
  if (canStream) {
771
771
  const stream = bucketRootValue[interfaces_js_1.$$streamMore];
772
772
  if (stream !== undefined) {
773
+ const labelStepId = childOutputPlan.layerPlan.reason.stream?.labelStepId;
773
774
  root.streams.push({
774
775
  root,
775
776
  path: mutablePath.slice(1),
776
777
  bucket,
777
778
  bucketIndex,
778
779
  outputPlan: childOutputPlan,
779
- label: childOutputPlan.layerPlan.reason.stream?.label,
780
+ label: labelStepId != null
781
+ ? bucket.store.get(labelStepId)?.unaryValue()
782
+ : undefined,
780
783
  stream,
781
784
  startIndex: bucketRootValue.length,
782
785
  });
@@ -32,6 +32,8 @@ class StepTracker {
32
32
  /** @internal */
33
33
  this.stepsWithNoDependenciesByConstructor = new Map();
34
34
  /** @internal */
35
+ this.internalDependencies = new Set();
36
+ /** @internal */
35
37
  this.outputPlansByRootStep = new Map();
36
38
  /** @internal */
37
39
  this.layerPlansByRootStep = new Map();
@@ -226,7 +228,7 @@ class StepTracker {
226
228
  if ($dependent.isFinalized) {
227
229
  throw new Error("You cannot add a dependency after the step is finalized.");
228
230
  }
229
- if (!($dependency instanceof step_js_1.ExecutableStep)) {
231
+ if (!($dependency instanceof step_js_1.Step)) {
230
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)}'`);
231
233
  }
232
234
  if (dev_js_1.isDev) {
@@ -274,7 +276,8 @@ class StepTracker {
274
276
  addStepUnaryDependency($dependent, options) {
275
277
  const $dependency = options.step;
276
278
  if (!$dependency._isUnary) {
277
- throw new Error(`${$dependent} attempted to create a unary step dependency on ${$dependency}, but that step is not unary. You may use \`.addDependency()\` instead of \`.addUnaryDependency()\`.`);
279
+ const { nonUnaryMessage = defaultNonUnaryMessage } = options;
280
+ throw new Error(nonUnaryMessage($dependent, $dependency));
278
281
  }
279
282
  $dependency._isUnaryLocked = true;
280
283
  return this.addStepDependency($dependent, options);
@@ -441,6 +444,9 @@ class StepTracker {
441
444
  return false;
442
445
  if ($step.hasSideEffects)
443
446
  return false;
447
+ if (this.internalDependencies.has($step)) {
448
+ return false;
449
+ }
444
450
  const s1 = this.outputPlansByRootStep.get($step);
445
451
  if (s1 && s1.size !== 0)
446
452
  return false;
@@ -586,4 +592,7 @@ class StepTracker {
586
592
  }
587
593
  }
588
594
  exports.StepTracker = StepTracker;
595
+ function defaultNonUnaryMessage($dependent, $dependency) {
596
+ return `${$dependent} attempted to create a unary step dependency on ${$dependency}, but that step is not unary. See https://err.red/gud`;
597
+ }
589
598
  //# sourceMappingURL=StepTracker.js.map
@@ -1,6 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.unaryExecutionValue = exports.batchExecutionValue = exports.bucketToString = exports.newBucket = exports.executeBucket = void 0;
3
+ exports.executeBucket = executeBucket;
4
+ exports.newBucket = newBucket;
5
+ exports.bucketToString = bucketToString;
6
+ exports.batchExecutionValue = batchExecutionValue;
7
+ exports.unaryExecutionValue = unaryExecutionValue;
4
8
  const tslib_1 = require("tslib");
5
9
  const iterall_1 = require("iterall");
6
10
  const assert = tslib_1.__importStar(require("../assert.js"));
@@ -8,7 +12,6 @@ const dev_js_1 = require("../dev.js");
8
12
  const error_js_1 = require("../error.js");
9
13
  const inspect_js_1 = require("../inspect.js");
10
14
  const interfaces_js_1 = require("../interfaces.js");
11
- const step_js_1 = require("../step.js");
12
15
  const timeSource_js_1 = require("../timeSource.js");
13
16
  const utils_js_1 = require("../utils.js");
14
17
  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 })));
@@ -89,9 +92,11 @@ function executeBucket(bucket, requestContext) {
89
92
  if (phase.normalSteps !== undefined) {
90
93
  const normalSteps = phase.normalSteps;
91
94
  for (let normalStepIndex = 0, l = normalSteps.length; normalStepIndex < l; normalStepIndex++) {
95
+ const step = normalSteps[normalStepIndex].step;
96
+ const stepSize = step._isUnary ? 1 : bucket.size;
92
97
  const r = timeoutError;
93
- const results = (0, utils_js_1.arrayOfLength)(bucket.size, r);
94
- const flags = (0, utils_js_1.arrayOfLength)(bucket.size, interfaces_js_1.FLAG_ERROR);
98
+ const results = (0, utils_js_1.arrayOfLength)(stepSize, r);
99
+ const flags = (0, utils_js_1.arrayOfLength)(stepSize, interfaces_js_1.FLAG_ERROR);
95
100
  resultList[normalStepIndex] = { flags, results };
96
101
  indexesPendingLoopOver.push(normalStepIndex);
97
102
  // TODO: I believe we can remove this line?
@@ -103,6 +108,7 @@ function executeBucket(bucket, requestContext) {
103
108
  const normalSteps = phase.normalSteps;
104
109
  for (let normalStepIndex = 0, l = normalSteps.length; normalStepIndex < l; normalStepIndex++) {
105
110
  const step = normalSteps[normalStepIndex].step;
111
+ const stepSize = step._isUnary ? 1 : bucket.size;
106
112
  try {
107
113
  const r = executeStep(step);
108
114
  if ((0, utils_js_1.isPromiseLike)(r)) {
@@ -123,8 +129,8 @@ function executeBucket(bucket, requestContext) {
123
129
  }
124
130
  catch (e) {
125
131
  const r = e;
126
- const results = (0, utils_js_1.arrayOfLength)(bucket.size, r);
127
- const flags = (0, utils_js_1.arrayOfLength)(bucket.size, interfaces_js_1.FLAG_ERROR);
132
+ const results = (0, utils_js_1.arrayOfLength)(stepSize, r);
133
+ const flags = (0, utils_js_1.arrayOfLength)(stepSize, interfaces_js_1.FLAG_ERROR);
128
134
  resultList[normalStepIndex] = { flags, results };
129
135
  indexesPendingLoopOver.push(normalStepIndex);
130
136
  // TODO: I believe we can remove this line?
@@ -196,15 +202,12 @@ function executeBucket(bucket, requestContext) {
196
202
  return;
197
203
  }
198
204
  let valueIsAsyncIterable;
199
- if (
200
- // Are we streaming this? If so, we need an iterable or async
201
- // iterable.
202
- finishedStep._stepOptions.stream &&
205
+ if (finishedStep._stepOptions.walkIterable &&
206
+ // PERF: do we want to handle arrays differently?
203
207
  ((valueIsAsyncIterable = (0, iterall_1.isAsyncIterable)(value)) || (0, iterall_1.isIterable)(value))) {
204
- const streamOptions = finishedStep._stepOptions.stream;
205
- const initialCount = streamOptions
206
- ? streamOptions.initialCount
207
- : Infinity;
208
+ // PERF: we've already calculated this once; can we reference that again here?
209
+ const stream = evaluateStream(bucket, finishedStep);
210
+ const initialCount = stream?.initialCount ?? Infinity;
208
211
  const iterator = valueIsAsyncIterable
209
212
  ? value[Symbol.asyncIterator]()
210
213
  : value[Symbol.iterator]();
@@ -345,6 +348,7 @@ function executeBucket(bucket, requestContext) {
345
348
  stopTime,
346
349
  meta,
347
350
  eventEmitter,
351
+ stream: evaluateStream(bucket, step),
348
352
  _bucket: bucket,
349
353
  _requestContext: requestContext,
350
354
  };
@@ -538,43 +542,22 @@ function executeBucket(bucket, requestContext) {
538
542
  if (dev_js_1.isDev && step._isUnary && count !== 1) {
539
543
  throw new Error(`GrafastInternalError<84a6cdfa-e8fe-4dea-85fe-9426a6a78027>: ${step} is a unary step, but we're attempting to pass it ${count} (!= 1) values`);
540
544
  }
541
- const streamOptions = step._stepOptions.stream;
542
- if (streamOptions && (0, step_js_1.isStreamableStep)(step)) {
543
- if (step.stream.length > 1) {
544
- throw new Error(`${step} is using a legacy form of 'stream' which accepts multiple arguments, please see https://err.red/gev2`);
545
- }
546
- const streamDetails = {
547
- indexMap: makeIndexMap(count),
548
- indexForEach: makeIndexForEach(count),
549
- count,
550
- values,
551
- extra,
552
- streamOptions,
553
- };
554
- if (!step.isSyncAndSafe && middleware != null) {
555
- return middleware.run("streamStep", { args, step, streamDetails }, streamStepFromEvent);
556
- }
557
- else {
558
- return step.stream(streamDetails);
559
- }
545
+ if (step.execute.length > 1) {
546
+ throw new Error(`${step} is using a legacy form of 'execute' which accepts multiple arguments, please see https://err.red/gev2`);
547
+ }
548
+ const executeDetails = {
549
+ indexMap: makeIndexMap(count),
550
+ indexForEach: makeIndexForEach(count),
551
+ count,
552
+ values,
553
+ extra,
554
+ stream: evaluateStream(bucket, step),
555
+ };
556
+ if (!step.isSyncAndSafe && middleware != null) {
557
+ return middleware.run("executeStep", { args, step, executeDetails }, executeStepFromEvent);
560
558
  }
561
559
  else {
562
- if (step.execute.length > 1) {
563
- throw new Error(`${step} is using a legacy form of 'execute' which accepts multiple arguments, please see https://err.red/gev2`);
564
- }
565
- const executeDetails = {
566
- indexMap: makeIndexMap(count),
567
- indexForEach: makeIndexForEach(count),
568
- count,
569
- values,
570
- extra,
571
- };
572
- if (!step.isSyncAndSafe && middleware != null) {
573
- return middleware.run("executeStep", { args, step, executeDetails }, executeStepFromEvent);
574
- }
575
- else {
576
- return step.execute(executeDetails);
577
- }
560
+ return step.execute(executeDetails);
578
561
  }
579
562
  }
580
563
  // Slow mode...
@@ -596,24 +579,40 @@ function executeBucket(bucket, requestContext) {
596
579
  let needsTransform = false;
597
580
  /** If all we see is errors, there's no need to execute! */
598
581
  let newSize = 0;
599
- const stepPolymorphicPaths = step.polymorphicPaths;
582
+ let stepPolymorphicPaths = step.polymorphicPaths;
600
583
  const legitDepsCount = (0, utils_js_1.sudo)(step).dependencies.length;
601
- let dependencies = step.implicitSideEffectStep
584
+ const dependenciesIncludingSideEffectsCount = dependenciesIncludingSideEffects.length;
585
+ let dependencies = dependenciesIncludingSideEffectsCount > legitDepsCount
602
586
  ? dependenciesIncludingSideEffects.slice(0, legitDepsCount)
603
587
  : dependenciesIncludingSideEffects;
604
588
  // OPTIM: if unariesIncludingSideEffects.some(isGrafastError) then shortcut execution because everything fails
605
- // for (let index = 0, l = polymorphicPathList.length; index < l; index++) {
589
+ let hasPolyMatch = true;
590
+ if (step._isUnary && stepPolymorphicPaths !== null) {
591
+ // Check that at least one datapoint matches one of our paths
592
+ hasPolyMatch = false;
593
+ for (let dataIndex = 0; dataIndex < size; dataIndex++) {
594
+ if (stepPolymorphicPaths.has(polymorphicPathList[dataIndex])) {
595
+ hasPolyMatch = true;
596
+ break;
597
+ }
598
+ }
599
+ stepPolymorphicPaths = null;
600
+ }
606
601
  for (let dataIndex = 0; dataIndex < expectedSize; dataIndex++) {
607
- let forceIndexValue = undefined;
602
+ let forceIndexValue = hasPolyMatch
603
+ ? undefined
604
+ : null;
608
605
  let rejectValue = undefined;
609
- let indexFlags = interfaces_js_1.NO_FLAGS;
606
+ let indexFlags = hasPolyMatch
607
+ ? interfaces_js_1.NO_FLAGS
608
+ : interfaces_js_1.FLAG_POLY_SKIPPED;
610
609
  if (stepPolymorphicPaths !== null &&
611
610
  !stepPolymorphicPaths.has(polymorphicPathList[dataIndex])) {
612
611
  indexFlags |= interfaces_js_1.FLAG_POLY_SKIPPED;
613
612
  forceIndexValue = null;
614
613
  }
615
614
  else if (extra._bucket.flagUnion) {
616
- for (let i = 0, l = dependenciesIncludingSideEffects.length; i < l; i++) {
615
+ for (let i = 0; i < dependenciesIncludingSideEffectsCount; i++) {
617
616
  const depExecutionVal = dependenciesIncludingSideEffects[i];
618
617
  const forbiddenFlags = dependencyForbiddenFlags[i];
619
618
  const onReject = dependencyOnReject[i];
@@ -714,12 +713,15 @@ function executeBucket(bucket, requestContext) {
714
713
  * This function MIGHT throw or reject, so be sure to handle that.
715
714
  */
716
715
  function executeStep(step) {
716
+ // DELIBERATE SHADOWING!
717
+ const size = step._isUnary ? 1 : bucket.size;
717
718
  try {
718
719
  const meta = step.metaKey !== undefined ? metaByMetaKey[step.metaKey] : undefined;
719
720
  const extra = {
720
721
  stopTime,
721
722
  meta,
722
723
  eventEmitter,
724
+ stream: evaluateStream(bucket, step),
723
725
  _bucket: bucket,
724
726
  _requestContext: requestContext,
725
727
  };
@@ -731,6 +733,9 @@ function executeBucket(bucket, requestContext) {
731
733
  let needsFiltering = false;
732
734
  const defaultForbiddenFlags = (0, utils_js_1.sudo)(step).defaultForbiddenFlags;
733
735
  const addDependency = ($dep, forbiddenFlags, onReject) => {
736
+ if (step._isUnary && !$dep._isUnary) {
737
+ throw new Error(`GrafastInternalError<58bc38e2-8722-4c19-ba38-fd01a020654b>: unary step ${step} cannot be made dependent on non-unary step ${$dep}!`);
738
+ }
734
739
  const executionValue = store.get($dep.id);
735
740
  if (executionValue === undefined) {
736
741
  throw new Error(`GrafastInternalError<d9e9eb37-4251-4659-a545-4730826ecf0e>: ${$dep} data couldn't be found, but required by ${step} (with side effect ${step.implicitSideEffectStep})!`);
@@ -753,7 +758,9 @@ function executeBucket(bucket, requestContext) {
753
758
  }
754
759
  const $sideEffect = step.implicitSideEffectStep;
755
760
  if ($sideEffect) {
756
- addDependency($sideEffect, defaultForbiddenFlags, undefined);
761
+ if ($sideEffect._isUnary || !step._isUnary) {
762
+ addDependency($sideEffect, defaultForbiddenFlags, undefined);
763
+ }
757
764
  }
758
765
  if (dev_js_1.isDev &&
759
766
  step.layerPlan.reason.type === "polymorphic" &&
@@ -768,7 +775,7 @@ function executeBucket(bucket, requestContext) {
768
775
  }
769
776
  const result = needsFiltering
770
777
  ? reallyExecuteStepWithFiltering(step, dependencies, _rawForbiddenFlags, _rawOnReject, bucket.polymorphicPathList, extra)
771
- : reallyExecuteStepWithoutFiltering(step._isUnary ? 1 : size, step, $sideEffect ? dependencies.slice(0, depCount) : dependencies, extra);
778
+ : reallyExecuteStepWithoutFiltering(size, step, $sideEffect ? dependencies.slice(0, depCount) : dependencies, extra);
772
779
  if ((0, utils_js_1.isPromiseLike)(result)) {
773
780
  return result.then(null, (error) => {
774
781
  // Don't need to do this here, it will be done where the
@@ -804,8 +811,10 @@ function executeBucket(bucket, requestContext) {
804
811
  * are called.
805
812
  */
806
813
  const enqueue = (callback) => {
807
- const result = (mutationQueue ?? Promise.resolve()).then(callback);
808
- mutationQueue = result.then(noop, noop);
814
+ const result = mutationQueue ? mutationQueue.then(callback) : callback();
815
+ if ((0, utils_js_1.isPromiseLike)(result)) {
816
+ mutationQueue = result.then(noop, noop);
817
+ }
809
818
  return result;
810
819
  };
811
820
  loop: for (const childLayerPlan of childLayerPlans) {
@@ -828,7 +837,9 @@ function executeBucket(bucket, requestContext) {
828
837
  if (childBucket !== null) {
829
838
  // Enqueue for execution (mutations must run in order)
830
839
  const promise = enqueue(() => executeBucket(childBucket, requestContext));
831
- childPromises.push(promise);
840
+ if ((0, utils_js_1.isPromiseLike)(promise)) {
841
+ childPromises.push(promise);
842
+ }
832
843
  }
833
844
  break;
834
845
  }
@@ -861,7 +872,6 @@ function executeBucket(bucket, requestContext) {
861
872
  }
862
873
  }
863
874
  }
864
- exports.executeBucket = executeBucket;
865
875
  /** @internal */
866
876
  function newBucket(spec, parentMetaByMetaKey) {
867
877
  if (dev_js_1.isDev) {
@@ -947,31 +957,60 @@ function newBucket(spec, parentMetaByMetaKey) {
947
957
  },
948
958
  };
949
959
  }
950
- exports.newBucket = newBucket;
951
960
  function bucketToString() {
952
961
  return `Bucket<${this.layerPlan}>`;
953
962
  }
954
- exports.bucketToString = bucketToString;
963
+ // NOTE: I evaluated using `__proto__: batchExecutionValueProto` to extract the
964
+ // shared properties of these objects to see if performance was improved, but
965
+ // this was actually a net loss in performance.
966
+ //
967
+ // This is also evidence that you shouldn't trust ChatGPT for performance
968
+ // advice, and should always run your own benchmarks instead:
969
+ // https://chatgpt.com/share/67d1746f-4da8-8012-bdf8-707e54a4238e
955
970
  // TODO: memoize?
956
971
  function batchExecutionValue(entries, _flags = (0, utils_js_1.arrayOfLength)(entries.length, 0)) {
957
- let cachedStateUnion = null;
958
972
  return {
959
- at: batchEntriesAt,
973
+ // Try and keep these properties in the same order as unaryExecutionValue
960
974
  isBatch: true,
961
- entries,
962
- _flags,
975
+ at: batchEntriesAt,
976
+ unaryValue: batchThrowNotUnary,
963
977
  _flagsAt: batchFlagsAt,
964
- _getStateUnion() {
965
- if (cachedStateUnion === null) {
966
- cachedStateUnion = _flags.reduce(bitwiseOr, interfaces_js_1.NO_FLAGS);
967
- }
968
- return cachedStateUnion;
969
- },
978
+ _getStateUnion: batchGetStateUnion,
970
979
  _setResult: batchSetResult,
971
- _copyResult,
980
+ _copyResult: batchCopyResult,
981
+ entries,
982
+ _flags,
983
+ _cachedStateUnion: null,
972
984
  };
973
985
  }
974
- exports.batchExecutionValue = batchExecutionValue;
986
+ // TODO: memoize?
987
+ function unaryExecutionValue(value, _entryFlags = 0) {
988
+ return {
989
+ // Try and keep these properties in the same order as batchExecutionValue
990
+ isBatch: false,
991
+ at: unaryAt,
992
+ unaryValue: unaryThisDotValue,
993
+ _flagsAt: unaryFlagsAt,
994
+ _getStateUnion: unaryGetStateUnion,
995
+ _setResult: unarySetResult,
996
+ _copyResult: unaryCopyResult,
997
+ value,
998
+ _entryFlags,
999
+ };
1000
+ }
1001
+ function batchThrowNotUnary() {
1002
+ throw new Error(`This is not a unary value so we cannot get the single value - there may be more than one!`);
1003
+ }
1004
+ function batchGetStateUnion() {
1005
+ if (this._cachedStateUnion === null) {
1006
+ let u = interfaces_js_1.NO_FLAGS;
1007
+ for (const flag of this._flags) {
1008
+ u = u | flag;
1009
+ }
1010
+ this._cachedStateUnion = u;
1011
+ }
1012
+ return this._cachedStateUnion;
1013
+ }
975
1014
  function batchEntriesAt(i) {
976
1015
  return this.entries[i];
977
1016
  }
@@ -982,26 +1021,17 @@ function batchSetResult(i, value, flags) {
982
1021
  this.entries[i] = value;
983
1022
  this._flags[i] = flags;
984
1023
  }
985
- function bitwiseOr(memo, a) {
986
- return memo | a;
1024
+ // NOTE: batchCopyResult and unaryCopyResult are **identical**, but we don't
1025
+ // want a single megamorphic function so we define it twice.
1026
+ function batchCopyResult(targetIndex, source, sourceIndex) {
1027
+ this._setResult(targetIndex, source.at(sourceIndex), source._flagsAt(sourceIndex));
987
1028
  }
988
- function _copyResult(targetIndex, source, sourceIndex) {
1029
+ function unaryCopyResult(targetIndex, source, sourceIndex) {
989
1030
  this._setResult(targetIndex, source.at(sourceIndex), source._flagsAt(sourceIndex));
990
1031
  }
991
- // TODO: memoize?
992
- function unaryExecutionValue(value, _entryFlags = 0) {
993
- return {
994
- at: unaryAt,
995
- isBatch: false,
996
- value,
997
- _entryFlags,
998
- _flagsAt: unaryFlagsAt,
999
- _getStateUnion: unaryGetStateUnion,
1000
- _setResult: unarySetResult,
1001
- _copyResult,
1002
- };
1032
+ function unaryThisDotValue() {
1033
+ return this.value;
1003
1034
  }
1004
- exports.unaryExecutionValue = unaryExecutionValue;
1005
1035
  function unaryAt() {
1006
1036
  return this.value;
1007
1037
  }
@@ -1052,10 +1082,21 @@ function makeIndexForEach(count) {
1052
1082
  }
1053
1083
  return result;
1054
1084
  }
1055
- function streamStepFromEvent(event) {
1056
- return event.step.stream(event.streamDetails);
1057
- }
1058
1085
  function executeStepFromEvent(event) {
1059
1086
  return event.step.execute(event.executeDetails);
1060
1087
  }
1088
+ function evaluateStream(bucket, step) {
1089
+ const stream = step._stepOptions.stream;
1090
+ if (!stream)
1091
+ return null;
1092
+ const shouldStream = stream.ifStepId == null
1093
+ ? true
1094
+ : (bucket.store.get(stream.ifStepId)?.unaryValue() ?? true);
1095
+ if (!shouldStream)
1096
+ return null;
1097
+ const initialCount = stream.initialCountStepId == null
1098
+ ? 0
1099
+ : (bucket.store.get(stream.initialCountStepId)?.unaryValue() ?? 0);
1100
+ return { initialCount };
1101
+ }
1061
1102
  //# sourceMappingURL=executeBucket.js.map
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.executeOutputPlan = void 0;
3
+ exports.executeOutputPlan = executeOutputPlan;
4
4
  const tslib_1 = require("tslib");
5
5
  const debug_1 = tslib_1.__importDefault(require("debug"));
6
6
  const assert = tslib_1.__importStar(require("../assert.js"));
@@ -23,5 +23,4 @@ function executeOutputPlan(ctx, outputPlan, bucket, bucketIndex, outputDataAsStr
23
23
  ? outputPlan.executeString(ctx.root, mutablePath, bucket, bucketIndex)
24
24
  : outputPlan.execute(ctx.root, mutablePath, bucket, bucketIndex);
25
25
  }
26
- exports.executeOutputPlan = executeOutputPlan;
27
26
  //# sourceMappingURL=executeOutputPlan.js.map
@@ -0,0 +1,6 @@
1
+ import type { FieldPlanResolver } from "../../interfaces.js";
2
+ import type { Step } from "../../step.js";
3
+ export declare const defaultPlanResolver: FieldPlanResolver<any, Step & {
4
+ get?: (field: string) => Step;
5
+ }, any>;
6
+ //# sourceMappingURL=defaultPlanResolver.d.ts.map
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultPlanResolver = void 0;
4
+ const access_js_1 = require("../../steps/access.js");
5
+ const defaultPlanResolver = ($step, _, { fieldName }) => {
6
+ return typeof $step.get === "function"
7
+ ? $step.get(fieldName)
8
+ : (0, access_js_1.access)($step, [fieldName]);
9
+ };
10
+ exports.defaultPlanResolver = defaultPlanResolver;
11
+ //# sourceMappingURL=defaultPlanResolver.js.map
@@ -1,7 +1,7 @@
1
- import type { ExecutableStep } from "../..";
1
+ import type { Step } from "../..";
2
2
  import type { LayerPlan } from "../LayerPlan";
3
3
  export declare function withGlobalLayerPlan<T, TThis = any, TArgs extends [...args: any[]] = [...args: any[]]>(layerPlan: LayerPlan, polymorphicPaths: ReadonlySet<string> | null, callback: (this: TThis, ...args: TArgs) => T, callbackThis?: TThis, ...callbackArgs: TArgs): T;
4
4
  export declare function currentLayerPlan(): LayerPlan;
5
5
  export declare function currentPolymorphicPaths(): ReadonlySet<string> | null;
6
- export declare function isUnaryStep($step: ExecutableStep): boolean;
6
+ export declare function isUnaryStep($step: Step): boolean;
7
7
  //# sourceMappingURL=withGlobalLayerPlan.d.ts.map
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isUnaryStep = exports.currentPolymorphicPaths = exports.currentLayerPlan = exports.withGlobalLayerPlan = void 0;
3
+ exports.withGlobalLayerPlan = withGlobalLayerPlan;
4
+ exports.currentLayerPlan = currentLayerPlan;
5
+ exports.currentPolymorphicPaths = currentPolymorphicPaths;
6
+ exports.isUnaryStep = isUnaryStep;
4
7
  let globalData_layerPlan = undefined;
5
8
  let globalData_polymorphicPaths = undefined;
6
9
  function withGlobalLayerPlan(layerPlan, polymorphicPaths, callback, callbackThis, ...callbackArgs) {
@@ -16,7 +19,6 @@ function withGlobalLayerPlan(layerPlan, polymorphicPaths, callback, callbackThis
16
19
  globalData_polymorphicPaths = oldPolymorphicPaths;
17
20
  }
18
21
  }
19
- exports.withGlobalLayerPlan = withGlobalLayerPlan;
20
22
  function currentLayerPlan() {
21
23
  if (globalData_layerPlan === undefined) {
22
24
  throw new Error(
@@ -25,16 +27,13 @@ function currentLayerPlan() {
25
27
  }
26
28
  return globalData_layerPlan;
27
29
  }
28
- exports.currentLayerPlan = currentLayerPlan;
29
30
  function currentPolymorphicPaths() {
30
31
  if (globalData_polymorphicPaths === undefined) {
31
32
  throw new Error("GrafastInternalError<b0b05743-8b21-42c6-9b53-925013d88bd1>: currentPolymorphicPaths called out of turn; must only called within a withGlobalLayerPlan callback");
32
33
  }
33
34
  return globalData_polymorphicPaths;
34
35
  }
35
- exports.currentPolymorphicPaths = currentPolymorphicPaths;
36
36
  function isUnaryStep($step) {
37
37
  return $step._isUnary;
38
38
  }
39
- exports.isUnaryStep = isUnaryStep;
40
39
  //# sourceMappingURL=withGlobalLayerPlan.js.map
@@ -1,4 +1,4 @@
1
- import type { ExecutableStep } from "..";
2
- export declare function lock($step: ExecutableStep): void;
3
- export declare function unlock($step: ExecutableStep): boolean;
1
+ import type { Step } from "..";
2
+ export declare function lock($step: Step): void;
3
+ export declare function unlock($step: Step): boolean;
4
4
  //# sourceMappingURL=lock.d.ts.map