@typeonce/effect-machine 0.9.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.
Files changed (92) hide show
  1. package/README.md +128 -28
  2. package/dist/Machine.d.ts +334 -238
  3. package/dist/Machine.d.ts.map +1 -1
  4. package/dist/Machine.js +45 -76
  5. package/dist/Machine.js.map +1 -1
  6. package/dist/internal/machine/atom.d.ts +6 -2
  7. package/dist/internal/machine/atom.d.ts.map +1 -1
  8. package/dist/internal/machine/atom.js +5 -0
  9. package/dist/internal/machine/atom.js.map +1 -1
  10. package/dist/internal/machine/cluster.d.ts.map +1 -1
  11. package/dist/internal/machine/cluster.js +2 -1
  12. package/dist/internal/machine/cluster.js.map +1 -1
  13. package/dist/internal/machine/command.js +2 -2
  14. package/dist/internal/machine/command.js.map +1 -1
  15. package/dist/internal/machine/commandRuntime.d.ts.map +1 -1
  16. package/dist/internal/machine/commandRuntime.js +6 -3
  17. package/dist/internal/machine/commandRuntime.js.map +1 -1
  18. package/dist/internal/machine/configuration.d.ts +8 -1
  19. package/dist/internal/machine/configuration.d.ts.map +1 -1
  20. package/dist/internal/machine/configuration.js +9 -4
  21. package/dist/internal/machine/configuration.js.map +1 -1
  22. package/dist/internal/machine/errors.d.ts +1 -1
  23. package/dist/internal/machine/errors.d.ts.map +1 -1
  24. package/dist/internal/machine/executionPlan.d.ts +3 -3
  25. package/dist/internal/machine/executionPlan.d.ts.map +1 -1
  26. package/dist/internal/machine/executionPlan.js +50 -25
  27. package/dist/internal/machine/executionPlan.js.map +1 -1
  28. package/dist/internal/machine/invocation.d.ts.map +1 -1
  29. package/dist/internal/machine/invocation.js +3 -2
  30. package/dist/internal/machine/invocation.js.map +1 -1
  31. package/dist/internal/machine/machine.d.ts +14 -19
  32. package/dist/internal/machine/machine.d.ts.map +1 -1
  33. package/dist/internal/machine/machine.js +12 -10
  34. package/dist/internal/machine/machine.js.map +1 -1
  35. package/dist/internal/machine/planner.d.ts +2 -1
  36. package/dist/internal/machine/planner.d.ts.map +1 -1
  37. package/dist/internal/machine/planner.js +61 -24
  38. package/dist/internal/machine/planner.js.map +1 -1
  39. package/dist/internal/machine/process.d.ts.map +1 -1
  40. package/dist/internal/machine/process.js +8 -8
  41. package/dist/internal/machine/process.js.map +1 -1
  42. package/dist/internal/machine/protocol.d.ts +7 -13
  43. package/dist/internal/machine/protocol.d.ts.map +1 -1
  44. package/dist/internal/machine/protocol.js +128 -50
  45. package/dist/internal/machine/protocol.js.map +1 -1
  46. package/dist/internal/machine/runtime.d.ts +8 -2
  47. package/dist/internal/machine/runtime.d.ts.map +1 -1
  48. package/dist/internal/machine/runtime.js +86 -8
  49. package/dist/internal/machine/runtime.js.map +1 -1
  50. package/dist/internal/machine/topology.d.ts +7 -0
  51. package/dist/internal/machine/topology.d.ts.map +1 -1
  52. package/dist/internal/machine/topology.js +6 -0
  53. package/dist/internal/machine/topology.js.map +1 -1
  54. package/dist/internal/testing/machine/finiteModel.js +1 -1
  55. package/dist/internal/testing/machine/finiteModel.js.map +1 -1
  56. package/dist/internal/testing/machine/runtime.d.ts.map +1 -1
  57. package/dist/internal/testing/machine/runtime.js +2 -1
  58. package/dist/internal/testing/machine/runtime.js.map +1 -1
  59. package/dist/internal/testing/machine/verification.d.ts.map +1 -1
  60. package/dist/internal/testing/machine/verification.js +5 -3
  61. package/dist/internal/testing/machine/verification.js.map +1 -1
  62. package/dist/testing/MachineTest.d.ts +7 -7
  63. package/dist/testing/MachineTest.js +7 -7
  64. package/dist/unstable/cluster/ClusterMachine.d.ts +1 -1
  65. package/dist/unstable/cluster/ClusterMachine.js +1 -1
  66. package/dist/unstable/reactivity/AtomMachine.d.ts +25 -8
  67. package/dist/unstable/reactivity/AtomMachine.d.ts.map +1 -1
  68. package/dist/unstable/reactivity/AtomMachine.js +18 -3
  69. package/dist/unstable/reactivity/AtomMachine.js.map +1 -1
  70. package/docs/agent-guide.md +143 -48
  71. package/package.json +1 -1
  72. package/src/Machine.ts +559 -307
  73. package/src/internal/machine/atom.ts +35 -10
  74. package/src/internal/machine/cluster.ts +2 -1
  75. package/src/internal/machine/command.ts +2 -2
  76. package/src/internal/machine/commandRuntime.ts +9 -4
  77. package/src/internal/machine/configuration.ts +23 -5
  78. package/src/internal/machine/errors.ts +1 -1
  79. package/src/internal/machine/executionPlan.ts +74 -29
  80. package/src/internal/machine/invocation.ts +3 -2
  81. package/src/internal/machine/machine.ts +68 -49
  82. package/src/internal/machine/planner.ts +68 -24
  83. package/src/internal/machine/process.ts +18 -8
  84. package/src/internal/machine/protocol.ts +207 -68
  85. package/src/internal/machine/runtime.ts +135 -9
  86. package/src/internal/machine/topology.ts +15 -0
  87. package/src/internal/testing/machine/finiteModel.ts +1 -1
  88. package/src/internal/testing/machine/runtime.ts +2 -1
  89. package/src/internal/testing/machine/verification.ts +5 -3
  90. package/src/testing/MachineTest.ts +7 -7
  91. package/src/unstable/cluster/ClusterMachine.ts +1 -1
  92. package/src/unstable/reactivity/AtomMachine.ts +42 -10
@@ -15,7 +15,7 @@ import { MachineSchemaDecodeError } from "./errors.js"
15
15
  import { getStateNodeSchema, isStateInput } from "./topology.js"
16
16
 
17
17
  export interface DecodeBoundaryOptions {
18
- readonly boundary: "input" | "event" | "emit" | "state" | "output" | "history" | "configuration"
18
+ readonly boundary: "input" | "event" | "emission" | "state" | "output" | "history" | "configuration"
19
19
  readonly state?: string
20
20
  readonly event?: string
21
21
  }
@@ -25,17 +25,33 @@ interface MachineProtocolSchemas {
25
25
  readonly emit: Schema.Top
26
26
  readonly eventConstructors: ReadonlySet<object>
27
27
  readonly trustedEvents: WeakSet<object>
28
+ readonly emissionConstructors: ReadonlySet<object>
29
+ readonly trustedEmissions: WeakSet<object>
28
30
  }
29
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
+
30
39
  export const EventConstructionTypeId: unique symbol = Symbol("effect/Machine/EventConstruction")
31
40
 
32
41
  interface EventConstruction {
33
42
  readonly [EventConstructionTypeId]: typeof EventConstructionTypeId
34
43
  readonly _tag: PropertyKey
44
+ }
45
+
46
+ interface EventConstructionDefinition {
47
+ readonly kind: Machine.EventProtocolKind
35
48
  readonly schema: Machine.TaggedSchema
36
49
  readonly input: unknown
50
+ readonly inputError?: unknown
37
51
  }
38
52
 
53
+ const eventConstructionDefinitions = new WeakMap<object, EventConstructionDefinition>()
54
+
39
55
  type BoundaryDecoder = (value: unknown) => Effect.Effect<unknown, Schema.SchemaError, unknown>
40
56
 
41
57
  type BoundaryResultDecoder = (value: unknown) => Result.Result<unknown, Schema.SchemaError>
@@ -105,13 +121,59 @@ const collectEventConstructors = (
105
121
  return constructors
106
122
  }
107
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
+
108
159
  export const setProtocol = (machine: Machine.Any): void => {
109
- const events = [...machine.events, ...machine.internalEvents]
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]
110
170
  setProtocolSchemas(machine, {
111
171
  event: Schema.Union(events),
112
- emit: Schema.Union(machine.emits),
172
+ emit: Schema.Union(emittedEvents),
113
173
  eventConstructors: collectEventConstructors(events),
114
- trustedEvents: new WeakSet()
174
+ trustedEvents: new WeakSet(),
175
+ emissionConstructors: collectEventConstructors(emittedEvents),
176
+ trustedEmissions: new WeakSet()
115
177
  })
116
178
  }
117
179
 
@@ -122,19 +184,39 @@ export const getEventName = (event: unknown): string | undefined =>
122
184
  hasProperty(event, "_tag") ? String(event._tag) : undefined
123
185
 
124
186
  const makeEventConstruction = (
187
+ kind: Machine.EventProtocolKind,
125
188
  schema: Machine.TaggedSchema,
126
189
  tag: PropertyKey,
127
190
  input: unknown
128
- ): EventConstruction => ({
129
- [EventConstructionTypeId]: EventConstructionTypeId,
130
- _tag: tag,
131
- schema,
132
- input
133
- })
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
+ }
134
214
 
135
- const isEventConstruction = (value: unknown): value is EventConstruction => hasProperty(value, EventConstructionTypeId)
215
+ const isEventConstruction = (value: unknown): value is EventConstruction =>
216
+ typeof value === "object" && value !== null && eventConstructionDefinitions.has(value)
136
217
 
137
- export const eventConstructors = (
218
+ const eventConstructors = (
219
+ kind: Machine.EventProtocolKind,
138
220
  schemas: ReadonlyArray<Machine.TaggedSchema>
139
221
  ): Readonly<Record<PropertyKey, (...args: ReadonlyArray<unknown>) => EventConstruction>> => {
140
222
  const leaves: Array<Machine.TaggedSchema> = []
@@ -182,20 +264,15 @@ export const eventConstructors = (
182
264
  for (const schema of leaves) {
183
265
  const discriminants = schemaTags(schema)
184
266
  if (discriminants.length === 0) {
185
- throw new Error("Machine event constructors require finite literal or unique symbol event tags")
267
+ continue
186
268
  }
187
269
  for (const tag of discriminants) {
188
270
  if (hasProperty(constructors, tag)) {
189
271
  throw new Error(`Duplicate machine event constructor tag: ${String(tag)}`)
190
272
  }
191
273
  Object.defineProperty(constructors, tag, {
192
- value: (...args: ReadonlyArray<unknown>) => {
193
- const fields = args.length === 0 ? {} : args[0]
194
- const input = typeof fields === "object" && fields !== null
195
- ? { ...fields, _tag: tag }
196
- : { _tag: tag }
197
- return makeEventConstruction(schema, tag, input)
198
- },
274
+ value: (...args: ReadonlyArray<unknown>) =>
275
+ makeEventConstruction(kind, schema, tag, args.length === 0 ? {} : args[0]),
199
276
  enumerable: true
200
277
  })
201
278
  }
@@ -203,6 +280,19 @@ export const eventConstructors = (
203
280
  return constructors
204
281
  }
205
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
+
206
296
  export const decodeBoundary = <A>(
207
297
  machine: Machine.Any,
208
298
  schema: Schema.Top,
@@ -264,74 +354,106 @@ const makeBoundarySync = <A>(
264
354
  }
265
355
  }
266
356
 
267
- /** Constructs an event through one of the machine protocol's own schemas and
268
- * records the decoded value as trusted by that protocol. Machine clones share
269
- * the protocol record, while unrelated machines retain independent trust. */
270
- export const makeEvent = <Schema extends Machine.TaggedSchema>(
357
+ const eventConstructionProtocolError = (
271
358
  machine: Machine.Any,
272
- schema: Schema,
273
- input: unknown
274
- ): Schema["Type"] => {
275
- const protocol = getProtocolSchemas(machine)
276
- if (!protocol.eventConstructors.has(schema as object)) {
277
- throw new Error("Machine.event expected a schema from the machine event protocol")
278
- }
279
- const inputName = getEventName(input)
280
- const event = makeBoundarySync<Schema["Type"]>(
281
- machine,
282
- schema,
283
- input,
284
- inputName === undefined ? { boundary: "event" } : { boundary: "event", event: inputName }
285
- )
286
- protocol.trustedEvents.add(event as object)
287
- return event
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 }
288
377
  }
289
378
 
290
- const eventConstructionProtocolError = (
379
+ const eventConstructionInputError = (
291
380
  machine: Machine.Any,
292
- construction: EventConstruction
381
+ construction: EventConstruction,
382
+ boundary: "event" | "emission",
383
+ cause: unknown
293
384
  ): MachineSchemaDecodeError =>
294
385
  new MachineSchemaDecodeError({
295
386
  machineId: machine.id,
296
- boundary: "event",
387
+ boundary,
297
388
  event: String(construction._tag),
298
- cause: Cause.die(new Error("Constructed event schema does not belong to the machine event protocol"))
389
+ cause: Cause.die(cause)
299
390
  })
300
391
 
301
392
  const decodeEventConstruction = (
302
393
  machine: Machine.Any,
303
394
  protocol: MachineProtocolSchemas,
304
- construction: EventConstruction
395
+ construction: EventConstruction,
396
+ boundary: "event" | "emission"
305
397
  ): Effect.Effect<unknown, MachineSchemaDecodeError> => {
306
- if (!protocol.eventConstructors.has(construction.schema as object)) {
307
- return Effect.fail(eventConstructionProtocolError(machine, construction))
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))
308
406
  }
309
- return construction.schema.makeEffect(construction.input as never).pipe(
310
- Effect.mapError((cause) =>
311
- new MachineSchemaDecodeError({
312
- machineId: machine.id,
313
- boundary: "event",
314
- event: String(construction._tag),
315
- cause: new Schema.SchemaError(cause)
316
- })
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
+ )
317
422
  ),
318
- Effect.tap((event) => Effect.sync(() => protocol.trustedEvents.add(event as object)))
423
+ Effect.tap((event) =>
424
+ Effect.sync(() =>
425
+ (boundary === "event" ? protocol.trustedEvents : protocol.trustedEmissions).add(event as object)
426
+ )
427
+ )
319
428
  )
320
429
  }
321
430
 
322
431
  const decodeEventConstructionSync = (
323
432
  machine: Machine.Any,
324
433
  protocol: MachineProtocolSchemas,
325
- construction: EventConstruction
434
+ construction: EventConstruction,
435
+ boundary: "event" | "emission"
326
436
  ): unknown => {
327
- if (!protocol.eventConstructors.has(construction.schema as object)) {
328
- throw eventConstructionProtocolError(machine, construction)
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)
329
451
  }
330
- const event = makeBoundarySync(machine, construction.schema, construction.input, {
331
- boundary: "event",
452
+ const event = makeBoundarySync(machine, definition.schema, input, {
453
+ boundary,
332
454
  event: String(construction._tag)
333
455
  })
334
- protocol.trustedEvents.add(event as object)
456
+ ;(boundary === "event" ? protocol.trustedEvents : protocol.trustedEmissions).add(event as object)
335
457
  return event
336
458
  }
337
459
 
@@ -351,7 +473,7 @@ export const decodeEvent = <const Events extends ReadonlyArray<Machine.TaggedSch
351
473
  ): Effect.Effect<Machine.EventOf<Events>, MachineSchemaDecodeError> => {
352
474
  const protocol = getProtocolSchemas(machine)
353
475
  if (isEventConstruction(event)) {
354
- return decodeEventConstruction(machine, protocol, event) as Effect.Effect<
476
+ return decodeEventConstruction(machine, protocol, event, "event") as Effect.Effect<
355
477
  Machine.EventOf<Events>,
356
478
  MachineSchemaDecodeError
357
479
  >
@@ -374,7 +496,7 @@ export const decodeEventSync = <const Events extends ReadonlyArray<Machine.Tagge
374
496
  ): Machine.EventOf<Events> => {
375
497
  const protocol = getProtocolSchemas(machine)
376
498
  if (isEventConstruction(event)) {
377
- return decodeEventConstructionSync(machine, protocol, event) as Machine.EventOf<Events>
499
+ return decodeEventConstructionSync(machine, protocol, event, "event") as Machine.EventOf<Events>
378
500
  }
379
501
  if (isTrustedEvent(protocol, event)) {
380
502
  return event as Machine.EventOf<Events>
@@ -392,12 +514,22 @@ export const decodeEmit = <const Emits extends ReadonlyArray<Machine.TaggedSchem
392
514
  machine: Machine.Any,
393
515
  event: unknown
394
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
+ }
395
527
  const eventName = getEventName(event)
396
528
  return decodeBoundary<Machine.EmitOf<Emits>>(
397
529
  machine,
398
- getProtocolSchemas(machine).emit,
530
+ protocol.emit,
399
531
  event,
400
- eventName === undefined ? { boundary: "emit" } : { boundary: "emit", event: eventName }
532
+ eventName === undefined ? { boundary: "emission" } : { boundary: "emission", event: eventName }
401
533
  )
402
534
  }
403
535
 
@@ -405,12 +537,19 @@ export const decodeEmitSync = <const Emits extends ReadonlyArray<Machine.TaggedS
405
537
  machine: Machine.Any,
406
538
  event: unknown
407
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
+ }
408
547
  const eventName = getEventName(event)
409
548
  return decodeBoundarySync<Machine.EmitOf<Emits>>(
410
549
  machine,
411
- getProtocolSchemas(machine).emit,
550
+ protocol.emit,
412
551
  event,
413
- eventName === undefined ? { boundary: "emit" } : { boundary: "emit", event: eventName }
552
+ eventName === undefined ? { boundary: "emission" } : { boundary: "emission", event: eventName }
414
553
  )
415
554
  }
416
555