@typeonce/effect-machine 0.8.0 → 0.10.0
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 +180 -40
- package/dist/Machine.d.ts +659 -481
- package/dist/Machine.d.ts.map +1 -1
- package/dist/Machine.js +86 -222
- package/dist/Machine.js.map +1 -1
- package/dist/internal/machine/activities.d.ts +5 -12
- package/dist/internal/machine/activities.d.ts.map +1 -1
- package/dist/internal/machine/activities.js +47 -17
- package/dist/internal/machine/activities.js.map +1 -1
- package/dist/internal/machine/atom.d.ts +6 -2
- package/dist/internal/machine/atom.d.ts.map +1 -1
- package/dist/internal/machine/atom.js +5 -0
- package/dist/internal/machine/atom.js.map +1 -1
- package/dist/internal/machine/cluster.d.ts.map +1 -1
- package/dist/internal/machine/cluster.js +2 -1
- package/dist/internal/machine/cluster.js.map +1 -1
- package/dist/internal/machine/command.js +2 -2
- package/dist/internal/machine/command.js.map +1 -1
- package/dist/internal/machine/commandRuntime.d.ts.map +1 -1
- package/dist/internal/machine/commandRuntime.js +6 -3
- package/dist/internal/machine/commandRuntime.js.map +1 -1
- package/dist/internal/machine/configuration.d.ts +8 -1
- package/dist/internal/machine/configuration.d.ts.map +1 -1
- package/dist/internal/machine/configuration.js +9 -4
- package/dist/internal/machine/configuration.js.map +1 -1
- package/dist/internal/machine/errors.d.ts +1 -1
- package/dist/internal/machine/errors.d.ts.map +1 -1
- package/dist/internal/machine/executionPlan.d.ts +3 -3
- package/dist/internal/machine/executionPlan.d.ts.map +1 -1
- package/dist/internal/machine/executionPlan.js +74 -24
- package/dist/internal/machine/executionPlan.js.map +1 -1
- package/dist/internal/machine/invocation.d.ts +10 -2
- package/dist/internal/machine/invocation.d.ts.map +1 -1
- package/dist/internal/machine/invocation.js +94 -34
- package/dist/internal/machine/invocation.js.map +1 -1
- package/dist/internal/machine/invocationEvent.d.ts +39 -0
- package/dist/internal/machine/invocationEvent.d.ts.map +1 -0
- package/dist/internal/machine/invocationEvent.js +43 -0
- package/dist/internal/machine/invocationEvent.js.map +1 -0
- package/dist/internal/machine/machine.d.ts +16 -65
- package/dist/internal/machine/machine.d.ts.map +1 -1
- package/dist/internal/machine/machine.js +18 -73
- package/dist/internal/machine/machine.js.map +1 -1
- package/dist/internal/machine/planner.d.ts +4 -2
- package/dist/internal/machine/planner.d.ts.map +1 -1
- package/dist/internal/machine/planner.js +104 -24
- package/dist/internal/machine/planner.js.map +1 -1
- package/dist/internal/machine/process.d.ts.map +1 -1
- package/dist/internal/machine/process.js +8 -8
- package/dist/internal/machine/process.js.map +1 -1
- package/dist/internal/machine/protocol.d.ts +8 -5
- package/dist/internal/machine/protocol.d.ts.map +1 -1
- package/dist/internal/machine/protocol.js +207 -15
- package/dist/internal/machine/protocol.js.map +1 -1
- package/dist/internal/machine/runtime.d.ts +8 -2
- package/dist/internal/machine/runtime.d.ts.map +1 -1
- package/dist/internal/machine/runtime.js +86 -8
- package/dist/internal/machine/runtime.js.map +1 -1
- package/dist/internal/machine/symbols.d.ts +2 -0
- package/dist/internal/machine/symbols.d.ts.map +1 -1
- package/dist/internal/machine/symbols.js +2 -0
- package/dist/internal/machine/symbols.js.map +1 -1
- package/dist/internal/machine/topology.d.ts +7 -0
- package/dist/internal/machine/topology.d.ts.map +1 -1
- package/dist/internal/machine/topology.js +29 -0
- package/dist/internal/machine/topology.js.map +1 -1
- package/dist/internal/testing/machine/finiteModel.js +1 -1
- package/dist/internal/testing/machine/finiteModel.js.map +1 -1
- package/dist/internal/testing/machine/runtime.d.ts.map +1 -1
- package/dist/internal/testing/machine/runtime.js +2 -1
- package/dist/internal/testing/machine/runtime.js.map +1 -1
- package/dist/internal/testing/machine/verification.d.ts.map +1 -1
- package/dist/internal/testing/machine/verification.js +5 -3
- package/dist/internal/testing/machine/verification.js.map +1 -1
- package/dist/testing/MachineTest.d.ts +7 -7
- package/dist/testing/MachineTest.js +7 -7
- package/dist/unstable/cluster/ClusterMachine.d.ts +1 -1
- package/dist/unstable/cluster/ClusterMachine.js +1 -1
- package/dist/unstable/reactivity/AtomMachine.d.ts +25 -8
- package/dist/unstable/reactivity/AtomMachine.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomMachine.js +18 -3
- package/dist/unstable/reactivity/AtomMachine.js.map +1 -1
- package/docs/agent-guide.md +242 -122
- package/package.json +2 -2
- package/src/Machine.ts +1453 -812
- package/src/internal/machine/activities.ts +48 -33
- package/src/internal/machine/atom.ts +38 -13
- package/src/internal/machine/cluster.ts +2 -1
- package/src/internal/machine/command.ts +2 -2
- package/src/internal/machine/commandRuntime.ts +9 -4
- package/src/internal/machine/configuration.ts +23 -5
- package/src/internal/machine/errors.ts +1 -1
- package/src/internal/machine/executionPlan.ts +102 -28
- package/src/internal/machine/invocation.ts +182 -50
- package/src/internal/machine/invocationEvent.ts +72 -0
- package/src/internal/machine/machine.ts +80 -387
- package/src/internal/machine/planner.ts +127 -32
- package/src/internal/machine/process.ts +18 -8
- package/src/internal/machine/protocol.ts +313 -25
- package/src/internal/machine/runtime.ts +135 -9
- package/src/internal/machine/symbols.ts +3 -0
- package/src/internal/machine/topology.ts +38 -0
- package/src/internal/testing/machine/finiteModel.ts +1 -1
- package/src/internal/testing/machine/runtime.ts +2 -1
- package/src/internal/testing/machine/verification.ts +5 -3
- package/src/testing/MachineTest.ts +7 -7
- package/src/unstable/cluster/ClusterMachine.ts +1 -1
- package/src/unstable/reactivity/AtomMachine.ts +45 -13
|
@@ -9,12 +9,13 @@ import * as Effect from "effect/Effect"
|
|
|
9
9
|
import { hasProperty } from "effect/Predicate"
|
|
10
10
|
import * as Result from "effect/Result"
|
|
11
11
|
import * as Schema from "effect/Schema"
|
|
12
|
+
import * as SchemaAST from "effect/SchemaAST"
|
|
12
13
|
import type { Machine } from "../../Machine.js"
|
|
13
14
|
import { MachineSchemaDecodeError } from "./errors.js"
|
|
14
15
|
import { getStateNodeSchema, isStateInput } from "./topology.js"
|
|
15
16
|
|
|
16
17
|
export interface DecodeBoundaryOptions {
|
|
17
|
-
readonly boundary: "input" | "event" | "
|
|
18
|
+
readonly boundary: "input" | "event" | "emission" | "state" | "output" | "history" | "configuration"
|
|
18
19
|
readonly state?: string
|
|
19
20
|
readonly event?: string
|
|
20
21
|
}
|
|
@@ -24,8 +25,33 @@ interface MachineProtocolSchemas {
|
|
|
24
25
|
readonly emit: Schema.Top
|
|
25
26
|
readonly eventConstructors: ReadonlySet<object>
|
|
26
27
|
readonly trustedEvents: WeakSet<object>
|
|
28
|
+
readonly emissionConstructors: ReadonlySet<object>
|
|
29
|
+
readonly trustedEmissions: WeakSet<object>
|
|
27
30
|
}
|
|
28
31
|
|
|
32
|
+
interface EventProtocolDefinition {
|
|
33
|
+
readonly kind: Machine.EventProtocolKind
|
|
34
|
+
readonly schemas: ReadonlyArray<Machine.TaggedSchema>
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const eventProtocolDefinitions = new WeakMap<object, EventProtocolDefinition>()
|
|
38
|
+
|
|
39
|
+
export const EventConstructionTypeId: unique symbol = Symbol("effect/Machine/EventConstruction")
|
|
40
|
+
|
|
41
|
+
interface EventConstruction {
|
|
42
|
+
readonly [EventConstructionTypeId]: typeof EventConstructionTypeId
|
|
43
|
+
readonly _tag: PropertyKey
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface EventConstructionDefinition {
|
|
47
|
+
readonly kind: Machine.EventProtocolKind
|
|
48
|
+
readonly schema: Machine.TaggedSchema
|
|
49
|
+
readonly input: unknown
|
|
50
|
+
readonly inputError?: unknown
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const eventConstructionDefinitions = new WeakMap<object, EventConstructionDefinition>()
|
|
54
|
+
|
|
29
55
|
type BoundaryDecoder = (value: unknown) => Effect.Effect<unknown, Schema.SchemaError, unknown>
|
|
30
56
|
|
|
31
57
|
type BoundaryResultDecoder = (value: unknown) => Result.Result<unknown, Schema.SchemaError>
|
|
@@ -95,13 +121,59 @@ const collectEventConstructors = (
|
|
|
95
121
|
return constructors
|
|
96
122
|
}
|
|
97
123
|
|
|
124
|
+
const getEventProtocolDefinition = (
|
|
125
|
+
protocol: Machine.EventProtocol.Any,
|
|
126
|
+
expectedKind?: Machine.EventProtocolKind
|
|
127
|
+
): EventProtocolDefinition => {
|
|
128
|
+
const definition = eventProtocolDefinitions.get(protocol as object)
|
|
129
|
+
if (definition === undefined) {
|
|
130
|
+
throw new Error(
|
|
131
|
+
"Machine expected an event protocol created with Machine.events, Machine.internalEvents, or Machine.emittedEvents"
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
if (expectedKind !== undefined && definition.kind !== expectedKind) {
|
|
135
|
+
throw new Error(`Machine expected a ${expectedKind} event protocol`)
|
|
136
|
+
}
|
|
137
|
+
return definition
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export const isEventProtocol = <Kind extends Machine.EventProtocolKind>(
|
|
141
|
+
value: unknown,
|
|
142
|
+
kind: Kind
|
|
143
|
+
): value is Machine.EventProtocol.Any<Kind> =>
|
|
144
|
+
typeof value === "object" && value !== null && eventProtocolDefinitions.get(value)?.kind === kind
|
|
145
|
+
|
|
146
|
+
export const eventProtocolSchemas = <Schemas extends ReadonlyArray<Machine.TaggedSchema>>(
|
|
147
|
+
protocol: Machine.EventProtocol<Machine.EventProtocolKind, Schemas>
|
|
148
|
+
): Schemas => getEventProtocolDefinition(protocol).schemas as Schemas
|
|
149
|
+
|
|
150
|
+
export const inputEventSchemas = (machine: Machine.Any): ReadonlyArray<Machine.TaggedSchema> =>
|
|
151
|
+
getEventProtocolDefinition(machine.events, "public").schemas
|
|
152
|
+
|
|
153
|
+
export const internalEventSchemas = (machine: Machine.Any): ReadonlyArray<Machine.TaggedSchema> =>
|
|
154
|
+
getEventProtocolDefinition(machine.internalEvents, "internal").schemas
|
|
155
|
+
|
|
156
|
+
export const emittedEventSchemas = (machine: Machine.Any): ReadonlyArray<Machine.TaggedSchema> =>
|
|
157
|
+
getEventProtocolDefinition(machine.emittedEvents, "emitted").schemas
|
|
158
|
+
|
|
98
159
|
export const setProtocol = (machine: Machine.Any): void => {
|
|
99
|
-
const
|
|
160
|
+
const inputEvents = inputEventSchemas(machine)
|
|
161
|
+
const localEvents = internalEventSchemas(machine)
|
|
162
|
+
const emittedEvents = emittedEventSchemas(machine)
|
|
163
|
+
const publicTags = new Set(Reflect.ownKeys(machine.events))
|
|
164
|
+
for (const tag of Reflect.ownKeys(machine.internalEvents)) {
|
|
165
|
+
if (publicTags.has(tag)) {
|
|
166
|
+
throw new Error(`Public and internal machine event tags must be disjoint: ${String(tag)}`)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const events = [...inputEvents, ...localEvents]
|
|
100
170
|
setProtocolSchemas(machine, {
|
|
101
171
|
event: Schema.Union(events),
|
|
102
|
-
emit: Schema.Union(
|
|
172
|
+
emit: Schema.Union(emittedEvents),
|
|
103
173
|
eventConstructors: collectEventConstructors(events),
|
|
104
|
-
trustedEvents: new WeakSet()
|
|
174
|
+
trustedEvents: new WeakSet(),
|
|
175
|
+
emissionConstructors: collectEventConstructors(emittedEvents),
|
|
176
|
+
trustedEmissions: new WeakSet()
|
|
105
177
|
})
|
|
106
178
|
}
|
|
107
179
|
|
|
@@ -111,6 +183,116 @@ export const copyProtocol = (source: Machine.Any, target: Machine.Any): void =>
|
|
|
111
183
|
export const getEventName = (event: unknown): string | undefined =>
|
|
112
184
|
hasProperty(event, "_tag") ? String(event._tag) : undefined
|
|
113
185
|
|
|
186
|
+
const makeEventConstruction = (
|
|
187
|
+
kind: Machine.EventProtocolKind,
|
|
188
|
+
schema: Machine.TaggedSchema,
|
|
189
|
+
tag: PropertyKey,
|
|
190
|
+
input: unknown
|
|
191
|
+
): EventConstruction => {
|
|
192
|
+
let ownedInput = input
|
|
193
|
+
let inputError: unknown
|
|
194
|
+
if (typeof input === "object" && input !== null) {
|
|
195
|
+
try {
|
|
196
|
+
ownedInput = { ...input }
|
|
197
|
+
} catch (cause) {
|
|
198
|
+
ownedInput = undefined
|
|
199
|
+
inputError = cause
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const construction: EventConstruction = {
|
|
203
|
+
[EventConstructionTypeId]: EventConstructionTypeId,
|
|
204
|
+
_tag: tag
|
|
205
|
+
}
|
|
206
|
+
eventConstructionDefinitions.set(construction, {
|
|
207
|
+
kind,
|
|
208
|
+
schema,
|
|
209
|
+
input: ownedInput,
|
|
210
|
+
...(inputError === undefined ? {} : { inputError })
|
|
211
|
+
})
|
|
212
|
+
return Object.freeze(construction)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const isEventConstruction = (value: unknown): value is EventConstruction =>
|
|
216
|
+
typeof value === "object" && value !== null && eventConstructionDefinitions.has(value)
|
|
217
|
+
|
|
218
|
+
const eventConstructors = (
|
|
219
|
+
kind: Machine.EventProtocolKind,
|
|
220
|
+
schemas: ReadonlyArray<Machine.TaggedSchema>
|
|
221
|
+
): Readonly<Record<PropertyKey, (...args: ReadonlyArray<unknown>) => EventConstruction>> => {
|
|
222
|
+
const leaves: Array<Machine.TaggedSchema> = []
|
|
223
|
+
const collect = (schema: Machine.TaggedSchema): void => {
|
|
224
|
+
if (hasProperty(schema, "cases") && typeof schema.cases === "object" && schema.cases !== null) {
|
|
225
|
+
for (const candidate of Reflect.ownKeys(schema.cases)) {
|
|
226
|
+
collect(Reflect.get(schema.cases, candidate) as Machine.TaggedSchema)
|
|
227
|
+
}
|
|
228
|
+
return
|
|
229
|
+
}
|
|
230
|
+
if (hasProperty(schema, "members") && Array.isArray(schema.members)) {
|
|
231
|
+
for (const member of schema.members) collect(member as Machine.TaggedSchema)
|
|
232
|
+
return
|
|
233
|
+
}
|
|
234
|
+
leaves.push(schema)
|
|
235
|
+
}
|
|
236
|
+
for (const schema of schemas) collect(schema)
|
|
237
|
+
const constructors = Object.create(null) as Record<
|
|
238
|
+
PropertyKey,
|
|
239
|
+
(...args: ReadonlyArray<unknown>) => EventConstruction
|
|
240
|
+
>
|
|
241
|
+
const tags = (ast: SchemaAST.AST): ReadonlyArray<PropertyKey> => {
|
|
242
|
+
if (SchemaAST.isLiteral(ast)) {
|
|
243
|
+
return typeof ast.literal === "string" || typeof ast.literal === "number" ? [ast.literal] : []
|
|
244
|
+
}
|
|
245
|
+
if (SchemaAST.isUniqueSymbol(ast)) return [ast.symbol]
|
|
246
|
+
if (SchemaAST.isEnum(ast)) return ast.enums.map(([, value]) => value)
|
|
247
|
+
if (SchemaAST.isUnion(ast)) return ast.types.flatMap(tags)
|
|
248
|
+
if (SchemaAST.isSuspend(ast)) return tags(ast.thunk())
|
|
249
|
+
return []
|
|
250
|
+
}
|
|
251
|
+
const schemaTags = (schema: Machine.TaggedSchema): ReadonlyArray<PropertyKey> => {
|
|
252
|
+
const ast = SchemaAST.toType(schema.ast)
|
|
253
|
+
if (SchemaAST.isObjects(ast)) {
|
|
254
|
+
const tag = ast.propertySignatures.find(({ name }) => name === "_tag")
|
|
255
|
+
const discriminants = tag === undefined ? [] : tags(tag.type)
|
|
256
|
+
if (discriminants.length > 0) return discriminants
|
|
257
|
+
}
|
|
258
|
+
try {
|
|
259
|
+
return Schema.Union([schema]).pipe(Schema.toTaggedUnion("_tag")).discriminants
|
|
260
|
+
} catch {
|
|
261
|
+
return []
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
for (const schema of leaves) {
|
|
265
|
+
const discriminants = schemaTags(schema)
|
|
266
|
+
if (discriminants.length === 0) {
|
|
267
|
+
continue
|
|
268
|
+
}
|
|
269
|
+
for (const tag of discriminants) {
|
|
270
|
+
if (hasProperty(constructors, tag)) {
|
|
271
|
+
throw new Error(`Duplicate machine event constructor tag: ${String(tag)}`)
|
|
272
|
+
}
|
|
273
|
+
Object.defineProperty(constructors, tag, {
|
|
274
|
+
value: (...args: ReadonlyArray<unknown>) =>
|
|
275
|
+
makeEventConstruction(kind, schema, tag, args.length === 0 ? {} : args[0]),
|
|
276
|
+
enumerable: true
|
|
277
|
+
})
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return constructors
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export const makeEventProtocol = <
|
|
284
|
+
Kind extends Machine.EventProtocolKind,
|
|
285
|
+
Schemas extends ReadonlyArray<Machine.TaggedSchema>
|
|
286
|
+
>(
|
|
287
|
+
kind: Kind,
|
|
288
|
+
schemas: Schemas
|
|
289
|
+
): Machine.EventProtocol<Kind, Schemas> => {
|
|
290
|
+
const ownedSchemas = Object.freeze(Array.from(schemas)) as unknown as Schemas
|
|
291
|
+
const protocol = eventConstructors(kind, ownedSchemas) as Machine.EventProtocol<Kind, Schemas>
|
|
292
|
+
eventProtocolDefinitions.set(protocol as object, { kind, schemas: ownedSchemas })
|
|
293
|
+
return Object.freeze(protocol) as Machine.EventProtocol<Kind, Schemas>
|
|
294
|
+
}
|
|
295
|
+
|
|
114
296
|
export const decodeBoundary = <A>(
|
|
115
297
|
machine: Machine.Any,
|
|
116
298
|
schema: Schema.Top,
|
|
@@ -172,26 +354,106 @@ const makeBoundarySync = <A>(
|
|
|
172
354
|
}
|
|
173
355
|
}
|
|
174
356
|
|
|
175
|
-
|
|
176
|
-
* records the decoded value as trusted by that protocol. Machine clones share
|
|
177
|
-
* the protocol record, while unrelated machines retain independent trust. */
|
|
178
|
-
export const makeEvent = <Schema extends Machine.TaggedSchema>(
|
|
357
|
+
const eventConstructionProtocolError = (
|
|
179
358
|
machine: Machine.Any,
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
):
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
359
|
+
construction: EventConstruction,
|
|
360
|
+
boundary: "event" | "emission"
|
|
361
|
+
): MachineSchemaDecodeError =>
|
|
362
|
+
new MachineSchemaDecodeError({
|
|
363
|
+
machineId: machine.id,
|
|
364
|
+
boundary,
|
|
365
|
+
event: String(construction._tag),
|
|
366
|
+
cause: Cause.die(new Error(`Constructed ${boundary} schema does not belong to the machine ${boundary} protocol`))
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
const eventConstructionInput = (
|
|
370
|
+
construction: EventConstruction,
|
|
371
|
+
definition: EventConstructionDefinition
|
|
372
|
+
): unknown => {
|
|
373
|
+
if (definition.inputError !== undefined) throw definition.inputError
|
|
374
|
+
return typeof definition.input === "object" && definition.input !== null
|
|
375
|
+
? { ...definition.input, _tag: construction._tag }
|
|
376
|
+
: { _tag: construction._tag }
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const eventConstructionInputError = (
|
|
380
|
+
machine: Machine.Any,
|
|
381
|
+
construction: EventConstruction,
|
|
382
|
+
boundary: "event" | "emission",
|
|
383
|
+
cause: unknown
|
|
384
|
+
): MachineSchemaDecodeError =>
|
|
385
|
+
new MachineSchemaDecodeError({
|
|
386
|
+
machineId: machine.id,
|
|
387
|
+
boundary,
|
|
388
|
+
event: String(construction._tag),
|
|
389
|
+
cause: Cause.die(cause)
|
|
390
|
+
})
|
|
391
|
+
|
|
392
|
+
const decodeEventConstruction = (
|
|
393
|
+
machine: Machine.Any,
|
|
394
|
+
protocol: MachineProtocolSchemas,
|
|
395
|
+
construction: EventConstruction,
|
|
396
|
+
boundary: "event" | "emission"
|
|
397
|
+
): Effect.Effect<unknown, MachineSchemaDecodeError> => {
|
|
398
|
+
const definition = eventConstructionDefinitions.get(construction)
|
|
399
|
+
const constructors = boundary === "event" ? protocol.eventConstructors : protocol.emissionConstructors
|
|
400
|
+
if (
|
|
401
|
+
definition === undefined ||
|
|
402
|
+
(boundary === "emission" ? definition.kind !== "emitted" : definition.kind === "emitted") ||
|
|
403
|
+
!constructors.has(definition.schema as object)
|
|
404
|
+
) {
|
|
405
|
+
return Effect.fail(eventConstructionProtocolError(machine, construction, boundary))
|
|
186
406
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
machine,
|
|
190
|
-
|
|
191
|
-
input
|
|
192
|
-
|
|
407
|
+
return Effect.try({
|
|
408
|
+
try: () => eventConstructionInput(construction, definition),
|
|
409
|
+
catch: (cause) => eventConstructionInputError(machine, construction, boundary, cause)
|
|
410
|
+
}).pipe(
|
|
411
|
+
Effect.flatMap((input) =>
|
|
412
|
+
definition.schema.makeEffect(input as never).pipe(
|
|
413
|
+
Effect.mapError((cause) =>
|
|
414
|
+
new MachineSchemaDecodeError({
|
|
415
|
+
machineId: machine.id,
|
|
416
|
+
boundary,
|
|
417
|
+
event: String(construction._tag),
|
|
418
|
+
cause: new Schema.SchemaError(cause)
|
|
419
|
+
})
|
|
420
|
+
)
|
|
421
|
+
)
|
|
422
|
+
),
|
|
423
|
+
Effect.tap((event) =>
|
|
424
|
+
Effect.sync(() =>
|
|
425
|
+
(boundary === "event" ? protocol.trustedEvents : protocol.trustedEmissions).add(event as object)
|
|
426
|
+
)
|
|
427
|
+
)
|
|
193
428
|
)
|
|
194
|
-
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
const decodeEventConstructionSync = (
|
|
432
|
+
machine: Machine.Any,
|
|
433
|
+
protocol: MachineProtocolSchemas,
|
|
434
|
+
construction: EventConstruction,
|
|
435
|
+
boundary: "event" | "emission"
|
|
436
|
+
): unknown => {
|
|
437
|
+
const definition = eventConstructionDefinitions.get(construction)
|
|
438
|
+
const constructors = boundary === "event" ? protocol.eventConstructors : protocol.emissionConstructors
|
|
439
|
+
if (
|
|
440
|
+
definition === undefined ||
|
|
441
|
+
(boundary === "emission" ? definition.kind !== "emitted" : definition.kind === "emitted") ||
|
|
442
|
+
!constructors.has(definition.schema as object)
|
|
443
|
+
) {
|
|
444
|
+
throw eventConstructionProtocolError(machine, construction, boundary)
|
|
445
|
+
}
|
|
446
|
+
let input: unknown
|
|
447
|
+
try {
|
|
448
|
+
input = eventConstructionInput(construction, definition)
|
|
449
|
+
} catch (cause) {
|
|
450
|
+
throw eventConstructionInputError(machine, construction, boundary, cause)
|
|
451
|
+
}
|
|
452
|
+
const event = makeBoundarySync(machine, definition.schema, input, {
|
|
453
|
+
boundary,
|
|
454
|
+
event: String(construction._tag)
|
|
455
|
+
})
|
|
456
|
+
;(boundary === "event" ? protocol.trustedEvents : protocol.trustedEmissions).add(event as object)
|
|
195
457
|
return event
|
|
196
458
|
}
|
|
197
459
|
|
|
@@ -210,6 +472,12 @@ export const decodeEvent = <const Events extends ReadonlyArray<Machine.TaggedSch
|
|
|
210
472
|
event: unknown
|
|
211
473
|
): Effect.Effect<Machine.EventOf<Events>, MachineSchemaDecodeError> => {
|
|
212
474
|
const protocol = getProtocolSchemas(machine)
|
|
475
|
+
if (isEventConstruction(event)) {
|
|
476
|
+
return decodeEventConstruction(machine, protocol, event, "event") as Effect.Effect<
|
|
477
|
+
Machine.EventOf<Events>,
|
|
478
|
+
MachineSchemaDecodeError
|
|
479
|
+
>
|
|
480
|
+
}
|
|
213
481
|
if (isTrustedEvent(protocol, event)) {
|
|
214
482
|
return Effect.succeed(event as Machine.EventOf<Events>)
|
|
215
483
|
}
|
|
@@ -227,6 +495,9 @@ export const decodeEventSync = <const Events extends ReadonlyArray<Machine.Tagge
|
|
|
227
495
|
event: unknown
|
|
228
496
|
): Machine.EventOf<Events> => {
|
|
229
497
|
const protocol = getProtocolSchemas(machine)
|
|
498
|
+
if (isEventConstruction(event)) {
|
|
499
|
+
return decodeEventConstructionSync(machine, protocol, event, "event") as Machine.EventOf<Events>
|
|
500
|
+
}
|
|
230
501
|
if (isTrustedEvent(protocol, event)) {
|
|
231
502
|
return event as Machine.EventOf<Events>
|
|
232
503
|
}
|
|
@@ -243,12 +514,22 @@ export const decodeEmit = <const Emits extends ReadonlyArray<Machine.TaggedSchem
|
|
|
243
514
|
machine: Machine.Any,
|
|
244
515
|
event: unknown
|
|
245
516
|
): Effect.Effect<Machine.EmitOf<Emits>, MachineSchemaDecodeError> => {
|
|
517
|
+
const protocol = getProtocolSchemas(machine)
|
|
518
|
+
if (isEventConstruction(event)) {
|
|
519
|
+
return decodeEventConstruction(machine, protocol, event, "emission") as Effect.Effect<
|
|
520
|
+
Machine.EmitOf<Emits>,
|
|
521
|
+
MachineSchemaDecodeError
|
|
522
|
+
>
|
|
523
|
+
}
|
|
524
|
+
if (typeof event === "object" && event !== null && protocol.trustedEmissions.has(event)) {
|
|
525
|
+
return Effect.succeed(event as Machine.EmitOf<Emits>)
|
|
526
|
+
}
|
|
246
527
|
const eventName = getEventName(event)
|
|
247
528
|
return decodeBoundary<Machine.EmitOf<Emits>>(
|
|
248
529
|
machine,
|
|
249
|
-
|
|
530
|
+
protocol.emit,
|
|
250
531
|
event,
|
|
251
|
-
eventName === undefined ? { boundary: "
|
|
532
|
+
eventName === undefined ? { boundary: "emission" } : { boundary: "emission", event: eventName }
|
|
252
533
|
)
|
|
253
534
|
}
|
|
254
535
|
|
|
@@ -256,12 +537,19 @@ export const decodeEmitSync = <const Emits extends ReadonlyArray<Machine.TaggedS
|
|
|
256
537
|
machine: Machine.Any,
|
|
257
538
|
event: unknown
|
|
258
539
|
): Machine.EmitOf<Emits> => {
|
|
540
|
+
const protocol = getProtocolSchemas(machine)
|
|
541
|
+
if (isEventConstruction(event)) {
|
|
542
|
+
return decodeEventConstructionSync(machine, protocol, event, "emission") as Machine.EmitOf<Emits>
|
|
543
|
+
}
|
|
544
|
+
if (typeof event === "object" && event !== null && protocol.trustedEmissions.has(event)) {
|
|
545
|
+
return event as Machine.EmitOf<Emits>
|
|
546
|
+
}
|
|
259
547
|
const eventName = getEventName(event)
|
|
260
548
|
return decodeBoundarySync<Machine.EmitOf<Emits>>(
|
|
261
549
|
machine,
|
|
262
|
-
|
|
550
|
+
protocol.emit,
|
|
263
551
|
event,
|
|
264
|
-
eventName === undefined ? { boundary: "
|
|
552
|
+
eventName === undefined ? { boundary: "emission" } : { boundary: "emission", event: eventName }
|
|
265
553
|
)
|
|
266
554
|
}
|
|
267
555
|
|