@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.
Files changed (82) hide show
  1. package/NOTICE +4 -0
  2. package/README.md +13 -13
  3. package/dist/DevToolsProtocol.d.ts +66 -630
  4. package/dist/DevToolsProtocol.d.ts.map +1 -1
  5. package/dist/DevToolsProtocol.js +0 -190
  6. package/dist/DevToolsProtocol.js.map +1 -1
  7. package/dist/MachineDocument.d.ts +38 -18
  8. package/dist/MachineDocument.d.ts.map +1 -1
  9. package/dist/MachineDocument.js +14 -12
  10. package/dist/MachineDocument.js.map +1 -1
  11. package/dist/MachineRegistry.d.ts +22 -2
  12. package/dist/MachineRegistry.d.ts.map +1 -1
  13. package/dist/MachineWalkthrough.d.ts +171 -0
  14. package/dist/MachineWalkthrough.d.ts.map +1 -0
  15. package/dist/MachineWalkthrough.js +98 -0
  16. package/dist/MachineWalkthrough.js.map +1 -0
  17. package/dist/ProjectInspector.d.ts +0 -2
  18. package/dist/ProjectInspector.d.ts.map +1 -1
  19. package/dist/ProjectInspector.js.map +1 -1
  20. package/dist/client/assets/index-BsorPSDS.css +1 -0
  21. package/dist/client/assets/index-eiptehRd.js +37 -0
  22. package/dist/client/index.html +4 -4
  23. package/dist/index.d.ts +2 -2
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +2 -2
  26. package/dist/index.js.map +1 -1
  27. package/dist/internal/devServer.d.ts.map +1 -1
  28. package/dist/internal/devServer.js +4 -64
  29. package/dist/internal/devServer.js.map +1 -1
  30. package/dist/internal/evaluationWorker.d.ts.map +1 -1
  31. package/dist/internal/evaluationWorker.js +7 -263
  32. package/dist/internal/evaluationWorker.js.map +1 -1
  33. package/dist/internal/machineDocument.d.ts.map +1 -1
  34. package/dist/internal/machineDocument.js +3 -1
  35. package/dist/internal/machineDocument.js.map +1 -1
  36. package/dist/internal/machineWalkthrough.d.ts +26 -0
  37. package/dist/internal/machineWalkthrough.d.ts.map +1 -0
  38. package/dist/internal/machineWalkthrough.js +256 -0
  39. package/dist/internal/machineWalkthrough.js.map +1 -0
  40. package/dist/internal/projectInspector.d.ts.map +1 -1
  41. package/dist/internal/projectInspector.js +1 -11
  42. package/dist/internal/projectInspector.js.map +1 -1
  43. package/index.html +2 -2
  44. package/package.json +8 -7
  45. package/src/DevToolsProtocol.ts +0 -285
  46. package/src/MachineDocument.ts +21 -19
  47. package/src/MachineWalkthrough.ts +199 -0
  48. package/src/ProjectInspector.ts +0 -5
  49. package/src/index.ts +2 -2
  50. package/src/internal/browser/chart-layout-policy.ts +206 -0
  51. package/src/internal/browser/chart-layout.ts +686 -0
  52. package/src/internal/browser/chart-model.ts +244 -0
  53. package/src/internal/browser/chart-renderer.ts +774 -0
  54. package/src/internal/browser/example-machine.ts +15 -6
  55. package/src/internal/browser/input-form.ts +1 -418
  56. package/src/internal/browser/invoke-outcomes-example.ts +231 -0
  57. package/src/internal/browser/parallel-completion-example.ts +199 -0
  58. package/src/internal/browser/planner-example.ts +2 -0
  59. package/src/internal/browser/protocol-events-example.ts +200 -0
  60. package/src/internal/browser/styles.css +974 -342
  61. package/src/internal/browser/transition-semantics-example.ts +245 -0
  62. package/src/internal/browser/visualizer-analysis.ts +52 -0
  63. package/src/internal/browser/visualizer-app.ts +874 -706
  64. package/src/internal/browser/visualizer-model.ts +104 -0
  65. package/src/internal/devServer.ts +4 -82
  66. package/src/internal/evaluationWorker.ts +7 -371
  67. package/src/internal/machineDocument.ts +3 -1
  68. package/src/internal/machineWalkthrough.ts +355 -0
  69. package/src/internal/projectInspector.ts +3 -31
  70. package/dist/MachineSimulator.d.ts +0 -169
  71. package/dist/MachineSimulator.d.ts.map +0 -1
  72. package/dist/MachineSimulator.js +0 -98
  73. package/dist/MachineSimulator.js.map +0 -1
  74. package/dist/client/assets/index-B49Tjawc.js +0 -14
  75. package/dist/client/assets/index-BKH0cOG2.css +0 -1
  76. package/dist/internal/machineSimulator.d.ts +0 -5
  77. package/dist/internal/machineSimulator.d.ts.map +0 -1
  78. package/dist/internal/machineSimulator.js +0 -156
  79. package/dist/internal/machineSimulator.js.map +0 -1
  80. package/src/MachineSimulator.ts +0 -154
  81. package/src/internal/browser/simulation-client.ts +0 -20
  82. package/src/internal/machineSimulator.ts +0 -199
@@ -0,0 +1,245 @@
1
+ import { Machine } from "@typeonce/effect-machine"
2
+ import { Schema } from "effect"
3
+
4
+ class Workspace extends Schema.TaggedClass<Workspace>("TransitionWorkspace")("Workspace", {
5
+ revision: Schema.Number,
6
+ preferredRoute: Schema.Literals(["draft", "review"])
7
+ }) {}
8
+ class Draft extends Schema.TaggedClass<Draft>("TransitionDraft")("Draft", {
9
+ text: Schema.String,
10
+ autosaves: Schema.Number
11
+ }) {}
12
+ class AutoSaving extends Schema.TaggedClass<AutoSaving>("TransitionAutoSaving")("AutoSaving", {}) {}
13
+ class Review extends Schema.TaggedClass<Review>("TransitionReview")("Review", {
14
+ requestedBy: Schema.String
15
+ }) {}
16
+ class Checking extends Schema.TaggedClass<Checking>("TransitionChecking")("Checking", {
17
+ checks: Schema.Array(Schema.String)
18
+ }) {}
19
+ class ChangesRequested extends Schema.TaggedClass<ChangesRequested>("TransitionChangesRequested")(
20
+ "ChangesRequested",
21
+ { reason: Schema.String }
22
+ ) {}
23
+ class Approved extends Schema.TaggedClass<Approved>("TransitionApproved")("Approved", {
24
+ reviewer: Schema.String
25
+ }) {}
26
+ class WorkspaceFinished extends Schema.TaggedClass<WorkspaceFinished>("TransitionWorkspaceFinished")(
27
+ "Finished",
28
+ { result: Schema.String }
29
+ ) {}
30
+ class Paused extends Schema.TaggedClass<Paused>("TransitionPaused")("Paused", {
31
+ reason: Schema.String
32
+ }) {}
33
+ class Published extends Schema.TaggedClass<Published>("TransitionPublished")("Published", {
34
+ result: Schema.String
35
+ }) {}
36
+ class Disabled extends Schema.TaggedClass<Disabled>("TransitionDisabled")("Disabled", {
37
+ reason: Schema.String
38
+ }) {}
39
+
40
+ class Create extends Schema.TaggedClass<Create>("TransitionCreate")("Create", {
41
+ text: Schema.String,
42
+ route: Schema.Literals(["draft", "review"])
43
+ }) {}
44
+ class Edit extends Schema.TaggedClass<Edit>("TransitionEdit")("Edit", { text: Schema.String }) {}
45
+ class Save extends Schema.TaggedClass<Save>("TransitionSave")("Save", {}) {}
46
+ class Submit extends Schema.TaggedClass<Submit>("TransitionSubmit")("Submit", {
47
+ mode: Schema.Literals(["review", "publish"]),
48
+ requestedBy: Schema.String
49
+ }) {}
50
+ class Approve extends Schema.TaggedClass<Approve>("TransitionApprove")("Approve", {
51
+ reviewer: Schema.String
52
+ }) {}
53
+ class Reject extends Schema.TaggedClass<Reject>("TransitionReject")("Reject", {
54
+ reason: Schema.String
55
+ }) {}
56
+ class Revise extends Schema.TaggedClass<Revise>("TransitionRevise")("Revise", {}) {}
57
+ class Pause extends Schema.TaggedClass<Pause>("TransitionPause")("Pause", { reason: Schema.String }) {}
58
+ class ResumeShallow extends Schema.TaggedClass<ResumeShallow>("TransitionResumeShallow")(
59
+ "ResumeShallow",
60
+ {}
61
+ ) {}
62
+ class ResumeDeep extends Schema.TaggedClass<ResumeDeep>("TransitionResumeDeep")("ResumeDeep", {}) {}
63
+ class Restart extends Schema.TaggedClass<Restart>("TransitionRestart")("Restart", {}) {}
64
+ class Refresh extends Schema.TaggedClass<Refresh>("TransitionRefresh")("Refresh", {}) {}
65
+ class Ignore extends Schema.TaggedClass<Ignore>("TransitionIgnore")("Ignore", {}) {}
66
+ class MaybeHandle extends Schema.TaggedClass<MaybeHandle>("TransitionMaybeHandle")("MaybeHandle", {
67
+ accept: Schema.Boolean
68
+ }) {}
69
+ class BumpWorkspace extends Schema.TaggedClass<BumpWorkspace>("TransitionBumpWorkspace")(
70
+ "BumpWorkspace",
71
+ {}
72
+ ) {}
73
+ class Archive extends Schema.TaggedClass<Archive>("TransitionArchive")("Archive", {
74
+ reason: Schema.String
75
+ }) {}
76
+
77
+ const TransitionStates = Machine.states({
78
+ Workspace: {
79
+ schema: Workspace,
80
+ initial: "Routing",
81
+ states: {
82
+ Routing: { type: "choice" },
83
+ Draft,
84
+ AutoSaving,
85
+ Review: {
86
+ schema: Review,
87
+ initial: "Checking",
88
+ states: {
89
+ Checking,
90
+ ChangesRequested,
91
+ Approved: { schema: Approved, type: "final" }
92
+ }
93
+ },
94
+ Finished: { schema: WorkspaceFinished, type: "final" },
95
+ recent: { type: "history" },
96
+ exact: { type: "history", history: "deep" }
97
+ }
98
+ },
99
+ Paused,
100
+ Disabled,
101
+ Published: { schema: Published, type: "final", output: Schema.String }
102
+ })
103
+
104
+ const defaultWorkspaceSnapshot = () => ({
105
+ path: "Workspace" as const,
106
+ value: new Workspace({ revision: 0, preferredRoute: "draft" as const }),
107
+ state: {
108
+ path: "Workspace.Draft" as const,
109
+ value: new Draft({ text: "Recovered draft", autosaves: 0 })
110
+ }
111
+ })
112
+
113
+ export const transitionSemanticsMachine = Machine.make({
114
+ id: "transition-semantics",
115
+ states: TransitionStates.states,
116
+ events: Machine.events(
117
+ Create,
118
+ Edit,
119
+ Save,
120
+ Submit,
121
+ Approve,
122
+ Reject,
123
+ Revise,
124
+ Pause,
125
+ ResumeShallow,
126
+ ResumeDeep,
127
+ Restart,
128
+ Refresh,
129
+ Ignore,
130
+ MaybeHandle,
131
+ BumpWorkspace,
132
+ Archive
133
+ ),
134
+ initial: (to) => to.Paused().resolve(({ target }) => target.decoded(new Paused({ reason: "not started" })))
135
+ }).handle({
136
+ Workspace: {
137
+ history: {
138
+ recent: { default: defaultWorkspaceSnapshot },
139
+ exact: { default: defaultWorkspaceSnapshot }
140
+ },
141
+ on: {
142
+ Pause: (to) =>
143
+ to.full.Paused().resolve(({ event, target }) => target.decoded(new Paused({ reason: event.reason }))),
144
+ BumpWorkspace: (to) =>
145
+ to.branch.Workspace.update(({ current, owner }) =>
146
+ owner.decoded(
147
+ new Workspace({
148
+ revision: current.revision + 1,
149
+ preferredRoute: current.preferredRoute
150
+ })
151
+ )
152
+ )
153
+ },
154
+ onDone: (to) =>
155
+ to.full.Published().resolve(({ target }) => target.decoded(new Published({ result: "workspace published" }))),
156
+ states: {
157
+ Routing: {
158
+ choice: (to) =>
159
+ to.branches({
160
+ draft: { title: "Preferred route is draft", target: to.local.Draft() },
161
+ review: { title: "Preferred route is review", target: to.local.Review.initial }
162
+ }).resolve(({ containingState, select }) =>
163
+ containingState.preferredRoute === "review"
164
+ ? select.review.decoded(new Review({ requestedBy: "initial route" }))
165
+ : select.draft.decoded(new Draft({ text: "", autosaves: 0 }))
166
+ )
167
+ },
168
+ Draft: {
169
+ on: {
170
+ Edit: (to) =>
171
+ to.local.Draft().resolve(({ event, state, target }) =>
172
+ target.decoded(new Draft({ text: event.text, autosaves: state.autosaves }))
173
+ ),
174
+ Save: (to) => to.local.AutoSaving().resolve(({ target }) => target.decoded(new AutoSaving({}))),
175
+ Submit: (to) =>
176
+ to.branches({
177
+ review: { title: "Enter the review flow", target: to.local.Review.initial },
178
+ publish: { title: "Publish without review", target: to.local.Finished() }
179
+ }).resolve(({ event, select }) =>
180
+ event.mode === "publish"
181
+ ? select.publish.decoded(new WorkspaceFinished({ result: "published directly" }))
182
+ : select.review.decoded(new Review({ requestedBy: event.requestedBy }))
183
+ ),
184
+ Refresh: (to) => to.none.resolve(() => undefined, { reenter: true }),
185
+ Ignore: (to) => to.none,
186
+ MaybeHandle: (to) =>
187
+ to.none.resolve(({ decline, event }) => event.accept ? undefined : decline(), {
188
+ declinable: true
189
+ })
190
+ }
191
+ },
192
+ AutoSaving: {
193
+ always: (to) =>
194
+ to.local.Draft().resolve(({ target }) => target.decoded(new Draft({ text: "Autosaved draft", autosaves: 1 })))
195
+ },
196
+ Review: {
197
+ initialize: ({ builder }) => builder.decoded(new Checking({ checks: ["types", "tests"] })),
198
+ onDone: (to) =>
199
+ to.branch.Workspace.Finished().resolve(({ target }) =>
200
+ target.decoded(new WorkspaceFinished({ result: "approved review" }))
201
+ ),
202
+ states: {
203
+ Checking: {
204
+ on: {
205
+ Approve: (to) =>
206
+ to.local.Approved().resolve(({ event, target }) =>
207
+ target.decoded(new Approved({ reviewer: event.reviewer }))
208
+ ),
209
+ Reject: (to) =>
210
+ to.local.ChangesRequested().resolve(({ event, target }) =>
211
+ target.decoded(new ChangesRequested({ reason: event.reason }))
212
+ )
213
+ }
214
+ },
215
+ ChangesRequested: {
216
+ on: {
217
+ Revise: (to) =>
218
+ to.branch.Workspace.Draft().resolve(({ target }) =>
219
+ target.decoded(new Draft({ text: "Revised draft", autosaves: 0 }))
220
+ )
221
+ }
222
+ }
223
+ }
224
+ }
225
+ }
226
+ },
227
+ Paused: {
228
+ on: {
229
+ Create: (to) =>
230
+ to.full.Workspace.initial.resolve(({ event, target }) =>
231
+ target.decoded(new Workspace({ revision: 0, preferredRoute: event.route }))
232
+ ),
233
+ ResumeShallow: (to) => to.history.Workspace.recent.resolve(({ target }) => target()),
234
+ ResumeDeep: (to) => to.history.Workspace.exact.resolve(({ target }) => target()),
235
+ Restart: (to) =>
236
+ to.full.Workspace.initial.resolve(({ target }) =>
237
+ target.decoded(new Workspace({ revision: 0, preferredRoute: "draft" }))
238
+ )
239
+ }
240
+ },
241
+ Disabled: {},
242
+ Published: {
243
+ output: ({ state }) => state.result
244
+ }
245
+ })
@@ -0,0 +1,52 @@
1
+ import type { MachineDocument as VisualizationDocument } from "../../MachineDocument.js"
2
+ import { makeChartLayoutPolicy } from "./chart-layout-policy.js"
3
+ import { makeChartModel } from "./chart-model.js"
4
+
5
+ export interface UnhandledPublicEventWarning {
6
+ readonly _tag: "UnhandledPublicEvent"
7
+ readonly event: string
8
+ }
9
+
10
+ export interface NoStaticPathNote {
11
+ readonly _tag: "NoStaticPathFromInitial"
12
+ readonly path: string
13
+ readonly label: string
14
+ readonly type: "atomic" | "compound" | "parallel" | "final" | "history" | "choice"
15
+ readonly descendantCount: number
16
+ }
17
+
18
+ export interface VisualizerAnalysis {
19
+ readonly warnings: ReadonlyArray<UnhandledPublicEventWarning>
20
+ readonly topologyNotes: ReadonlyArray<NoStaticPathNote>
21
+ }
22
+
23
+ /** Static findings derived without executing machine callbacks. */
24
+ export const analyzeVisualization = (document: VisualizationDocument): VisualizerAnalysis => {
25
+ const handledEvents = new Set(
26
+ document.transitions.flatMap((transition): ReadonlyArray<string> =>
27
+ transition.trigger.type === "event" ? [transition.trigger.event] : []
28
+ )
29
+ )
30
+ const declaredEvents = new Set(document.inputs.events.map(({ event }) => event))
31
+ const warnings = [...declaredEvents].flatMap((event): ReadonlyArray<UnhandledPublicEventWarning> =>
32
+ handledEvents.has(event) ? [] : [{ _tag: "UnhandledPublicEvent", event }]
33
+ )
34
+
35
+ const chart = makeChartModel(document)
36
+ const policy = makeChartLayoutPolicy(chart)
37
+ const topologyNotes = chart.nodes.flatMap((node): ReadonlyArray<NoStaticPathNote> => {
38
+ const hasStaticPath = policy.node(node.path).staticPath
39
+ const parentHasStaticPath = node.parent === null || policy.node(node.parent).staticPath
40
+ if (hasStaticPath || !parentHasStaticPath) return []
41
+ const descendantCount = chart.nodes.filter(({ path }) => path.startsWith(`${node.path}.`)).length
42
+ return [{
43
+ _tag: "NoStaticPathFromInitial",
44
+ path: node.path,
45
+ label: node.label,
46
+ type: node.type,
47
+ descendantCount
48
+ }]
49
+ })
50
+
51
+ return { warnings, topologyNotes }
52
+ }