@typeonce/effect-machine-devtools 0.23.0 → 0.25.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/NOTICE +4 -0
- package/README.md +14 -8
- package/dist/DevServer.d.ts +2 -1
- package/dist/DevServer.d.ts.map +1 -1
- package/dist/DevServer.js.map +1 -1
- package/dist/DevToolsProtocol.d.ts +167 -17
- package/dist/DevToolsProtocol.d.ts.map +1 -1
- package/dist/DevToolsProtocol.js +1 -1
- package/dist/MachineDocument.d.ts +98 -2
- package/dist/MachineDocument.d.ts.map +1 -1
- package/dist/MachineDocument.js +35 -1
- package/dist/MachineDocument.js.map +1 -1
- package/dist/MachineRegistry.d.ts +56 -6
- package/dist/MachineRegistry.d.ts.map +1 -1
- package/dist/MachineWalkthrough.d.ts +171 -0
- package/dist/MachineWalkthrough.d.ts.map +1 -0
- package/dist/MachineWalkthrough.js +98 -0
- package/dist/MachineWalkthrough.js.map +1 -0
- package/dist/client/assets/index-BTOAhezX.js +37 -0
- package/dist/client/assets/index-Cg7xzSkz.css +1 -0
- package/dist/client/index.html +4 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/internal/devServer.d.ts +2 -1
- package/dist/internal/devServer.d.ts.map +1 -1
- package/dist/internal/devServer.js +4 -3
- package/dist/internal/devServer.js.map +1 -1
- package/dist/internal/evaluationWorker.d.ts.map +1 -1
- package/dist/internal/evaluationWorker.js +28 -9
- package/dist/internal/evaluationWorker.js.map +1 -1
- package/dist/internal/machineDocument.d.ts.map +1 -1
- package/dist/internal/machineDocument.js +65 -2
- package/dist/internal/machineDocument.js.map +1 -1
- package/dist/internal/machineWalkthrough.d.ts +26 -0
- package/dist/internal/machineWalkthrough.d.ts.map +1 -0
- package/dist/internal/machineWalkthrough.js +256 -0
- package/dist/internal/machineWalkthrough.js.map +1 -0
- package/dist/internal/projectInspector.d.ts.map +1 -1
- package/dist/internal/projectInspector.js +15 -9
- package/dist/internal/projectInspector.js.map +1 -1
- package/index.html +2 -2
- package/package.json +4 -3
- package/src/DevServer.ts +6 -2
- package/src/DevToolsProtocol.ts +1 -1
- package/src/MachineDocument.ts +56 -1
- package/src/MachineWalkthrough.ts +199 -0
- package/src/index.ts +2 -2
- package/src/internal/browser/chart-layout.ts +433 -0
- package/src/internal/browser/chart-model.ts +234 -0
- package/src/internal/browser/chart-renderer.ts +661 -0
- package/src/internal/browser/example-machine.ts +15 -6
- package/src/internal/browser/input-form.ts +252 -0
- package/src/internal/browser/invoke-outcomes-example.ts +231 -0
- package/src/internal/browser/parallel-completion-example.ts +199 -0
- package/src/internal/browser/planner-example.ts +145 -0
- package/src/internal/browser/protocol-events-example.ts +200 -0
- package/src/internal/browser/styles.css +959 -185
- package/src/internal/browser/transition-semantics-example.ts +236 -0
- package/src/internal/browser/visualizer-app.ts +818 -389
- package/src/internal/browser/visualizer-model.ts +104 -0
- package/src/internal/browser/visualizer.ts +1 -1
- package/src/internal/devServer.ts +9 -4
- package/src/internal/evaluationWorker.ts +28 -10
- package/src/internal/machineDocument.ts +77 -2
- package/src/internal/machineWalkthrough.ts +355 -0
- package/src/internal/projectInspector.ts +29 -14
- package/dist/MachineSimulator.d.ts +0 -169
- package/dist/MachineSimulator.d.ts.map +0 -1
- package/dist/MachineSimulator.js +0 -98
- package/dist/MachineSimulator.js.map +0 -1
- package/dist/client/assets/index-BGOhE3Ng.css +0 -1
- package/dist/client/assets/index-DiqGhsGR.js +0 -14
- package/dist/internal/machineSimulator.d.ts +0 -5
- package/dist/internal/machineSimulator.d.ts.map +0 -1
- package/dist/internal/machineSimulator.js +0 -156
- package/dist/internal/machineSimulator.js.map +0 -1
- package/src/MachineSimulator.ts +0 -154
- package/src/internal/machineSimulator.ts +0 -199
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { Machine } from "@typeonce/effect-machine"
|
|
2
|
+
import { Schema } from "effect"
|
|
3
|
+
import * as Effect from "effect/Effect"
|
|
4
|
+
|
|
5
|
+
class Idle extends Schema.TaggedClass<Idle>("PlannerIdle")("Idle", { owner: Schema.String }) {}
|
|
6
|
+
class Working extends Schema.TaggedClass<Working>("PlannerWorking")("Working", {
|
|
7
|
+
owner: Schema.String,
|
|
8
|
+
job: Schema.String
|
|
9
|
+
}) {}
|
|
10
|
+
class Finished extends Schema.TaggedClass<Finished>("PlannerFinished")("Finished", { job: Schema.String }) {}
|
|
11
|
+
|
|
12
|
+
const Owner = Schema.NonEmptyString.annotate({
|
|
13
|
+
title: "Owner",
|
|
14
|
+
description: "A non-empty name carried into the initial Idle state."
|
|
15
|
+
})
|
|
16
|
+
const Attempts = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 5 })).annotate({
|
|
17
|
+
title: "Attempts",
|
|
18
|
+
description: "An integer between one and five."
|
|
19
|
+
})
|
|
20
|
+
const Labels = Schema.Array(Schema.NonEmptyString).check(Schema.isLengthBetween(1, 3)).annotate({
|
|
21
|
+
title: "Labels",
|
|
22
|
+
description: "One to three non-empty labels."
|
|
23
|
+
})
|
|
24
|
+
const Route = Schema.Union([
|
|
25
|
+
Schema.Literal("direct").annotate({ title: "Direct" }),
|
|
26
|
+
Schema.Struct({
|
|
27
|
+
queue: Schema.NonEmptyString.annotate({
|
|
28
|
+
title: "Queue",
|
|
29
|
+
description: "The queue used by the queued route."
|
|
30
|
+
})
|
|
31
|
+
}).annotate({ title: "Queued" })
|
|
32
|
+
]).annotate({
|
|
33
|
+
title: "Route",
|
|
34
|
+
description: "Choose a literal direct route or provide a queue."
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
class Begin extends Schema.TaggedClass<Begin>("PlannerBegin")("Begin", {
|
|
38
|
+
job: Schema.NonEmptyString.annotate({
|
|
39
|
+
title: "Job",
|
|
40
|
+
description: "A non-empty job name used as the final output."
|
|
41
|
+
}),
|
|
42
|
+
priority: Schema.Literals(["normal", "urgent"]).annotate({
|
|
43
|
+
title: "Priority",
|
|
44
|
+
description: "Urgent jobs raise AutoFinish during the same macrostep."
|
|
45
|
+
}),
|
|
46
|
+
estimate: Schema.Finite.check(Schema.isBetween({ minimum: 0, maximum: 100 })).annotate({
|
|
47
|
+
title: "Estimate",
|
|
48
|
+
description: "A numeric estimate between zero and one hundred."
|
|
49
|
+
}),
|
|
50
|
+
approved: Schema.Boolean.annotate({
|
|
51
|
+
title: "Approved",
|
|
52
|
+
description: "A boolean checkbox included in the event payload."
|
|
53
|
+
}),
|
|
54
|
+
notes: Schema.optionalKey(
|
|
55
|
+
Schema.String.check(Schema.isMaxLength(80)).annotate({
|
|
56
|
+
title: "Notes",
|
|
57
|
+
description: "Optional text limited to eighty characters."
|
|
58
|
+
})
|
|
59
|
+
),
|
|
60
|
+
labels: Schema.optionalKey(Labels),
|
|
61
|
+
route: Schema.optionalKey(Route)
|
|
62
|
+
}) {}
|
|
63
|
+
class Cancel extends Schema.TaggedClass<Cancel>("PlannerCancel")("Cancel", { reason: Schema.String }) {}
|
|
64
|
+
class AutoFinish extends Schema.TaggedClass<AutoFinish>("PlannerAutoFinish")("AutoFinish", {}) {}
|
|
65
|
+
class Planned extends Schema.TaggedClass<Planned>("PlannerPlanned")("Planned", { job: Schema.String }) {}
|
|
66
|
+
|
|
67
|
+
const Events = Machine.events(Begin, Cancel)
|
|
68
|
+
const InternalEvents = Machine.internalEvents(AutoFinish)
|
|
69
|
+
const Emissions = Machine.emittedEvents(Planned)
|
|
70
|
+
const States = Machine.states({
|
|
71
|
+
Idle,
|
|
72
|
+
Working,
|
|
73
|
+
Finished: { schema: Finished, type: "final", output: Schema.String }
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
export const plannerMachine = Machine.make({
|
|
77
|
+
id: "planner-example",
|
|
78
|
+
states: States.states,
|
|
79
|
+
events: Events,
|
|
80
|
+
internalEvents: InternalEvents,
|
|
81
|
+
emittedEvents: Emissions,
|
|
82
|
+
input: Schema.Struct({
|
|
83
|
+
owner: Owner,
|
|
84
|
+
attempts: Attempts,
|
|
85
|
+
notifications: Schema.Boolean.annotate({
|
|
86
|
+
title: "Notifications",
|
|
87
|
+
description: "A required boolean with false as a valid value."
|
|
88
|
+
}),
|
|
89
|
+
mode: Schema.Literals(["guided", "automatic"]).annotate({
|
|
90
|
+
title: "Mode",
|
|
91
|
+
description: "A fixed set of startup modes."
|
|
92
|
+
}),
|
|
93
|
+
note: Schema.optionalKey(
|
|
94
|
+
Schema.String.check(Schema.isMaxLength(40)).annotate({
|
|
95
|
+
title: "Note",
|
|
96
|
+
description: "Optional startup text limited to forty characters."
|
|
97
|
+
})
|
|
98
|
+
),
|
|
99
|
+
labels: Schema.optionalKey(Labels),
|
|
100
|
+
preferences: Schema.optionalKey(
|
|
101
|
+
Schema.Struct({
|
|
102
|
+
retries: Schema.Int.check(Schema.isBetween({ minimum: 0, maximum: 3 })).annotate({
|
|
103
|
+
title: "Retries"
|
|
104
|
+
}),
|
|
105
|
+
dryRun: Schema.Boolean.annotate({ title: "Dry run" })
|
|
106
|
+
}).annotate({
|
|
107
|
+
title: "Preferences",
|
|
108
|
+
description: "An optional nested object."
|
|
109
|
+
})
|
|
110
|
+
)
|
|
111
|
+
}),
|
|
112
|
+
initial: (to) => to.Idle().resolve(({ input, target }) => target.decoded(new Idle({ owner: input.owner })))
|
|
113
|
+
}).handle({
|
|
114
|
+
Idle: {
|
|
115
|
+
on: {
|
|
116
|
+
Begin: (to) =>
|
|
117
|
+
to.branches({
|
|
118
|
+
urgent: { title: "Finish immediately", target: to.full.Working() },
|
|
119
|
+
normal: { title: "Wait in working", target: to.full.Working() }
|
|
120
|
+
}).resolve(({ event, self, select, state }, enqueue) => {
|
|
121
|
+
enqueue.emit(new Planned({ job: event.job }))
|
|
122
|
+
enqueue.sendTo(self, Events.Cancel({ reason: "planner command example" }))
|
|
123
|
+
if (event.priority === "urgent") enqueue.raise(InternalEvents.AutoFinish())
|
|
124
|
+
const working = new Working({ owner: state.owner, job: event.job })
|
|
125
|
+
return event.priority === "urgent"
|
|
126
|
+
? select.urgent.decoded(working)
|
|
127
|
+
: select.normal.decoded(working)
|
|
128
|
+
})
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
Working: {
|
|
132
|
+
invoke: (from) => from.effect("monitor-job", () => Effect.never),
|
|
133
|
+
on: {
|
|
134
|
+
AutoFinish: (to) =>
|
|
135
|
+
to.full.Finished().resolve(({ state, target }) => target.decoded(new Finished({ job: state.job }))),
|
|
136
|
+
Cancel: (to) =>
|
|
137
|
+
to.full.Idle().resolve(({ event, state, target }) =>
|
|
138
|
+
target.decoded(new Idle({ owner: `${state.owner} · ${event.reason}` }))
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
Finished: {
|
|
143
|
+
output: ({ state }) => state.job
|
|
144
|
+
}
|
|
145
|
+
})
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { Machine } from "@typeonce/effect-machine"
|
|
2
|
+
import { Schema } from "effect"
|
|
3
|
+
|
|
4
|
+
class ChildProgress extends Schema.TaggedClass<ChildProgress>("ProtocolChildProgress")("ChildProgress", {
|
|
5
|
+
percent: Schema.Number
|
|
6
|
+
}) {}
|
|
7
|
+
class ChildFinished extends Schema.TaggedClass<ChildFinished>("ProtocolChildFinished")("ChildFinished", {
|
|
8
|
+
result: Schema.String
|
|
9
|
+
}) {}
|
|
10
|
+
class ChildProblem extends Schema.TaggedClass<ChildProblem>("ProtocolChildProblem")("ChildProblem", {
|
|
11
|
+
message: Schema.String
|
|
12
|
+
}) {}
|
|
13
|
+
|
|
14
|
+
const ParentEvents = Machine.events(ChildProgress, ChildFinished, ChildProblem)
|
|
15
|
+
|
|
16
|
+
class ChildIdle extends Schema.TaggedClass<ChildIdle>("ProtocolChildIdle")("Idle", {}) {}
|
|
17
|
+
class ChildWorking extends Schema.TaggedClass<ChildWorking>("ProtocolChildWorking")("Working", {
|
|
18
|
+
job: Schema.String,
|
|
19
|
+
progress: Schema.Number
|
|
20
|
+
}) {}
|
|
21
|
+
class ChildDone extends Schema.TaggedClass<ChildDone>("ProtocolChildDone")("Done", {
|
|
22
|
+
result: Schema.String
|
|
23
|
+
}) {}
|
|
24
|
+
class ChildCancelled extends Schema.TaggedClass<ChildCancelled>("ProtocolChildCancelled")("Cancelled", {
|
|
25
|
+
reason: Schema.String
|
|
26
|
+
}) {}
|
|
27
|
+
|
|
28
|
+
class BeginChildWork extends Schema.TaggedClass<BeginChildWork>("ProtocolBeginChildWork")("BeginChildWork", {
|
|
29
|
+
job: Schema.String
|
|
30
|
+
}) {}
|
|
31
|
+
class CancelChildWork extends Schema.TaggedClass<CancelChildWork>("ProtocolCancelChildWork")(
|
|
32
|
+
"CancelChildWork",
|
|
33
|
+
{ reason: Schema.String }
|
|
34
|
+
) {}
|
|
35
|
+
class Heartbeat extends Schema.TaggedClass<Heartbeat>("ProtocolHeartbeat")("Heartbeat", {
|
|
36
|
+
percent: Schema.Number
|
|
37
|
+
}) {}
|
|
38
|
+
class CommitChildWork extends Schema.TaggedClass<CommitChildWork>("ProtocolCommitChildWork")(
|
|
39
|
+
"CommitChildWork",
|
|
40
|
+
{}
|
|
41
|
+
) {}
|
|
42
|
+
class ChildTrace extends Schema.TaggedClass<ChildTrace>("ProtocolChildTrace")("ChildTrace", {
|
|
43
|
+
message: Schema.String
|
|
44
|
+
}) {}
|
|
45
|
+
|
|
46
|
+
const ChildEvents = Machine.events(BeginChildWork, CancelChildWork)
|
|
47
|
+
const ChildInternalEvents = Machine.internalEvents(Heartbeat, CommitChildWork)
|
|
48
|
+
const ChildEmissions = Machine.emittedEvents(ChildTrace)
|
|
49
|
+
const ChildStates = Machine.states({
|
|
50
|
+
Idle: ChildIdle,
|
|
51
|
+
Working: ChildWorking,
|
|
52
|
+
Done: { schema: ChildDone, type: "final", output: Schema.String },
|
|
53
|
+
Cancelled: { schema: ChildCancelled, type: "final", output: Schema.String }
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
export const requiredParentChildMachine = Machine.make({
|
|
57
|
+
id: "required-parent-child",
|
|
58
|
+
states: ChildStates.states,
|
|
59
|
+
events: ChildEvents,
|
|
60
|
+
internalEvents: ChildInternalEvents,
|
|
61
|
+
emittedEvents: ChildEmissions,
|
|
62
|
+
parent: Machine.parent(ParentEvents),
|
|
63
|
+
initial: (to) => to.Idle().resolve(({ target }) => target.decoded(new ChildIdle({})))
|
|
64
|
+
}).handle({
|
|
65
|
+
Idle: {
|
|
66
|
+
on: {
|
|
67
|
+
BeginChildWork: (to) =>
|
|
68
|
+
to.full.Working().resolve(({ event, target }, enqueue) => {
|
|
69
|
+
enqueue.raise(ChildInternalEvents.Heartbeat({ percent: 25 }))
|
|
70
|
+
enqueue.emit(ChildEmissions.ChildTrace({ message: `started ${event.job}` }))
|
|
71
|
+
return target.decoded(new ChildWorking({ job: event.job, progress: 0 }))
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
Working: {
|
|
76
|
+
invoke: (from) =>
|
|
77
|
+
from.effect(
|
|
78
|
+
"report-progress-to-parent",
|
|
79
|
+
({ parent, state }) => parent.send(ParentEvents.ChildProgress({ percent: state.progress }))
|
|
80
|
+
).onDone((to) => to.none).onFailure((to) =>
|
|
81
|
+
to.full.Cancelled().resolve(({ error, target }) =>
|
|
82
|
+
target.decoded(new ChildCancelled({ reason: String(error) }))
|
|
83
|
+
)
|
|
84
|
+
),
|
|
85
|
+
on: {
|
|
86
|
+
Heartbeat: (to) =>
|
|
87
|
+
to.full.Working().resolve(({ event, state, target }, enqueue) => {
|
|
88
|
+
enqueue.raise(ChildInternalEvents.CommitChildWork())
|
|
89
|
+
return target.decoded(new ChildWorking({ job: state.job, progress: event.percent }))
|
|
90
|
+
}),
|
|
91
|
+
CommitChildWork: (to) =>
|
|
92
|
+
to.full.Done().resolve(({ state, target }) =>
|
|
93
|
+
target.decoded(new ChildDone({ result: `${state.job}:complete` }))
|
|
94
|
+
),
|
|
95
|
+
CancelChildWork: (to) =>
|
|
96
|
+
to.full.Cancelled().resolve(({ event, target }) => target.decoded(new ChildCancelled({ reason: event.reason })))
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
Done: {
|
|
100
|
+
output: ({ state }) => state.result
|
|
101
|
+
},
|
|
102
|
+
Cancelled: {
|
|
103
|
+
output: ({ state }) => state.reason
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
const ProtocolChild = Machine.child("protocol-child", requiredParentChildMachine)
|
|
108
|
+
|
|
109
|
+
class ParentIdle extends Schema.TaggedClass<ParentIdle>("ProtocolParentIdle")("Idle", {}) {}
|
|
110
|
+
class Supervising extends Schema.TaggedClass<Supervising>("ProtocolSupervising")("Supervising", {
|
|
111
|
+
latestProgress: Schema.Number
|
|
112
|
+
}) {}
|
|
113
|
+
class ParentComplete extends Schema.TaggedClass<ParentComplete>("ProtocolParentComplete")("Complete", {
|
|
114
|
+
result: Schema.String
|
|
115
|
+
}) {}
|
|
116
|
+
class ParentFailed extends Schema.TaggedClass<ParentFailed>("ProtocolParentFailed")("Failed", {
|
|
117
|
+
message: Schema.String
|
|
118
|
+
}) {}
|
|
119
|
+
class LaunchChild extends Schema.TaggedClass<LaunchChild>("ProtocolLaunchChild")("LaunchChild", {}) {}
|
|
120
|
+
class ResetParent extends Schema.TaggedClass<ResetParent>("ProtocolResetParent")("ResetParent", {}) {}
|
|
121
|
+
|
|
122
|
+
const ParentStates = Machine.states({
|
|
123
|
+
Idle: ParentIdle,
|
|
124
|
+
Supervising,
|
|
125
|
+
Complete: { schema: ParentComplete, type: "final", output: Schema.String },
|
|
126
|
+
Failed: ParentFailed
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
export const parentProtocolMachine = Machine.make({
|
|
130
|
+
id: "parent-child-protocol",
|
|
131
|
+
states: ParentStates.states,
|
|
132
|
+
events: Machine.events(LaunchChild, ResetParent, ParentEvents),
|
|
133
|
+
initial: (to) => to.Idle().resolve(({ target }) => target.decoded(new ParentIdle({})))
|
|
134
|
+
}).handle({
|
|
135
|
+
Idle: {
|
|
136
|
+
on: {
|
|
137
|
+
LaunchChild: (to) =>
|
|
138
|
+
to.full.Supervising().resolve(({ target }) => target.decoded(new Supervising({ latestProgress: 0 })))
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
Supervising: {
|
|
142
|
+
invoke: (from) =>
|
|
143
|
+
from.child(ProtocolChild).onDone((to) =>
|
|
144
|
+
to.full.Complete().resolve(({ output, target }) => target.decoded(new ParentComplete({ result: output })))
|
|
145
|
+
).onFailure((to) =>
|
|
146
|
+
to.full.Failed().resolve(({ error, target }) => target.decoded(new ParentFailed({ message: String(error) })))
|
|
147
|
+
),
|
|
148
|
+
on: {
|
|
149
|
+
ChildProgress: (to) =>
|
|
150
|
+
to.full.Supervising().resolve(({ event, target }) =>
|
|
151
|
+
target.decoded(new Supervising({ latestProgress: event.percent }))
|
|
152
|
+
),
|
|
153
|
+
ChildFinished: (to) =>
|
|
154
|
+
to.full.Complete().resolve(({ event, target }) => target.decoded(new ParentComplete({ result: event.result }))),
|
|
155
|
+
ChildProblem: (to) =>
|
|
156
|
+
to.full.Failed().resolve(({ event, target }) => target.decoded(new ParentFailed({ message: event.message }))),
|
|
157
|
+
ResetParent: (to) => to.full.Idle().resolve(({ target }) => target.decoded(new ParentIdle({})))
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
Complete: {
|
|
161
|
+
output: ({ state }) => state.result
|
|
162
|
+
},
|
|
163
|
+
Failed: {
|
|
164
|
+
on: {
|
|
165
|
+
ResetParent: (to) => to.full.Idle().resolve(({ target }) => target.decoded(new ParentIdle({})))
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
class Detached extends Schema.TaggedClass<Detached>("OptionalParentDetached")("Detached", {}) {}
|
|
171
|
+
class Published extends Schema.TaggedClass<Published>("OptionalParentPublished")("Published", {
|
|
172
|
+
deliveredToParent: Schema.Boolean
|
|
173
|
+
}) {}
|
|
174
|
+
class PublishOutside extends Schema.TaggedClass<PublishOutside>("OptionalParentPublishOutside")(
|
|
175
|
+
"PublishOutside",
|
|
176
|
+
{ result: Schema.String }
|
|
177
|
+
) {}
|
|
178
|
+
|
|
179
|
+
const OptionalParentStates = Machine.states({ Detached, Published })
|
|
180
|
+
|
|
181
|
+
export const optionalParentMachine = Machine.make({
|
|
182
|
+
id: "optional-parent-protocol",
|
|
183
|
+
states: OptionalParentStates.states,
|
|
184
|
+
events: Machine.events(PublishOutside),
|
|
185
|
+
parent: Machine.optionalParent(ParentEvents),
|
|
186
|
+
initial: (to) => to.Detached().resolve(({ target }) => target.decoded(new Detached({})))
|
|
187
|
+
}).handle({
|
|
188
|
+
Detached: {
|
|
189
|
+
on: {
|
|
190
|
+
PublishOutside: (to) =>
|
|
191
|
+
to.full.Published().resolve(({ event, parent, target }, enqueue) => {
|
|
192
|
+
if (parent !== undefined) {
|
|
193
|
+
enqueue.sendTo(parent, ParentEvents.ChildFinished({ result: event.result }))
|
|
194
|
+
}
|
|
195
|
+
return target.decoded(new Published({ deliveredToParent: parent !== undefined }))
|
|
196
|
+
})
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
Published: {}
|
|
200
|
+
})
|