@toa.io/core 1.0.0-alpha.31 → 1.0.0-alpha.310
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/package.json +28 -12
- package/transpiled/abandon.d.ts +9 -0
- package/transpiled/abandon.js +37 -0
- package/transpiled/abandon.js.map +1 -0
- package/transpiled/assignment.d.ts +6 -0
- package/transpiled/assignment.js +25 -0
- package/transpiled/assignment.js.map +1 -0
- package/transpiled/call.d.ts +10 -0
- package/transpiled/call.js +165 -0
- package/transpiled/call.js.map +1 -0
- package/transpiled/cascade.d.ts +7 -0
- package/transpiled/cascade.js +28 -0
- package/transpiled/cascade.js.map +1 -0
- package/transpiled/component.d.ts +15 -0
- package/transpiled/component.js +148 -0
- package/transpiled/component.js.map +1 -0
- package/transpiled/composition.d.ts +6 -0
- package/transpiled/composition.js +20 -0
- package/transpiled/composition.js.map +1 -0
- package/transpiled/connector.d.ts +71 -0
- package/transpiled/connector.js +248 -0
- package/transpiled/connector.js.map +1 -0
- package/transpiled/context.d.ts +25 -0
- package/transpiled/context.js +55 -0
- package/transpiled/context.js.map +1 -0
- package/transpiled/contract/component.d.ts +24 -0
- package/transpiled/contract/component.js +48 -0
- package/transpiled/contract/component.js.map +1 -0
- package/transpiled/contract/contract.d.ts +10 -0
- package/transpiled/contract/contract.js +14 -0
- package/transpiled/contract/contract.js.map +1 -0
- package/transpiled/contract/index.d.ts +3 -0
- package/transpiled/contract/index.js +4 -0
- package/transpiled/contract/index.js.map +1 -0
- package/transpiled/contract/reply.d.ts +7 -0
- package/transpiled/contract/reply.js +48 -0
- package/transpiled/contract/reply.js.map +1 -0
- package/transpiled/contract/request.d.ts +39 -0
- package/transpiled/contract/request.js +115 -0
- package/transpiled/contract/request.js.map +1 -0
- package/transpiled/contract/schemas.d.ts +4 -0
- package/transpiled/contract/schemas.js +36 -0
- package/transpiled/contract/schemas.js.map +1 -0
- package/transpiled/deliveries.d.ts +22 -0
- package/transpiled/deliveries.js +31 -0
- package/transpiled/deliveries.js.map +1 -0
- package/transpiled/effect.d.ts +7 -0
- package/transpiled/effect.js +13 -0
- package/transpiled/effect.js.map +1 -0
- package/transpiled/emission.d.ts +10 -0
- package/transpiled/emission.js +16 -0
- package/transpiled/emission.js.map +1 -0
- package/transpiled/encoded.d.ts +16 -0
- package/transpiled/encoded.js +25 -0
- package/transpiled/encoded.js.map +1 -0
- package/transpiled/entities/changeset.d.ts +10 -0
- package/transpiled/entities/changeset.js +27 -0
- package/transpiled/entities/changeset.js.map +1 -0
- package/transpiled/entities/entity.d.ts +19 -0
- package/transpiled/entities/entity.js +137 -0
- package/transpiled/entities/entity.js.map +1 -0
- package/transpiled/entities/factory.d.ts +27 -0
- package/transpiled/entities/factory.js +38 -0
- package/transpiled/entities/factory.js.map +1 -0
- package/transpiled/entities/index.d.ts +5 -0
- package/transpiled/entities/index.js +6 -0
- package/transpiled/entities/index.js.map +1 -0
- package/transpiled/entities/newid.d.ts +11 -0
- package/transpiled/entities/newid.js +41 -0
- package/transpiled/entities/newid.js.map +1 -0
- package/transpiled/entities/set.d.ts +10 -0
- package/transpiled/entities/set.js +19 -0
- package/transpiled/entities/set.js.map +1 -0
- package/transpiled/event.d.ts +14 -0
- package/transpiled/event.js +53 -0
- package/transpiled/event.js.map +1 -0
- package/transpiled/exceptions.d.ts +104 -0
- package/transpiled/exceptions.js +205 -0
- package/transpiled/exceptions.js.map +1 -0
- package/transpiled/gate.d.ts +40 -0
- package/transpiled/gate.js +84 -0
- package/transpiled/gate.js.map +1 -0
- package/transpiled/guard.d.ts +7 -0
- package/transpiled/guard.js +12 -0
- package/transpiled/guard.js.map +1 -0
- package/transpiled/halting.d.ts +16 -0
- package/transpiled/halting.js +25 -0
- package/transpiled/halting.js.map +1 -0
- package/transpiled/index.d.ts +41 -0
- package/transpiled/index.js +34 -0
- package/transpiled/index.js.map +1 -0
- package/transpiled/instance.d.ts +10 -0
- package/transpiled/instance.js +30 -0
- package/transpiled/instance.js.map +1 -0
- package/transpiled/locator.d.ts +12 -0
- package/transpiled/locator.js +32 -0
- package/transpiled/locator.js.map +1 -0
- package/transpiled/measurements.d.ts +20 -0
- package/transpiled/measurements.js +40 -0
- package/transpiled/measurements.js.map +1 -0
- package/transpiled/observation.d.ts +7 -0
- package/transpiled/observation.js +14 -0
- package/transpiled/observation.js.map +1 -0
- package/transpiled/operation.d.ts +69 -0
- package/transpiled/operation.js +174 -0
- package/transpiled/operation.js.map +1 -0
- package/transpiled/outbox.d.ts +45 -0
- package/transpiled/outbox.js +448 -0
- package/transpiled/outbox.js.map +1 -0
- package/transpiled/outbox.measurements.d.ts +4 -0
- package/transpiled/outbox.measurements.js +38 -0
- package/transpiled/outbox.measurements.js.map +1 -0
- package/transpiled/query/criteria.d.ts +6 -0
- package/transpiled/query/criteria.js +74 -0
- package/transpiled/query/criteria.js.map +1 -0
- package/transpiled/query/options.d.ts +3 -0
- package/transpiled/query/options.js +34 -0
- package/transpiled/query/options.js.map +1 -0
- package/transpiled/query.d.ts +9 -0
- package/transpiled/query.js +57 -0
- package/transpiled/query.js.map +1 -0
- package/transpiled/receiver.d.ts +20 -0
- package/transpiled/receiver.js +113 -0
- package/transpiled/receiver.js.map +1 -0
- package/transpiled/reflection.d.ts +9 -0
- package/transpiled/reflection.js +13 -0
- package/transpiled/reflection.js.map +1 -0
- package/transpiled/remote.d.ts +10 -0
- package/transpiled/remote.js +11 -0
- package/transpiled/remote.js.map +1 -0
- package/transpiled/safety.d.ts +5 -0
- package/transpiled/safety.js +26 -0
- package/transpiled/safety.js.map +1 -0
- package/transpiled/state.d.ts +36 -0
- package/transpiled/state.js +131 -0
- package/transpiled/state.js.map +1 -0
- package/transpiled/trail.d.ts +78 -0
- package/transpiled/trail.js +112 -0
- package/transpiled/trail.js.map +1 -0
- package/transpiled/transition.d.ts +14 -0
- package/transpiled/transition.js +51 -0
- package/transpiled/transition.js.map +1 -0
- package/transpiled/transmission.d.ts +8 -0
- package/transpiled/transmission.js +30 -0
- package/transpiled/transmission.js.map +1 -0
- package/transpiled/types/atomicity.d.ts +58 -0
- package/transpiled/types/atomicity.js +2 -0
- package/transpiled/types/atomicity.js.map +1 -0
- package/transpiled/types/bindings.d.ts +77 -0
- package/transpiled/types/bindings.js +2 -0
- package/transpiled/types/bindings.js.map +1 -0
- package/transpiled/types/bridges.d.ts +41 -0
- package/transpiled/types/bridges.js +2 -0
- package/transpiled/types/bridges.js.map +1 -0
- package/transpiled/types/extensions.d.ts +116 -0
- package/transpiled/types/extensions.js +2 -0
- package/transpiled/types/extensions.js.map +1 -0
- package/transpiled/types/inbox.d.ts +22 -0
- package/transpiled/types/inbox.js +2 -0
- package/transpiled/types/inbox.js.map +1 -0
- package/transpiled/types/index.d.ts +14 -0
- package/transpiled/types/index.js +9 -0
- package/transpiled/types/index.js.map +1 -0
- package/transpiled/types/message.d.ts +16 -0
- package/transpiled/types/message.js +2 -0
- package/transpiled/types/message.js.map +1 -0
- package/transpiled/types/operations.d.ts +15 -0
- package/transpiled/types/operations.js +2 -0
- package/transpiled/types/operations.js.map +1 -0
- package/transpiled/types/outbox.d.ts +54 -0
- package/transpiled/types/outbox.js +2 -0
- package/transpiled/types/outbox.js.map +1 -0
- package/transpiled/types/receiver.d.ts +9 -0
- package/transpiled/types/receiver.js +2 -0
- package/transpiled/types/receiver.js.map +1 -0
- package/transpiled/types/request.d.ts +119 -0
- package/transpiled/types/request.js +2 -0
- package/transpiled/types/request.js.map +1 -0
- package/transpiled/types/state.d.ts +9 -0
- package/transpiled/types/state.js +2 -0
- package/transpiled/types/state.js.map +1 -0
- package/transpiled/types/storages.d.ts +146 -0
- package/transpiled/types/storages.js +2 -0
- package/transpiled/types/storages.js.map +1 -0
- package/transpiled/unmanaged.d.ts +5 -0
- package/transpiled/unmanaged.js +7 -0
- package/transpiled/unmanaged.js.map +1 -0
- package/src/assignment.js +0 -31
- package/src/call.js +0 -42
- package/src/cascade.js +0 -35
- package/src/component.js +0 -41
- package/src/composition.js +0 -25
- package/src/connector.js +0 -183
- package/src/context.js +0 -55
- package/src/contract/conditions.js +0 -21
- package/src/contract/index.js +0 -7
- package/src/contract/reply.js +0 -25
- package/src/contract/request.js +0 -67
- package/src/contract/schemas/error.yaml +0 -9
- package/src/contract/schemas/index.js +0 -7
- package/src/contract/schemas/query.yaml +0 -30
- package/src/discovery.js +0 -44
- package/src/emission.js +0 -23
- package/src/entities/changeset.js +0 -38
- package/src/entities/entity.js +0 -74
- package/src/entities/factory.js +0 -33
- package/src/entities/index.js +0 -5
- package/src/entities/set.js +0 -15
- package/src/event.js +0 -40
- package/src/exceptions.js +0 -100
- package/src/exposition.js +0 -27
- package/src/index.js +0 -47
- package/src/locator.js +0 -54
- package/src/observation.js +0 -20
- package/src/operation.js +0 -69
- package/src/query/criteria.js +0 -41
- package/src/query/options.js +0 -40
- package/src/query.js +0 -41
- package/src/receiver.js +0 -61
- package/src/reflection.js +0 -28
- package/src/remote.js +0 -17
- package/src/state.js +0 -99
- package/src/transition.js +0 -67
- package/src/transmission.js +0 -33
- package/test/call.fixtures.js +0 -27
- package/test/call.test.js +0 -46
- package/test/component.fixtures.js +0 -21
- package/test/component.test.js +0 -40
- package/test/connector.fixtures.js +0 -40
- package/test/connector.test.js +0 -176
- package/test/context.fixtures.js +0 -18
- package/test/context.test.js +0 -29
- package/test/contract/conditions.test.js +0 -26
- package/test/contract/contract.fixtures.js +0 -33
- package/test/contract/request.test.js +0 -112
- package/test/emission.fixtures.js +0 -17
- package/test/emission.test.js +0 -35
- package/test/entities/entity.fixtures.js +0 -29
- package/test/entities/entity.test.js +0 -65
- package/test/entities/factory.fixtures.js +0 -18
- package/test/entities/factory.test.js +0 -48
- package/test/entities/set.fixtures.js +0 -11
- package/test/entities/set.test.js +0 -12
- package/test/event.fixtures.js +0 -29
- package/test/event.test.js +0 -118
- package/test/locator.test.js +0 -113
- package/test/query.fixtures.js +0 -100
- package/test/query.test.js +0 -86
- package/test/receiver.fixtures.js +0 -23
- package/test/receiver.test.js +0 -95
- package/test/reflection.test.js +0 -30
- package/test/state.fixtures.js +0 -47
- package/test/state.test.js +0 -46
- package/test/transmission.fixtures.js +0 -15
- package/test/transmission.test.js +0 -46
- package/types/bindings.d.ts +0 -40
- package/types/bridges.ts +0 -30
- package/types/component.d.ts +0 -9
- package/types/connector.d.ts +0 -18
- package/types/context.d.ts +0 -21
- package/types/entity.d.ts +0 -46
- package/types/event.d.ts +0 -11
- package/types/exception.d.ts +0 -4
- package/types/extensions.d.ts +0 -29
- package/types/index.ts +0 -14
- package/types/locator.d.ts +0 -13
- package/types/message.d.ts +0 -3
- package/types/operations.d.ts +0 -2
- package/types/query.d.ts +0 -15
- package/types/receiver.d.ts +0 -12
- package/types/reflection.d.ts +0 -14
- package/types/request.d.ts +0 -23
- package/types/state.d.ts +0 -35
- package/types/storages.d.ts +0 -71
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Request } from './request.ts';
|
|
2
|
+
export type type = 'transition' | 'observation' | 'assignment' | 'computation' | 'effect' | 'unmanaged';
|
|
3
|
+
export type scope = 'object' | 'objects' | 'changeset' | 'stream' | 'none';
|
|
4
|
+
/**
|
|
5
|
+
* How an endpoint is called. What it resolves to is what the operation declares — `toa types`
|
|
6
|
+
* writes that per operation, and these are what a hand-written context says instead.
|
|
7
|
+
*/
|
|
8
|
+
export type Call<Output = any, Input = any> = (request: Request<Input>) => Promise<Output>;
|
|
9
|
+
export type Observation<Output = any, Input = never, Entity = unknown> = (request: Request<Input, Entity>) => Promise<Output extends unknown[] ? Output : Output | null>;
|
|
10
|
+
export type Transition<Output = any, Input = never, Entity = unknown> = (request: Request<Input, Entity>) => Promise<Output | null>;
|
|
11
|
+
/**
|
|
12
|
+
* Runs on every change to an entity's state, before the contract is applied. `false` refuses
|
|
13
|
+
* the change as `EntityGuard`.
|
|
14
|
+
*/
|
|
15
|
+
export type Guard<T, C = unknown> = (state: T, origin: T | null, context: C) => boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../../source/types/operations.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Connector } from '../connector.ts';
|
|
2
|
+
import type { Event } from './state.ts';
|
|
3
|
+
/**
|
|
4
|
+
* The intent to publish, committed with the state change it belongs to. Everything about it
|
|
5
|
+
* is core's: the storage writes it and, where the images are the write's own, fills
|
|
6
|
+
* `event.origin` and `event.state` in.
|
|
7
|
+
*/
|
|
8
|
+
export interface Row {
|
|
9
|
+
id: string;
|
|
10
|
+
/** which replica pumps this row; carries no other meaning, and no ordering */
|
|
11
|
+
lane: number;
|
|
12
|
+
/** settled for every destination */
|
|
13
|
+
published: boolean;
|
|
14
|
+
/** not before this */
|
|
15
|
+
pending: number;
|
|
16
|
+
/** the destinations it has not been sent to yet, by name */
|
|
17
|
+
outstanding: string[];
|
|
18
|
+
/**
|
|
19
|
+
* The hops that led to the change. Written onto the row rather than left in scope, because
|
|
20
|
+
* the pump publishes off the operation's path — possibly in another replica, an hour later.
|
|
21
|
+
* Absent on a row written before this existed, which reads as a chain that starts there.
|
|
22
|
+
*/
|
|
23
|
+
trail?: string[];
|
|
24
|
+
/** an assignment's images are absent until the storage fills them in */
|
|
25
|
+
event: Event;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Somewhere a committed state change goes. A component's `Emission` is one, under the name
|
|
29
|
+
* `events`; an extension may contribute others, and each is published and settled on its own,
|
|
30
|
+
* so one that is down delays nothing but itself.
|
|
31
|
+
*/
|
|
32
|
+
export interface Destination extends Connector {
|
|
33
|
+
/** what a row is outstanding for, as the row records it */
|
|
34
|
+
readonly name: string;
|
|
35
|
+
/** the row, not its event: what goes on the wire is the chain it carries too */
|
|
36
|
+
emit(row: Row): Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The read side of an outbox. What writes a row is the storage's own: it happens inside the
|
|
40
|
+
* transaction the storage opened, which core never reaches into.
|
|
41
|
+
*/
|
|
42
|
+
export interface Storage {
|
|
43
|
+
/**
|
|
44
|
+
* One page of what is due, not settled for every destination, and in one of the given lanes,
|
|
45
|
+
* in the order the rows were written. `after` continues from the last id of the page before.
|
|
46
|
+
*/
|
|
47
|
+
pending(lanes: number[], now: number, limit: number, after?: string): Promise<Row[]>;
|
|
48
|
+
/**
|
|
49
|
+
* Takes `destinations` out of what those rows are outstanding for, and marks published the
|
|
50
|
+
* ones left outstanding for nothing. Several destinations at once, because the ordinary case
|
|
51
|
+
* is all of them landing in one window, and that is then one write.
|
|
52
|
+
*/
|
|
53
|
+
settle(ids: string[], destinations: string[]): Promise<void>;
|
|
54
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbox.js","sourceRoot":"","sources":["../../source/types/outbox.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Connector } from '../connector.ts';
|
|
2
|
+
import type { Message } from './message.ts';
|
|
3
|
+
/**
|
|
4
|
+
* What consumes an event of the context. Core ships one, and an extension may put its own
|
|
5
|
+
* in its place, so what a binding is handed is this rather than core's class.
|
|
6
|
+
*/
|
|
7
|
+
export interface Receiver extends Connector {
|
|
8
|
+
receive(message: Message): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receiver.js","sourceRoot":"","sources":["../../source/types/receiver.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { Exception } from '../exceptions.ts';
|
|
2
|
+
/**
|
|
3
|
+
* What a call asks for. `Entity` is the record it is about, which narrows the projection;
|
|
4
|
+
* left out, any name is accepted.
|
|
5
|
+
*/
|
|
6
|
+
export interface Query<Entity = any> {
|
|
7
|
+
id?: string;
|
|
8
|
+
ids?: string[];
|
|
9
|
+
criteria?: string;
|
|
10
|
+
search?: string;
|
|
11
|
+
sample?: number;
|
|
12
|
+
omit?: number;
|
|
13
|
+
limit?: number;
|
|
14
|
+
sort?: string[];
|
|
15
|
+
projection?: Array<string & keyof Entity>;
|
|
16
|
+
version?: number;
|
|
17
|
+
deleted?: boolean;
|
|
18
|
+
}
|
|
19
|
+
/** Origin of a call. Stamped by the framework; whoever reads it takes the keys it knows. */
|
|
20
|
+
export type Source = {
|
|
21
|
+
namespace: string;
|
|
22
|
+
component: string;
|
|
23
|
+
operation: string;
|
|
24
|
+
} | {
|
|
25
|
+
namespace: string;
|
|
26
|
+
component: string;
|
|
27
|
+
event: string;
|
|
28
|
+
} | {
|
|
29
|
+
service: string;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* What a caller asks for, and what a caller may say about it — the identity of the call, where the
|
|
33
|
+
* caller has one to give, and whatever of the envelope whoever hands it over already knows. A
|
|
34
|
+
* receiver stamps the identity and the chain off the message the call came from.
|
|
35
|
+
*/
|
|
36
|
+
export interface Request<Input = any, Entity = any> {
|
|
37
|
+
input?: Input;
|
|
38
|
+
query?: Query<Entity>;
|
|
39
|
+
/** What the operation acquires, where the caller supplies it rather than the storage. */
|
|
40
|
+
entity?: Entity;
|
|
41
|
+
task?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* The process a call to a stateful operation goes to: that process's `context.instance`. Named
|
|
44
|
+
* for a stateful operation, and for no other.
|
|
45
|
+
*/
|
|
46
|
+
instance?: string;
|
|
47
|
+
/**
|
|
48
|
+
* What this call is, so that the same call arriving twice is written once. Left out, the caller
|
|
49
|
+
* stamps one: derived from the call it is itself serving, where there is one, and minted where
|
|
50
|
+
* there is not. See `core/source/entities/newid.ts` and the inbox.
|
|
51
|
+
*/
|
|
52
|
+
id?: string;
|
|
53
|
+
source?: Source;
|
|
54
|
+
/**
|
|
55
|
+
* The hops this call passed through, oldest first. Stamped by the framework; a call that has
|
|
56
|
+
* been where it is going already is refused rather than made. See `core/source/trail.ts`.
|
|
57
|
+
*/
|
|
58
|
+
trail?: string[];
|
|
59
|
+
/**
|
|
60
|
+
* The properties of the output this caller receives, of each object the operation answers. An
|
|
61
|
+
* empty list receives none of it, and a request that names none receives the output whole.
|
|
62
|
+
*/
|
|
63
|
+
output?: string[];
|
|
64
|
+
/**
|
|
65
|
+
* Whether this caller reads an output encoded rather than as values: a gateway writing it as a
|
|
66
|
+
* response body spends nothing on reading it. What answers one encodes it once.
|
|
67
|
+
*/
|
|
68
|
+
encoded?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Whether this call, and every call made under it, may reach only a safe operation. Stamped by
|
|
71
|
+
* the framework and carried down the chain; set and never cleared, so a call made under one is
|
|
72
|
+
* readonly whatever it says of itself. See `core/source/safety.ts`.
|
|
73
|
+
*/
|
|
74
|
+
readonly?: boolean;
|
|
75
|
+
/** the sender validated against the contract, so the recipient does not */
|
|
76
|
+
authentic?: boolean;
|
|
77
|
+
/** W3C traceparent */
|
|
78
|
+
telemetry?: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* How a caller waits for a call, given beside the request: neither is part of what the call asks,
|
|
82
|
+
* and neither is sent with it.
|
|
83
|
+
*/
|
|
84
|
+
export interface Options {
|
|
85
|
+
/**
|
|
86
|
+
* Milliseconds the caller waits for the reply. An addressed call waits the context's default
|
|
87
|
+
* without one; an ordinary call waits for as long as it takes.
|
|
88
|
+
*/
|
|
89
|
+
timeout?: number;
|
|
90
|
+
/** Ends the wait when it aborts, within the timeout. */
|
|
91
|
+
signal?: AbortSignal;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* What an operation receives: the request, in the envelope the framework put it in. The one
|
|
95
|
+
* difference from what a caller may hand over is that the identity is settled, which is why an
|
|
96
|
+
* operation may rely on it and a caller need not supply it.
|
|
97
|
+
*
|
|
98
|
+
* The envelope is the framework's own object rather than the caller's written over, because a
|
|
99
|
+
* caller may hand one object to several calls — `id` alone makes that fatal, as two calls cannot
|
|
100
|
+
* share an identity — and because what a caller wrote and what the runtime added are then two
|
|
101
|
+
* things rather than one.
|
|
102
|
+
*/
|
|
103
|
+
export interface Envelope<Input = any, Entity = any> extends Request<Input, Entity> {
|
|
104
|
+
id: string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* An error an operation declares and returns. A call resolves to it rather than throwing:
|
|
108
|
+
* only an exception is thrown.
|
|
109
|
+
*/
|
|
110
|
+
export interface RemoteError<Code extends string = string> extends Error {
|
|
111
|
+
code: Code;
|
|
112
|
+
}
|
|
113
|
+
/** What an operation returns where it may refuse: the value, or the error it refused with. */
|
|
114
|
+
export type Maybe<T> = T | Error;
|
|
115
|
+
export interface Reply {
|
|
116
|
+
output?: any;
|
|
117
|
+
error?: object;
|
|
118
|
+
exception?: Exception;
|
|
119
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../source/types/request.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** What a commit publishes: the images of one state change. */
|
|
2
|
+
export interface Event<State = object, Trailers = object> {
|
|
3
|
+
/** the pre-image; null when the entity did not exist before */
|
|
4
|
+
origin: State | null;
|
|
5
|
+
state: State;
|
|
6
|
+
/** out-of-band values an algorithm wrote into `state._trailers`; must be serializable */
|
|
7
|
+
trailers?: Trailers;
|
|
8
|
+
input?: object;
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../source/types/state.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import type { Readable } from 'node:stream';
|
|
2
|
+
import type { Connector } from '../connector.ts';
|
|
3
|
+
import type { Locator } from '../locator.ts';
|
|
4
|
+
import type { Call, Inbox } from './inbox.ts';
|
|
5
|
+
import type { Row, Storage as Outbox } from './outbox.ts';
|
|
6
|
+
/** the RSQL tree `@rsql/parser` produces; a storage translates it into its own dialect */
|
|
7
|
+
export interface Node {
|
|
8
|
+
type: 'LOGIC' | 'COMPARISON' | 'SELECTOR' | 'VALUE';
|
|
9
|
+
left?: Node;
|
|
10
|
+
right?: Node;
|
|
11
|
+
operator?: string;
|
|
12
|
+
selector?: string;
|
|
13
|
+
value?: unknown;
|
|
14
|
+
}
|
|
15
|
+
/** What a storage stores. `id` is the key; the upper-cased names are core's. */
|
|
16
|
+
export interface Record {
|
|
17
|
+
id: string;
|
|
18
|
+
VERSION: number;
|
|
19
|
+
CREATED?: number;
|
|
20
|
+
UPDATED?: number;
|
|
21
|
+
/** a tombstone's timestamp; `null` on a live record */
|
|
22
|
+
DELETED?: number | null;
|
|
23
|
+
/** the rank of the region that last wrote it; `0` where there is one region */
|
|
24
|
+
REGION?: number;
|
|
25
|
+
[key: string]: any;
|
|
26
|
+
}
|
|
27
|
+
/** Everything a request query carried that was not a selector. */
|
|
28
|
+
export interface Options {
|
|
29
|
+
omit?: number;
|
|
30
|
+
limit?: number;
|
|
31
|
+
/** normalised by `query/options.ts` from `'name:asc'` into pairs */
|
|
32
|
+
sort?: Array<[property: string, direction: string]>;
|
|
33
|
+
/** always includes `VERSION`, `CREATED`, `UPDATED`, `DELETED` */
|
|
34
|
+
projection?: string[];
|
|
35
|
+
sample?: number;
|
|
36
|
+
/** include tombstones; without it an observation answers `null` over one */
|
|
37
|
+
deleted?: boolean;
|
|
38
|
+
}
|
|
39
|
+
/** What core hands a storage, written by `Query.parse`. */
|
|
40
|
+
export interface Query {
|
|
41
|
+
id?: string;
|
|
42
|
+
/** many identities at once; `State.objects` inits whichever of them are missing */
|
|
43
|
+
ids?: string[];
|
|
44
|
+
version?: number;
|
|
45
|
+
criteria?: Node;
|
|
46
|
+
search?: string;
|
|
47
|
+
options?: Options;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* What core requires of a storage. Every member but `outbox` is called unguarded, so a
|
|
51
|
+
* storage that leaves one out throws where an operation needs it — a storage may serve
|
|
52
|
+
* only some scopes, and says so by failing rather than by declaring less.
|
|
53
|
+
*/
|
|
54
|
+
export interface Storage extends Connector {
|
|
55
|
+
/** scope `object` */
|
|
56
|
+
get(query: Query): Promise<Record | null>;
|
|
57
|
+
/** scope `objects` */
|
|
58
|
+
find(query: Query): Promise<Record[]>;
|
|
59
|
+
/** scope `stream` */
|
|
60
|
+
stream(query?: Query): Promise<Readable>;
|
|
61
|
+
/**
|
|
62
|
+
* A transition's commit. `false` is a lost compare-and-swap, not an error. Where `row` is
|
|
63
|
+
* given, it is committed in the same transaction as the record or not at all, and where
|
|
64
|
+
* `call` is, so is that — and an identity already recorded raises `DuplicateCall` instead,
|
|
65
|
+
* having written nothing.
|
|
66
|
+
*/
|
|
67
|
+
store(record: Record, row?: Row, call?: Call): Promise<boolean>;
|
|
68
|
+
/** a transition over `objects` */
|
|
69
|
+
massStore(records: Record[], rows?: Row[]): Promise<boolean>;
|
|
70
|
+
/** an assignment; `null` where the query matched nothing */
|
|
71
|
+
upsert(query: Query, changeset: object, row?: Row, call?: Call): Promise<Record | null>;
|
|
72
|
+
/** get-or-create, in one indivisible step */
|
|
73
|
+
ensure(query: Query | undefined, properties: object, record: Record, row?: Row, call?: Call): Promise<Record>;
|
|
74
|
+
/** the driver's own handle, which an unmanaged operation is given as its state */
|
|
75
|
+
readonly raw: unknown;
|
|
76
|
+
/**
|
|
77
|
+
* Present only where a row can be committed atomically with the entity. Its absence is
|
|
78
|
+
* what makes the runtime publish inline, so a storage that cannot do this must not offer
|
|
79
|
+
* it: a row written outside the transaction would be a second write with a crash window
|
|
80
|
+
* in front of it, which is the defect the outbox exists to close.
|
|
81
|
+
*/
|
|
82
|
+
readonly outbox?: Outbox;
|
|
83
|
+
/**
|
|
84
|
+
* Present only where a call can be recorded atomically with the entity, and only where a
|
|
85
|
+
* component declares `once`. Unlike the outbox there is no weaker thing to fall back to —
|
|
86
|
+
* a record written outside the transaction guarantees nothing — so a storage that cannot
|
|
87
|
+
* says so through `claims`, and a component that asked for it does not boot.
|
|
88
|
+
*/
|
|
89
|
+
readonly inbox?: Inbox;
|
|
90
|
+
/**
|
|
91
|
+
* Whether this storage can record a call at all, which is a property of the storage rather
|
|
92
|
+
* than of the deployment it is pointed at, and so is answerable before it is connected.
|
|
93
|
+
*/
|
|
94
|
+
readonly claims?: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Whether this storage applies `entity.migrations`. Absent is what a storage that does not
|
|
97
|
+
* says, and a component declaring migrations against one is refused at boot rather than
|
|
98
|
+
* starting with a structure nothing has made.
|
|
99
|
+
*/
|
|
100
|
+
readonly migrates?: boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Writes `record` as it stands — its `VERSION`, its timestamps, its `REGION` and whatever
|
|
103
|
+
* else it carries — where what it would replace precedes it: a lower `VERSION`, or the same
|
|
104
|
+
* `VERSION` written by a region this one outranks. `false` where it does not: nothing is
|
|
105
|
+
* written, and that is not an error.
|
|
106
|
+
*
|
|
107
|
+
* Both sides of the comparison are on the two records, so this takes nothing else. What it
|
|
108
|
+
* is for is a record that was written somewhere else and has to land here as it was, which
|
|
109
|
+
* is neither a transition nor an assignment: it is not the writer's version to increment,
|
|
110
|
+
* nor its timestamps to set.
|
|
111
|
+
*/
|
|
112
|
+
converge?(record: Record): Promise<boolean>;
|
|
113
|
+
/**
|
|
114
|
+
* Whether this storage converges. Absent is what a storage that does not says, and a
|
|
115
|
+
* component of a context that converges stands down rather than running where it would
|
|
116
|
+
* never take a record from another region.
|
|
117
|
+
*/
|
|
118
|
+
readonly converges?: boolean;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* The subset of a component's entity declaration a storage reads. Structural, so that core
|
|
122
|
+
* names no type of `@toa.io/norm`, which depends on core.
|
|
123
|
+
*/
|
|
124
|
+
export interface Entity {
|
|
125
|
+
associated?: boolean;
|
|
126
|
+
custom?: boolean;
|
|
127
|
+
/** in the order they are applied; what a step is belongs to the storage that reads it */
|
|
128
|
+
migrations?: Migration[];
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* One file of a `migrations` directory, named after it — the component's own, or a prototype's,
|
|
132
|
+
* which every descendant applies to its collection ahead of its own.
|
|
133
|
+
*/
|
|
134
|
+
export interface Migration {
|
|
135
|
+
id: string;
|
|
136
|
+
steps: unknown[];
|
|
137
|
+
/** the prototype it is inherited from; absent on the component's own */
|
|
138
|
+
prototype?: string;
|
|
139
|
+
}
|
|
140
|
+
export interface StorageOptions {
|
|
141
|
+
/** whether the component publishes anything, and so needs a place to commit a row */
|
|
142
|
+
outbox?: boolean;
|
|
143
|
+
}
|
|
144
|
+
export interface Factory {
|
|
145
|
+
storage(locator: Locator, entity: Entity, options?: StorageOptions): Storage;
|
|
146
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storages.js","sourceRoot":"","sources":["../../source/types/storages.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unmanaged.js","sourceRoot":"","sources":["../source/unmanaged.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAG1C,MAAM,OAAO,SAAU,SAAQ,SAAS;IACnB,KAAK,CAAC,OAAO,CAAC,KAAY;QAC3C,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAA;IACtC,CAAC;CACF"}
|
package/src/assignment.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { Operation } = require('./operation')
|
|
4
|
-
|
|
5
|
-
class Assignment extends Operation {
|
|
6
|
-
async acquire (store) {
|
|
7
|
-
store.scope = this.scope.changeset(store.request.query)
|
|
8
|
-
store.state = store.scope.get()
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async commit (store) {
|
|
12
|
-
const {
|
|
13
|
-
scope,
|
|
14
|
-
state,
|
|
15
|
-
reply
|
|
16
|
-
} = store
|
|
17
|
-
|
|
18
|
-
if (reply.error !== undefined) return
|
|
19
|
-
|
|
20
|
-
scope.set(state)
|
|
21
|
-
|
|
22
|
-
const output = await this.scope.apply(scope)
|
|
23
|
-
|
|
24
|
-
// assignment returns new state by default
|
|
25
|
-
if (store.reply.output === undefined) {
|
|
26
|
-
store.reply.output = output
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
exports.Assignment = Assignment
|
package/src/call.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { Readable } = require('node:stream')
|
|
4
|
-
const { Connector } = require('./connector')
|
|
5
|
-
const { Err } = require('error-value')
|
|
6
|
-
|
|
7
|
-
class Call extends Connector {
|
|
8
|
-
#transmitter
|
|
9
|
-
#contract
|
|
10
|
-
|
|
11
|
-
constructor (transmitter, contract) {
|
|
12
|
-
super()
|
|
13
|
-
|
|
14
|
-
this.#transmitter = transmitter
|
|
15
|
-
this.#contract = contract
|
|
16
|
-
|
|
17
|
-
this.depends(transmitter)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async invoke (request = {}) {
|
|
21
|
-
this.#contract.fit(request)
|
|
22
|
-
|
|
23
|
-
// avoid validation on the recipient's side
|
|
24
|
-
request.authentic = true
|
|
25
|
-
|
|
26
|
-
const reply = await this.#transmitter.request(request)
|
|
27
|
-
|
|
28
|
-
if (reply === null) return null
|
|
29
|
-
else if (reply instanceof Readable) return reply
|
|
30
|
-
else {
|
|
31
|
-
if (reply.exception !== undefined)
|
|
32
|
-
throw reply.exception
|
|
33
|
-
|
|
34
|
-
if (reply.error !== undefined)
|
|
35
|
-
return Err(reply.error.code, reply.error)
|
|
36
|
-
else
|
|
37
|
-
return reply.output
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
exports.Call = Call
|
package/src/cascade.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { Connector } = require('./connector')
|
|
4
|
-
|
|
5
|
-
class Cascade extends Connector {
|
|
6
|
-
// #bridges
|
|
7
|
-
#last
|
|
8
|
-
|
|
9
|
-
constructor (bridges) {
|
|
10
|
-
super()
|
|
11
|
-
|
|
12
|
-
// this.#bridges = bridges
|
|
13
|
-
this.#last = bridges[bridges.length - 1]
|
|
14
|
-
|
|
15
|
-
this.depends(bridges)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async run (...args) {
|
|
19
|
-
// const reply = {}
|
|
20
|
-
//
|
|
21
|
-
// for (const bridge of this.#bridges) {
|
|
22
|
-
// const partial = await bridge.execute(...args)
|
|
23
|
-
//
|
|
24
|
-
// if (partial.error) return { error: partial.error }
|
|
25
|
-
//
|
|
26
|
-
// merge(reply, partial)
|
|
27
|
-
// }
|
|
28
|
-
//
|
|
29
|
-
// return reply
|
|
30
|
-
|
|
31
|
-
return this.#last.execute(...args)
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
exports.Cascade = Cascade
|
package/src/component.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { console } = require('@toa.io/console')
|
|
4
|
-
const { Connector } = require('./connector')
|
|
5
|
-
const { NotImplementedException } = require('./exceptions')
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @implements {toa.core.Component}
|
|
9
|
-
*/
|
|
10
|
-
class Component extends Connector {
|
|
11
|
-
locator
|
|
12
|
-
|
|
13
|
-
#operations
|
|
14
|
-
|
|
15
|
-
constructor (locator, operations) {
|
|
16
|
-
super()
|
|
17
|
-
|
|
18
|
-
this.locator = locator
|
|
19
|
-
this.#operations = operations
|
|
20
|
-
|
|
21
|
-
Object.values(operations).forEach((operation) => this.depends(operation))
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async open () {
|
|
25
|
-
console.info(`Runtime '${this.locator.id}' connected`)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async dispose () {
|
|
29
|
-
console.info(`Runtime '${this.locator.id}' disconnected`)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async invoke (endpoint, request) {
|
|
33
|
-
if (!(endpoint in this.#operations)) {
|
|
34
|
-
throw new NotImplementedException(`Endpoint '${endpoint}' not found in '${this.locator.id}'`)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return this.#operations[endpoint].invoke(request)
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
exports.Component = Component
|
package/src/composition.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { console } = require('@toa.io/console')
|
|
4
|
-
const { Connector } = require('./connector')
|
|
5
|
-
|
|
6
|
-
class Composition extends Connector {
|
|
7
|
-
constructor (expositions, producers, receivers, tenants) {
|
|
8
|
-
super()
|
|
9
|
-
|
|
10
|
-
if (expositions.length > 0) this.depends(expositions)
|
|
11
|
-
if (producers.length > 0) this.depends(producers)
|
|
12
|
-
if (receivers.length > 0) this.depends(receivers)
|
|
13
|
-
if (tenants.length > 0) this.depends(tenants)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async open () {
|
|
17
|
-
console.info('Composition complete')
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async dispose () {
|
|
21
|
-
console.info('Composition shutdown complete')
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
exports.Composition = Composition
|