@toa.io/core 1.0.0-alpha.29 → 1.0.0-alpha.291
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/CHANGELOG.md +35 -0
- package/package.json +22 -12
- package/source/assignment.ts +27 -0
- package/source/call.ts +63 -0
- package/source/cascade.ts +32 -0
- package/source/component.ts +83 -0
- package/source/composition.ts +27 -0
- package/source/connector.ts +217 -0
- package/source/context.ts +68 -0
- package/source/contract/contract.ts +23 -0
- package/source/contract/index.ts +2 -0
- package/source/contract/reply.ts +56 -0
- package/source/contract/request.ts +140 -0
- package/source/contract/schemas.ts +39 -0
- package/source/discovery.ts +53 -0
- package/source/effect.ts +14 -0
- package/source/emission.ts +21 -0
- package/source/entities/changeset.ts +37 -0
- package/source/entities/entity.ts +137 -0
- package/source/entities/factory.ts +52 -0
- package/source/entities/index.ts +4 -0
- package/source/entities/newid.ts +9 -0
- package/source/entities/set.ts +27 -0
- package/source/event.ts +57 -0
- package/source/exceptions.ts +133 -0
- package/source/exposition.ts +33 -0
- package/source/guard.ts +16 -0
- package/source/index.ts +36 -0
- package/source/locator.ts +37 -0
- package/source/observation.ts +16 -0
- package/source/operation.ts +139 -0
- package/source/outbox/index.ts +1 -0
- package/source/outbox/outbox.ts +341 -0
- package/source/query/criteria.ts +90 -0
- package/source/query/options.ts +35 -0
- package/source/query.ts +67 -0
- package/source/receiver.ts +120 -0
- package/source/reflection.ts +20 -0
- package/source/remote.ts +20 -0
- package/source/state.ts +179 -0
- package/source/transition.ts +79 -0
- package/source/transmission.ts +38 -0
- package/source/types/atomicity.ts +63 -0
- package/source/types/bindings.ts +59 -0
- package/source/types/bridges.ts +54 -0
- package/source/types/extensions.ts +89 -0
- package/source/types/index.ts +14 -0
- package/{types/message.d.ts → source/types/message.ts} +2 -0
- package/source/types/operations.ts +31 -0
- package/source/types/outbox.ts +35 -0
- package/source/types/receiver.ts +10 -0
- package/source/types/request.ts +54 -0
- package/source/types/state.ts +9 -0
- package/source/types/storages.ts +134 -0
- package/source/unmanaged.ts +8 -0
- package/test/call.fixtures.js +10 -12
- package/test/call.test.js +42 -9
- package/test/component.fixtures.js +5 -8
- package/test/component.test.js +27 -10
- package/test/connector.fixtures.js +29 -13
- package/test/connector.test.js +128 -38
- package/test/context.fixtures.js +8 -12
- package/test/context.test.js +19 -8
- package/test/contract/conditions.test.js +15 -9
- package/test/contract/contract.fixtures.js +11 -16
- package/test/contract/request.test.js +130 -46
- package/test/discovery.test.js +71 -0
- package/test/emission.fixtures.js +6 -10
- package/test/emission.test.js +37 -12
- package/test/entities/entity.fixtures.js +11 -16
- package/test/entities/entity.test.js +105 -50
- package/test/entities/factory.fixtures.js +26 -13
- package/test/entities/factory.test.js +68 -17
- package/test/entities/set.fixtures.js +6 -8
- package/test/entities/set.test.js +6 -5
- package/test/event.fixtures.js +9 -14
- package/test/event.test.js +78 -34
- package/test/locator.test.js +32 -25
- package/test/outbox.test.js +202 -0
- package/test/query.fixtures.js +1 -5
- package/test/query.test.js +111 -14
- package/test/receiver.fixtures.js +9 -12
- package/test/receiver.test.js +80 -31
- package/test/reflection.test.js +9 -8
- package/test/state.fixtures.js +33 -31
- package/test/state.test.js +135 -19
- package/test/transmission.fixtures.js +4 -6
- package/test/transmission.test.js +47 -16
- package/transpiled/assignment.d.ts +6 -0
- package/transpiled/assignment.js +20 -0
- package/transpiled/assignment.js.map +1 -0
- package/transpiled/call.d.ts +10 -0
- package/transpiled/call.js +52 -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 +61 -0
- package/transpiled/component.js.map +1 -0
- package/transpiled/composition.d.ts +6 -0
- package/transpiled/composition.js +23 -0
- package/transpiled/composition.js.map +1 -0
- package/transpiled/connector.d.ts +47 -0
- package/transpiled/connector.js +185 -0
- package/transpiled/connector.js.map +1 -0
- package/transpiled/context.d.ts +18 -0
- package/transpiled/context.js +42 -0
- package/transpiled/context.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 +2 -0
- package/transpiled/contract/index.js +3 -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 +29 -0
- package/transpiled/contract/request.js +103 -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/discovery.d.ts +12 -0
- package/transpiled/discovery.js +34 -0
- package/transpiled/discovery.js.map +1 -0
- package/transpiled/effect.d.ts +5 -0
- package/transpiled/effect.js +11 -0
- package/transpiled/effect.js.map +1 -0
- package/transpiled/emission.d.ts +8 -0
- package/transpiled/emission.js +14 -0
- package/transpiled/emission.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 +109 -0
- package/transpiled/entities/entity.js.map +1 -0
- package/transpiled/entities/factory.d.ts +22 -0
- package/transpiled/entities/factory.js +34 -0
- package/transpiled/entities/factory.js.map +1 -0
- package/transpiled/entities/index.d.ts +4 -0
- package/transpiled/entities/index.js +5 -0
- package/transpiled/entities/index.js.map +1 -0
- package/transpiled/entities/newid.d.ts +1 -0
- package/transpiled/entities/newid.js +7 -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 +38 -0
- package/transpiled/event.js.map +1 -0
- package/transpiled/exceptions.d.ts +61 -0
- package/transpiled/exceptions.js +93 -0
- package/transpiled/exceptions.js.map +1 -0
- package/transpiled/exposition.d.ts +18 -0
- package/transpiled/exposition.js +18 -0
- package/transpiled/exposition.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/index.d.ts +35 -0
- package/transpiled/index.js +29 -0
- package/transpiled/index.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/observation.d.ts +5 -0
- package/transpiled/observation.js +12 -0
- package/transpiled/observation.js.map +1 -0
- package/transpiled/operation.d.ts +49 -0
- package/transpiled/operation.js +78 -0
- package/transpiled/operation.js.map +1 -0
- package/transpiled/outbox/index.d.ts +1 -0
- package/transpiled/outbox/index.js +2 -0
- package/transpiled/outbox/index.js.map +1 -0
- package/transpiled/outbox/outbox.d.ts +46 -0
- package/transpiled/outbox/outbox.js +268 -0
- package/transpiled/outbox/outbox.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 +27 -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 +92 -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 +12 -0
- package/transpiled/remote.js.map +1 -0
- package/transpiled/state.d.ts +33 -0
- package/transpiled/state.js +126 -0
- package/transpiled/state.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 +56 -0
- package/transpiled/types/atomicity.js +2 -0
- package/transpiled/types/atomicity.js.map +1 -0
- package/transpiled/types/bindings.d.ts +42 -0
- package/transpiled/types/bindings.js +2 -0
- package/transpiled/types/bindings.js.map +1 -0
- package/transpiled/types/bridges.d.ts +38 -0
- package/transpiled/types/bridges.js +2 -0
- package/transpiled/types/bridges.js.map +1 -0
- package/transpiled/types/extensions.d.ts +62 -0
- package/transpiled/types/extensions.js +2 -0
- package/transpiled/types/extensions.js.map +1 -0
- package/transpiled/types/index.d.ts +13 -0
- package/transpiled/types/index.js +8 -0
- package/transpiled/types/index.js.map +1 -0
- package/transpiled/types/message.d.ts +5 -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 +28 -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 +55 -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 +111 -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/tsconfig.json +10 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/src/assignment.js +0 -31
- package/src/call.js +0 -42
- package/src/cascade.js +0 -36
- 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 -43
- package/src/entities/entity.js +0 -73
- 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 -65
- package/src/reflection.js +0 -28
- package/src/remote.js +0 -17
- package/src/state.js +0 -99
- package/src/transition.js +0 -73
- package/src/transmission.js +0 -33
- 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/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,133 @@
|
|
|
1
|
+
import { swap } from '@toa.io/generic'
|
|
2
|
+
import type { SchemaError } from '@toa.io/schemas'
|
|
3
|
+
|
|
4
|
+
export const codes = {
|
|
5
|
+
System: 0,
|
|
6
|
+
|
|
7
|
+
Contract: 200,
|
|
8
|
+
RequestSyntax: 201,
|
|
9
|
+
RequestContract: 202,
|
|
10
|
+
RequestConflict: 203,
|
|
11
|
+
ResponseContract: 211,
|
|
12
|
+
EntityContract: 212,
|
|
13
|
+
EntityGuard: 213,
|
|
14
|
+
QuerySyntax: 221,
|
|
15
|
+
|
|
16
|
+
State: 300,
|
|
17
|
+
StateNotFound: 302,
|
|
18
|
+
StatePrecondition: 303,
|
|
19
|
+
StateConcurrency: 304,
|
|
20
|
+
StateInitialization: 305,
|
|
21
|
+
Duplicate: 306,
|
|
22
|
+
|
|
23
|
+
Communication: 400,
|
|
24
|
+
Transmission: 401
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class Exception {
|
|
28
|
+
public readonly code: number
|
|
29
|
+
public readonly message: string
|
|
30
|
+
public cause?: unknown;
|
|
31
|
+
|
|
32
|
+
/** what a contract exception copies off the schema error it refused with */
|
|
33
|
+
[key: string]: unknown
|
|
34
|
+
|
|
35
|
+
public constructor(code: number, message: string, cause?: unknown) {
|
|
36
|
+
this.code = code
|
|
37
|
+
this.message = message
|
|
38
|
+
|
|
39
|
+
if (cause !== undefined) this.cause = cause
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export class SystemException extends Exception {
|
|
44
|
+
public readonly stack?: string
|
|
45
|
+
|
|
46
|
+
public constructor(error: Error | string) {
|
|
47
|
+
super(codes.System, typeof error === 'string' ? error : error.message)
|
|
48
|
+
|
|
49
|
+
if (typeof error !== 'string' && error.stack !== undefined) this.stack = error.stack
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export class ContractException extends Exception {
|
|
54
|
+
public constructor(
|
|
55
|
+
code: number | undefined,
|
|
56
|
+
error: SchemaError | string | null,
|
|
57
|
+
cause?: unknown
|
|
58
|
+
) {
|
|
59
|
+
super(
|
|
60
|
+
code ?? codes.Contract,
|
|
61
|
+
typeof error === 'string' ? error : (error?.message ?? ''),
|
|
62
|
+
cause
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
if (typeof error === 'object' && error !== null)
|
|
66
|
+
for (const k of ['keyword', 'property', 'schema', 'path', 'params'] as const)
|
|
67
|
+
if (k in error) this[k] = (error as unknown as Record<string, unknown>)[k]
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export class RequestContractException extends ContractException {
|
|
72
|
+
public constructor(error: SchemaError | string, cause?: unknown) {
|
|
73
|
+
super(codes.RequestContract, error, cause)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export class ResponseContractException extends ContractException {
|
|
78
|
+
public constructor(error: SchemaError | string, cause?: unknown) {
|
|
79
|
+
super(codes.ResponseContract, error, cause)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export class EntityContractException extends ContractException {
|
|
84
|
+
public constructor(error: SchemaError | string, cause?: unknown) {
|
|
85
|
+
super(codes.EntityContract, error, cause)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export class EntityGuardException extends ContractException {
|
|
90
|
+
public constructor(name: string, cause?: unknown) {
|
|
91
|
+
super(codes.EntityGuard, name, cause)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// #region exports
|
|
96
|
+
|
|
97
|
+
// a module's exports are static, so the ones that follow a code are named rather
|
|
98
|
+
// than generated onto the namespace
|
|
99
|
+
type Derived = new (message?: string, cause?: unknown) => Exception
|
|
100
|
+
|
|
101
|
+
function derive(name: keyof typeof codes): Derived {
|
|
102
|
+
const classname = name + 'Exception'
|
|
103
|
+
|
|
104
|
+
const derived = class extends Exception {
|
|
105
|
+
public constructor(message?: string, cause?: unknown) {
|
|
106
|
+
super(
|
|
107
|
+
codes[name],
|
|
108
|
+
message === undefined ? classname : `${classname}: ${message}`,
|
|
109
|
+
cause
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// the name is the class's own, and a class expression has none worth reporting
|
|
115
|
+
Object.defineProperty(derived, 'name', { value: classname })
|
|
116
|
+
|
|
117
|
+
return derived
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export const RequestSyntaxException = derive('RequestSyntax')
|
|
121
|
+
export const RequestConflictException = derive('RequestConflict')
|
|
122
|
+
export const QuerySyntaxException = derive('QuerySyntax')
|
|
123
|
+
export const StateException = derive('State')
|
|
124
|
+
export const StateNotFoundException = derive('StateNotFound')
|
|
125
|
+
export const StatePreconditionException = derive('StatePrecondition')
|
|
126
|
+
export const StateConcurrencyException = derive('StateConcurrency')
|
|
127
|
+
export const StateInitializationException = derive('StateInitialization')
|
|
128
|
+
export const DuplicateException = derive('Duplicate')
|
|
129
|
+
export const CommunicationException = derive('Communication')
|
|
130
|
+
export const TransmissionException = derive('Transmission')
|
|
131
|
+
|
|
132
|
+
export const names = swap(codes)
|
|
133
|
+
// #endregion
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Connector } from './connector.js'
|
|
2
|
+
import type { Locator } from './locator.js'
|
|
3
|
+
|
|
4
|
+
interface Manifest {
|
|
5
|
+
namespace: string
|
|
6
|
+
name: string
|
|
7
|
+
entity?: object
|
|
8
|
+
operations?: object
|
|
9
|
+
events?: object
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class Exposition extends Connector {
|
|
13
|
+
public readonly locator: Locator
|
|
14
|
+
|
|
15
|
+
readonly #exposition: Partial<Manifest>
|
|
16
|
+
|
|
17
|
+
public constructor(locator: Locator, manifest: Manifest) {
|
|
18
|
+
super()
|
|
19
|
+
|
|
20
|
+
this.locator = locator
|
|
21
|
+
this.#exposition = expose(manifest)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public async invoke(): Promise<{ output: Partial<Manifest> }> {
|
|
25
|
+
return { output: this.#exposition }
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function expose(manifest: Manifest): Partial<Manifest> {
|
|
30
|
+
const { namespace, name, entity, operations, events } = manifest
|
|
31
|
+
|
|
32
|
+
return { namespace, name, entity, operations, events }
|
|
33
|
+
}
|
package/source/guard.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Guard as Bridge } from './types/bridges.js'
|
|
2
|
+
|
|
3
|
+
export class Guard {
|
|
4
|
+
public readonly name: string
|
|
5
|
+
|
|
6
|
+
readonly #bridge: Bridge
|
|
7
|
+
|
|
8
|
+
public constructor(name: string, bridge: Bridge) {
|
|
9
|
+
this.name = name
|
|
10
|
+
this.#bridge = bridge
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public fit(state: object, origin: object | null): boolean {
|
|
14
|
+
return this.#bridge.fit(state, origin)
|
|
15
|
+
}
|
|
16
|
+
}
|
package/source/index.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export { Assignment } from './assignment.js'
|
|
2
|
+
export { Call } from './call.js'
|
|
3
|
+
export { Cascade } from './cascade.js'
|
|
4
|
+
export { Component } from './component.js'
|
|
5
|
+
export { Composition } from './composition.js'
|
|
6
|
+
export { Connector } from './connector.js'
|
|
7
|
+
export { Context } from './context.js'
|
|
8
|
+
export { Discovery } from './discovery.js'
|
|
9
|
+
export { Effect } from './effect.js'
|
|
10
|
+
export { Emission } from './emission.js'
|
|
11
|
+
export { Event } from './event.js'
|
|
12
|
+
export { Exposition } from './exposition.js'
|
|
13
|
+
export { Locator } from './locator.js'
|
|
14
|
+
export { Observation } from './observation.js'
|
|
15
|
+
export { Outbox } from './outbox/index.js'
|
|
16
|
+
export { Operation } from './operation.js'
|
|
17
|
+
export { Query } from './query.js'
|
|
18
|
+
export { Receiver } from './receiver.js'
|
|
19
|
+
export { Reflection } from './reflection.js'
|
|
20
|
+
export { Remote } from './remote.js'
|
|
21
|
+
export { State } from './state.js'
|
|
22
|
+
export { Transition } from './transition.js'
|
|
23
|
+
export { Transmission } from './transmission.js'
|
|
24
|
+
export { Unmanaged } from './unmanaged.js'
|
|
25
|
+
export { Guard } from './guard.js'
|
|
26
|
+
export * as entities from './entities/index.js'
|
|
27
|
+
export * as exceptions from './exceptions.js'
|
|
28
|
+
export * as contract from './contract/index.js'
|
|
29
|
+
|
|
30
|
+
export type { Exception } from './exceptions.js'
|
|
31
|
+
export type { Invocable } from './component.js'
|
|
32
|
+
export type { Explicable } from './remote.js'
|
|
33
|
+
export type { Scoped, Store } from './operation.js'
|
|
34
|
+
export type { Source as ReflectionSource } from './reflection.js'
|
|
35
|
+
export type { Explanation } from './contract/request.js'
|
|
36
|
+
export type { JSONSchema } from './contract/schemas.js'
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { concat } from '@toa.io/generic'
|
|
2
|
+
|
|
3
|
+
/** Where a component is, as every name derived from it. */
|
|
4
|
+
export class Locator {
|
|
5
|
+
public readonly name: string
|
|
6
|
+
public readonly namespace: string | undefined
|
|
7
|
+
|
|
8
|
+
public readonly id: string
|
|
9
|
+
public readonly label: string
|
|
10
|
+
public readonly uppercase: string
|
|
11
|
+
public readonly lowercase: string
|
|
12
|
+
|
|
13
|
+
public constructor(name: string, namespace?: string) {
|
|
14
|
+
if (name === undefined) throw new TypeError('Locator name must be defined')
|
|
15
|
+
|
|
16
|
+
this.name = name
|
|
17
|
+
this.namespace = namespace
|
|
18
|
+
|
|
19
|
+
this.id = concat(namespace, '.') + name
|
|
20
|
+
this.label = (concat(namespace, '-') + name).toLowerCase()
|
|
21
|
+
this.uppercase = (concat(namespace, '_') + name).toUpperCase()
|
|
22
|
+
this.lowercase = (concat(namespace, '_') + name).toLowerCase()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public static parse(string: string): Locator {
|
|
26
|
+
const [namespace, name] = string.split(DOT)
|
|
27
|
+
|
|
28
|
+
if (name === undefined) return new Locator(namespace)
|
|
29
|
+
else return new Locator(name, namespace)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public hostname(prefix?: string): string {
|
|
33
|
+
return concat(prefix?.toLowerCase(), '-') + this.label
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const DOT = '.'
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Operation } from './operation.js'
|
|
2
|
+
import type { Store } from './operation.js'
|
|
3
|
+
import type { Entity } from './entities/entity.js'
|
|
4
|
+
|
|
5
|
+
export class Observation extends Operation {
|
|
6
|
+
protected override async run(store: Store): Promise<void> {
|
|
7
|
+
const scope = store.scope as Entity | null
|
|
8
|
+
|
|
9
|
+
if (
|
|
10
|
+
scope === null ||
|
|
11
|
+
(scope?.deleted === true && (store.request.query as any)?.options?.deleted !== true)
|
|
12
|
+
)
|
|
13
|
+
store.reply = null
|
|
14
|
+
else await super.run(store)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { Readable } from 'node:stream'
|
|
2
|
+
import { Connector } from './connector.js'
|
|
3
|
+
import { SystemException, RequestContractException } from './exceptions.js'
|
|
4
|
+
import { environment } from '@toa.io/generic'
|
|
5
|
+
import type { Cascade } from './cascade.js'
|
|
6
|
+
import type { State } from './state.js'
|
|
7
|
+
import type { Query as Translator } from './query.js'
|
|
8
|
+
import type { Contract } from './contract/contract.js'
|
|
9
|
+
import type { Entity } from './entities/entity.js'
|
|
10
|
+
import type { EntitySet } from './entities/set.js'
|
|
11
|
+
import type { Changeset } from './entities/changeset.js'
|
|
12
|
+
import type { scope as Scope } from './types/operations.js'
|
|
13
|
+
import type { Query, Request } from './types/request.js'
|
|
14
|
+
|
|
15
|
+
/** What an operation acquires for the algorithm to run against. */
|
|
16
|
+
export type Scoped = Entity | EntitySet | Changeset | Readable | null
|
|
17
|
+
|
|
18
|
+
/** What one invocation carries from step to step. */
|
|
19
|
+
export interface Store {
|
|
20
|
+
request: Request
|
|
21
|
+
scope?: Scoped
|
|
22
|
+
state?: any
|
|
23
|
+
reply?: any
|
|
24
|
+
/** set by a transition, which is the only operation that runs its steps again */
|
|
25
|
+
retry?: () => Promise<any>
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface Contracts {
|
|
29
|
+
request: Contract
|
|
30
|
+
reply: Contract
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface Definition {
|
|
34
|
+
scope: Scope
|
|
35
|
+
concurrency?: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export class Operation extends Connector {
|
|
39
|
+
public scope: State
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Whether what this operation acquires may be modified and committed. Only a
|
|
43
|
+
* transition commits, and only a commit needs the pre-image an entity keeps
|
|
44
|
+
* to diff the new state against.
|
|
45
|
+
*
|
|
46
|
+
* @protected
|
|
47
|
+
*/
|
|
48
|
+
protected mutable: boolean = false
|
|
49
|
+
|
|
50
|
+
readonly #cascade: Cascade
|
|
51
|
+
readonly #contracts: Contracts
|
|
52
|
+
readonly #query: Translator
|
|
53
|
+
readonly #scope: Scope
|
|
54
|
+
|
|
55
|
+
// eslint-disable-next-line max-params
|
|
56
|
+
public constructor(
|
|
57
|
+
cascade: Cascade,
|
|
58
|
+
scope: State,
|
|
59
|
+
contracts: Contracts,
|
|
60
|
+
query: Translator,
|
|
61
|
+
definition: Definition
|
|
62
|
+
) {
|
|
63
|
+
super()
|
|
64
|
+
|
|
65
|
+
this.scope = scope
|
|
66
|
+
|
|
67
|
+
this.#cascade = cascade
|
|
68
|
+
this.#contracts = contracts
|
|
69
|
+
this.#query = query
|
|
70
|
+
this.#scope = definition.scope
|
|
71
|
+
|
|
72
|
+
this.depends(cascade)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public async invoke(request: Request): Promise<any> {
|
|
76
|
+
try {
|
|
77
|
+
if (request.authentic !== true) this.#contracts.request.fit(request)
|
|
78
|
+
|
|
79
|
+
// the request carries the query onward in its parsed form: what a storage is given,
|
|
80
|
+
// not what the caller sent
|
|
81
|
+
if ('query' in request)
|
|
82
|
+
request.query = this.#query.parse(request.query as Query) as any
|
|
83
|
+
|
|
84
|
+
// validate entity
|
|
85
|
+
if ('entity' in request) this.scope.fit(request.entity)
|
|
86
|
+
|
|
87
|
+
const store = { request }
|
|
88
|
+
|
|
89
|
+
return await this.process(store)
|
|
90
|
+
} catch (e) {
|
|
91
|
+
const exception = e instanceof Error ? new SystemException(e) : e
|
|
92
|
+
|
|
93
|
+
return { exception }
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
protected async process(store: Store): Promise<any> {
|
|
98
|
+
await this.acquire(store)
|
|
99
|
+
await this.run(store)
|
|
100
|
+
await this.commit(store)
|
|
101
|
+
|
|
102
|
+
return store.reply
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
protected async acquire(store: Store): Promise<void> {
|
|
106
|
+
if (this.#scope === 'none') return
|
|
107
|
+
|
|
108
|
+
const scope = await this.query(store.request.query)
|
|
109
|
+
const raw = scope === null || scope instanceof Readable
|
|
110
|
+
|
|
111
|
+
store.scope = scope
|
|
112
|
+
store.state = raw ? scope : (scope as Entity).get()
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
protected async run(store: Store): Promise<void> {
|
|
116
|
+
const { request, state } = store
|
|
117
|
+
const reply = await this.#cascade.run(request.input, state)
|
|
118
|
+
|
|
119
|
+
// validate reply only on local environments
|
|
120
|
+
if (environment.get('TOA_ENV') === 'local' && !(reply instanceof Readable))
|
|
121
|
+
this.#contracts.reply.fit(reply)
|
|
122
|
+
|
|
123
|
+
store.reply = reply
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
protected async commit(_store: Store): Promise<void> {}
|
|
127
|
+
|
|
128
|
+
protected async query(query?: Query): Promise<Scoped> {
|
|
129
|
+
if (query === undefined)
|
|
130
|
+
throw new RequestContractException('Request query is required')
|
|
131
|
+
|
|
132
|
+
const acquire = this.scope[this.#scope] as (
|
|
133
|
+
query: Query,
|
|
134
|
+
mutable?: boolean
|
|
135
|
+
) => Promise<Scoped>
|
|
136
|
+
|
|
137
|
+
return acquire.call(this.scope, query, this.mutable)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Outbox, LANES } from './outbox.js'
|