@astrale-os/sdk 0.6.0-beta.43 → 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 +6 -6
- 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/{recipe/recipe.d.ts → defined/query.d.ts} +21 -20
- 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 +5 -5
- package/dist/application/query/execution/bounds.js +2 -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 +23 -23
- 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/{recipe.d.ts → run.d.ts} +21 -31
- package/dist/application/query/execution/{recipe.js → run.js} +49 -49
- 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 +4 -4
- package/dist/application/query/handles/rows.d.ts +1 -1
- 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/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 +1 -1
- 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} +5 -5
- package/dist/testing/{recipe.js → query.js} +9 -9
- 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} +27 -27
- 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 +6 -6
- package/docs/queries.md +38 -38
- package/package.json +6 -6
- package/dist/application/query/recipe/define.d.ts +0 -44
- package/dist/application/query/recipe/define.js +0 -95
- 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
package/README.md
CHANGED
|
@@ -59,7 +59,7 @@ Install the URL printed by `astrale-domain deploy` on each intended instance.
|
|
|
59
59
|
## Handler authority and dependencies
|
|
60
60
|
|
|
61
61
|
Handlers use Domain self authority for `kernel`, `graph`, Query V6 definitions, and a `mutate`
|
|
62
|
-
given no options; a Query
|
|
62
|
+
given no options; a Query v7, and a `mutate` given `{ as }`, name their authority on each call.
|
|
63
63
|
`dependencies.directory.caller.invoke(d => d.functions.lookup, input)` calls a direct declared
|
|
64
64
|
dependency on behalf of the incoming caller Identity; `.self` calls it as the executing Domain.
|
|
65
65
|
Explicit `caller` or `self` authority is also available on `kernel` and `graph`; the former
|
|
@@ -69,14 +69,14 @@ has no caller: its handler acts as the Domain alone, without the `caller` select
|
|
|
69
69
|
|
|
70
70
|
## Queries
|
|
71
71
|
|
|
72
|
-
`defineQuery<Schema>()(id, { build, output?, errors? })` defines a Query
|
|
72
|
+
`defineQuery<Schema>()(id, { build, output?, errors? })` defines a Query: typed handles over
|
|
73
73
|
the Domain (`d.Article.where((a) => a.state.eq('published')).first(50)`), reads bounded by
|
|
74
74
|
their verbs, a pure `output` and declared errors. An Action calls
|
|
75
|
-
`query(
|
|
76
|
-
`step.query(step,
|
|
77
|
-
|
|
75
|
+
`query(query, input, { as: 'executor' | 'caller' })`; a durable Workflow reads in
|
|
76
|
+
`step.query(step, query, input, { as: 'executor' })`. Before anything is sent, the SDK checks the
|
|
77
|
+
Query's bounds and the requirements its relations need; `checkQuery` from
|
|
78
78
|
`@astrale-os/sdk/testing` runs both checks in a test, on the first step it builds for a sample
|
|
79
|
-
input. A
|
|
79
|
+
input. A Query reads on a Host whose Kernel serves Query v7 and the Class of each row. Query V6
|
|
80
80
|
definitions keep their meaning and are deprecated. See [the Query guide](docs/queries.md) and
|
|
81
81
|
[Query V6 and the move to v7](docs/legacy/query-v6.md).
|
|
82
82
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { defineAction } from './define.js';
|
|
2
2
|
export type { Action, ActionDefinition } from './action.js';
|
|
3
|
-
export type { ActionContext, ActionBinaryInput, ActionExecution, Caller, DomainGraphExecutor, DomainGraphExecutors, DomainKernelSessions, } from './context.js';
|
|
3
|
+
export type { ActionContext, ActionBinaryInput, ActionExecution, Caller, DomainGraphExecutor, DomainGraphExecutors, DomainKernelSessions, DomainMutate, DomainQuery, } from './context.js';
|
|
4
4
|
export type { ActionBinary, ActionOutputOf } from './output.js';
|
|
5
5
|
export type { DeclaredErrorDefinition, DeclaredErrorFactory, DeclaredErrorFamily, DeclaredErrorOptions, DeclaredErrors, } from '../error/index.js';
|
|
@@ -6,8 +6,8 @@ import type { CallableInputOf, CallableInputModeOf, Domain, ResolvedFunction, Re
|
|
|
6
6
|
import type { HandlerDependencies } from '../dependency/index.js';
|
|
7
7
|
import type { DeclaredErrorFactory, DeclaredErrors, NoDeclaredErrors } from '../error/index.js';
|
|
8
8
|
import type { IntegrationClients, Integrations } from '../integration/index.js';
|
|
9
|
-
import type { Mutation, MutationExecutor, MutationInputOf, MutationOutputOf,
|
|
10
|
-
import type { InputOf, OutputOf, QueryDefinition, QueryExecutor,
|
|
9
|
+
import type { Mutation, MutationExecutor, MutationInputOf, MutationOutputOf, DefinedMutation } from '../mutation/index.js';
|
|
10
|
+
import type { InputOf, OutputOf, QueryDefinition, QueryExecutor, DefinedQuery, QueryOptions } from '../query/index.js';
|
|
11
11
|
export type ResolvedCallable = ResolvedFunction | ResolvedMethod;
|
|
12
12
|
/** Bearer-free caller evidence established before an Action or Workflow runs. */
|
|
13
13
|
export interface AuthenticatedCaller {
|
|
@@ -38,7 +38,8 @@ export interface ActionExecution {
|
|
|
38
38
|
* One admitted, single-consumer binary Function request body: the Core request body itself, so a
|
|
39
39
|
* handler can hand it as it is to the Kernel's content upload without reading it first.
|
|
40
40
|
*/
|
|
41
|
-
export
|
|
41
|
+
export interface ActionBinaryInput extends BinaryRequestBody {
|
|
42
|
+
}
|
|
42
43
|
type BinaryInputOf<Callable> = CallableInputModeOf<Callable> extends 'binary' ? {
|
|
43
44
|
readonly body: ActionBinaryInput;
|
|
44
45
|
} : {
|
|
@@ -56,20 +57,20 @@ export type AuthorityMode = 'caller' | 'self';
|
|
|
56
57
|
*/
|
|
57
58
|
export type AuthorityName<Authority extends AuthorityMode = AuthorityMode> = Authority extends 'self' ? 'executor' : 'caller';
|
|
58
59
|
/**
|
|
59
|
-
* Reads under the authority `as` names. A
|
|
60
|
+
* Reads under the authority `as` names. A Query v7 names it on every call; a V6 Query definition
|
|
60
61
|
* reads as the executor.
|
|
61
62
|
*/
|
|
62
63
|
export interface DomainQuery<DomainValue extends Domain = Domain, As extends AuthorityName = AuthorityName> {
|
|
63
|
-
<R extends
|
|
64
|
+
<R extends DefinedQuery>(query: R, input: InputOf<R>, options: QueryOptions<R, As>): Promise<OutputOf<R>>;
|
|
64
65
|
<Output>(query: QueryDefinition<DomainValue, void, Output>): Promise<Output>;
|
|
65
66
|
<Input, Output>(query: QueryDefinition<DomainValue, Input, Output>, input: Input): Promise<Output>;
|
|
66
67
|
}
|
|
67
68
|
/**
|
|
68
|
-
* Writes under the authority `as` names. A Mutation
|
|
69
|
+
* Writes under the authority `as` names. A defined Mutation names it on every call; a Mutation of
|
|
69
70
|
* the closure form may omit it, and writes as the executor.
|
|
70
71
|
*/
|
|
71
72
|
export interface DomainMutate<DomainValue extends Domain = Domain, As extends AuthorityName = AuthorityName> {
|
|
72
|
-
<M extends
|
|
73
|
+
<M extends DefinedMutation>(mutation: M, input: MutationInputOf<M>, options: {
|
|
73
74
|
readonly as: As;
|
|
74
75
|
}): Promise<MutationOutputOf<M>>;
|
|
75
76
|
<Input, Output>(definition: Mutation<DomainValue, Input, Output>, input: Input, options: {
|
|
@@ -97,7 +98,7 @@ export interface DomainCapabilities<DomainValue extends Domain = Domain, Authori
|
|
|
97
98
|
readonly dependencies: HandlerDependencies<DomainValue, Authority>;
|
|
98
99
|
readonly kernel: DomainKernelSessions<Authority>;
|
|
99
100
|
readonly graph: DomainGraphExecutors<DomainValue, Authority>;
|
|
100
|
-
/** A
|
|
101
|
+
/** A Query v7 under `as`; a V6 Query definition as the executor (`graph.self`). */
|
|
101
102
|
readonly query: DomainQuery<DomainValue, As>;
|
|
102
103
|
/** A Mutation under `as`, or as the executor (`graph.self`). */
|
|
103
104
|
readonly mutate: DomainMutate<DomainValue, As>;
|
|
@@ -10,7 +10,7 @@ export interface DeclaredErrorOptions<out Errors extends DeclaredErrors = Declar
|
|
|
10
10
|
export type DeclaredErrorFactory<Errors extends DeclaredErrors> = <Code extends Extract<keyof Errors, string>>(code: Code, details: z.input<Errors[Code]['details']>) => Error;
|
|
11
11
|
interface DeclaredErrorRecord {
|
|
12
12
|
readonly definition: object;
|
|
13
|
-
/** The declaration as written: the object a Function re-declares a
|
|
13
|
+
/** The declaration as written: the object a Function re-declares a Query or Mutation error with. */
|
|
14
14
|
readonly declaration: object;
|
|
15
15
|
readonly code: string;
|
|
16
16
|
readonly family: DeclaredErrorDefinition['family'];
|
|
@@ -20,19 +20,19 @@ interface DeclaredErrorRecord {
|
|
|
20
20
|
/** Retain one implementation-local expected-error contract without publishing it in the Schema. */
|
|
21
21
|
export declare function rememberDeclaredErrors(definition: object, input: unknown): void;
|
|
22
22
|
/**
|
|
23
|
-
* Retain a
|
|
23
|
+
* Retain a Query or Mutation's declared errors, as an implementation's are. A Function that declares one of
|
|
24
24
|
* its codes with the same definition object exposes that error to its own caller.
|
|
25
25
|
*/
|
|
26
|
-
export declare function
|
|
26
|
+
export declare function rememberDefinedErrors(defined: object, id: string, input: unknown): void;
|
|
27
27
|
/** Create a receiver-free factory closed over one admitted Action or Workflow definition. */
|
|
28
28
|
export declare function declaredErrorFactory<Errors extends DeclaredErrors>(definition: object): DeclaredErrorFactory<Errors>;
|
|
29
29
|
/**
|
|
30
30
|
* Return admitted evidence only when the error belongs to the active implementation: raised by it,
|
|
31
|
-
* or by a
|
|
31
|
+
* or by a Query or Mutation whose code it declares with the same definition object.
|
|
32
32
|
*/
|
|
33
33
|
export declare function declaredErrorOf(input: unknown, definition: object): DeclaredErrorRecord | undefined;
|
|
34
|
-
/** The code and the
|
|
35
|
-
export declare function
|
|
34
|
+
/** The code and the id of a Query or Mutation's declared error, whichever Function it reaches. */
|
|
35
|
+
export declare function definedErrorOf(input: unknown): {
|
|
36
36
|
readonly code: string;
|
|
37
|
-
readonly
|
|
37
|
+
readonly id: string;
|
|
38
38
|
} | undefined;
|
|
@@ -5,8 +5,8 @@ const MAXIMUM_DETAILS_BYTES = 16 * 1024;
|
|
|
5
5
|
const CODE_PATTERN = /^[A-Z][A-Z0-9_]{0,127}$/u;
|
|
6
6
|
const declarations = new WeakMap();
|
|
7
7
|
const errors = new WeakMap();
|
|
8
|
-
/**
|
|
9
|
-
const
|
|
8
|
+
/** The id of each Query or Mutation: their errors cross into a Function that re-declares them. */
|
|
9
|
+
const definedIds = new WeakMap();
|
|
10
10
|
class BusinessError extends Error {
|
|
11
11
|
name = 'BusinessError';
|
|
12
12
|
constructor(code) {
|
|
@@ -35,12 +35,12 @@ export function rememberDeclaredErrors(definition, input) {
|
|
|
35
35
|
declarations.set(definition, accepted);
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
|
-
* Retain a
|
|
38
|
+
* Retain a Query or Mutation's declared errors, as an implementation's are. A Function that declares one of
|
|
39
39
|
* its codes with the same definition object exposes that error to its own caller.
|
|
40
40
|
*/
|
|
41
|
-
export function
|
|
42
|
-
rememberDeclaredErrors(
|
|
43
|
-
|
|
41
|
+
export function rememberDefinedErrors(defined, id, input) {
|
|
42
|
+
rememberDeclaredErrors(defined, { errors: input });
|
|
43
|
+
definedIds.set(defined, id);
|
|
44
44
|
}
|
|
45
45
|
/** Create a receiver-free factory closed over one admitted Action or Workflow definition. */
|
|
46
46
|
export function declaredErrorFactory(definition) {
|
|
@@ -81,7 +81,7 @@ export function declaredErrorFactory(definition) {
|
|
|
81
81
|
}
|
|
82
82
|
/**
|
|
83
83
|
* Return admitted evidence only when the error belongs to the active implementation: raised by it,
|
|
84
|
-
* or by a
|
|
84
|
+
* or by a Query or Mutation whose code it declares with the same definition object.
|
|
85
85
|
*/
|
|
86
86
|
export function declaredErrorOf(input, definition) {
|
|
87
87
|
if (!(input instanceof Error))
|
|
@@ -91,19 +91,19 @@ export function declaredErrorOf(input, definition) {
|
|
|
91
91
|
return undefined;
|
|
92
92
|
if (record.definition === definition)
|
|
93
93
|
return record;
|
|
94
|
-
if (!
|
|
94
|
+
if (!definedIds.has(record.definition))
|
|
95
95
|
return undefined;
|
|
96
96
|
return declarations.get(definition)?.get(record.code)?.declaration === record.declaration
|
|
97
97
|
? record
|
|
98
98
|
: undefined;
|
|
99
99
|
}
|
|
100
|
-
/** The code and the
|
|
101
|
-
export function
|
|
100
|
+
/** The code and the id of a Query or Mutation's declared error, whichever Function it reaches. */
|
|
101
|
+
export function definedErrorOf(input) {
|
|
102
102
|
const record = input instanceof Error ? errors.get(input) : undefined;
|
|
103
103
|
if (record === undefined)
|
|
104
104
|
return undefined;
|
|
105
|
-
const
|
|
106
|
-
return
|
|
105
|
+
const id = definedIds.get(record.definition);
|
|
106
|
+
return id === undefined ? undefined : { code: record.code, id };
|
|
107
107
|
}
|
|
108
108
|
function isRecord(input) {
|
|
109
109
|
return input !== null && typeof input === 'object' && !Array.isArray(input);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export type { DeclaredErrorDefinition, DeclaredErrorFactory, DeclaredErrorFamily, DeclaredErrorOptions, DeclaredErrors, NoDeclaredErrors, } from './error.js';
|
|
2
|
-
export { declaredErrorFactory, declaredErrorOf,
|
|
2
|
+
export { declaredErrorFactory, declaredErrorOf, definedErrorOf, rememberDeclaredErrors, rememberDefinedErrors, } from './error.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { declaredErrorFactory, declaredErrorOf,
|
|
1
|
+
export { declaredErrorFactory, declaredErrorOf, definedErrorOf, rememberDeclaredErrors, rememberDefinedErrors, } from './error.js';
|
|
@@ -10,10 +10,10 @@ import type { RichPropertyConditions, RichPropertyDelta, RichPropertyInput } fro
|
|
|
10
10
|
import { type PreconditionNames } from './names.js';
|
|
11
11
|
import { type EventOfTopology, type StatePropertyName, type StatePropertyTopology, type StateOfTopology, type StateTransitionInput } from './transition.js';
|
|
12
12
|
/**
|
|
13
|
-
* The builder a Mutation's `build` receives: of
|
|
13
|
+
* The builder a Mutation's `build` receives: of a defined Mutation over `Schema`
|
|
14
14
|
* (`RichMutationBuilder<Schema>`), or of the deprecated closure form (`RichMutationBuilder`).
|
|
15
15
|
*/
|
|
16
|
-
export type RichMutationBuilder<Schema = never> = [Schema] extends [never] ? ClosureMutationBuilder :
|
|
16
|
+
export type RichMutationBuilder<Schema = never> = [Schema] extends [never] ? ClosureMutationBuilder : DefinedMutationBuilder<Schema>;
|
|
17
17
|
/** A write names one Class: the handle of a union, `d.A.union(d.B)`, names none. */
|
|
18
18
|
type OneClass<K, All = K> = K extends unknown ? [All] extends [K] ? unknown : '✗ a write names one Class, not a union' : never;
|
|
19
19
|
/** A Node Class handle, `d.<Class>`, on which no method was called. */
|
|
@@ -27,41 +27,41 @@ interface HandleEdgeSelector<S, E extends string> {
|
|
|
27
27
|
readonly class: EdgeClassHandle<S, E>;
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
|
-
* The builder a Mutation
|
|
30
|
+
* The builder a defined Mutation's `build` receives (D31): each verb names its Class by its handle,
|
|
31
31
|
* `d.<Class>`, and each guard takes a range. Each precondition verb (`expect.*`) takes `{ name }`
|
|
32
32
|
* last: a refusal of the Mutation because that precondition fails carries the name as
|
|
33
33
|
* `failure.precondition`. A name is unique in its Mutation.
|
|
34
34
|
*/
|
|
35
|
-
export interface
|
|
35
|
+
export interface DefinedMutationBuilder<S> {
|
|
36
36
|
readonly expect: {
|
|
37
37
|
/** The Node exists, of this Class, and its Properties meet `props`. */
|
|
38
38
|
node<K extends string>(input: {
|
|
39
39
|
readonly node: ExistingEndpoint;
|
|
40
40
|
readonly class: NodeClassHandle<S, K>;
|
|
41
41
|
readonly props?: RichPropertyConditions<Cls<S, K>>;
|
|
42
|
-
}, options?: PreconditionOptions):
|
|
42
|
+
}, options?: PreconditionOptions): DefinedMutationBuilder<S>;
|
|
43
43
|
/** The Edge exists, its slug is `slug`, and its Properties meet `props`. */
|
|
44
44
|
edge<E extends string>(input: HandleEdgeSelector<S, E> & {
|
|
45
45
|
readonly slug?: EdgeSlug | null;
|
|
46
46
|
readonly props?: RichPropertyConditions<Cls<S, E>>;
|
|
47
|
-
}, options?: PreconditionOptions):
|
|
47
|
+
}, options?: PreconditionOptions): DefinedMutationBuilder<S>;
|
|
48
48
|
/**
|
|
49
49
|
* A guard (Mutation v4): no root of the range matches. A range is a Class handle after
|
|
50
50
|
* `where`, `union` and `orderBy`, `d.<Class>.where(…)`, or a canonical v7 Query.
|
|
51
51
|
*/
|
|
52
|
-
none<K extends string>(range: GuardRange<S, K>, options?: PreconditionOptions):
|
|
52
|
+
none<K extends string>(range: GuardRange<S, K>, options?: PreconditionOptions): DefinedMutationBuilder<S>;
|
|
53
53
|
/** A guard (Mutation v4): a root of the range matches. */
|
|
54
|
-
exists<K extends string>(range: GuardRange<S, K>, options?: PreconditionOptions):
|
|
54
|
+
exists<K extends string>(range: GuardRange<S, K>, options?: PreconditionOptions): DefinedMutationBuilder<S>;
|
|
55
55
|
/**
|
|
56
56
|
* A guard (Mutation v4): the number of the range's roots is `bounds`, or lies within
|
|
57
57
|
* `{ atLeast?, atMost? }`, bounded at least once.
|
|
58
58
|
*/
|
|
59
|
-
count<K extends string>(range: GuardRange<S, K>, bounds: CountBounds, options?: PreconditionOptions):
|
|
59
|
+
count<K extends string>(range: GuardRange<S, K>, bounds: CountBounds, options?: PreconditionOptions): DefinedMutationBuilder<S>;
|
|
60
60
|
/**
|
|
61
61
|
* A guard (Mutation v4): the range's roots, in its `orderBy`, are exactly these identities, in
|
|
62
62
|
* the order a read of them returned them: a `NodeId` per Node, an `EdgeKey` per Edge.
|
|
63
63
|
*/
|
|
64
|
-
unchanged<K extends string>(range: GuardRange<S, K>, ids: readonly GuardIdentity[], options?: PreconditionOptions):
|
|
64
|
+
unchanged<K extends string>(range: GuardRange<S, K>, ids: readonly GuardIdentity[], options?: PreconditionOptions): DefinedMutationBuilder<S>;
|
|
65
65
|
};
|
|
66
66
|
createNode<K extends string>(input: {
|
|
67
67
|
readonly as: string;
|
|
@@ -91,8 +91,8 @@ export interface RecipeMutationBuilder<S> {
|
|
|
91
91
|
}): this;
|
|
92
92
|
deleteEdge<E extends string>(input: HandleEdgeSelector<S, E>): this;
|
|
93
93
|
}
|
|
94
|
-
/** The form of the Mutation a builder writes: a
|
|
95
|
-
export type BuilderForm = '
|
|
94
|
+
/** The form of the Mutation a builder writes: a defined Mutation's, or the deprecated closure form's. */
|
|
95
|
+
export type BuilderForm = 'defined' | 'closure';
|
|
96
96
|
/**
|
|
97
97
|
* The SDK's builder over the core one, for both forms: a verb's Class is a Class handle
|
|
98
98
|
* (`d.<Class>`) or, in the closure form only, the resolved Class, and only the closure form has a
|
|
@@ -59,7 +59,7 @@ export function richMutationBuilder(portable, names = preconditionNames(), form
|
|
|
59
59
|
return rich;
|
|
60
60
|
},
|
|
61
61
|
};
|
|
62
|
-
const expectation = Object.freeze(form === '
|
|
62
|
+
const expectation = Object.freeze(form === 'defined'
|
|
63
63
|
? guards
|
|
64
64
|
: {
|
|
65
65
|
...guards,
|
|
@@ -149,8 +149,8 @@ export function richMutationBuilder(portable, names = preconditionNames(), form
|
|
|
149
149
|
function writtenClass(selected, kind, form) {
|
|
150
150
|
const cls = handleClass(selected);
|
|
151
151
|
if (cls === undefined) {
|
|
152
|
-
if (form === '
|
|
153
|
-
throw new TypeError('A Mutation
|
|
152
|
+
if (form === 'defined')
|
|
153
|
+
throw new TypeError('A defined Mutation names each Class by its handle, `d.<Class>`.');
|
|
154
154
|
return selected;
|
|
155
155
|
}
|
|
156
156
|
if (kind === 'node' && cls.kind === 'edge')
|
|
@@ -9,12 +9,12 @@ import type { MutationGuardInput } from '@astrale-os/kernel-core/graph/mutate';
|
|
|
9
9
|
import type { NodeId } from '../../../platform/graph/node/index.js';
|
|
10
10
|
import type { EdgeSet, NodeSet } from '../../query/handles/handles.js';
|
|
11
11
|
import type { EdgeKey } from '../../query/handles/rows.js';
|
|
12
|
-
import type {
|
|
12
|
+
import type { QueryDocument } from '../../query/language/query.js';
|
|
13
13
|
/**
|
|
14
14
|
* What a guard reads: a range, the Nodes or Edges of a Class handle `build` receives after
|
|
15
15
|
* `where`, `union` and `orderBy`, or a canonical v7 Query.
|
|
16
16
|
*/
|
|
17
|
-
export type GuardRange<S, K extends string> = NodeSet<S, K, {}, 'value', false> | EdgeSet<S, K, 'value', false> |
|
|
17
|
+
export type GuardRange<S, K extends string> = NodeSet<S, K, {}, 'value', false> | EdgeSet<S, K, 'value', false> | QueryDocument;
|
|
18
18
|
/** How many roots a `count` guard admits: exactly `n`, or within bounds, bounded at least once. */
|
|
19
19
|
export type CountBounds = number | {
|
|
20
20
|
readonly atLeast?: number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { richMutationBuilder, type BuilderForm, type
|
|
1
|
+
export { richMutationBuilder, type BuilderForm, type DefinedMutationBuilder, type RichMutationBuilder, } from './builder.js';
|
|
2
2
|
export type { CreatedNode, ExistingEndpoint, MutationEndpoint } from './endpoint.js';
|
|
3
3
|
export type { RichPropertyConditions, RichPropertyDelta, RichPropertyInput, RichPropertyName, } from './properties.js';
|
|
4
4
|
export type { CountBounds, GuardIdentity, GuardRange, PreconditionOptions } from './guard.js';
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `defineMutation<Schema>()`: one name for both forms. A string id first defines a Mutation
|
|
2
|
+
* `defineMutation<Schema>()`: one name for both forms. A string id first defines a Mutation
|
|
3
3
|
* (D31); a function first defines a Mutation of the closure form, deprecated, which stays in
|
|
4
|
-
* `legacy/v6`. A
|
|
4
|
+
* `legacy/v6`. A defined Mutation is inert: its id and the errors it declares are public, and what it
|
|
5
5
|
* writes is kept for the runtime.
|
|
6
6
|
*/
|
|
7
7
|
import type { schema } from '../../platform/schema/index.js';
|
|
8
8
|
import type { MutationProjector } from './legacy/v6/define.js';
|
|
9
|
-
import type {
|
|
9
|
+
import type { DefinedMutationFactory } from './mutation.js';
|
|
10
10
|
type Callback = (...parameters: never[]) => unknown;
|
|
11
|
-
/** What a Mutation
|
|
12
|
-
export interface
|
|
11
|
+
/** What a defined Mutation writes and answers: its `build`, `output` and `reject`. */
|
|
12
|
+
export interface MutationSpec {
|
|
13
13
|
/** Receives `(input, d, mutation)`. */
|
|
14
14
|
readonly build: Callback;
|
|
15
15
|
readonly output?: Callback;
|
|
16
16
|
readonly reject?: Callback;
|
|
17
17
|
}
|
|
18
|
-
/** The `build`, `output` and `reject` of a Mutation
|
|
19
|
-
export declare function
|
|
18
|
+
/** The `build`, `output` and `reject` of a defined Mutation; `undefined` for anything else. */
|
|
19
|
+
export declare function mutationSpecOf(mutation: unknown): MutationSpec | undefined;
|
|
20
20
|
/**
|
|
21
21
|
* Define a Mutation: `defineMutation<Schema>()('issues.issue.open', { build, output?, reject?,
|
|
22
22
|
* errors? })`. The closure form, `defineMutation<Schema>()((domain) => ({ id, build, project? }))`,
|
|
23
23
|
* stays, deprecated.
|
|
24
24
|
*/
|
|
25
|
-
export declare function defineMutation<Schema extends schema.DomainSchema>():
|
|
25
|
+
export declare function defineMutation<Schema extends schema.DomainSchema>(): DefinedMutationFactory<Schema> & MutationProjector<Schema>;
|
|
26
26
|
export {};
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
+
import { collectDefinition, MAXIMUM_DEFINITION_ID, DEFINITION_ID } from '../query/defined/define.js';
|
|
1
2
|
import { describe } from '../query/handles/terms.js';
|
|
2
|
-
import { collectRecipe, MAXIMUM_RECIPE_ID, RECIPE_ID } from '../query/recipe/define.js';
|
|
3
3
|
import { defineMutation as defineClosureMutation } from './legacy/v6/define.js';
|
|
4
4
|
const FIELDS = new Set(['build', 'output', 'reject', 'errors']);
|
|
5
5
|
const specs = new WeakMap();
|
|
6
|
-
/** The `build`, `output` and `reject` of a Mutation
|
|
7
|
-
export function
|
|
8
|
-
return typeof
|
|
6
|
+
/** The `build`, `output` and `reject` of a defined Mutation; `undefined` for anything else. */
|
|
7
|
+
export function mutationSpecOf(mutation) {
|
|
8
|
+
return typeof mutation === 'object' && mutation !== null ? specs.get(mutation) : undefined;
|
|
9
9
|
}
|
|
10
|
-
function
|
|
11
|
-
if (typeof id !== 'string' || id.length >
|
|
12
|
-
throw new TypeError(`A Mutation id is lowercase segments of letters, digits and hyphens joined by dots, at most ${
|
|
10
|
+
function defineV7Mutation(id, spec) {
|
|
11
|
+
if (typeof id !== 'string' || id.length > MAXIMUM_DEFINITION_ID || !DEFINITION_ID.test(id))
|
|
12
|
+
throw new TypeError(`A Mutation id is lowercase segments of letters, digits and hyphens joined by dots, at most ${MAXIMUM_DEFINITION_ID} characters ('issues.issue.open'); got ${describe(id)}.`);
|
|
13
13
|
if (typeof spec !== 'object' || spec === null || Array.isArray(spec))
|
|
14
14
|
throw new TypeError(`Mutation ${id} takes { build, output?, reject?, errors? }; got ${describe(spec)}.`);
|
|
15
15
|
const fields = spec;
|
|
@@ -26,18 +26,18 @@ function defineMutationRecipe(id, spec) {
|
|
|
26
26
|
const errors = fields.errors ?? {};
|
|
27
27
|
if (typeof errors !== 'object' || errors === null || Array.isArray(errors))
|
|
28
28
|
throw new TypeError(`Mutation ${id}'s errors is a record of declared errors by UPPER_SNAKE code; got ${describe(errors)}.`);
|
|
29
|
-
const
|
|
29
|
+
const mutation = Object.freeze({
|
|
30
30
|
kind: 'mutation',
|
|
31
31
|
id,
|
|
32
32
|
errors: Object.freeze({ ...errors }),
|
|
33
33
|
});
|
|
34
|
-
|
|
35
|
-
specs.set(
|
|
34
|
+
collectDefinition(mutation);
|
|
35
|
+
specs.set(mutation, Object.freeze({
|
|
36
36
|
build: build,
|
|
37
37
|
...(output === undefined ? {} : { output: output }),
|
|
38
38
|
...(reject === undefined ? {} : { reject: reject }),
|
|
39
39
|
}));
|
|
40
|
-
return
|
|
40
|
+
return mutation;
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
43
|
* Define a Mutation: `defineMutation<Schema>()('issues.issue.open', { build, output?, reject?,
|
|
@@ -47,6 +47,6 @@ function defineMutationRecipe(id, spec) {
|
|
|
47
47
|
export function defineMutation() {
|
|
48
48
|
const closure = defineClosureMutation();
|
|
49
49
|
return ((first, spec) => typeof first === 'string'
|
|
50
|
-
?
|
|
50
|
+
? defineV7Mutation(first, spec)
|
|
51
51
|
: closure(first));
|
|
52
52
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { type MutationAST as MutationASTValue, type MutationResult } from '@astrale-os/kernel-core/graph/mutate';
|
|
2
2
|
import type { GraphMutationOptions } from '../../../platform/client/index.js';
|
|
3
3
|
import type { Domain } from '../../../platform/schema/index.js';
|
|
4
|
-
import type { Mutation,
|
|
4
|
+
import type { Mutation, DefinedMutation } from '../mutation.js';
|
|
5
5
|
/** Exact caller-scoped canonical document capability required by Mutation execution. */
|
|
6
6
|
export type MutationClient = Readonly<{
|
|
7
7
|
mutate(ast: MutationASTValue, options?: GraphMutationOptions): Promise<MutationResult>;
|
|
8
8
|
}>;
|
|
9
|
-
export declare function executeMutation<DomainValue extends Domain, Input, Output>(client: MutationClient, domain: DomainValue, definition: Mutation<DomainValue, Input, Output> |
|
|
9
|
+
export declare function executeMutation<DomainValue extends Domain, Input, Output>(client: MutationClient, domain: DomainValue, definition: Mutation<DomainValue, Input, Output> | DefinedMutation<string, Input, Output>, input: Input): Promise<Output>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { MutationAST, } from '@astrale-os/kernel-core/graph/mutate';
|
|
2
|
-
import { outputContext } from '../../query/execution/
|
|
2
|
+
import { outputContext } from '../../query/execution/run.js';
|
|
3
3
|
import { handlesOf } from '../../query/handles/build.js';
|
|
4
4
|
import { modelOf } from '../../query/handles/model.js';
|
|
5
5
|
import { preconditionNames, richMutationBuilder } from '../authoring/index.js';
|
|
6
|
-
import {
|
|
6
|
+
import { mutationSpecOf } from '../define.js';
|
|
7
7
|
import { mutationFailure } from '../failure.js';
|
|
8
8
|
import { realizeMutation } from '../legacy/v6/define.js';
|
|
9
9
|
import { projectMutation } from './projection.js';
|
|
@@ -11,15 +11,15 @@ export async function executeMutation(client, domain, definition, input) {
|
|
|
11
11
|
if (client === null || typeof client !== 'object' || typeof client.mutate !== 'function') {
|
|
12
12
|
throw new TypeError('Mutation execution requires a Client mutate capability.');
|
|
13
13
|
}
|
|
14
|
-
const spec =
|
|
14
|
+
const spec = mutationSpecOf(definition);
|
|
15
15
|
const operation = spec === undefined
|
|
16
16
|
? closureOperation(definition, domain)
|
|
17
|
-
:
|
|
17
|
+
: definedOperation(definition, spec, domain);
|
|
18
18
|
const names = preconditionNames();
|
|
19
19
|
let ast;
|
|
20
20
|
try {
|
|
21
|
-
// `build` receives the handles a
|
|
22
|
-
// guards take.
|
|
21
|
+
// `build` receives the same handles as a Query's `build`, for the Classes it names and the
|
|
22
|
+
// ranges its guards take.
|
|
23
23
|
const d = lazyHandles(domain);
|
|
24
24
|
// What `build` returns reaches the core builder, which refuses a promise or a value.
|
|
25
25
|
ast = MutationAST.build((builder) => operation.build(input, richMutationBuilder(builder, names, operation.form), d));
|
|
@@ -45,17 +45,17 @@ function closureOperation(mutation, domain) {
|
|
|
45
45
|
: { reject: (failure) => definition.reject(failure) }),
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
|
-
function
|
|
48
|
+
function definedOperation(mutation, spec, domain) {
|
|
49
49
|
const { build, output, reject } = spec;
|
|
50
50
|
return {
|
|
51
|
-
form: '
|
|
51
|
+
form: 'defined',
|
|
52
52
|
build: (input, builder, d) => {
|
|
53
53
|
const written = build(input, d, builder);
|
|
54
54
|
if (isPromiseLike(written)) {
|
|
55
55
|
// Refused before any write is sent: a write after its first await fails, and is observed.
|
|
56
56
|
;
|
|
57
57
|
written.then(undefined, () => undefined);
|
|
58
|
-
throw new TypeError(`Mutation ${
|
|
58
|
+
throw new TypeError(`Mutation ${mutation.id}'s build is synchronous: it writes the Mutation, and awaits nothing.`);
|
|
59
59
|
}
|
|
60
60
|
return written;
|
|
61
61
|
},
|
|
@@ -63,7 +63,7 @@ function recipeOperation(recipe, spec, domain) {
|
|
|
63
63
|
...(reject === undefined
|
|
64
64
|
? {}
|
|
65
65
|
: {
|
|
66
|
-
reject: (failure, input) => reject(failure, input, outputContext(
|
|
66
|
+
reject: (failure, input) => reject(failure, input, outputContext(mutation, modelOf(domain))),
|
|
67
67
|
}),
|
|
68
68
|
};
|
|
69
69
|
}
|
|
@@ -2,8 +2,8 @@ import type { Domain, schema } from '../../../platform/schema/index.js';
|
|
|
2
2
|
import type { Mutation } from '../mutation.js';
|
|
3
3
|
import type { MutationClient } from './execute.js';
|
|
4
4
|
/**
|
|
5
|
-
* Invocation-bound executor for Mutations of the closure form. A Mutation
|
|
6
|
-
* authority on each call, `mutate(
|
|
5
|
+
* Invocation-bound executor for Mutations of the closure form. A defined Mutation names its
|
|
6
|
+
* authority on each call, `mutate(mutation, input, { as })`, so it is refused here.
|
|
7
7
|
*/
|
|
8
8
|
export interface MutationExecutor<DomainValue extends Domain = Domain> {
|
|
9
9
|
<Input, Output>(definition: Mutation<DomainValue, Input, Output>, input: Input): Promise<Output>;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { mutationSpecOf } from '../define.js';
|
|
2
2
|
import { executeMutation } from './execute.js';
|
|
3
3
|
/** Private Runtime binding to one Client and the exact loaded root Domain. */
|
|
4
4
|
export function bindMutation(client, domain) {
|
|
5
5
|
const executable = domain;
|
|
6
6
|
const execute = async (definition, input) => {
|
|
7
|
-
if (
|
|
7
|
+
if (mutationSpecOf(definition) !== undefined)
|
|
8
8
|
throw new TypeError(`Mutation ${definition.id} is called with mutate(mutation, input, { as: 'executor' | 'caller' }).`);
|
|
9
9
|
return executeMutation(client, executable, definition, input);
|
|
10
10
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { defineMutation } from './define.js';
|
|
2
2
|
export { executeMutation, type MutationClient, type MutationExecutor } from './execution/index.js';
|
|
3
3
|
export type { MutationFailure } from './failure.js';
|
|
4
|
-
export type { Mutation, MutationDefinition, MutationInputOf, MutationOutputOf,
|
|
5
|
-
export type { ClosureMutationBuilder, CountBounds, CreatedNode, EdgeSelector, ExistingEndpoint, GuardIdentity, GuardRange, MutationEndpoint, PreconditionOptions, QueryPrecondition,
|
|
4
|
+
export type { Mutation, MutationDefinition, MutationInputOf, MutationOutputOf, DefinedMutation, DefinedMutationFactory, } from './mutation.js';
|
|
5
|
+
export type { ClosureMutationBuilder, CountBounds, CreatedNode, EdgeSelector, ExistingEndpoint, GuardIdentity, GuardRange, MutationEndpoint, PreconditionOptions, QueryPrecondition, DefinedMutationBuilder, RichMutationBuilder, RichPropertyConditions, RichPropertyDelta, RichPropertyInput, RichPropertyName, } from './authoring/index.js';
|
|
6
6
|
/**
|
|
7
7
|
* Canonical low-level Mutation documents remain available as the explicit escape hatch, listed one
|
|
8
8
|
* by one as the SDK has exported them, so a newer Kernel's Mutation internals never reach it.
|
|
@@ -6,7 +6,7 @@ type ResolvedDomainOf<Schema extends schema.DomainSchema> = Extract<schema.Domai
|
|
|
6
6
|
type AuthoringDomainOf<Schema extends schema.DomainSchema> = ResolvedDomainOf<Schema>;
|
|
7
7
|
export interface MutationProjector<Schema extends schema.DomainSchema> {
|
|
8
8
|
/**
|
|
9
|
-
* @deprecated The closure form: define the Mutation
|
|
9
|
+
* @deprecated The closure form: define the Mutation from a string id,
|
|
10
10
|
* `defineMutation<Schema>()(id, { build(input, d, mutation), output?, reject?, errors? })`. A
|
|
11
11
|
* Mutation of this form called without `as` writes as the executor.
|
|
12
12
|
*/
|
|
@@ -17,7 +17,7 @@ export interface Mutation<DomainValue extends Domain = Domain, Input = unknown,
|
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* Canonical admitted operation produced by realizing one Mutation of the closure form. `build`
|
|
20
|
-
* receives the handles `D` a
|
|
20
|
+
* receives the same handles `D` as a Query's `build`, for the ranges its guards take.
|
|
21
21
|
*/
|
|
22
22
|
export interface MutationDefinition<Input, Output = MutationResult, D = unknown> {
|
|
23
23
|
readonly id: string;
|
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
import type { MutationResult } from '@astrale-os/kernel-core/graph/mutate';
|
|
2
|
+
import type { Errors, OutputContext } from '../query/defined/query.js';
|
|
2
3
|
import type { Handles } from '../query/handles/handles.js';
|
|
3
|
-
import type {
|
|
4
|
-
import type { RecipeMutationBuilder } from './authoring/builder.js';
|
|
4
|
+
import type { DefinedMutationBuilder } from './authoring/builder.js';
|
|
5
5
|
import type { MutationFailure } from './failure.js';
|
|
6
6
|
import type { Mutation, MutationDefinition } from './legacy/v6/mutation.js';
|
|
7
7
|
export type { Mutation, MutationDefinition } from './legacy/v6/mutation.js';
|
|
8
8
|
/**
|
|
9
|
-
* A Mutation
|
|
10
|
-
* public, and what it writes is kept for the runtime. A call names its authority,
|
|
11
|
-
* `mutate(
|
|
9
|
+
* A Mutation defined from a string id (D31): inert, its id and the errors its `reject` may raise
|
|
10
|
+
* are public, and what it writes is kept for the runtime. A call names its authority,
|
|
11
|
+
* `mutate(mutation, input, { as: 'executor' | 'caller' })`.
|
|
12
12
|
*/
|
|
13
|
-
export interface
|
|
13
|
+
export interface DefinedMutation<Id extends string = string, Input = unknown, Output = unknown, E extends Errors = Errors> {
|
|
14
14
|
readonly kind: 'mutation';
|
|
15
15
|
readonly id: Id;
|
|
16
16
|
readonly errors: E;
|
|
17
17
|
readonly '~input'?: Input;
|
|
18
18
|
readonly '~output'?: Output;
|
|
19
19
|
}
|
|
20
|
-
/** `defineMutation<Schema>()`
|
|
21
|
-
export interface
|
|
20
|
+
/** `defineMutation<Schema>()` given a string id first. */
|
|
21
|
+
export interface DefinedMutationFactory<S> {
|
|
22
22
|
/**
|
|
23
23
|
* `build` writes the Mutation with the builder, naming each Class by its handle, `d.<Class>`;
|
|
24
24
|
* `output` maps the committed result, `reject` an expected refusal, and may raise a declared
|
|
25
25
|
* error through `context.error`, which a Function that calls the Mutation re-declares.
|
|
26
26
|
*/
|
|
27
27
|
<const Id extends string, Input, Output = MutationResult, E extends Errors = {}>(id: Id, spec: {
|
|
28
|
-
readonly build: (input: Input, d: Handles<S>, mutation:
|
|
28
|
+
readonly build: (input: Input, d: Handles<S>, mutation: DefinedMutationBuilder<S>) => undefined;
|
|
29
29
|
readonly output?: (result: MutationResult, input: Input) => Output;
|
|
30
30
|
readonly reject?: (failure: MutationFailure, input: Input, context: OutputContext<S, E>) => NoInfer<Output>;
|
|
31
31
|
readonly errors?: E;
|
|
32
|
-
}):
|
|
32
|
+
}): DefinedMutation<Id, Input, Output, E>;
|
|
33
33
|
}
|
|
34
|
-
export type MutationInputOf<Value> = Value extends
|
|
35
|
-
export type MutationOutputOf<Value> = Value extends
|
|
34
|
+
export type MutationInputOf<Value> = Value extends DefinedMutation<string, infer Input, infer _Output, Errors> ? Input : Value extends Mutation<infer _Domain, infer Input, infer _Output> ? Input : Value extends MutationDefinition<infer Input, infer _Output> ? Input : never;
|
|
35
|
+
export type MutationOutputOf<Value> = Value extends DefinedMutation<string, infer _Input, infer Output, Errors> ? Output : Value extends Mutation<infer _Domain, infer _Input, infer Output> ? Output : Value extends MutationDefinition<infer _Input, infer Output> ? Output : never;
|
|
@@ -12,7 +12,7 @@ export function createQueryComposition() {
|
|
|
12
12
|
requireOpen(open);
|
|
13
13
|
requireLocalId(id, ids);
|
|
14
14
|
if (definition?.kind !== 'query')
|
|
15
|
-
invalid('Composite leaves must be single
|
|
15
|
+
invalid('Composite leaves must be single Queries.');
|
|
16
16
|
requireLocalReferences(input, token);
|
|
17
17
|
return createPlan(token, Object.freeze({
|
|
18
18
|
kind: 'leaf',
|