@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.
- package/README.md +7 -7
- package/dist/application/action/authoring.d.ts +1 -1
- package/dist/application/action/context.d.ts +9 -8
- package/dist/application/error/error.d.ts +7 -7
- package/dist/application/error/error.js +12 -12
- package/dist/application/error/index.d.ts +1 -1
- package/dist/application/error/index.js +1 -1
- package/dist/application/mutation/authoring/builder.d.ts +12 -12
- package/dist/application/mutation/authoring/builder.js +3 -3
- package/dist/application/mutation/authoring/guard.d.ts +2 -2
- package/dist/application/mutation/authoring/index.d.ts +1 -1
- package/dist/application/mutation/define.d.ts +8 -8
- package/dist/application/mutation/define.js +12 -12
- package/dist/application/mutation/execution/execute.d.ts +2 -2
- package/dist/application/mutation/execution/execute.js +10 -10
- package/dist/application/mutation/execution/executor.d.ts +2 -2
- package/dist/application/mutation/execution/executor.js +2 -2
- package/dist/application/mutation/index.d.ts +2 -2
- package/dist/application/mutation/legacy/v6/define.d.ts +1 -1
- package/dist/application/mutation/legacy/v6/mutation.d.ts +1 -1
- package/dist/application/mutation/mutation.d.ts +12 -12
- package/dist/application/query/composite/builder.js +1 -1
- package/dist/application/query/define.d.ts +1 -1
- package/dist/application/query/define.js +3 -3
- package/dist/application/query/defined/define.d.ts +45 -0
- package/dist/application/query/defined/define.js +96 -0
- package/dist/application/query/defined/query.d.ts +135 -0
- package/dist/application/query/definition.d.ts +5 -5
- package/dist/application/query/definition.js +4 -4
- package/dist/application/query/execution/bounds.d.ts +7 -5
- package/dist/application/query/execution/bounds.js +4 -2
- package/dist/application/query/execution/client.d.ts +20 -0
- package/dist/application/query/execution/client.js +1 -0
- package/dist/application/query/execution/crossings.d.ts +3 -3
- package/dist/application/query/execution/crossings.js +55 -32
- package/dist/application/query/execution/error.d.ts +8 -8
- package/dist/application/query/execution/error.js +5 -5
- package/dist/application/query/execution/execute.d.ts +4 -4
- package/dist/application/query/execution/executor.d.ts +2 -2
- package/dist/application/query/execution/rows.d.ts +5 -5
- package/dist/application/query/execution/rows.js +42 -30
- package/dist/application/query/execution/run.d.ts +75 -0
- package/dist/application/query/execution/{recipe.js → run.js} +116 -68
- package/dist/application/query/execution/split.d.ts +3 -3
- package/dist/application/query/execution/split.js +1 -1
- package/dist/application/query/handles/build.d.ts +1 -1
- package/dist/application/query/handles/domain.d.ts +1 -1
- package/dist/application/query/handles/handles.d.ts +14 -12
- package/dist/application/query/handles/plan.d.ts +10 -9
- package/dist/application/query/handles/plan.js +1 -1
- package/dist/application/query/handles/reads.js +7 -7
- package/dist/application/query/handles/rows.d.ts +1 -1
- package/dist/application/query/handles/terms.d.ts +9 -1
- package/dist/application/query/handles/terms.js +20 -3
- package/dist/application/query/index.d.ts +8 -5
- package/dist/application/query/index.js +3 -3
- package/dist/application/query/language/index.d.ts +1 -1
- package/dist/application/query/language/query.d.ts +5 -5
- package/dist/application/query/legacy/v6/collection/union.d.ts +1 -1
- package/dist/application/query/legacy/v6/collection/union.js +3 -3
- package/dist/application/query/legacy/v6/define.d.ts +1 -1
- package/dist/application/query/legacy/v6/define.js +3 -3
- package/dist/application/query/legacy/v6/execution/execute.d.ts +6 -4
- package/dist/application/query/legacy/v6/index.d.ts +1 -1
- package/dist/application/query/legacy/v6/index.js +1 -1
- package/dist/application/query/query.d.ts +3 -3
- package/dist/application/routes/admission.d.ts +1 -1
- package/dist/application/routes/admission.js +2 -2
- package/dist/application/routes/index.d.ts +3 -2
- package/dist/application/routes/route.d.ts +1 -1
- package/dist/application/runtime/declarations.d.ts +6 -6
- package/dist/application/runtime/define.d.ts +5 -5
- package/dist/application/workflow/durable.d.ts +9 -9
- package/dist/deployment/build/build.d.ts +8 -1
- package/dist/deployment/build/material.js +3 -0
- package/dist/execution/invocation/capabilities/bind.d.ts +1 -1
- package/dist/execution/invocation/capabilities/bind.js +8 -8
- package/dist/execution/invocation/dispatch/action.js +2 -2
- package/dist/execution/invocation/dispatch/workflow.js +2 -2
- package/dist/execution/invocation/result/index.d.ts +1 -1
- package/dist/execution/invocation/result/index.js +1 -1
- package/dist/execution/invocation/result/undeclared.d.ts +7 -0
- package/dist/execution/invocation/result/undeclared.js +18 -0
- package/dist/execution/workflows/failure.d.ts +7 -7
- package/dist/execution/workflows/failure.js +19 -18
- package/dist/execution/workflows/receiver.d.ts +1 -1
- package/dist/execution/workflows/run.js +2 -2
- package/dist/execution/workflows/steps.d.ts +1 -1
- package/dist/platform/schema/class-authoring.d.ts +2 -8
- package/dist/platform/schema/index.d.ts +1 -1
- package/dist/platform/schema/kernel-compiled.d.ts +1 -1
- package/dist/platform/schema/kernel-compiled.js +2 -2
- package/dist/platform/schema/kernel.d.ts +4 -2
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +1 -1
- package/dist/testing/{recipe.d.ts → query.d.ts} +6 -6
- package/dist/testing/{recipe.js → query.js} +16 -11
- package/dist/tooling/cli/orchestrate.js +7 -6
- package/dist/tooling/linter/adapters/typescript/{recipe-definitions.d.ts → definition-calls.d.ts} +10 -10
- package/dist/tooling/linter/adapters/typescript/{recipe-definitions.js → definition-calls.js} +10 -10
- package/dist/tooling/linter/adapters/typescript/index.d.ts +1 -1
- package/dist/tooling/linter/adapters/typescript/index.js +1 -1
- package/dist/tooling/linter/adapters/typescript/query-observation.js +6 -6
- package/dist/tooling/linter/implementations/source/definitions.d.ts +2 -0
- package/dist/tooling/linter/implementations/source/{recipes.js → definitions.js} +60 -44
- package/dist/tooling/linter/implementations/source/global.js +8 -6
- package/dist/tooling/linter/implementations/source/mutations.js +5 -5
- package/dist/tooling/linter/implementations/source/shared.d.ts +2 -2
- package/dist/tooling/linter/implementations/source/shared.js +7 -7
- package/dist/tooling/linter/implementations/source/verifiers.js +2 -2
- package/dist/tooling/linter/policy/generated.js +3 -3
- package/dist/tooling/linter/requirements/registry.js +4 -4
- package/docs/durable-workflows.md +8 -8
- package/docs/handler-dependencies.md +1 -1
- package/docs/legacy/query-v6.md +7 -7
- package/docs/queries.md +60 -56
- package/package.json +6 -6
- package/dist/application/query/execution/recipe.d.ts +0 -70
- package/dist/application/query/recipe/define.d.ts +0 -45
- package/dist/application/query/recipe/define.js +0 -102
- package/dist/application/query/recipe/recipe.d.ts +0 -134
- package/dist/execution/invocation/result/recipe.d.ts +0 -6
- package/dist/execution/invocation/result/recipe.js +0 -17
- package/dist/tooling/linter/implementations/source/recipes.d.ts +0 -2
- /package/dist/application/query/{recipe/recipe.js → defined/query.js} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The one error a
|
|
3
|
-
* of that code. A
|
|
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
|
|
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
|
|
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
|
|
58
|
-
readonly
|
|
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
|
|
63
|
-
|
|
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
|
-
|
|
33
|
+
query;
|
|
34
34
|
details;
|
|
35
35
|
name = 'QueryError';
|
|
36
36
|
constructor(code,
|
|
37
|
-
/** The
|
|
38
|
-
|
|
37
|
+
/** The Query's id. */
|
|
38
|
+
query, details, options) {
|
|
39
39
|
const reason = options?.reason === undefined ? '' : `: ${options.reason}`;
|
|
40
|
-
super(`${
|
|
40
|
+
super(`${query}: ${sentence(code, details)}${reason}`, options);
|
|
41
41
|
this.code = code;
|
|
42
|
-
this.
|
|
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 {
|
|
3
|
+
import type { QueryV6Client } from '../legacy/v6/execution/execute.js';
|
|
4
4
|
import type { QueryDefinition } from '../query.js';
|
|
5
|
-
export type { QueryClient } from '
|
|
6
|
-
export declare function executeQuery<DomainValue extends Domain, Output>(client:
|
|
7
|
-
export declare function executeQuery<DomainValue extends Domain, Input, Output>(client:
|
|
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:
|
|
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
|
|
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
|
|
26
|
+
readonly query: string;
|
|
27
27
|
readonly model: Model;
|
|
28
|
-
constructor(
|
|
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(
|
|
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(
|
|
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
|
|
7
|
+
/** What renders one answer: the Query it errs for, the Domain's Classes, the answer's facts. */
|
|
7
8
|
export class Renderer {
|
|
8
|
-
|
|
9
|
+
query;
|
|
9
10
|
model;
|
|
10
11
|
#facts;
|
|
11
|
-
constructor(
|
|
12
|
-
this.
|
|
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.
|
|
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
|
-
/**
|
|
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
|
-
|
|
87
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
126
|
-
row[plan.target.role] = end(item.target, plan.target
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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(
|
|
222
|
+
export function emptyResult(query, plan) {
|
|
212
223
|
switch (plan.verb) {
|
|
213
224
|
case 'get':
|
|
214
|
-
throw new QueryError('NOT_FOUND',
|
|
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(
|
|
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(
|
|
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',
|
|
259
|
+
throw new QueryError('INTEGRITY', query, { relation: classLabel(plan), found: 2 });
|
|
249
260
|
const [item] = items;
|
|
250
261
|
if (item === undefined)
|
|
251
|
-
return emptyResult(
|
|
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',
|
|
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
|
|
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:
|
|
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 {};
|