@astrale-os/sdk 0.6.0-beta.42 → 0.6.0-beta.44

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 (125) hide show
  1. package/README.md +7 -7
  2. package/dist/application/action/authoring.d.ts +1 -1
  3. package/dist/application/action/context.d.ts +9 -8
  4. package/dist/application/error/error.d.ts +7 -7
  5. package/dist/application/error/error.js +12 -12
  6. package/dist/application/error/index.d.ts +1 -1
  7. package/dist/application/error/index.js +1 -1
  8. package/dist/application/mutation/authoring/builder.d.ts +12 -12
  9. package/dist/application/mutation/authoring/builder.js +3 -3
  10. package/dist/application/mutation/authoring/guard.d.ts +2 -2
  11. package/dist/application/mutation/authoring/index.d.ts +1 -1
  12. package/dist/application/mutation/define.d.ts +8 -8
  13. package/dist/application/mutation/define.js +12 -12
  14. package/dist/application/mutation/execution/execute.d.ts +2 -2
  15. package/dist/application/mutation/execution/execute.js +10 -10
  16. package/dist/application/mutation/execution/executor.d.ts +2 -2
  17. package/dist/application/mutation/execution/executor.js +2 -2
  18. package/dist/application/mutation/index.d.ts +2 -2
  19. package/dist/application/mutation/legacy/v6/define.d.ts +1 -1
  20. package/dist/application/mutation/legacy/v6/mutation.d.ts +1 -1
  21. package/dist/application/mutation/mutation.d.ts +12 -12
  22. package/dist/application/query/composite/builder.js +1 -1
  23. package/dist/application/query/define.d.ts +1 -1
  24. package/dist/application/query/define.js +3 -3
  25. package/dist/application/query/defined/define.d.ts +45 -0
  26. package/dist/application/query/defined/define.js +96 -0
  27. package/dist/application/query/defined/query.d.ts +135 -0
  28. package/dist/application/query/definition.d.ts +5 -5
  29. package/dist/application/query/definition.js +4 -4
  30. package/dist/application/query/execution/bounds.d.ts +7 -5
  31. package/dist/application/query/execution/bounds.js +4 -2
  32. package/dist/application/query/execution/client.d.ts +20 -0
  33. package/dist/application/query/execution/client.js +1 -0
  34. package/dist/application/query/execution/crossings.d.ts +3 -3
  35. package/dist/application/query/execution/crossings.js +55 -32
  36. package/dist/application/query/execution/error.d.ts +8 -8
  37. package/dist/application/query/execution/error.js +5 -5
  38. package/dist/application/query/execution/execute.d.ts +4 -4
  39. package/dist/application/query/execution/executor.d.ts +2 -2
  40. package/dist/application/query/execution/rows.d.ts +5 -5
  41. package/dist/application/query/execution/rows.js +42 -30
  42. package/dist/application/query/execution/run.d.ts +75 -0
  43. package/dist/application/query/execution/{recipe.js → run.js} +116 -68
  44. package/dist/application/query/execution/split.d.ts +3 -3
  45. package/dist/application/query/execution/split.js +1 -1
  46. package/dist/application/query/handles/build.d.ts +1 -1
  47. package/dist/application/query/handles/domain.d.ts +1 -1
  48. package/dist/application/query/handles/handles.d.ts +14 -12
  49. package/dist/application/query/handles/plan.d.ts +10 -9
  50. package/dist/application/query/handles/plan.js +1 -1
  51. package/dist/application/query/handles/reads.js +7 -7
  52. package/dist/application/query/handles/rows.d.ts +1 -1
  53. package/dist/application/query/handles/terms.d.ts +9 -1
  54. package/dist/application/query/handles/terms.js +20 -3
  55. package/dist/application/query/index.d.ts +8 -5
  56. package/dist/application/query/index.js +3 -3
  57. package/dist/application/query/language/index.d.ts +1 -1
  58. package/dist/application/query/language/query.d.ts +5 -5
  59. package/dist/application/query/legacy/v6/collection/union.d.ts +1 -1
  60. package/dist/application/query/legacy/v6/collection/union.js +3 -3
  61. package/dist/application/query/legacy/v6/define.d.ts +1 -1
  62. package/dist/application/query/legacy/v6/define.js +3 -3
  63. package/dist/application/query/legacy/v6/execution/execute.d.ts +6 -4
  64. package/dist/application/query/legacy/v6/index.d.ts +1 -1
  65. package/dist/application/query/legacy/v6/index.js +1 -1
  66. package/dist/application/query/query.d.ts +3 -3
  67. package/dist/application/routes/admission.d.ts +1 -1
  68. package/dist/application/routes/admission.js +2 -2
  69. package/dist/application/routes/index.d.ts +3 -2
  70. package/dist/application/routes/route.d.ts +1 -1
  71. package/dist/application/runtime/declarations.d.ts +6 -6
  72. package/dist/application/runtime/define.d.ts +5 -5
  73. package/dist/application/workflow/durable.d.ts +9 -9
  74. package/dist/deployment/build/build.d.ts +8 -1
  75. package/dist/deployment/build/material.js +3 -0
  76. package/dist/execution/invocation/capabilities/bind.d.ts +1 -1
  77. package/dist/execution/invocation/capabilities/bind.js +8 -8
  78. package/dist/execution/invocation/dispatch/action.js +2 -2
  79. package/dist/execution/invocation/dispatch/workflow.js +2 -2
  80. package/dist/execution/invocation/result/index.d.ts +1 -1
  81. package/dist/execution/invocation/result/index.js +1 -1
  82. package/dist/execution/invocation/result/undeclared.d.ts +7 -0
  83. package/dist/execution/invocation/result/undeclared.js +18 -0
  84. package/dist/execution/workflows/failure.d.ts +7 -7
  85. package/dist/execution/workflows/failure.js +19 -18
  86. package/dist/execution/workflows/receiver.d.ts +1 -1
  87. package/dist/execution/workflows/run.js +2 -2
  88. package/dist/execution/workflows/steps.d.ts +1 -1
  89. package/dist/platform/schema/class-authoring.d.ts +2 -8
  90. package/dist/platform/schema/index.d.ts +1 -1
  91. package/dist/platform/schema/kernel-compiled.d.ts +1 -1
  92. package/dist/platform/schema/kernel-compiled.js +2 -2
  93. package/dist/platform/schema/kernel.d.ts +4 -2
  94. package/dist/testing/index.d.ts +2 -2
  95. package/dist/testing/index.js +1 -1
  96. package/dist/testing/{recipe.d.ts → query.d.ts} +6 -6
  97. package/dist/testing/{recipe.js → query.js} +16 -11
  98. package/dist/tooling/cli/orchestrate.js +7 -6
  99. package/dist/tooling/linter/adapters/typescript/{recipe-definitions.d.ts → definition-calls.d.ts} +10 -10
  100. package/dist/tooling/linter/adapters/typescript/{recipe-definitions.js → definition-calls.js} +10 -10
  101. package/dist/tooling/linter/adapters/typescript/index.d.ts +1 -1
  102. package/dist/tooling/linter/adapters/typescript/index.js +1 -1
  103. package/dist/tooling/linter/adapters/typescript/query-observation.js +6 -6
  104. package/dist/tooling/linter/implementations/source/definitions.d.ts +2 -0
  105. package/dist/tooling/linter/implementations/source/{recipes.js → definitions.js} +60 -44
  106. package/dist/tooling/linter/implementations/source/global.js +8 -6
  107. package/dist/tooling/linter/implementations/source/mutations.js +5 -5
  108. package/dist/tooling/linter/implementations/source/shared.d.ts +2 -2
  109. package/dist/tooling/linter/implementations/source/shared.js +7 -7
  110. package/dist/tooling/linter/implementations/source/verifiers.js +2 -2
  111. package/dist/tooling/linter/policy/generated.js +3 -3
  112. package/dist/tooling/linter/requirements/registry.js +4 -4
  113. package/docs/durable-workflows.md +8 -8
  114. package/docs/handler-dependencies.md +1 -1
  115. package/docs/legacy/query-v6.md +7 -7
  116. package/docs/queries.md +60 -56
  117. package/package.json +6 -6
  118. package/dist/application/query/execution/recipe.d.ts +0 -70
  119. package/dist/application/query/recipe/define.d.ts +0 -45
  120. package/dist/application/query/recipe/define.js +0 -102
  121. package/dist/application/query/recipe/recipe.d.ts +0 -134
  122. package/dist/execution/invocation/result/recipe.d.ts +0 -6
  123. package/dist/execution/invocation/result/recipe.js +0 -17
  124. package/dist/tooling/linter/implementations/source/recipes.d.ts +0 -2
  125. /package/dist/application/query/{recipe/recipe.js → defined/query.js} +0 -0
@@ -1,6 +1,6 @@
1
1
  /**
2
- * The one error a recipe's reads raise (spec § Errors): a code, the recipe's id and the details
3
- * of that code. A recipe's own business refusals are its declared errors, raised by `output`.
2
+ * The one error a Query's reads raise (spec § Errors): a code, the Query's id and the details
3
+ * of that code. A Query's own business refusals are its declared errors, raised by `output`.
4
4
  */
5
5
  import type { NodeId } from '../../../platform/graph/node/index.js';
6
6
  import type { EdgeKey } from '../handles/rows.js';
@@ -25,7 +25,7 @@ export interface QueryErrorDetails {
25
25
  readonly parent?: NodeId;
26
26
  readonly found: 0 | 2;
27
27
  };
28
- /** Past a verb's `max`, the recipe's 100,000 rows or its 32 reads. */
28
+ /** Past a verb's `max`, the Query's 100,000 rows or its 32 reads. */
29
29
  TOO_MANY: {
30
30
  readonly limit: 'max' | 'rows' | 'reads';
31
31
  readonly bound: number;
@@ -35,7 +35,7 @@ export interface QueryErrorDetails {
35
35
  readonly kernelCode: string;
36
36
  readonly retryable: boolean;
37
37
  };
38
- /** The Kernel refused the query the recipe built, before reading anything. */
38
+ /** The Kernel refused the document the Query built, before reading anything. */
39
39
  INPUT_INVALID: {
40
40
  readonly kernelCode?: string;
41
41
  readonly phase?: string;
@@ -54,13 +54,13 @@ export interface QueryErrorDetails {
54
54
  export type QueryErrorCode = keyof QueryErrorDetails;
55
55
  export declare class QueryError<C extends QueryErrorCode = QueryErrorCode> extends Error {
56
56
  readonly code: C;
57
- /** The recipe's id. */
58
- readonly recipe: string;
57
+ /** The Query's id. */
58
+ readonly query: string;
59
59
  readonly details: QueryErrorDetails[C];
60
60
  readonly name = "QueryError";
61
61
  constructor(code: C,
62
- /** The recipe's id. */
63
- recipe: string, details: QueryErrorDetails[C], options?: ErrorOptions & {
62
+ /** The Query's id. */
63
+ query: string, details: QueryErrorDetails[C], options?: ErrorOptions & {
64
64
  readonly reason?: string;
65
65
  });
66
66
  }
@@ -30,16 +30,16 @@ function sentence(code, details) {
30
30
  }
31
31
  export class QueryError extends Error {
32
32
  code;
33
- recipe;
33
+ query;
34
34
  details;
35
35
  name = 'QueryError';
36
36
  constructor(code,
37
- /** The recipe's id. */
38
- recipe, details, options) {
37
+ /** The Query's id. */
38
+ query, details, options) {
39
39
  const reason = options?.reason === undefined ? '' : `: ${options.reason}`;
40
- super(`${recipe}: ${sentence(code, details)}${reason}`, options);
40
+ super(`${query}: ${sentence(code, details)}${reason}`, options);
41
41
  this.code = code;
42
- this.recipe = recipe;
42
+ this.query = query;
43
43
  this.details = details;
44
44
  Object.freeze(this.details);
45
45
  }
@@ -1,8 +1,8 @@
1
1
  import type { Domain } from '../../../platform/schema/index.js';
2
2
  import type { CompositeQuery } from '../composite/index.js';
3
- import type { QueryClient } from '../legacy/v6/execution/execute.js';
3
+ import type { QueryV6Client } from '../legacy/v6/execution/execute.js';
4
4
  import type { QueryDefinition } from '../query.js';
5
- export type { QueryClient } from '../legacy/v6/execution/execute.js';
6
- export declare function executeQuery<DomainValue extends Domain, Output>(client: QueryClient, domain: DomainValue, query: QueryDefinition<DomainValue, void, Output>): Promise<Output>;
7
- export declare function executeQuery<DomainValue extends Domain, Input, Output>(client: QueryClient, domain: DomainValue, query: QueryDefinition<DomainValue, Input, Output>, input: Input): Promise<Output>;
5
+ export type { QueryClient } from './client.js';
6
+ export declare function executeQuery<DomainValue extends Domain, Output>(client: QueryV6Client, domain: DomainValue, query: QueryDefinition<DomainValue, void, Output>): Promise<Output>;
7
+ export declare function executeQuery<DomainValue extends Domain, Input, Output>(client: QueryV6Client, domain: DomainValue, query: QueryDefinition<DomainValue, Input, Output>, input: Input): Promise<Output>;
8
8
  export type ExecutableCompositeQuery = CompositeQuery<unknown, unknown, unknown>;
@@ -1,6 +1,6 @@
1
1
  import type { Domain, schema } from '../../../platform/schema/index.js';
2
+ import type { QueryV6Client } from '../legacy/v6/execution/execute.js';
2
3
  import type { QueryDefinition } from '../query.js';
3
- import type { QueryClient } from './execute.js';
4
4
  /** Invocation-bound executor for authored Query definitions. */
5
5
  export interface QueryExecutor<DomainValue extends Domain = Domain> {
6
6
  <Output>(query: QueryDefinition<DomainValue, void, Output>): Promise<Output>;
@@ -10,5 +10,5 @@ type ExecutableDomain<DomainValue extends Domain> = DomainValue extends {
10
10
  readonly source: infer Source extends schema.DomainSchema;
11
11
  } ? Extract<schema.DomainOf<Source>, Domain> : DomainValue;
12
12
  /** Private Runtime binding to one Client and the exact loaded root Domain. */
13
- export declare function bindQuery<DomainValue extends Domain>(client: QueryClient, domain: DomainValue): QueryExecutor<ExecutableDomain<DomainValue>>;
13
+ export declare function bindQuery<DomainValue extends Domain>(client: QueryV6Client, domain: DomainValue): QueryExecutor<ExecutableDomain<DomainValue>>;
14
14
  export {};
@@ -20,12 +20,12 @@ interface Item {
20
20
  readonly target?: Item;
21
21
  readonly branches: Readonly<Record<string, unknown>>;
22
22
  }
23
- /** What renders one answer: the recipe it errs for, the Domain's Classes, the answer's facts. */
23
+ /** What renders one answer: the Query it errs for, the Domain's Classes, the answer's facts. */
24
24
  export declare class Renderer {
25
25
  #private;
26
- readonly recipe: string;
26
+ readonly query: string;
27
27
  readonly model: Model;
28
- constructor(recipe: string, model: Model, answer: QueryListAnswer<unknown, unknown>);
28
+ constructor(query: string, model: Model, answer: QueryListAnswer<unknown, unknown>);
29
29
  /** A Node row, or `undefined` when the reader may not read it and the read does not keep it. */
30
30
  node(item: Item, pattern: Pattern): Json | undefined;
31
31
  /** An Edge root row: its identity, its values and both ends by role. */
@@ -36,7 +36,7 @@ export declare class Renderer {
36
36
  rootOne(item: Item, root: NodeRootPlan | EdgeRootPlan): Json;
37
37
  }
38
38
  /** The answer of a root read with nothing to read: its verb's empty answer. */
39
- export declare function emptyResult(recipe: string, plan: ReadPlan): unknown;
39
+ export declare function emptyResult(query: string, plan: ReadPlan): unknown;
40
40
  /** A root read's result from its answer, by its verb. */
41
- export declare function rootResult(recipe: string, model: Model, plan: ReadPlan, answer: unknown): unknown;
41
+ export declare function rootResult(query: string, model: Model, plan: ReadPlan, answer: unknown): unknown;
42
42
  export {};
@@ -1,15 +1,16 @@
1
1
  import { factKey, factsOf } from '../answer/facts.js';
2
+ import { QueryValueMismatchError } from '../failure.js';
2
3
  import { ROW_KEYS } from '../handles/model.js';
3
4
  import { QueryError } from './error.js';
4
5
  const NO_TAKEN = new Set();
5
6
  const freeze = (value) => Object.freeze(value);
6
- /** What renders one answer: the recipe it errs for, the Domain's Classes, the answer's facts. */
7
+ /** What renders one answer: the Query it errs for, the Domain's Classes, the answer's facts. */
7
8
  export class Renderer {
8
- recipe;
9
+ query;
9
10
  model;
10
11
  #facts;
11
- constructor(recipe, model, answer) {
12
- this.recipe = recipe;
12
+ constructor(query, model, answer) {
13
+ this.query = query;
13
14
  this.model = model;
14
15
  this.#facts = factsOf(answer);
15
16
  }
@@ -22,7 +23,7 @@ export class Renderer {
22
23
  }
23
24
  #class(item) {
24
25
  if (item.class === undefined)
25
- throw new QueryError('UNSUPPORTED', this.recipe, { feature: 'classes' });
26
+ throw new QueryError('UNSUPPORTED', this.query, { feature: 'classes' });
26
27
  return item.class;
27
28
  }
28
29
  /**
@@ -46,11 +47,19 @@ export class Renderer {
46
47
  return (candidates.find((c) => candidates.every((o) => this.model.satisfies(c).has(o.key))) ??
47
48
  candidates[0]);
48
49
  }
49
- /** The values of a fact by the layout of a Class: flat names, then groups (F6). */
50
+ /**
51
+ * The values of a fact by the layout of a Class: flat names, then groups (F6). The row types a
52
+ * required value as present, so a fact without one breaks the Domain as a value that does not
53
+ * match its Property does.
54
+ */
50
55
  #values(fact, c, taken) {
51
56
  if (c === undefined)
52
57
  return {};
53
58
  const values = (this.#fact(fact)?.values ?? {});
59
+ for (const property of c.properties) {
60
+ if (property.definition.required && values[property.key] === undefined)
61
+ throw new QueryValueMismatchError(`${factKey(fact)} has no value for ${property.key}, which its Property requires in this Domain`);
62
+ }
54
63
  const { flat, groups } = this.model.layout(c, taken);
55
64
  const row = {};
56
65
  for (const [name, key] of flat)
@@ -83,12 +92,15 @@ export class Renderer {
83
92
  Object.assign(row, this.#values(id, layout, ROW_KEYS));
84
93
  for (const branch of pattern.branches)
85
94
  row[branch.key] = this.#relation(item, branch);
86
- if ('edge' in pattern && pattern.edge && item.edge !== undefined)
87
- row.$edge = this.#edgeValues(item.edge);
95
+ const edge = pattern.edge;
96
+ if (edge !== undefined && item.edge !== undefined)
97
+ row.$edge = this.#edgeValues(item.edge, edge);
88
98
  return freeze(row);
89
99
  }
90
- /** What `.withEdge()` adds: the Edge's Class and values, or the names it withholds. */
91
- #edgeValues(edge) {
100
+ /** What `.withEdge()` adds: the Edge's Class, and its values or the names it withholds. */
101
+ #edgeValues(edge, select) {
102
+ if (select === 'reference')
103
+ return freeze({ $class: edge.class });
92
104
  const c = this.#known(edge.class);
93
105
  if (this.#withheld(edge))
94
106
  return freeze({ $class: edge.class, $withheld: this.#names(c) });
@@ -116,14 +128,13 @@ export class Renderer {
116
128
  const row = { ...identity };
117
129
  if (plan.select === 'value')
118
130
  Object.assign(row, this.#values(key, c, roles));
119
- const end = (rendered, classes) => {
131
+ const end = (rendered, { classes, select }) => {
120
132
  if (rendered === undefined)
121
133
  return undefined;
122
- const pattern = { classes, select: plan.select, withheld: true, branches: [] };
123
- return this.node(rendered, pattern);
134
+ return this.node(rendered, { classes, select, withheld: true, branches: [] });
124
135
  };
125
- row[plan.source.role] = end(item.source, plan.source.classes);
126
- row[plan.target.role] = end(item.target, plan.target.classes);
136
+ row[plan.source.role] = end(item.source, plan.source);
137
+ row[plan.target.role] = end(item.target, plan.target);
127
138
  return freeze(row);
128
139
  }
129
140
  /** A relation's answer for one parent, by its verb. */
@@ -154,7 +165,7 @@ export class Renderer {
154
165
  return items[0] === undefined ? undefined : this.node(items[0], plan);
155
166
  case 'all':
156
167
  if (items.length > plan.bound)
157
- throw new QueryError('TOO_MANY', this.recipe, { limit: 'max', bound: plan.bound });
168
+ throw new QueryError('TOO_MANY', this.query, { limit: 'max', bound: plan.bound });
158
169
  return this.#rows(items, plan);
159
170
  default:
160
171
  return this.#rows(items, plan);
@@ -176,12 +187,12 @@ export class Renderer {
176
187
  }
177
188
  }
178
189
  #integrity(at, found) {
179
- return new QueryError('INTEGRITY', this.recipe, { ...at, found });
190
+ return new QueryError('INTEGRITY', this.query, { ...at, found });
180
191
  }
181
192
  /** The one row `get` or `find` gives: one the reader may not read is an error, since it exists. */
182
193
  #one(item, pattern) {
183
194
  if (this.#withheld(item.fact))
184
- throw new QueryError('NOT_READABLE', this.recipe, { class: this.#class(item), id: item.fact });
195
+ throw new QueryError('NOT_READABLE', this.query, { class: this.#class(item), id: item.fact });
185
196
  return this.node(item, pattern);
186
197
  }
187
198
  #rows(items, pattern) {
@@ -195,7 +206,7 @@ export class Renderer {
195
206
  rootOne(item, root) {
196
207
  if (this.#withheld(item.fact)) {
197
208
  const fact = item.fact;
198
- throw new QueryError('NOT_READABLE', this.recipe, {
209
+ throw new QueryError('NOT_READABLE', this.query, {
199
210
  class: typeof fact === 'string' ? this.#class(item) : fact.class,
200
211
  id: fact,
201
212
  });
@@ -208,10 +219,10 @@ function classLabel(plan) {
208
219
  return plan.root?.classes.join(' | ') ?? '';
209
220
  }
210
221
  /** The answer of a root read with nothing to read: its verb's empty answer. */
211
- export function emptyResult(recipe, plan) {
222
+ export function emptyResult(query, plan) {
212
223
  switch (plan.verb) {
213
224
  case 'get':
214
- throw new QueryError('NOT_FOUND', recipe, {
225
+ throw new QueryError('NOT_FOUND', query, {
215
226
  class: classLabel(plan),
216
227
  ...(plan.target === undefined ? {} : { target: plan.target }),
217
228
  });
@@ -231,24 +242,24 @@ export function emptyResult(recipe, plan) {
231
242
  }
232
243
  }
233
244
  /** A root read's result from its answer, by its verb. */
234
- export function rootResult(recipe, model, plan, answer) {
245
+ export function rootResult(query, model, plan, answer) {
235
246
  const json = answer;
236
247
  if ('exists' in json)
237
248
  return json.exists === true;
238
249
  if ('count' in json)
239
250
  return freeze({ count: json.count, more: json.more === true });
240
251
  const listAnswer = answer;
241
- const renderer = new Renderer(recipe, model, listAnswer);
252
+ const renderer = new Renderer(query, model, listAnswer);
242
253
  const { items, complete, cursor } = listAnswer.list;
243
254
  const root = plan.root ?? documentRoot(plan);
244
255
  switch (plan.verb) {
245
256
  case 'get':
246
257
  case 'find': {
247
258
  if (items.length > 1)
248
- throw new QueryError('INTEGRITY', recipe, { relation: classLabel(plan), found: 2 });
259
+ throw new QueryError('INTEGRITY', query, { relation: classLabel(plan), found: 2 });
249
260
  const [item] = items;
250
261
  if (item === undefined)
251
- return emptyResult(recipe, plan);
262
+ return emptyResult(query, plan);
252
263
  return renderer.rootOne(item, root);
253
264
  }
254
265
  case 'first':
@@ -264,7 +275,7 @@ export function rootResult(recipe, model, plan, answer) {
264
275
  });
265
276
  case 'all':
266
277
  if (items.length > plan.bound)
267
- throw new QueryError('TOO_MANY', recipe, { limit: 'max', bound: plan.bound });
278
+ throw new QueryError('TOO_MANY', query, { limit: 'max', bound: plan.bound });
268
279
  return renderer.rootRows(items, root);
269
280
  default:
270
281
  return renderer.rootRows(items, root);
@@ -282,7 +293,7 @@ function documentRoot(plan) {
282
293
  relation: b.name,
283
294
  verb: b.mode === 'count' ? 'count' : 'firstN',
284
295
  empty: false,
285
- edge: b.selectEdge !== undefined,
296
+ edge: b.selectEdge,
286
297
  classes: [],
287
298
  select: b.select === 'value' ? 'value' : 'reference',
288
299
  withheld: false,
@@ -297,12 +308,13 @@ function documentRoot(plan) {
297
308
  branches: branches(list),
298
309
  };
299
310
  const select = (list.select ?? {});
311
+ const rendering = (side) => (select[side] === 'value' ? 'value' : 'reference');
300
312
  return {
301
313
  kind: 'edges',
302
314
  classes: [],
303
- select: select.edge === 'value' ? 'value' : 'reference',
315
+ select: rendering('edge'),
304
316
  withheld: false,
305
- source: { role: 'source', classes: [] },
306
- target: { role: 'target', classes: [] },
317
+ source: { role: 'source', classes: [], select: rendering('source') },
318
+ target: { role: 'target', classes: [], select: rendering('target') },
307
319
  };
308
320
  }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Run a Query v7 (WP-S3): its steps in order, each one's reads together, at most 8 in flight,
3
+ * each read at its own snapshot (the stand-in); then `output`. A step's bounds (S11) are checked
4
+ * before it sends anything, and every Kernel refusal of a read is a `QueryError`.
5
+ */
6
+ import type { Domain } from '../../../platform/schema/index.js';
7
+ import type { Errors, InputOf, OutputContext, OutputOf, DefinedQuery } from '../defined/query.js';
8
+ import type { ReadPlan } from '../handles/plan.js';
9
+ import type { QueryClient } from './client.js';
10
+ import { type Model } from '../handles/model.js';
11
+ import { type DeclaredClass } from './crossings.js';
12
+ /** A page Query's call: its size, from 1 to its `max` (by default), and the cursor it continues. */
13
+ export interface QueryPageOptions {
14
+ readonly size?: number;
15
+ readonly after?: string;
16
+ }
17
+ /** A Query call's options: the authority it reads under, and a page Query's size and cursor. */
18
+ export type QueryOptions<R, As extends string> = {
19
+ readonly as: As;
20
+ } & ('~page' extends keyof R ? QueryPageOptions : {});
21
+ type Step = (...parameters: readonly unknown[]) => unknown;
22
+ /** One Query call: its reads so far, against S11, and the Classes they cross, against S12. */
23
+ export declare class Run {
24
+ #private;
25
+ readonly client: QueryClient;
26
+ readonly domain: Domain;
27
+ readonly query: string;
28
+ readonly model: Model;
29
+ constructor(client: QueryClient, domain: Domain, query: string, declared?: readonly DeclaredClass[]);
30
+ /**
31
+ * S11, before a step sends: its reads, its verbs' bounds, its rows and each property `in` its
32
+ * documents write. Then S12: each foreign Class its relations cross.
33
+ */
34
+ admit(plans: readonly ReadPlan[]): void;
35
+ /** One read's result: its verb's empty answer, or its documents' answers merged and rendered. */
36
+ read(plan: ReadPlan, paging?: QueryPageOptions): Promise<unknown>;
37
+ }
38
+ /** What `steps(…)` returned: its first record of facets, and the functions of the next ones. */
39
+ interface StepsOf {
40
+ readonly first: unknown;
41
+ readonly next: readonly Step[];
42
+ }
43
+ /**
44
+ * The `steps` a Query's `build` receives: two to eight steps, the first a record of facets and
45
+ * each next one a function of the merged results before it. It reads nothing: what it returns is
46
+ * read when `build` returns it.
47
+ */
48
+ export declare function stepsFor(query: string): (...steps: readonly unknown[]) => object;
49
+ /** The steps `build` returned, or `undefined` for one read or one record of facets. */
50
+ export declare function stepsOf(built: unknown): StepsOf | undefined;
51
+ /** Where each facet's results go: one read's index, a list of them, or nothing. */
52
+ type Shape = readonly (readonly [string, number | readonly number[] | undefined])[];
53
+ /**
54
+ * The reads of one step, admitted (S11, S12): a single read, or each facet's in order and the
55
+ * shape that puts their results back. A facet takes a name no `earlier` step read: the merged
56
+ * results keep one value per name.
57
+ */
58
+ export declare function planStep(run: Run, built: unknown, single: boolean, earlier?: Readonly<Record<string, unknown>>): {
59
+ readonly plans: readonly ReadPlan[];
60
+ readonly shape?: Shape;
61
+ };
62
+ /**
63
+ * Run a Query for `input` against `domain`, the resolved Domain it was written for: what `build`
64
+ * returns, each of its steps in order, then its `output`. A page Query takes its call's `size`
65
+ * and `after`. A read the Kernel refuses raises a `QueryError`; `output` raises the Query's
66
+ * declared errors. With the Class requirements
67
+ * the Domain's build `declared`, each step's relations are checked against them first (S12).
68
+ */
69
+ export declare function runQuery<R extends DefinedQuery>(client: QueryClient, domain: Domain, query: R, input: InputOf<R>, call?: QueryPageOptions, declared?: readonly DeclaredClass[]): Promise<OutputOf<R>>;
70
+ /**
71
+ * The context a Query's `output`, or a defined Mutation's `reject`, receives: its declared errors,
72
+ * and `is`, which narrows a row by Class.
73
+ */
74
+ export declare function outputContext(query: object, model: Model): OutputContext<unknown, Errors>;
75
+ export {};