@typeonce/effect-machine-devtools 0.24.0 → 0.26.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 +13 -13
- package/dist/DevToolsProtocol.d.ts +66 -630
- package/dist/DevToolsProtocol.d.ts.map +1 -1
- package/dist/DevToolsProtocol.js +0 -190
- package/dist/DevToolsProtocol.js.map +1 -1
- package/dist/MachineDocument.d.ts +38 -18
- package/dist/MachineDocument.d.ts.map +1 -1
- package/dist/MachineDocument.js +14 -12
- package/dist/MachineDocument.js.map +1 -1
- package/dist/MachineRegistry.d.ts +22 -2
- 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/ProjectInspector.d.ts +0 -2
- package/dist/ProjectInspector.d.ts.map +1 -1
- package/dist/ProjectInspector.js.map +1 -1
- package/dist/client/assets/index-BsorPSDS.css +1 -0
- package/dist/client/assets/index-eiptehRd.js +37 -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.map +1 -1
- package/dist/internal/devServer.js +4 -64
- package/dist/internal/devServer.js.map +1 -1
- package/dist/internal/evaluationWorker.d.ts.map +1 -1
- package/dist/internal/evaluationWorker.js +7 -263
- package/dist/internal/evaluationWorker.js.map +1 -1
- package/dist/internal/machineDocument.d.ts.map +1 -1
- package/dist/internal/machineDocument.js +3 -1
- 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 +1 -11
- package/dist/internal/projectInspector.js.map +1 -1
- package/index.html +2 -2
- package/package.json +8 -7
- package/src/DevToolsProtocol.ts +0 -285
- package/src/MachineDocument.ts +21 -19
- package/src/MachineWalkthrough.ts +199 -0
- package/src/ProjectInspector.ts +0 -5
- package/src/index.ts +2 -2
- package/src/internal/browser/chart-layout-policy.ts +206 -0
- package/src/internal/browser/chart-layout.ts +686 -0
- package/src/internal/browser/chart-model.ts +244 -0
- package/src/internal/browser/chart-renderer.ts +774 -0
- package/src/internal/browser/example-machine.ts +15 -6
- package/src/internal/browser/input-form.ts +1 -418
- 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 +2 -0
- package/src/internal/browser/protocol-events-example.ts +200 -0
- package/src/internal/browser/styles.css +974 -342
- package/src/internal/browser/transition-semantics-example.ts +245 -0
- package/src/internal/browser/visualizer-analysis.ts +52 -0
- package/src/internal/browser/visualizer-app.ts +874 -706
- package/src/internal/browser/visualizer-model.ts +104 -0
- package/src/internal/devServer.ts +4 -82
- package/src/internal/evaluationWorker.ts +7 -371
- package/src/internal/machineDocument.ts +3 -1
- package/src/internal/machineWalkthrough.ts +355 -0
- package/src/internal/projectInspector.ts +3 -31
- 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-B49Tjawc.js +0 -14
- package/dist/client/assets/index-BKH0cOG2.css +0 -1
- 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/browser/simulation-client.ts +0 -20
- package/src/internal/machineSimulator.ts +0 -199
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { Machine } from "@typeonce/effect-machine"
|
|
2
|
+
import { Effect, Schema, Stream } from "effect"
|
|
3
|
+
|
|
4
|
+
class ChildWorking extends Schema.TaggedClass<ChildWorking>("InvokeGalleryChildWorking")("Working", {
|
|
5
|
+
task: Schema.String
|
|
6
|
+
}) {}
|
|
7
|
+
class ChildDone extends Schema.TaggedClass<ChildDone>("InvokeGalleryChildDone")("Done", {
|
|
8
|
+
result: Schema.String
|
|
9
|
+
}) {}
|
|
10
|
+
class FinishChild extends Schema.TaggedClass<FinishChild>("InvokeGalleryFinishChild")("FinishChild", {}) {}
|
|
11
|
+
|
|
12
|
+
const ChildStates = Machine.states({
|
|
13
|
+
Working: ChildWorking,
|
|
14
|
+
Done: { schema: ChildDone, type: "final", output: Schema.String }
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
export const invokeGalleryChildMachine = Machine.make({
|
|
18
|
+
id: "invoke-gallery-child",
|
|
19
|
+
states: ChildStates.states,
|
|
20
|
+
events: Machine.events(FinishChild),
|
|
21
|
+
initial: (to) => to.Working().resolve(({ target }) => target.decoded(new ChildWorking({ task: "render-preview" })))
|
|
22
|
+
}).handle({
|
|
23
|
+
Working: {
|
|
24
|
+
on: {
|
|
25
|
+
FinishChild: (to) =>
|
|
26
|
+
to.full.Done().resolve(({ state, target }) =>
|
|
27
|
+
target.decoded(new ChildDone({ result: `${state.task}:complete` }))
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
Done: {
|
|
32
|
+
output: ({ state }) => state.result
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const InvokedChild = Machine.child("preview-worker", invokeGalleryChildMachine)
|
|
37
|
+
|
|
38
|
+
class Gallery extends Schema.TaggedClass<Gallery>("InvokeGallery")("Gallery", {
|
|
39
|
+
selectedDemo: Schema.NullOr(Schema.String)
|
|
40
|
+
}) {}
|
|
41
|
+
class Choose extends Schema.TaggedClass<Choose>("InvokeGalleryChoose")("Choose", {}) {}
|
|
42
|
+
class LoadingDocument extends Schema.TaggedClass<LoadingDocument>("InvokeGalleryLoadingDocument")(
|
|
43
|
+
"LoadingDocument",
|
|
44
|
+
{ request: Schema.String }
|
|
45
|
+
) {}
|
|
46
|
+
class StreamingUpdates extends Schema.TaggedClass<StreamingUpdates>("InvokeGalleryStreamingUpdates")(
|
|
47
|
+
"StreamingUpdates",
|
|
48
|
+
{ values: Schema.Array(Schema.Number) }
|
|
49
|
+
) {}
|
|
50
|
+
class WaitingForTimeout extends Schema.TaggedClass<WaitingForTimeout>("InvokeGalleryWaitingForTimeout")(
|
|
51
|
+
"WaitingForTimeout",
|
|
52
|
+
{ delay: Schema.Literal("2 seconds") }
|
|
53
|
+
) {}
|
|
54
|
+
class WatchingProcess extends Schema.TaggedClass<WatchingProcess>("InvokeGalleryWatchingProcess")(
|
|
55
|
+
"WatchingProcess",
|
|
56
|
+
{ revision: Schema.Number }
|
|
57
|
+
) {}
|
|
58
|
+
class RunningChild extends Schema.TaggedClass<RunningChild>("InvokeGalleryRunningChild")("RunningChild", {}) {}
|
|
59
|
+
class Completed extends Schema.TaggedClass<Completed>("InvokeGalleryCompleted")("Completed", {
|
|
60
|
+
source: Schema.String,
|
|
61
|
+
result: Schema.String
|
|
62
|
+
}) {}
|
|
63
|
+
class Failed extends Schema.TaggedClass<Failed>("InvokeGalleryFailed")("Failed", {
|
|
64
|
+
source: Schema.String,
|
|
65
|
+
message: Schema.String
|
|
66
|
+
}) {}
|
|
67
|
+
|
|
68
|
+
class RunEffect extends Schema.TaggedClass<RunEffect>("InvokeGalleryRunEffect")("RunEffect", {
|
|
69
|
+
request: Schema.String
|
|
70
|
+
}) {}
|
|
71
|
+
class RunStream extends Schema.TaggedClass<RunStream>("InvokeGalleryRunStream")("RunStream", {}) {}
|
|
72
|
+
class RunTimer extends Schema.TaggedClass<RunTimer>("InvokeGalleryRunTimer")("RunTimer", {}) {}
|
|
73
|
+
class RunProcess extends Schema.TaggedClass<RunProcess>("InvokeGalleryRunProcess")("RunProcess", {}) {}
|
|
74
|
+
class RunChild extends Schema.TaggedClass<RunChild>("InvokeGalleryRunChild")("RunChild", {}) {}
|
|
75
|
+
class Reset extends Schema.TaggedClass<Reset>("InvokeGalleryReset")("Reset", {}) {}
|
|
76
|
+
class StreamValue extends Schema.TaggedClass<StreamValue>("InvokeGalleryStreamValue")("StreamValue", {
|
|
77
|
+
value: Schema.Number
|
|
78
|
+
}) {}
|
|
79
|
+
|
|
80
|
+
const GalleryEvents = Machine.events(RunEffect, RunStream, RunTimer, RunProcess, RunChild, Reset)
|
|
81
|
+
const GalleryInternalEvents = Machine.internalEvents(StreamValue)
|
|
82
|
+
const processLogic = Machine.logic({
|
|
83
|
+
initial: "starting" as "starting" | "ready",
|
|
84
|
+
run: () => Effect.fail("process stopped")
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
const GalleryStates = Machine.states({
|
|
88
|
+
Gallery: {
|
|
89
|
+
schema: Gallery,
|
|
90
|
+
initial: "Choose",
|
|
91
|
+
states: {
|
|
92
|
+
Choose,
|
|
93
|
+
LoadingDocument,
|
|
94
|
+
StreamingUpdates,
|
|
95
|
+
WaitingForTimeout,
|
|
96
|
+
WatchingProcess,
|
|
97
|
+
RunningChild
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
Completed,
|
|
101
|
+
Failed
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
export const invokeOutcomesMachine = Machine.make({
|
|
105
|
+
id: "invoke-outcomes",
|
|
106
|
+
states: GalleryStates.states,
|
|
107
|
+
events: GalleryEvents,
|
|
108
|
+
internalEvents: GalleryInternalEvents,
|
|
109
|
+
initial: (to) =>
|
|
110
|
+
to.Gallery.initial.resolve(({ target }) =>
|
|
111
|
+
target.decoded(
|
|
112
|
+
new Gallery({ selectedDemo: null }),
|
|
113
|
+
(gallery) => gallery.Choose.decoded(new Choose({}))
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
}).handle({
|
|
117
|
+
Gallery: {
|
|
118
|
+
initialize: ({ builder }) => builder.decoded(new Choose({})),
|
|
119
|
+
on: {
|
|
120
|
+
Reset: (to) => to.local.Choose().resolve(({ target }) => target.decoded(new Choose({})))
|
|
121
|
+
},
|
|
122
|
+
states: {
|
|
123
|
+
Choose: {
|
|
124
|
+
on: {
|
|
125
|
+
RunEffect: (to) =>
|
|
126
|
+
to.local.LoadingDocument().resolve(({ event, target }) =>
|
|
127
|
+
target.decoded(new LoadingDocument({ request: event.request }))
|
|
128
|
+
),
|
|
129
|
+
RunStream: (to) =>
|
|
130
|
+
to.local.StreamingUpdates().resolve(({ target }) => target.decoded(new StreamingUpdates({ values: [] }))),
|
|
131
|
+
RunTimer: (to) =>
|
|
132
|
+
to.local.WaitingForTimeout().resolve(({ target }) =>
|
|
133
|
+
target.decoded(new WaitingForTimeout({ delay: "2 seconds" }))
|
|
134
|
+
),
|
|
135
|
+
RunProcess: (to) =>
|
|
136
|
+
to.local.WatchingProcess().resolve(({ target }) => target.decoded(new WatchingProcess({ revision: 1 }))),
|
|
137
|
+
RunChild: (to) => to.local.RunningChild().resolve(({ target }) => target.decoded(new RunningChild({})))
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
LoadingDocument: {
|
|
141
|
+
invoke: (from) =>
|
|
142
|
+
from.effect(
|
|
143
|
+
"load-document",
|
|
144
|
+
({ state }) =>
|
|
145
|
+
state.request === "fail" ? Effect.fail("document unavailable") : Effect.succeed("document loaded")
|
|
146
|
+
).onDone((to) =>
|
|
147
|
+
to.full.Completed().resolve(({ output, target }) =>
|
|
148
|
+
target.decoded(new Completed({ source: "effect", result: output }))
|
|
149
|
+
)
|
|
150
|
+
).onFailure((to) =>
|
|
151
|
+
to.full.Failed().resolve(({ error, target }) =>
|
|
152
|
+
target.decoded(new Failed({ source: "effect", message: error }))
|
|
153
|
+
)
|
|
154
|
+
)
|
|
155
|
+
},
|
|
156
|
+
StreamingUpdates: {
|
|
157
|
+
invoke: (from) =>
|
|
158
|
+
from.stream(
|
|
159
|
+
"document-updates",
|
|
160
|
+
() => Stream.fromIterable([1, 2, 3]).pipe(Stream.concat(Stream.fail("stream disconnected")))
|
|
161
|
+
).onElement((to) =>
|
|
162
|
+
to.none.resolve(({ element }, enqueue) => {
|
|
163
|
+
enqueue.raise(GalleryInternalEvents.StreamValue({ value: element }))
|
|
164
|
+
})
|
|
165
|
+
).onDone((to) =>
|
|
166
|
+
to.full.Completed().resolve(({ state, target }) =>
|
|
167
|
+
target.decoded(new Completed({ source: "stream", result: state.values.join(", ") }))
|
|
168
|
+
)
|
|
169
|
+
).onFailure((to) =>
|
|
170
|
+
to.full.Failed().resolve(({ error, target }) =>
|
|
171
|
+
target.decoded(new Failed({ source: "stream", message: error }))
|
|
172
|
+
)
|
|
173
|
+
),
|
|
174
|
+
on: {
|
|
175
|
+
StreamValue: (to) =>
|
|
176
|
+
to.local.StreamingUpdates().resolve(({ event, state, target }) =>
|
|
177
|
+
target.decoded(new StreamingUpdates({ values: [...state.values, event.value] }))
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
WaitingForTimeout: {
|
|
182
|
+
invoke: (from) =>
|
|
183
|
+
from.timer("request-timeout", "2 seconds").onDone((to) =>
|
|
184
|
+
to.full.Completed().resolve(({ target }) =>
|
|
185
|
+
target.decoded(new Completed({ source: "timer", result: "timeout elapsed" }))
|
|
186
|
+
)
|
|
187
|
+
)
|
|
188
|
+
},
|
|
189
|
+
WatchingProcess: {
|
|
190
|
+
invoke: (from) =>
|
|
191
|
+
from.logic("status-worker", {
|
|
192
|
+
address: Machine.childAddress("status-worker"),
|
|
193
|
+
logic: processLogic
|
|
194
|
+
}).onFailure((to) =>
|
|
195
|
+
to.full.Failed().resolve(({ error, target }) =>
|
|
196
|
+
target.decoded(new Failed({ source: "process", message: String(error) }))
|
|
197
|
+
)
|
|
198
|
+
).onSnapshot((to) =>
|
|
199
|
+
to.branches({
|
|
200
|
+
ready: { title: "Worker reports ready", target: to.full.Completed() },
|
|
201
|
+
waiting: { title: "Worker is still starting", target: to.none }
|
|
202
|
+
}).resolve(({ select, snapshot }) =>
|
|
203
|
+
snapshot.state === "ready"
|
|
204
|
+
? select.ready.decoded(new Completed({ source: "process", result: "ready" }))
|
|
205
|
+
: select.waiting()
|
|
206
|
+
)
|
|
207
|
+
)
|
|
208
|
+
},
|
|
209
|
+
RunningChild: {
|
|
210
|
+
invoke: (from) =>
|
|
211
|
+
from.child(InvokedChild).onDone((to) =>
|
|
212
|
+
to.full.Completed().resolve(({ output, target }) =>
|
|
213
|
+
target.decoded(new Completed({ source: "child machine", result: output }))
|
|
214
|
+
)
|
|
215
|
+
)
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
Completed: {
|
|
220
|
+
on: {
|
|
221
|
+
Reset: (to) =>
|
|
222
|
+
to.full.Gallery.initial.resolve(({ target }) => target.decoded(new Gallery({ selectedDemo: null })))
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
Failed: {
|
|
226
|
+
on: {
|
|
227
|
+
Reset: (to) =>
|
|
228
|
+
to.full.Gallery.initial.resolve(({ target }) => target.decoded(new Gallery({ selectedDemo: null })))
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
})
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { Machine } from "@typeonce/effect-machine"
|
|
2
|
+
import { Schema } from "effect"
|
|
3
|
+
|
|
4
|
+
class Cart extends Schema.TaggedClass<Cart>("ParallelCart")("Cart", {
|
|
5
|
+
items: Schema.Number
|
|
6
|
+
}) {}
|
|
7
|
+
class Order extends Schema.TaggedClass<Order>("ParallelOrder")("Order", {
|
|
8
|
+
orderId: Schema.String,
|
|
9
|
+
total: Schema.Number
|
|
10
|
+
}) {}
|
|
11
|
+
class Payment extends Schema.TaggedClass<Payment>("ParallelPayment")("Payment", {
|
|
12
|
+
attempts: Schema.Number
|
|
13
|
+
}) {}
|
|
14
|
+
class AwaitingAuthorization extends Schema.TaggedClass<AwaitingAuthorization>("ParallelAwaitingAuthorization")(
|
|
15
|
+
"AwaitingAuthorization",
|
|
16
|
+
{}
|
|
17
|
+
) {}
|
|
18
|
+
class Authorized extends Schema.TaggedClass<Authorized>("ParallelAuthorized")("Authorized", {
|
|
19
|
+
authorizationId: Schema.String
|
|
20
|
+
}) {}
|
|
21
|
+
class Fulfillment extends Schema.TaggedClass<Fulfillment>("ParallelFulfillment")("Fulfillment", {
|
|
22
|
+
warehouse: Schema.String
|
|
23
|
+
}) {}
|
|
24
|
+
class WaitingForPayment extends Schema.TaggedClass<WaitingForPayment>("ParallelWaitingForPayment")(
|
|
25
|
+
"WaitingForPayment",
|
|
26
|
+
{}
|
|
27
|
+
) {}
|
|
28
|
+
class Packing extends Schema.TaggedClass<Packing>("ParallelPacking")("Packing", {
|
|
29
|
+
packageCount: Schema.Number
|
|
30
|
+
}) {}
|
|
31
|
+
class Shipped extends Schema.TaggedClass<Shipped>("ParallelShipped")("Shipped", {
|
|
32
|
+
trackingCode: Schema.String
|
|
33
|
+
}) {}
|
|
34
|
+
class OrderComplete extends Schema.TaggedClass<OrderComplete>("ParallelOrderComplete")("OrderComplete", {
|
|
35
|
+
orderId: Schema.String
|
|
36
|
+
}) {}
|
|
37
|
+
class OrderCancelled extends Schema.TaggedClass<OrderCancelled>("ParallelOrderCancelled")(
|
|
38
|
+
"OrderCancelled",
|
|
39
|
+
{ reason: Schema.String }
|
|
40
|
+
) {}
|
|
41
|
+
|
|
42
|
+
class Checkout extends Schema.TaggedClass<Checkout>("ParallelCheckout")("Checkout", {
|
|
43
|
+
orderId: Schema.String,
|
|
44
|
+
total: Schema.Number
|
|
45
|
+
}) {}
|
|
46
|
+
class Authorize extends Schema.TaggedClass<Authorize>("ParallelAuthorize")("Authorize", {
|
|
47
|
+
authorizationId: Schema.String
|
|
48
|
+
}) {}
|
|
49
|
+
class DeclinePayment extends Schema.TaggedClass<DeclinePayment>("ParallelDeclinePayment")(
|
|
50
|
+
"DeclinePayment",
|
|
51
|
+
{ reason: Schema.String }
|
|
52
|
+
) {}
|
|
53
|
+
class Pack extends Schema.TaggedClass<Pack>("ParallelPack")("Pack", { packages: Schema.Number }) {}
|
|
54
|
+
class Ship extends Schema.TaggedClass<Ship>("ParallelShip")("Ship", { trackingCode: Schema.String }) {}
|
|
55
|
+
class CompleteAll extends Schema.TaggedClass<CompleteAll>("ParallelCompleteAll")("CompleteAll", {
|
|
56
|
+
authorizationId: Schema.String,
|
|
57
|
+
trackingCode: Schema.String
|
|
58
|
+
}) {}
|
|
59
|
+
class CancelOrder extends Schema.TaggedClass<CancelOrder>("ParallelCancelOrder")("CancelOrder", {
|
|
60
|
+
reason: Schema.String
|
|
61
|
+
}) {}
|
|
62
|
+
class RetryOrder extends Schema.TaggedClass<RetryOrder>("ParallelRetryOrder")("RetryOrder", {}) {}
|
|
63
|
+
class AutoShip extends Schema.TaggedClass<AutoShip>("ParallelAutoShip")("AutoShip", {}) {}
|
|
64
|
+
|
|
65
|
+
const ParallelInternalEvents = Machine.internalEvents(AutoShip)
|
|
66
|
+
const ParallelStates = Machine.states({
|
|
67
|
+
Cart,
|
|
68
|
+
Order: {
|
|
69
|
+
schema: Order,
|
|
70
|
+
type: "parallel",
|
|
71
|
+
states: {
|
|
72
|
+
payment: {
|
|
73
|
+
schema: Payment,
|
|
74
|
+
initial: "AwaitingAuthorization",
|
|
75
|
+
states: {
|
|
76
|
+
AwaitingAuthorization,
|
|
77
|
+
Authorized: { schema: Authorized, type: "final" }
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
fulfillment: {
|
|
81
|
+
schema: Fulfillment,
|
|
82
|
+
initial: "WaitingForPayment",
|
|
83
|
+
states: {
|
|
84
|
+
WaitingForPayment,
|
|
85
|
+
Packing,
|
|
86
|
+
Shipped: { schema: Shipped, type: "final" }
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
Complete: { schema: OrderComplete, type: "final", output: Schema.String },
|
|
92
|
+
Cancelled: OrderCancelled
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
export const parallelCompletionMachine = Machine.make({
|
|
96
|
+
id: "parallel-completion",
|
|
97
|
+
states: ParallelStates.states,
|
|
98
|
+
events: Machine.events(
|
|
99
|
+
Checkout,
|
|
100
|
+
Authorize,
|
|
101
|
+
DeclinePayment,
|
|
102
|
+
Pack,
|
|
103
|
+
Ship,
|
|
104
|
+
CompleteAll,
|
|
105
|
+
CancelOrder,
|
|
106
|
+
RetryOrder
|
|
107
|
+
),
|
|
108
|
+
internalEvents: ParallelInternalEvents,
|
|
109
|
+
initial: (to) => to.Cart().resolve(({ target }) => target.decoded(new Cart({ items: 2 })))
|
|
110
|
+
}).handle({
|
|
111
|
+
Cart: {
|
|
112
|
+
on: {
|
|
113
|
+
Checkout: (to) =>
|
|
114
|
+
to.full.Order.initial.resolve(({ event, target }) =>
|
|
115
|
+
target.decoded(new Order({ orderId: event.orderId, total: event.total }))
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
Order: {
|
|
120
|
+
initialize: ({ builder }) => builder.payment.from({ attempts: 0 }).fulfillment.from({ warehouse: "north" }),
|
|
121
|
+
on: {
|
|
122
|
+
CancelOrder: (to) =>
|
|
123
|
+
to.full.Cancelled().resolve(({ event, target }) => target.decoded(new OrderCancelled({ reason: event.reason })))
|
|
124
|
+
},
|
|
125
|
+
onDone: (to) =>
|
|
126
|
+
to.full.Complete().resolve(({ target }) => target.decoded(new OrderComplete({ orderId: "completed-order" }))),
|
|
127
|
+
states: {
|
|
128
|
+
payment: {
|
|
129
|
+
initialize: ({ builder }) => builder.from(),
|
|
130
|
+
states: {
|
|
131
|
+
AwaitingAuthorization: {
|
|
132
|
+
on: {
|
|
133
|
+
Authorize: (to) =>
|
|
134
|
+
to.local.Authorized().resolve(({ event, target }) =>
|
|
135
|
+
target.decoded(new Authorized({ authorizationId: event.authorizationId }))
|
|
136
|
+
),
|
|
137
|
+
CompleteAll: (to) =>
|
|
138
|
+
to.local.Authorized().resolve(({ event, target }) =>
|
|
139
|
+
target.decoded(new Authorized({ authorizationId: event.authorizationId }))
|
|
140
|
+
),
|
|
141
|
+
DeclinePayment: (to) =>
|
|
142
|
+
to.full.Cancelled().resolve(({ event, target }) =>
|
|
143
|
+
target.decoded(new OrderCancelled({ reason: event.reason }))
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
fulfillment: {
|
|
150
|
+
initialize: ({ builder }) => builder.from(),
|
|
151
|
+
states: {
|
|
152
|
+
WaitingForPayment: {
|
|
153
|
+
on: {
|
|
154
|
+
Authorize: (to) =>
|
|
155
|
+
to.local.Packing().resolve(({ target }) => target.decoded(new Packing({ packageCount: 1 }))),
|
|
156
|
+
Pack: (to) =>
|
|
157
|
+
to.local.Packing().resolve(({ event, target }) =>
|
|
158
|
+
target.decoded(new Packing({ packageCount: event.packages }))
|
|
159
|
+
),
|
|
160
|
+
CompleteAll: (to) =>
|
|
161
|
+
to.local.Shipped().resolve(({ event, target }) =>
|
|
162
|
+
target.decoded(new Shipped({ trackingCode: event.trackingCode }))
|
|
163
|
+
)
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
Packing: {
|
|
167
|
+
invoke: (from) =>
|
|
168
|
+
from.timer("packing-sla", "5 seconds").onDone((to) =>
|
|
169
|
+
to.none.resolve((_, enqueue) => {
|
|
170
|
+
enqueue.raise(ParallelInternalEvents.AutoShip())
|
|
171
|
+
})
|
|
172
|
+
),
|
|
173
|
+
on: {
|
|
174
|
+
AutoShip: (to) =>
|
|
175
|
+
to.local.Shipped().resolve(({ target }) => target.decoded(new Shipped({ trackingCode: "automatic" }))),
|
|
176
|
+
Ship: (to) =>
|
|
177
|
+
to.local.Shipped().resolve(({ event, target }) =>
|
|
178
|
+
target.decoded(new Shipped({ trackingCode: event.trackingCode }))
|
|
179
|
+
),
|
|
180
|
+
CompleteAll: (to) =>
|
|
181
|
+
to.local.Shipped().resolve(({ event, target }) =>
|
|
182
|
+
target.decoded(new Shipped({ trackingCode: event.trackingCode }))
|
|
183
|
+
)
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
Complete: {
|
|
191
|
+
output: ({ state }) => state.orderId
|
|
192
|
+
},
|
|
193
|
+
Cancelled: {
|
|
194
|
+
on: {
|
|
195
|
+
RetryOrder: (to) =>
|
|
196
|
+
to.full.Order.initial.resolve(({ target }) => target.decoded(new Order({ orderId: "retry", total: 0 })))
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Machine } from "@typeonce/effect-machine"
|
|
2
2
|
import { Schema } from "effect"
|
|
3
|
+
import * as Effect from "effect/Effect"
|
|
3
4
|
|
|
4
5
|
class Idle extends Schema.TaggedClass<Idle>("PlannerIdle")("Idle", { owner: Schema.String }) {}
|
|
5
6
|
class Working extends Schema.TaggedClass<Working>("PlannerWorking")("Working", {
|
|
@@ -128,6 +129,7 @@ export const plannerMachine = Machine.make({
|
|
|
128
129
|
}
|
|
129
130
|
},
|
|
130
131
|
Working: {
|
|
132
|
+
invoke: (from) => from.effect("monitor-job", () => Effect.never),
|
|
131
133
|
on: {
|
|
132
134
|
AutoFinish: (to) =>
|
|
133
135
|
to.full.Finished().resolve(({ state, target }) => target.decoded(new Finished({ job: state.job }))),
|
|
@@ -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
|
+
})
|