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
package/dist/mermaid.js CHANGED
@@ -65,9 +65,6 @@ exports.mermaidEscape = mermaidEscape;
65
65
  function isGrafastPlanJSONv1(json) {
66
66
  return json.version === "v1";
67
67
  }
68
- function shouldHideStep(step) {
69
- return step.extra?.constant?.type === "undefined";
70
- }
71
68
  function planToMermaid(planJSON, {
72
69
  // printPathRelations = false,
73
70
  concise = false, skipBuckets = global.grafastExplainMermaidSkipBuckets ?? false, } = {}) {
@@ -79,6 +76,9 @@ concise = false, skipBuckets = global.grafastExplainMermaidSkipBuckets ?? false,
79
76
  const dependentsByStepId = Object.create(null);
80
77
  const sortedSteps = [];
81
78
  const extractSteps = (bucket) => {
79
+ if (layerPlanById[bucket.id]) {
80
+ throw new Error(`Two buckets with the same ID ${bucket.id}?`);
81
+ }
82
82
  layerPlanById[bucket.id] = bucket;
83
83
  // Shallowest bucket first, then most dependencies
84
84
  const sorted = [...bucket.steps].sort((a, z) => z.dependencyIds.length - a.dependencyIds.length);
@@ -97,11 +97,46 @@ concise = false, skipBuckets = global.grafastExplainMermaidSkipBuckets ?? false,
97
97
  }
98
98
  }
99
99
  }
100
- for (const child of bucket.children) {
101
- extractSteps(child);
100
+ };
101
+ planJSON.buckets.forEach(extractSteps);
102
+ const shouldHideStep = (step) => {
103
+ if (step.stepClass === "ConstantStep")
104
+ return true;
105
+ if (step.extra?.constant?.type === "undefined") {
106
+ return true;
107
+ }
108
+ if (step.bucketId === 0 &&
109
+ step.isSyncAndSafe &&
110
+ (dependentsByStepId[step.id]?.length ?? 0) === 0) {
111
+ return true;
112
+ }
113
+ return false;
114
+ };
115
+ const partitionToPoly = (bucketId) => {
116
+ const lp = layerPlanById[bucketId];
117
+ if (lp.reason.type === "polymorphicPartition") {
118
+ return layerPlans.find((lp) => lp.childIds.includes(bucketId));
119
+ }
120
+ else {
121
+ return bucketId;
102
122
  }
103
123
  };
104
- extractSteps(planJSON.rootBucket);
124
+ const isExcessivelyReferenced = (stepId) => {
125
+ const step = stepById[stepId];
126
+ if (!step)
127
+ return true;
128
+ if (step.stepClass === "ConstantStep")
129
+ return true;
130
+ if (step.bucketId !== 0)
131
+ return false;
132
+ const dependents = dependentsByStepId[stepId];
133
+ if (!dependents || dependents.length === 0)
134
+ return false;
135
+ const firstDependent = dependents[0];
136
+ // If it's referenced by more than one layer plan, it's excessive
137
+ return dependents.some((d) => partitionToPoly(d.bucketId) !==
138
+ partitionToPoly(firstDependent.bucketId));
139
+ };
105
140
  const color = (i) => {
106
141
  return exports.COLORS[i % exports.COLORS.length];
107
142
  };
@@ -126,6 +161,45 @@ concise = false, skipBuckets = global.grafastExplainMermaidSkipBuckets ?? false,
126
161
  }
127
162
  return str;
128
163
  };
164
+ const stepToString = (step) => {
165
+ return `${step.stepClass.replace(/Step$/, "")}${step.bucketId === 0 ? "" : `{${step.bucketId}}`}${step.metaString ? `<${step.metaString}>` : ""}[${step.id}]`;
166
+ };
167
+ const layerPlans = Object.values(layerPlanById);
168
+ if (!skipBuckets) {
169
+ if (!concise)
170
+ graph.push(" subgraph Buckets");
171
+ for (let i = 0, l = layerPlans.length; i < l; i++) {
172
+ const layerPlan = layerPlans[i];
173
+ const raisonDEtre = ` (${layerPlan.reason.type})` +
174
+ (layerPlan.reason.type === "polymorphicPartition"
175
+ ? `\n|${layerPlan.reason.typeNames.join("\n|")}`
176
+ : layerPlan.reason.type === "polymorphic"
177
+ ? `\n__typename: ${shortStep(stepById[layerPlan.reason.parentStepId])}`
178
+ : ``);
179
+ graph.push(` Bucket${layerPlan.id}(${(0, exports.mermaidEscape)(`Bucket ${layerPlan.id}${raisonDEtre}${layerPlan.parentSideEffectStepId != null
180
+ ? `\nParent side effect step: ${stepById[layerPlan.parentSideEffectStepId].id}`
181
+ : ""}${layerPlan.copyStepIds.length > 0
182
+ ? `\nDeps: ${layerPlan.copyStepIds
183
+ .map((pId) => stepById[pId].id)
184
+ .join(", ")}`
185
+ : ""}${layerPlan.reason.type === "polymorphicPartition"
186
+ ? "\n" + pp(layerPlan.reason.polymorphicPaths)
187
+ : ""}\n${layerPlan.rootStepId != null && layerPlan.reason.type !== "root"
188
+ ? `\nROOT ${stepToString(stepById[layerPlan.rootStepId])}`
189
+ : ""}${startSteps(layerPlan)}`)}):::bucket`);
190
+ }
191
+ if (!concise)
192
+ graph.push(" end");
193
+ }
194
+ if (!skipBuckets) {
195
+ for (let i = 0, l = layerPlans.length; i < l; i++) {
196
+ const layerPlan = layerPlans[i];
197
+ const childNodes = layerPlan.childIds.map((cId) => `Bucket${cId}`);
198
+ if (childNodes.length > 0) {
199
+ graph.push(` Bucket${layerPlan.id} --> ${childNodes.join(" & ")}`);
200
+ }
201
+ }
202
+ }
129
203
  const planIdMap = Object.create(null);
130
204
  const planId = (plan) => {
131
205
  if (!planIdMap[plan.id]) {
@@ -140,18 +214,32 @@ concise = false, skipBuckets = global.grafastExplainMermaidSkipBuckets ?? false,
140
214
  const meta = concise && strippedMeta ? squish(strippedMeta) : strippedMeta;
141
215
  const isUnbatched = plan.supportsUnbatched;
142
216
  const polyPaths = pp(plan.polymorphicPaths);
143
- const polyPathsIfDifferent = plan.dependencyIds.length === 1 &&
144
- pp(stepById[plan.dependencyIds[0]].polymorphicPaths) === polyPaths
145
- ? ""
146
- : `\n${polyPaths}`;
147
- const planString = `${planName}[${plan.id}${`∈${plan.bucketId}`}${plan.stream ? "@s" : ""}]${plan.isUnary ? " ➊" : ""}${meta ? `\n<${meta}>` : ""}${polyPathsIfDifferent}`;
148
- const [lBrace, rBrace] = plan.stepClass === "__ItemStep"
217
+ const depIdsInSameBucket = plan.dependencyIds.filter((id) => stepById[id].bucketId === plan.bucketId);
218
+ const polyPathsAreSame = depIdsInSameBucket.length >= 1 &&
219
+ depIdsInSameBucket.every((id) => pp(stepById[id].polymorphicPaths) === polyPaths);
220
+ const polyPathsIfDifferent = polyPathsAreSame || polyPaths === "" ? "" : `\n${polyPaths}`;
221
+ const [lBrace, rBrace, shape = "", planNameText = planName] = plan.stepClass === "__ItemStep"
149
222
  ? ["[/", "\\]"]
150
- : plan.isSyncAndSafe
151
- ? isUnbatched
152
- ? ["{{", "}}"]
153
- : ["[", "]"]
154
- : ["[[", "]]"];
223
+ : plan.stepClass === "__ValueStep" && plan.extra?.combined
224
+ ? [null, null, "docs", "__Combined"]
225
+ : plan.isSyncAndSafe
226
+ ? isUnbatched
227
+ ? ["{{", "}}"]
228
+ : ["[", "]"]
229
+ : ["[[", "]]"];
230
+ const depCount = isExcessivelyReferenced(plan.id)
231
+ ? `\nDependents: ${dependentsByStepId[plan.id]?.length}`
232
+ : ``;
233
+ const extraDeps = plan.dependencyIds.filter(isExcessivelyReferenced);
234
+ const extraDependencies = extraDeps.length > 0
235
+ ? `\nMore deps:\n${extraDeps
236
+ .map((depId) => {
237
+ const step = stepById[depId];
238
+ return `- ${shortStep(step)}`;
239
+ })
240
+ .join("\n")}`
241
+ : ``;
242
+ const planString = `${planNameText}[${plan.id}${`∈${plan.bucketId}`}${plan.stream ? "@s" : ""}]${plan.isUnary ? " ➊" : ""}${polyPathsAreSame && polyPaths !== "" ? "^" : ""}${meta ? `\n<${meta}>` : ""}${polyPathsIfDifferent}${depCount}${extraDependencies}`;
155
243
  const planClass = plan.hasSideEffects
156
244
  ? "sideeffectplan"
157
245
  : plan.stepClass === "__ItemStep"
@@ -159,7 +247,12 @@ concise = false, skipBuckets = global.grafastExplainMermaidSkipBuckets ?? false,
159
247
  : isUnbatched && !plan.isSyncAndSafe
160
248
  ? "unbatchedplan"
161
249
  : "plan";
162
- graph.push(` ${planNode}${lBrace}${(0, exports.mermaidEscape)(planString)}${rBrace}:::${planClass}`);
250
+ if (lBrace === null) {
251
+ graph.push(` ${planNode}:::${planClass}@{shape: ${shape}, label: ${(0, exports.mermaidEscape)(planString)}}`);
252
+ }
253
+ else {
254
+ graph.push(` ${planNode}${lBrace}${(0, exports.mermaidEscape)(planString)}${rBrace}:::${planClass}`);
255
+ }
163
256
  }
164
257
  return planIdMap[plan.id];
165
258
  };
@@ -169,6 +262,9 @@ concise = false, skipBuckets = global.grafastExplainMermaidSkipBuckets ?? false,
169
262
  const depDeets = (step, idx) => {
170
263
  const forbiddenFlags = step.dependencyForbiddenFlags[idx];
171
264
  const onReject = step.dependencyOnReject[idx];
265
+ // TODO: factor 'data only' into the diagrams
266
+ //
267
+ // const dataOnly = step.dependencyDataOnly[idx];
172
268
  const info = [];
173
269
  if (forbiddenFlags) {
174
270
  if ((forbiddenFlags & 2) === 2) {
@@ -198,17 +294,15 @@ concise = false, skipBuckets = global.grafastExplainMermaidSkipBuckets ?? false,
198
294
  if (shouldHideStep(plan))
199
295
  return;
200
296
  const planNode = planId(plan);
201
- const depNodes = plan.dependencyIds
202
- .map((depId) => {
297
+ const depNodes = plan.dependencyIds.map((depId) => {
203
298
  const step = stepById[depId];
204
- if (shouldHideStep(step)) {
299
+ if (shouldHideStep(step) || isExcessivelyReferenced(depId)) {
205
300
  return null;
206
301
  }
207
302
  else {
208
303
  return planId(step);
209
304
  }
210
- })
211
- .filter((n) => n !== null);
305
+ });
212
306
  const transformItemPlanNode = null;
213
307
  /*
214
308
  plan.stepClass === '__ListTransformStep'
@@ -217,23 +311,25 @@ concise = false, skipBuckets = global.grafastExplainMermaidSkipBuckets ?? false,
217
311
  )
218
312
  : null;
219
313
  */
220
- if (depNodes.length > 0) {
314
+ const firstDep = depNodes.find((n) => n != null);
315
+ if (depNodes.length > 0 && firstDep) {
221
316
  if (plan.stepClass === "__ItemStep") {
222
- const [firstDep, ...rest] = depNodes;
223
317
  const arrow = plan.extra?.transformStepId == null ? "==>" : "-.->";
224
318
  graph.push(` ${firstDep} ${arrow}${depDeets(plan, 0)} ${planNode}`);
225
- if (rest.length > 0) {
226
- const normal = [];
227
- for (let i = 0; i < rest.length; i++) {
228
- const r = rest[i];
229
- const deets = depDeets(plan, i + 1);
230
- if (deets) {
231
- graph.push(` ${r} -->${deets} ${planNode}`);
232
- }
233
- else {
234
- normal.push(r);
235
- }
319
+ const normal = [];
320
+ for (let i = 0; i < depNodes.length; i++) {
321
+ const r = depNodes[i];
322
+ if (r == null || r === firstDep)
323
+ continue;
324
+ const deets = depDeets(plan, i);
325
+ if (deets) {
326
+ graph.push(` ${r} -->${deets} ${planNode}`);
327
+ }
328
+ else {
329
+ normal.push(r);
236
330
  }
331
+ }
332
+ if (normal.length > 0) {
237
333
  outputGroupedNormalLinks(graph, planNode, normal);
238
334
  }
239
335
  }
@@ -242,20 +338,21 @@ concise = false, skipBuckets = global.grafastExplainMermaidSkipBuckets ?? false,
242
338
  !dependentsByStepId[plan.id] &&
243
339
  depNodes.length === 1) {
244
340
  // Try alternating the nodes so they render closer together
245
- const depNode = depNodes[0];
246
- if (chainByDep[depNode] === undefined) {
247
- graph.push(` ${depNode} -->${depDeets(plan, 0)} ${planNode}`);
341
+ if (chainByDep[firstDep] === undefined) {
342
+ graph.push(` ${firstDep} -->${depDeets(plan, 0)} ${planNode}`);
248
343
  }
249
344
  else {
250
- graph.push(` ${chainByDep[depNode]} o--o${depDeets(plan, 0)} ${planNode}`);
345
+ graph.push(` ${chainByDep[firstDep]} o--o${depDeets(plan, 0)} ${planNode}`);
251
346
  }
252
- chainByDep[depNode] = planNode;
347
+ chainByDep[firstDep] = planNode;
253
348
  }
254
349
  else {
255
350
  const normal = [];
256
351
  for (let i = 0; i < depNodes.length; i++) {
257
352
  const r = depNodes[i];
258
- const deets = depDeets(plan, i + 1);
353
+ if (r == null)
354
+ continue;
355
+ const deets = depDeets(plan, i);
259
356
  if (deets) {
260
357
  graph.push(` ${r} -->${deets} ${planNode}`);
261
358
  }
@@ -279,9 +376,15 @@ concise = false, skipBuckets = global.grafastExplainMermaidSkipBuckets ?? false,
279
376
  planId(step);
280
377
  }
281
378
  });
282
- const stepToString = (step) => {
283
- return `${step.stepClass.replace(/Step$/, "")}${step.bucketId === 0 ? "" : `{${step.bucketId}}`}${step.metaString ? `<${step.metaString}>` : ""}[${step.id}]`;
284
- };
379
+ for (let i = 0, l = layerPlans.length; i < l; i++) {
380
+ const layerPlan = layerPlans[i];
381
+ const steps = layerPlan.steps;
382
+ graph.push(` classDef bucket${layerPlan.id} stroke:${color(typeof layerPlan.id === "number" ? layerPlan.id : Object.values(layerPlanById).indexOf(layerPlan))}`);
383
+ graph.push(` class ${[
384
+ `Bucket${layerPlan.id}`,
385
+ ...steps.filter((s) => !shouldHideStep(s)).map(planId),
386
+ ].join(",")} bucket${layerPlan.id}`);
387
+ }
285
388
  let firstSideEffect = true;
286
389
  sortedSteps.forEach((step) => {
287
390
  if (step.implicitSideEffectStepId) {
@@ -295,64 +398,22 @@ concise = false, skipBuckets = global.grafastExplainMermaidSkipBuckets ?? false,
295
398
  }
296
399
  });
297
400
  graph.push("");
298
- if (!concise && !skipBuckets)
299
- graph.push(" subgraph Buckets");
300
- const layerPlans = Object.values(layerPlanById);
401
+ // Handle concat for any "combination" layer plans
301
402
  for (let i = 0, l = layerPlans.length; i < l; i++) {
302
403
  const layerPlan = layerPlans[i];
303
- const steps = layerPlan.steps;
304
- const raisonDEtre = ` (${layerPlan.reason.type})` +
305
- (layerPlan.reason.type === "polymorphic"
306
- ? `\n${layerPlan.reason.typeNames}`
307
- : ``);
308
- if (!skipBuckets) {
309
- graph.push(` Bucket${layerPlan.id}(${(0, exports.mermaidEscape)(`Bucket ${layerPlan.id}${raisonDEtre}${layerPlan.parentSideEffectStepId != null
310
- ? `\nParent side effect step: ${stepById[layerPlan.parentSideEffectStepId].id}`
311
- : ""}${layerPlan.copyStepIds.length > 0
312
- ? `\nDeps: ${layerPlan.copyStepIds
313
- .map((pId) => stepById[pId].id)
314
- .join(", ")}`
315
- : ""}${layerPlan.reason.type === "polymorphic"
316
- ? "\n" + pp(layerPlan.reason.polymorphicPaths)
317
- : ""}\n${layerPlan.rootStepId != null && layerPlan.reason.type !== "root"
318
- ? `\nROOT ${stepToString(stepById[layerPlan.rootStepId])}`
319
- : ""}${startSteps(layerPlan)}`)}):::bucket`);
320
- }
321
- graph.push(` classDef bucket${layerPlan.id} stroke:${color(layerPlan.id)}`);
322
- graph.push(` class ${[
323
- `Bucket${layerPlan.id}`,
324
- ...steps.filter((s) => !shouldHideStep(s)).map(planId),
325
- ].join(",")} bucket${layerPlan.id}`);
326
- }
327
- if (!skipBuckets) {
328
- for (let i = 0, l = layerPlans.length; i < l; i++) {
329
- const layerPlan = layerPlans[i];
330
- const childNodes = layerPlan.children.map((c) => `Bucket${c.id}`);
331
- if (childNodes.length > 0) {
332
- graph.push(` Bucket${layerPlan.id} --> ${childNodes.join(" & ")}`);
404
+ if (layerPlan.reason.type === "combined") {
405
+ for (const { targetStepId, sources } of layerPlan.reason.combinations) {
406
+ const targetStep = stepById[targetStepId];
407
+ for (const { stepId } of sources) {
408
+ const step = stepById[stepId];
409
+ graph.push(` ${planId(step)} -.-x ${planId(targetStep)}`);
410
+ }
333
411
  }
334
412
  }
335
413
  }
336
- if (!concise && !skipBuckets)
337
- graph.push(" end");
338
414
  const graphString = graph.join("\n");
339
415
  return graphString;
340
416
  function startSteps(layerPlan) {
341
- function shortStep(step) {
342
- return `${step.stepClass.replace(/Step$/, "") ?? ""}[${step.id}]`;
343
- }
344
- function shortSteps(steps) {
345
- if (!steps) {
346
- return "";
347
- }
348
- const str = steps.map(shortStep).join(", ");
349
- if (str.length < 40) {
350
- return str;
351
- }
352
- else {
353
- return steps.map((s) => s.id).join(", ");
354
- }
355
- }
356
417
  return layerPlan.phases.length === 1
357
418
  ? ``
358
419
  : `\n${layerPlan.phases
@@ -362,11 +423,51 @@ concise = false, skipBuckets = global.grafastExplainMermaidSkipBuckets ?? false,
362
423
  .join("\n")}`;
363
424
  }
364
425
  }
426
+ function shortStep(step) {
427
+ if (step.stepClass === "ConstantStep") {
428
+ return `Constant${step.metaString ? `<${step.metaString}>` : ""}[${step.id}]`;
429
+ }
430
+ return `${step.stepClass.replace(/Step$/, "") ?? ""}[${step.id}]`;
431
+ }
432
+ function shortSteps(steps) {
433
+ if (!steps) {
434
+ return "";
435
+ }
436
+ const str = steps.map(shortStep).join(", ");
437
+ if (str.length < 40) {
438
+ return str;
439
+ }
440
+ else {
441
+ return steps.map((s) => s.id).join(", ");
442
+ }
443
+ }
365
444
  function pp(polymorphicPaths) {
366
- if (!polymorphicPaths) {
445
+ if (polymorphicPaths == null) {
367
446
  return "";
368
447
  }
369
- return polymorphicPaths.map((p) => `${p}`).join("\n");
448
+ const counts = Object.create(null);
449
+ const out = [];
450
+ const last = Object.create(null);
451
+ for (const p of polymorphicPaths) {
452
+ const i = p.lastIndexOf(">");
453
+ if (i <= 0) {
454
+ out.push(p);
455
+ }
456
+ else {
457
+ const end = p.slice(i);
458
+ last[end] = p;
459
+ if (counts[end]) {
460
+ counts[end]++;
461
+ }
462
+ else {
463
+ counts[end] = 1;
464
+ }
465
+ }
466
+ }
467
+ for (const [end, count] of Object.entries(counts)) {
468
+ out.push(count === 1 ? last[end] : `(${count}) ...${end}`);
469
+ }
470
+ return out.join("\n");
370
471
  }
371
472
  tslib_1.__exportStar(require("./planJSONInterfaces.js"), exports);
372
473
  function trim(string, length = 15) {
@@ -3,6 +3,6 @@ import type { OperationPlan } from "./engine/OperationPlan.js";
3
3
  import type { FieldArgs, TrackedArguments } from "./interfaces.js";
4
4
  import type { Step } from "./step.js";
5
5
  export type ApplyAfterModeArg = "plan" | "subscribePlan";
6
- export declare function withFieldArgsForArguments<T extends Step>(operationPlan: OperationPlan, $all: TrackedArguments, field: GraphQLField<any, any, any>, $parent: Step, applyAfterMode: ApplyAfterModeArg, coordinate: string, callback: (fieldArgs: FieldArgs) => T | null | undefined): Exclude<T, undefined | null> | null;
6
+ export declare function withFieldArgsForArguments<T extends Step>(operationPlan: OperationPlan, trackedArguments: TrackedArguments, field: GraphQLField<any, any, any>, $parent: Step, applyAfterMode: ApplyAfterModeArg, coordinate: string, callback: (fieldArgs: FieldArgs) => T | null | undefined): T | null;
7
7
  export declare function getNullableInputTypeAtPath(startType: GraphQLInputType, path: ReadonlyArray<string | number>): GraphQLInputType & GraphQLNullableType;
8
8
  //# sourceMappingURL=operationPlan-input.d.ts.map
@@ -13,7 +13,7 @@ function assertNotRuntime(operationPlan, description) {
13
13
  throw new Error(`${description} may only be called at planning time; however you have code that has attempted to call it during execution time. Please revisit your plan resolvers to locate the issue.`);
14
14
  }
15
15
  }
16
- function withFieldArgsForArguments(operationPlan, $all, field, $parent, applyAfterMode, coordinate, callback) {
16
+ function withFieldArgsForArguments(operationPlan, trackedArguments, field, $parent, applyAfterMode, coordinate, callback) {
17
17
  if (operationPlan.loc !== null)
18
18
  operationPlan.loc.push(`withFieldArgsForArguments(${field.name})`);
19
19
  const args = Object.create(null);
@@ -62,17 +62,17 @@ function withFieldArgsForArguments(operationPlan, $all, field, $parent, applyAft
62
62
  getRaw(path) {
63
63
  assertNotRuntime(operationPlan, `fieldArgs.getRaw()`);
64
64
  if (path === undefined) {
65
- return (0, index_js_1.object)(Object.fromEntries(Object.keys(args).map((argName) => [argName, $all.get(argName)])));
65
+ return (0, index_js_1.object)(trackedArguments);
66
66
  }
67
67
  else if (typeof path === "string") {
68
- return $all.get(path);
68
+ return trackedArguments[path];
69
69
  }
70
70
  else if (Array.isArray(path)) {
71
71
  const [first, ...rest] = path;
72
72
  if (!first) {
73
73
  throw new Error(`getRaw() must be called with a non-empty path`);
74
74
  }
75
- let $entry = $all.get(first);
75
+ let $entry = trackedArguments[first];
76
76
  for (const pathSegment of rest) {
77
77
  if (typeof pathSegment === "number" && "at" in $entry) {
78
78
  $entry = $entry.at(pathSegment);
@@ -141,13 +141,16 @@ function withFieldArgsForArguments(operationPlan, $all, field, $parent, applyAft
141
141
  });
142
142
  }
143
143
  const result = callback(fieldArgs);
144
+ if (result === undefined) {
145
+ throw new Error(`Field ${coordinate} returned 'undefined'; perhaps you forgot the 'return' statement?`);
146
+ }
144
147
  (0, utils_js_1.assertNotPromise)(result, callback, operationPlan.loc?.join(">") ?? "???");
145
148
  if (!explicitlyApplied && result != null) {
146
149
  processAfter($parent, fieldArgs, result, args, applyAfterMode, coordinate);
147
150
  }
148
151
  if (operationPlan.loc !== null)
149
152
  operationPlan.loc.pop();
150
- return (result ?? null);
153
+ return result;
151
154
  }
152
155
  function processAfter($parent, rootFieldArgs, $result, args, applyAfterMode, coordinate) {
153
156
  const schema = $parent.operationPlan.schema;
@@ -158,6 +161,13 @@ function processAfter($parent, rootFieldArgs, $result, args, applyAfterMode, coo
158
161
  ? arg.extensions.grafast?.applySubscribePlan
159
162
  : null;
160
163
  if (autoApply) {
164
+ if (arg.defaultValue === undefined) {
165
+ const $argVal = rootFieldArgs.getRaw(argName);
166
+ if ($argVal instanceof index_js_1.ConstantStep && $argVal.data === undefined) {
167
+ // no action necessary
168
+ continue;
169
+ }
170
+ }
161
171
  // TODO: should this have dollars on it for accessing subkeys?
162
172
  const input = {
163
173
  typeAt(path) {
@@ -12,6 +12,7 @@ export interface GrafastPlanStepJSONv1 {
12
12
  dependencyIds: ReadonlyArray<string | number>;
13
13
  dependencyForbiddenFlags: ReadonlyArray<ExecutionEntryFlags>;
14
14
  dependencyOnReject: ReadonlyArray<string | null | undefined>;
15
+ dependencyDataOnly: ReadonlyArray<boolean>;
15
16
  polymorphicPaths: readonly string[] | undefined;
16
17
  isSyncAndSafe: boolean | undefined;
17
18
  supportsUnbatched: boolean | undefined;
@@ -25,7 +26,7 @@ export interface GrafastPlanBucketPhaseJSONv1 {
25
26
  normalStepIds?: ReadonlyArray<string | number>;
26
27
  unbatchedStepIds?: ReadonlyArray<string | number>;
27
28
  }
28
- export type GrafastPlanBucketReasonJSONv1 = GrafastPlanBucketReasonRootJSONv1 | GrafastPlanBucketReasonNullableFieldJSONv1 | GrafastPlanBucketReasonListItemJSONv1 | GrafastPlanBucketReasonSubscriptionJSONv1 | GrafastPlanBucketReasonMutationFieldJSONv1 | GrafastPlanBucketReasonDeferJSONv1 | GrafastPlanBucketReasonPolymorphicJSONv1 | GrafastPlanBucketReasonSubroutineJSONv1;
29
+ export type GrafastPlanBucketReasonJSONv1 = GrafastPlanBucketReasonRootJSONv1 | GrafastPlanBucketReasonNullableFieldJSONv1 | GrafastPlanBucketReasonListItemJSONv1 | GrafastPlanBucketReasonSubscriptionJSONv1 | GrafastPlanBucketReasonMutationFieldJSONv1 | GrafastPlanBucketReasonDeferJSONv1 | GrafastPlanBucketReasonPolymorphicJSONv1 | GrafastPlanBucketReasonPolymorphicPartitionJSONv1 | GrafastPlanBucketReasonCombinedJSONv1 | GrafastPlanBucketReasonSubroutineJSONv1;
29
30
  export interface GrafastPlanBucketReasonRootJSONv1 {
30
31
  type: "root";
31
32
  }
@@ -59,31 +60,49 @@ export interface GrafastPlanBucketReasonDeferJSONv1 {
59
60
  type: "defer";
60
61
  label?: string;
61
62
  }
62
- /** Branching, non-deferred */
63
+ /** Non-branching, non-deferred */
63
64
  export interface GrafastPlanBucketReasonPolymorphicJSONv1 {
64
65
  type: "polymorphic";
65
66
  typeNames: readonly string[];
66
67
  parentStepId: string | number;
67
68
  polymorphicPaths: ReadonlyArray<string>;
68
69
  }
70
+ /** Branching, non-deferred */
71
+ export interface GrafastPlanBucketReasonPolymorphicPartitionJSONv1 {
72
+ type: "polymorphicPartition";
73
+ typeNames: readonly string[];
74
+ polymorphicPaths: ReadonlyArray<string>;
75
+ }
69
76
  /** Non-branching, non-deferred */
70
77
  export interface GrafastPlanBucketReasonSubroutineJSONv1 {
71
78
  type: "subroutine";
72
79
  parentStepId: string | number;
73
80
  }
81
+ /** Anti-branching, non-deferred */
82
+ export interface GrafastPlanBucketReasonCombinedJSONv1 {
83
+ type: "combined";
84
+ parentLayerPlanIds: ReadonlyArray<string | number>;
85
+ combinations: ReadonlyArray<{
86
+ sources: readonly {
87
+ layerPlanId: string | number;
88
+ stepId: string | number;
89
+ }[];
90
+ targetStepId: number;
91
+ }>;
92
+ }
74
93
  export interface GrafastPlanBucketJSONv1 {
75
- id: number;
94
+ id: number | string;
76
95
  reason: GrafastPlanBucketReasonJSONv1;
77
96
  parentSideEffectStepId: string | number | null;
78
97
  copyStepIds: ReadonlyArray<string | number>;
79
98
  steps: ReadonlyArray<GrafastPlanStepJSONv1>;
80
99
  rootStepId: string | number | null;
81
100
  phases: ReadonlyArray<GrafastPlanBucketPhaseJSONv1>;
82
- children: ReadonlyArray<GrafastPlanBucketJSONv1>;
101
+ childIds: ReadonlyArray<number | string>;
83
102
  }
84
103
  export interface GrafastPlanJSONv1 extends GrafastPlanJSON {
85
104
  version: "v1";
86
- rootBucket: GrafastPlanBucketJSONv1;
105
+ buckets: ReadonlyArray<GrafastPlanBucketJSONv1>;
87
106
  }
88
107
  export type JSONValue = boolean | number | string | null | JSONObject | JSONArray;
89
108
  export interface JSONObject {
package/dist/prepare.d.ts CHANGED
@@ -1,7 +1,5 @@
1
- import type { GrafastPlanJSON } from "./index.js";
2
1
  import type { GrafastTimeouts } from "./interfaces.js";
3
- declare const $$contextPlanCache: unique symbol;
4
- export interface GrafastPrepareOptions {
2
+ export interface GrafastOperationOptions {
5
3
  /**
6
4
  * A list of 'explain' types that should be included in `extensions.explain`.
7
5
  *
@@ -18,11 +16,20 @@ export interface GrafastPrepareOptions {
18
16
  */
19
17
  outputDataAsString?: boolean;
20
18
  timeouts?: GrafastTimeouts;
19
+ /**
20
+ * How many planning layers deep do we allow? Should be handled by validation.
21
+ *
22
+ * A planning layer can happen due to:
23
+ *
24
+ * - A nested selection set
25
+ * - Planning a field return type
26
+ * - A list position
27
+ * - A polymorphic type
28
+ * - A deferred/streamed response
29
+ *
30
+ * These reasons may each cause 1, 2 or 3 planning layers to be added, so this
31
+ * limit should be set quite high - e.g. 6x the selection set depth.
32
+ */
33
+ maxPlanningDepth?: number;
21
34
  }
22
- declare module "./engine/OperationPlan.js" {
23
- interface OperationPlan {
24
- [$$contextPlanCache]?: GrafastPlanJSON;
25
- }
26
- }
27
- export {};
28
35
  //# sourceMappingURL=prepare.d.ts.map