@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,206 @@
1
+ import type { ChartEdge, ChartModel, ChartNode } from "./chart-model.js"
2
+
3
+ export type ChartPortSide = "NORTH" | "EAST" | "SOUTH" | "WEST"
4
+
5
+ export interface ChartNodeLayoutPolicy {
6
+ readonly reachable: boolean
7
+ readonly staticPath: boolean
8
+ readonly rank: number | null
9
+ readonly order: number
10
+ readonly layerConstraint: "LAST" | null
11
+ }
12
+
13
+ export interface ChartEdgeLayoutPolicy {
14
+ readonly direction: "forward" | "backward" | "self"
15
+ readonly sourceSide: ChartPortSide
16
+ readonly targetSide: ChartPortSide
17
+ }
18
+
19
+ export interface ChartLayoutPolicy {
20
+ readonly children: (parent: string | null) => ReadonlyArray<ChartNode>
21
+ readonly node: (path: string) => ChartNodeLayoutPolicy
22
+ readonly edge: (edge: ChartEdge) => ChartEdgeLayoutPolicy
23
+ }
24
+
25
+ const unreachableNode: ChartNodeLayoutPolicy = {
26
+ reachable: false,
27
+ staticPath: false,
28
+ rank: null,
29
+ order: Number.MAX_SAFE_INTEGER,
30
+ layerConstraint: null
31
+ }
32
+
33
+ const directChild = (
34
+ path: string,
35
+ parent: string | null,
36
+ nodes: ReadonlyMap<string, ChartNode>
37
+ ): string | null => {
38
+ let current = nodes.get(path)
39
+ while (current !== undefined && current.parent !== parent) {
40
+ current = current.parent === null ? undefined : nodes.get(current.parent)
41
+ }
42
+ return current?.path ?? null
43
+ }
44
+
45
+ const lineage = (path: string, nodes: ReadonlyMap<string, ChartNode>): ReadonlyArray<string> => {
46
+ const result: Array<string> = []
47
+ let current = nodes.get(path)
48
+ while (current !== undefined) {
49
+ result.push(current.path)
50
+ current = current.parent === null ? undefined : nodes.get(current.parent)
51
+ }
52
+ return result.reverse()
53
+ }
54
+
55
+ export const makeChartLayoutPolicy = (model: ChartModel): ChartLayoutPolicy => {
56
+ const nodes = new Map(model.nodes.map((node) => [node.path, node]))
57
+ const declarationOrder = new Map(model.nodes.map((node, index) => [node.path, index]))
58
+ const childrenByParent = new Map<string | null, Array<ChartNode>>()
59
+ for (const node of model.nodes) {
60
+ const children = childrenByParent.get(node.parent) ?? []
61
+ children.push(node)
62
+ childrenByParent.set(node.parent, children)
63
+ }
64
+
65
+ const nodePolicies = new Map<string, ChartNodeLayoutPolicy>()
66
+ const orderedChildren = new Map<string | null, ReadonlyArray<ChartNode>>()
67
+
68
+ const initialsByParent = new Map<string | null, Array<string>>()
69
+ for (const initial of model.initials) {
70
+ const initials = initialsByParent.get(initial.parent) ?? []
71
+ initials.push(initial.target)
72
+ initialsByParent.set(initial.parent, initials)
73
+ }
74
+ const outgoing = new Map<string, Array<string>>()
75
+ for (const edge of model.edges) {
76
+ if (edge.kind !== "target" || edge.target === null) continue
77
+ const targets = outgoing.get(edge.source) ?? []
78
+ targets.push(edge.target)
79
+ outgoing.set(edge.source, targets)
80
+ }
81
+
82
+ const staticPaths = new Set<string>()
83
+ const entered = new Set<string>()
84
+ const queue: Array<string> = []
85
+ const markReachable = (path: string): void => {
86
+ let current = nodes.get(path)
87
+ while (current !== undefined) {
88
+ if (!staticPaths.has(current.path)) {
89
+ staticPaths.add(current.path)
90
+ queue.push(current.path)
91
+ }
92
+ current = current.parent === null ? undefined : nodes.get(current.parent)
93
+ }
94
+ }
95
+ const enter = (path: string): void => {
96
+ const node = nodes.get(path)
97
+ if (node === undefined) return
98
+ markReachable(path)
99
+ if (entered.has(path)) return
100
+ entered.add(path)
101
+ if (node.type === "parallel") {
102
+ for (const child of node.children) enter(child)
103
+ } else if (node.type === "compound") {
104
+ for (const initial of initialsByParent.get(node.path) ?? []) enter(initial)
105
+ }
106
+ }
107
+ for (const initial of initialsByParent.get(null) ?? []) enter(initial)
108
+ for (let index = 0; index < queue.length; index++) {
109
+ for (const target of outgoing.get(queue[index]!) ?? []) enter(target)
110
+ }
111
+
112
+ for (const [parent, children] of childrenByParent) {
113
+ const childPaths = new Set(children.map(({ path }) => path))
114
+ const adjacency = new Map(children.map(({ path }) => [path, new Set<string>()]))
115
+ for (const edge of model.edges) {
116
+ if (edge.kind !== "target" || edge.target === null) continue
117
+ const source = directChild(edge.source, parent, nodes)
118
+ const target = directChild(edge.target, parent, nodes)
119
+ if (source !== null && target !== null && source !== target && childPaths.has(source) && childPaths.has(target)) {
120
+ adjacency.get(source)?.add(target)
121
+ }
122
+ }
123
+
124
+ const ranks = new Map<string, number>()
125
+ const queue: Array<string> = []
126
+ for (const initial of model.initials) {
127
+ if (initial.parent !== parent) continue
128
+ const target = directChild(initial.target, parent, nodes)
129
+ if (target !== null && childPaths.has(target) && !ranks.has(target)) {
130
+ ranks.set(target, 0)
131
+ queue.push(target)
132
+ }
133
+ }
134
+ for (let index = 0; index < queue.length; index++) {
135
+ const source = queue[index]!
136
+ const nextRank = ranks.get(source)! + 1
137
+ for (const target of adjacency.get(source) ?? []) {
138
+ const current = ranks.get(target)
139
+ if (current === undefined || nextRank < current) {
140
+ ranks.set(target, nextRank)
141
+ queue.push(target)
142
+ }
143
+ }
144
+ }
145
+
146
+ const ordered = [...children].sort((left, right) => {
147
+ const leftRank = ranks.get(left.path)
148
+ const rightRank = ranks.get(right.path)
149
+ if (leftRank !== undefined && rightRank === undefined) return -1
150
+ if (leftRank === undefined && rightRank !== undefined) return 1
151
+ if (leftRank !== undefined && rightRank !== undefined && leftRank !== rightRank) return leftRank - rightRank
152
+ return declarationOrder.get(left.path)! - declarationOrder.get(right.path)!
153
+ })
154
+ orderedChildren.set(parent, ordered)
155
+ ordered.forEach((node, order) => {
156
+ const rank = ranks.get(node.path) ?? null
157
+ nodePolicies.set(node.path, {
158
+ reachable: rank !== null,
159
+ staticPath: staticPaths.has(node.path),
160
+ rank,
161
+ order,
162
+ layerConstraint: node.type === "final" ? "LAST" : null
163
+ })
164
+ })
165
+ }
166
+
167
+ const edgePolicy = (edge: ChartEdge): ChartEdgeLayoutPolicy => {
168
+ if (edge.kind === "targetless" || edge.target === edge.source) {
169
+ return { direction: "self", sourceSide: "SOUTH", targetSide: "SOUTH" }
170
+ }
171
+ if (edge.target === null) {
172
+ return { direction: "forward", sourceSide: "EAST", targetSide: "WEST" }
173
+ }
174
+
175
+ const sourceLineage = lineage(edge.source, nodes)
176
+ const targetLineage = lineage(edge.target, nodes)
177
+ let differentAt = 0
178
+ while (
179
+ differentAt < sourceLineage.length && differentAt < targetLineage.length &&
180
+ sourceLineage[differentAt] === targetLineage[differentAt]
181
+ ) {
182
+ differentAt++
183
+ }
184
+ if (differentAt === sourceLineage.length) {
185
+ return { direction: "forward", sourceSide: "EAST", targetSide: "WEST" }
186
+ }
187
+ if (differentAt === targetLineage.length) {
188
+ return { direction: "backward", sourceSide: "WEST", targetSide: "EAST" }
189
+ }
190
+
191
+ const source = nodePolicies.get(sourceLineage[differentAt]!) ?? unreachableNode
192
+ const target = nodePolicies.get(targetLineage[differentAt]!) ?? unreachableNode
193
+ const backward = source.rank !== null && target.rank !== null
194
+ ? target.rank < source.rank || target.rank === source.rank && target.order < source.order
195
+ : target.order < source.order
196
+ return backward
197
+ ? { direction: "backward", sourceSide: "WEST", targetSide: "EAST" }
198
+ : { direction: "forward", sourceSide: "EAST", targetSide: "WEST" }
199
+ }
200
+
201
+ return {
202
+ children: (parent) => orderedChildren.get(parent) ?? [],
203
+ node: (path) => nodePolicies.get(path) ?? unreachableNode,
204
+ edge: edgePolicy
205
+ }
206
+ }