@typeonce/effect-machine-devtools 0.31.2 → 0.33.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 (33) hide show
  1. package/dist/MachineRegistry.d.ts +4 -3
  2. package/dist/MachineRegistry.d.ts.map +1 -1
  3. package/dist/MachineRegistry.js +4 -3
  4. package/dist/MachineRegistry.js.map +1 -1
  5. package/dist/client/assets/index-2uvShdlX.js +37 -0
  6. package/dist/client/index.html +1 -1
  7. package/dist/internal/devServer.d.ts +3 -1
  8. package/dist/internal/devServer.d.ts.map +1 -1
  9. package/dist/internal/devServer.js +8 -6
  10. package/dist/internal/devServer.js.map +1 -1
  11. package/dist/internal/machineRegistry.js +9 -6
  12. package/dist/internal/machineRegistry.js.map +1 -1
  13. package/package.json +2 -2
  14. package/src/MachineRegistry.ts +4 -3
  15. package/src/internal/browser/chart-layout-policy.ts +2 -2
  16. package/src/internal/browser/chart-layout.ts +236 -51
  17. package/src/internal/browser/chart-model.ts +3 -0
  18. package/src/internal/browser/chart-renderer.ts +5 -4
  19. package/src/internal/browser/example-machine.ts +94 -85
  20. package/src/internal/browser/hierarchy-routing-example.ts +67 -58
  21. package/src/internal/browser/invoke-outcomes-example.ts +153 -143
  22. package/src/internal/browser/layout-resilience-example.ts +115 -104
  23. package/src/internal/browser/parallel-completion-example.ts +117 -107
  24. package/src/internal/browser/parallel-owner-routing-example.ts +104 -0
  25. package/src/internal/browser/planner-example.ts +44 -38
  26. package/src/internal/browser/protocol-events-example.ts +123 -102
  27. package/src/internal/browser/shared-terminal-routing-example.ts +125 -120
  28. package/src/internal/browser/text-tree.ts +2 -2
  29. package/src/internal/browser/transition-semantics-example.ts +143 -131
  30. package/src/internal/browser/visualizer-model.ts +7 -7
  31. package/src/internal/devServer.ts +15 -12
  32. package/src/internal/machineRegistry.ts +17 -17
  33. package/dist/client/assets/index-CSgOYHLh.js +0 -37
@@ -11,7 +11,7 @@ class ChildProblem extends Schema.TaggedClass<ChildProblem>("ProtocolChildProble
11
11
  message: Schema.String
12
12
  }) {}
13
13
 
14
- const ParentEvents = Machine.events(ChildProgress, ChildFinished, ChildProblem)
14
+ const ParentEvents = Machine.eventsFromSchemas(ChildProgress, ChildFinished, ChildProblem)
15
15
 
16
16
  class ChildIdle extends Schema.TaggedClass<ChildIdle>("ProtocolChildIdle")("Idle", {}) {}
17
17
  class ChildWorking extends Schema.TaggedClass<ChildWorking>("ProtocolChildWorking")("Working", {
@@ -43,64 +43,71 @@ class ChildTrace extends Schema.TaggedClass<ChildTrace>("ProtocolChildTrace")("C
43
43
  message: Schema.String
44
44
  }) {}
45
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 }
46
+ const ChildEvents = Machine.eventsFromSchemas(BeginChildWork, CancelChildWork)
47
+ const ChildInternalEvents = Machine.internalEventsFromSchemas(Heartbeat, CommitChildWork)
48
+ const ChildEmissions = Machine.emittedEventsFromSchemas(ChildTrace)
49
+ const ChildStates = Machine.state({
50
+ initial: "Idle",
51
+ states: {
52
+ Idle: ChildIdle,
53
+ Working: ChildWorking,
54
+ Done: { schema: ChildDone, type: "final", output: Schema.String },
55
+ Cancelled: { schema: ChildCancelled, type: "final", output: Schema.String }
56
+ }
54
57
  })
55
58
 
56
59
  export const requiredParentChildMachine = Machine.make({
57
60
  id: "required-parent-child",
58
- states: ChildStates.states,
61
+ root: ChildStates,
59
62
  events: ChildEvents,
60
63
  internalEvents: ChildInternalEvents,
61
64
  emittedEvents: ChildEmissions,
62
65
  parent: Machine.parent(ParentEvents),
63
- initial: (to) => to.Idle().resolve(({ target }) => target.decoded(new ChildIdle({})))
66
+ initialConfiguration: (root) => root.resolve(({ target }) => target.from((to) => to.Idle.decoded(new ChildIdle({}))))
64
67
  }).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` }))
68
+ states: {
69
+ Idle: {
70
+ on: {
71
+ BeginChildWork: (to) =>
72
+ to.branch.Working().resolve(({ event, target }, enqueue) => {
73
+ enqueue.raise(ChildInternalEvents.Heartbeat({ percent: 25 }))
74
+ enqueue.emit(ChildEmissions.ChildTrace({ message: `started ${event.job}` }))
75
+ return target.decoded(new ChildWorking({ job: event.job, progress: 0 }))
76
+ })
77
+ }
78
+ },
79
+ Working: {
80
+ invoke: (from) =>
81
+ from.effect(
82
+ "report-progress-to-parent",
83
+ ({ parent, state }) => parent.send(ParentEvents.ChildProgress({ percent: state.progress }))
84
+ ).onDone((to) => to.none).onFailure((to) =>
85
+ to.branch.Cancelled().resolve(({ error, target }) =>
86
+ target.decoded(new ChildCancelled({ reason: String(error) }))
87
+ )
94
88
  ),
95
- CancelChildWork: (to) =>
96
- to.full.Cancelled().resolve(({ event, target }) => target.decoded(new ChildCancelled({ reason: event.reason })))
89
+ on: {
90
+ Heartbeat: (to) =>
91
+ to.branch.Working().resolve(({ event, state, target }, enqueue) => {
92
+ enqueue.raise(ChildInternalEvents.CommitChildWork())
93
+ return target.decoded(new ChildWorking({ job: state.job, progress: event.percent }))
94
+ }),
95
+ CommitChildWork: (to) =>
96
+ to.branch.Done().resolve(({ state, target }) =>
97
+ target.decoded(new ChildDone({ result: `${state.job}:complete` }))
98
+ ),
99
+ CancelChildWork: (to) =>
100
+ to.branch.Cancelled().resolve(({ event, target }) =>
101
+ target.decoded(new ChildCancelled({ reason: event.reason }))
102
+ )
103
+ }
104
+ },
105
+ Done: {
106
+ output: ({ state }) => state.result
107
+ },
108
+ Cancelled: {
109
+ output: ({ state }) => state.reason
97
110
  }
98
- },
99
- Done: {
100
- output: ({ state }) => state.result
101
- },
102
- Cancelled: {
103
- output: ({ state }) => state.reason
104
111
  }
105
112
  })
106
113
 
@@ -119,50 +126,61 @@ class ParentFailed extends Schema.TaggedClass<ParentFailed>("ProtocolParentFaile
119
126
  class LaunchChild extends Schema.TaggedClass<LaunchChild>("ProtocolLaunchChild")("LaunchChild", {}) {}
120
127
  class ResetParent extends Schema.TaggedClass<ResetParent>("ProtocolResetParent")("ResetParent", {}) {}
121
128
 
122
- const ParentStates = Machine.states({
123
- Idle: ParentIdle,
124
- Supervising,
125
- Complete: { schema: ParentComplete, type: "final", output: Schema.String },
126
- Failed: ParentFailed
129
+ const ParentStates = Machine.state({
130
+ initial: "Idle",
131
+ states: {
132
+ Idle: ParentIdle,
133
+ Supervising,
134
+ Complete: { schema: ParentComplete, type: "final", output: Schema.String },
135
+ Failed: ParentFailed
136
+ }
127
137
  })
128
138
 
129
139
  export const parentProtocolMachine = Machine.make({
130
140
  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({})))
141
+ root: ParentStates,
142
+ events: Machine.eventsFromSchemas(LaunchChild, ResetParent, ParentEvents),
143
+ initialConfiguration: (root) => root.resolve(({ target }) => target.from((to) => to.Idle.decoded(new ParentIdle({}))))
134
144
  }).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 }))
145
+ states: {
146
+ Idle: {
147
+ on: {
148
+ LaunchChild: (to) =>
149
+ to.branch.Supervising().resolve(({ target }) => target.decoded(new Supervising({ latestProgress: 0 })))
150
+ }
151
+ },
152
+ Supervising: {
153
+ invoke: (from) =>
154
+ from.child(ProtocolChild).onDone((to) =>
155
+ to.branch.Complete().resolve(({ output, target }) => target.decoded(new ParentComplete({ result: output })))
156
+ ).onFailure((to) =>
157
+ to.branch.Failed().resolve(({ error, target }) =>
158
+ target.decoded(new ParentFailed({ message: String(error) }))
159
+ )
152
160
  ),
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({})))
161
+ on: {
162
+ ChildProgress: (to) =>
163
+ to.branch.Supervising().resolve(({ event, target }) =>
164
+ target.decoded(new Supervising({ latestProgress: event.percent }))
165
+ ),
166
+ ChildFinished: (to) =>
167
+ to.branch.Complete().resolve(({ event, target }) =>
168
+ target.decoded(new ParentComplete({ result: event.result }))
169
+ ),
170
+ ChildProblem: (to) =>
171
+ to.branch.Failed().resolve(({ event, target }) =>
172
+ target.decoded(new ParentFailed({ message: event.message }))
173
+ ),
174
+ ResetParent: (to) => to.branch.Idle().resolve(({ target }) => target.decoded(new ParentIdle({})))
175
+ }
176
+ },
177
+ Complete: {
178
+ output: ({ state }) => state.result
179
+ },
180
+ Failed: {
181
+ on: {
182
+ ResetParent: (to) => to.branch.Idle().resolve(({ target }) => target.decoded(new ParentIdle({})))
183
+ }
166
184
  }
167
185
  }
168
186
  })
@@ -176,25 +194,28 @@ class PublishOutside extends Schema.TaggedClass<PublishOutside>("OptionalParentP
176
194
  { result: Schema.String }
177
195
  ) {}
178
196
 
179
- const OptionalParentStates = Machine.states({ Detached, Published })
197
+ const OptionalParentStates = Machine.state({ initial: "Detached", states: { Detached, Published } })
180
198
 
181
199
  export const optionalParentMachine = Machine.make({
182
200
  id: "optional-parent-protocol",
183
- states: OptionalParentStates.states,
184
- events: Machine.events(PublishOutside),
201
+ root: OptionalParentStates,
202
+ events: Machine.eventsFromSchemas(PublishOutside),
185
203
  parent: Machine.optionalParent(ParentEvents),
186
- initial: (to) => to.Detached().resolve(({ target }) => target.decoded(new Detached({})))
204
+ initialConfiguration: (root) =>
205
+ root.resolve(({ target }) => target.from((to) => to.Detached.decoded(new Detached({}))))
187
206
  }).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: {}
207
+ states: {
208
+ Detached: {
209
+ on: {
210
+ PublishOutside: (to) =>
211
+ to.branch.Published().resolve(({ event, parent, target }, enqueue) => {
212
+ if (parent !== undefined) {
213
+ enqueue.sendTo(parent, ParentEvents.ChildFinished({ result: event.result }))
214
+ }
215
+ return target.decoded(new Published({ deliveredToParent: parent !== undefined }))
216
+ })
217
+ }
218
+ },
219
+ Published: {}
220
+ }
200
221
  })
@@ -1,23 +1,26 @@
1
1
  import { Machine } from "@typeonce/effect-machine"
2
2
  import { Effect, Schema } from "effect"
3
3
 
4
- const ReplicationStates = Machine.states({
5
- Connecting: {},
6
- IdentifyingSource: {},
7
- ReadingServerInfo: {},
8
- ReadingSlot: {},
9
- CreatingSlot: {},
10
- CopyingSnapshot: {},
11
- CatchingUp: {},
12
- ApplyingChanges: {},
13
- Ready: {},
14
- SessionUnavailable: {},
15
- Stopping: {},
16
- Stopped: {},
17
- Failed: {}
4
+ const ReplicationStates = Machine.state({
5
+ initial: "Connecting",
6
+ states: {
7
+ Connecting: {},
8
+ IdentifyingSource: {},
9
+ ReadingServerInfo: {},
10
+ ReadingSlot: {},
11
+ CreatingSlot: {},
12
+ CopyingSnapshot: {},
13
+ CatchingUp: {},
14
+ ApplyingChanges: {},
15
+ Ready: {},
16
+ SessionUnavailable: {},
17
+ Stopping: {},
18
+ Stopped: {},
19
+ Failed: {}
20
+ }
18
21
  })
19
22
 
20
- const ReplicationEvents = Machine.events(
23
+ const ReplicationEvents = Machine.eventsFromSchemas(
21
24
  Schema.TaggedUnion({
22
25
  Retry: {},
23
26
  SessionUnavailable: {},
@@ -29,113 +32,115 @@ const operation = (): Effect.Effect<void, string> => Effect.succeed(undefined)
29
32
 
30
33
  export const sharedTerminalRoutingMachine = Machine.make({
31
34
  id: "shared-terminal-routing",
32
- states: ReplicationStates.states,
35
+ root: ReplicationStates,
33
36
  events: ReplicationEvents,
34
- initial: (to) => to.Connecting()
37
+ initialConfiguration: (root) => root.resolve(({ target }) => target.from((to) => to.Connecting.from()))
35
38
  }).handle({
36
- Connecting: {
37
- invoke: (from) =>
38
- from.effect("connect", operation)
39
- .onDone((to) => to.full.IdentifyingSource())
40
- .onFailure((to) => to.full.Failed()),
41
- on: {
42
- SessionUnavailable: (to) => to.full.SessionUnavailable(),
43
- StopRequested: (to) => to.full.Stopping()
44
- }
45
- },
46
- IdentifyingSource: {
47
- invoke: (from) =>
48
- from.effect("identify-source", operation)
49
- .onDone((to) => to.full.ReadingServerInfo())
50
- .onFailure((to) => to.full.Failed()),
51
- on: {
52
- SessionUnavailable: (to) => to.full.SessionUnavailable(),
53
- StopRequested: (to) => to.full.Stopping()
54
- }
55
- },
56
- ReadingServerInfo: {
57
- invoke: (from) =>
58
- from.effect("read-server-info", operation)
59
- .onDone((to) => to.full.ReadingSlot())
60
- .onFailure((to) => to.full.Failed()),
61
- on: {
62
- SessionUnavailable: (to) => to.full.SessionUnavailable(),
63
- StopRequested: (to) => to.full.Stopping()
64
- }
65
- },
66
- ReadingSlot: {
67
- invoke: (from) =>
68
- from.effect("read-slot", operation)
69
- .onDone((to) => to.full.CreatingSlot())
70
- .onFailure((to) => to.full.Failed()),
71
- on: {
72
- SessionUnavailable: (to) => to.full.SessionUnavailable(),
73
- StopRequested: (to) => to.full.Stopping()
74
- }
75
- },
76
- CreatingSlot: {
77
- invoke: (from) =>
78
- from.effect("create-slot", operation)
79
- .onDone((to) => to.full.CopyingSnapshot())
80
- .onFailure((to) => to.full.Failed()),
81
- on: {
82
- SessionUnavailable: (to) => to.full.SessionUnavailable(),
83
- StopRequested: (to) => to.full.Stopping()
84
- }
85
- },
86
- CopyingSnapshot: {
87
- invoke: (from) =>
88
- from.effect("copy-snapshot", operation)
89
- .onDone((to) => to.full.CatchingUp())
90
- .onFailure((to) => to.full.Failed()),
91
- on: {
92
- SessionUnavailable: (to) => to.full.SessionUnavailable(),
93
- StopRequested: (to) => to.full.Stopping()
94
- }
95
- },
96
- CatchingUp: {
97
- invoke: (from) =>
98
- from.effect("catch-up", operation)
99
- .onDone((to) => to.full.ApplyingChanges())
100
- .onFailure((to) => to.full.Failed()),
101
- on: {
102
- SessionUnavailable: (to) => to.full.SessionUnavailable(),
103
- StopRequested: (to) => to.full.Stopping()
104
- }
105
- },
106
- ApplyingChanges: {
107
- invoke: (from) =>
108
- from.effect("apply-changes", operation)
109
- .onDone((to) => to.full.Ready())
110
- .onFailure((to) => to.full.Failed()),
111
- on: {
112
- SessionUnavailable: (to) => to.full.SessionUnavailable(),
113
- StopRequested: (to) => to.full.Stopping()
114
- }
115
- },
116
- Ready: {
117
- on: {
118
- SessionUnavailable: (to) => to.full.SessionUnavailable(),
119
- StopRequested: (to) => to.full.Stopping()
120
- }
121
- },
122
- SessionUnavailable: {
123
- on: {
124
- Retry: (to) => to.full.Connecting(),
125
- StopRequested: (to) => to.full.Stopping()
126
- }
127
- },
128
- Stopping: {
129
- invoke: (from) =>
130
- from.effect("stop-session", operation)
131
- .onDone((to) => to.full.Stopped())
132
- .onFailure((to) => to.full.Failed())
133
- },
134
- Stopped: {},
135
- Failed: {
136
- on: {
137
- Retry: (to) => to.full.Connecting(),
138
- StopRequested: (to) => to.full.Stopping()
39
+ states: {
40
+ Connecting: {
41
+ invoke: (from) =>
42
+ from.effect("connect", operation)
43
+ .onDone((to) => to.branch.IdentifyingSource())
44
+ .onFailure((to) => to.branch.Failed()),
45
+ on: {
46
+ SessionUnavailable: (to) => to.branch.SessionUnavailable(),
47
+ StopRequested: (to) => to.branch.Stopping()
48
+ }
49
+ },
50
+ IdentifyingSource: {
51
+ invoke: (from) =>
52
+ from.effect("identify-source", operation)
53
+ .onDone((to) => to.branch.ReadingServerInfo())
54
+ .onFailure((to) => to.branch.Failed()),
55
+ on: {
56
+ SessionUnavailable: (to) => to.branch.SessionUnavailable(),
57
+ StopRequested: (to) => to.branch.Stopping()
58
+ }
59
+ },
60
+ ReadingServerInfo: {
61
+ invoke: (from) =>
62
+ from.effect("read-server-info", operation)
63
+ .onDone((to) => to.branch.ReadingSlot())
64
+ .onFailure((to) => to.branch.Failed()),
65
+ on: {
66
+ SessionUnavailable: (to) => to.branch.SessionUnavailable(),
67
+ StopRequested: (to) => to.branch.Stopping()
68
+ }
69
+ },
70
+ ReadingSlot: {
71
+ invoke: (from) =>
72
+ from.effect("read-slot", operation)
73
+ .onDone((to) => to.branch.CreatingSlot())
74
+ .onFailure((to) => to.branch.Failed()),
75
+ on: {
76
+ SessionUnavailable: (to) => to.branch.SessionUnavailable(),
77
+ StopRequested: (to) => to.branch.Stopping()
78
+ }
79
+ },
80
+ CreatingSlot: {
81
+ invoke: (from) =>
82
+ from.effect("create-slot", operation)
83
+ .onDone((to) => to.branch.CopyingSnapshot())
84
+ .onFailure((to) => to.branch.Failed()),
85
+ on: {
86
+ SessionUnavailable: (to) => to.branch.SessionUnavailable(),
87
+ StopRequested: (to) => to.branch.Stopping()
88
+ }
89
+ },
90
+ CopyingSnapshot: {
91
+ invoke: (from) =>
92
+ from.effect("copy-snapshot", operation)
93
+ .onDone((to) => to.branch.CatchingUp())
94
+ .onFailure((to) => to.branch.Failed()),
95
+ on: {
96
+ SessionUnavailable: (to) => to.branch.SessionUnavailable(),
97
+ StopRequested: (to) => to.branch.Stopping()
98
+ }
99
+ },
100
+ CatchingUp: {
101
+ invoke: (from) =>
102
+ from.effect("catch-up", operation)
103
+ .onDone((to) => to.branch.ApplyingChanges())
104
+ .onFailure((to) => to.branch.Failed()),
105
+ on: {
106
+ SessionUnavailable: (to) => to.branch.SessionUnavailable(),
107
+ StopRequested: (to) => to.branch.Stopping()
108
+ }
109
+ },
110
+ ApplyingChanges: {
111
+ invoke: (from) =>
112
+ from.effect("apply-changes", operation)
113
+ .onDone((to) => to.branch.Ready())
114
+ .onFailure((to) => to.branch.Failed()),
115
+ on: {
116
+ SessionUnavailable: (to) => to.branch.SessionUnavailable(),
117
+ StopRequested: (to) => to.branch.Stopping()
118
+ }
119
+ },
120
+ Ready: {
121
+ on: {
122
+ SessionUnavailable: (to) => to.branch.SessionUnavailable(),
123
+ StopRequested: (to) => to.branch.Stopping()
124
+ }
125
+ },
126
+ SessionUnavailable: {
127
+ on: {
128
+ Retry: (to) => to.branch.Connecting(),
129
+ StopRequested: (to) => to.branch.Stopping()
130
+ }
131
+ },
132
+ Stopping: {
133
+ invoke: (from) =>
134
+ from.effect("stop-session", operation)
135
+ .onDone((to) => to.branch.Stopped())
136
+ .onFailure((to) => to.branch.Failed())
137
+ },
138
+ Stopped: {},
139
+ Failed: {
140
+ on: {
141
+ Retry: (to) => to.branch.Connecting(),
142
+ StopRequested: (to) => to.branch.Stopping()
143
+ }
139
144
  }
140
145
  }
141
146
  })
@@ -30,10 +30,10 @@ export interface TextTree {
30
30
 
31
31
  const nodeLabel = (node: VisualizationState, active: ReadonlySet<string>): string => {
32
32
  const status = active.has(node.path) ? "●" : "○"
33
- const label = node.title === null ? node.key : `${node.title} (${node.key})`
33
+ const label = node.title === null ? (node.path === "" ? "(root)" : node.key) : `${node.title} (${node.key})`
34
34
  const details: Array<string> = node.type === "atomic" ? [] : [node.type]
35
35
  if (node.initial !== null) {
36
- details.push(`initial: ${node.initial.slice(node.path.length + 1)}`)
36
+ details.push(`initial: ${node.initial.slice(node.path === "" ? 0 : node.path.length + 1)}`)
37
37
  }
38
38
  if (node.history !== null) {
39
39
  details.push(node.history)