@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,355 @@
|
|
|
1
|
+
import * as Result from "effect/Result"
|
|
2
|
+
import type * as MachineDocument from "../MachineDocument.js"
|
|
3
|
+
import type * as MachineWalkthrough from "../MachineWalkthrough.js"
|
|
4
|
+
|
|
5
|
+
/** @internal */
|
|
6
|
+
export const SessionTypeId = "@typeonce/effect-machine-devtools/MachineWalkthrough/Session" as const
|
|
7
|
+
|
|
8
|
+
interface HistoryRecord {
|
|
9
|
+
readonly mode: "shallow" | "deep"
|
|
10
|
+
readonly paths: ReadonlyArray<string>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface InternalSnapshot {
|
|
14
|
+
readonly activePaths: ReadonlyArray<string>
|
|
15
|
+
readonly history: ReadonlyMap<string, HistoryRecord>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface InternalFrame {
|
|
19
|
+
readonly public: MachineWalkthrough.Frame
|
|
20
|
+
readonly snapshot: InternalSnapshot
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface SessionImpl extends MachineWalkthrough.Session {
|
|
24
|
+
readonly document: MachineDocument.MachineDocument
|
|
25
|
+
readonly cursor: number
|
|
26
|
+
readonly frames: ReadonlyArray<InternalFrame>
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface Model {
|
|
30
|
+
readonly states: ReadonlyMap<string, MachineDocument.State>
|
|
31
|
+
readonly order: ReadonlyMap<string, number>
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface PublicApi {
|
|
35
|
+
readonly ChoiceNotFound: typeof MachineWalkthrough.ChoiceNotFound
|
|
36
|
+
readonly ChoiceUnavailable: typeof MachineWalkthrough.ChoiceUnavailable
|
|
37
|
+
readonly StepNotFound: typeof MachineWalkthrough.StepNotFound
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const makeModel = (document: MachineDocument.MachineDocument): Model => ({
|
|
41
|
+
states: new Map(document.states.map((state) => [state.path, state])),
|
|
42
|
+
order: new Map(document.states.map((state) => [state.path, state.order]))
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
const ordered = (model: Model, paths: Iterable<string>): ReadonlyArray<string> =>
|
|
46
|
+
[...new Set(paths)].sort((left, right) => (model.order.get(left) ?? 0) - (model.order.get(right) ?? 0))
|
|
47
|
+
|
|
48
|
+
const ancestors = (model: Model, path: string): ReadonlyArray<string> => {
|
|
49
|
+
const result: Array<string> = []
|
|
50
|
+
let current = model.states.get(path)
|
|
51
|
+
while (current !== undefined) {
|
|
52
|
+
result.unshift(current.path)
|
|
53
|
+
current = current.parent === null ? undefined : model.states.get(current.parent)
|
|
54
|
+
}
|
|
55
|
+
return result
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const isDescendant = (model: Model, path: string, ancestor: string): boolean =>
|
|
59
|
+
path !== ancestor && ancestors(model, path).includes(ancestor)
|
|
60
|
+
|
|
61
|
+
const leastCommonAncestor = (model: Model, left: string, right: string): string | null => {
|
|
62
|
+
const leftAncestors = ancestors(model, left)
|
|
63
|
+
const rightAncestors = ancestors(model, right)
|
|
64
|
+
let result: string | null = null
|
|
65
|
+
const length = Math.min(leftAncestors.length, rightAncestors.length)
|
|
66
|
+
for (let index = 0; index < length; index++) {
|
|
67
|
+
if (leftAncestors[index] !== rightAncestors[index]) break
|
|
68
|
+
result = leftAncestors[index] ?? null
|
|
69
|
+
}
|
|
70
|
+
return result
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const add = (active: Set<string>, entered: Set<string>, path: string): void => {
|
|
74
|
+
if (!active.has(path)) entered.add(path)
|
|
75
|
+
active.add(path)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const enter = (
|
|
79
|
+
model: Model,
|
|
80
|
+
path: string,
|
|
81
|
+
active: Set<string>,
|
|
82
|
+
entered: Set<string>,
|
|
83
|
+
history: ReadonlyMap<string, HistoryRecord>
|
|
84
|
+
): void => {
|
|
85
|
+
const state = model.states.get(path)
|
|
86
|
+
if (state === undefined) return
|
|
87
|
+
if (state.type === "history") {
|
|
88
|
+
const record = history.get(path)
|
|
89
|
+
if (record === undefined) {
|
|
90
|
+
add(active, entered, path)
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
if (record.mode === "deep") {
|
|
94
|
+
record.paths.forEach((recorded) => add(active, entered, recorded))
|
|
95
|
+
} else {
|
|
96
|
+
record.paths.forEach((recorded) => enter(model, recorded, active, entered, history))
|
|
97
|
+
}
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
add(active, entered, path)
|
|
101
|
+
if (state.type === "parallel") {
|
|
102
|
+
state.children.forEach((child) => enter(model, child, active, entered, history))
|
|
103
|
+
} else if (state.type === "compound" && state.initial !== null) {
|
|
104
|
+
enter(model, state.initial, active, entered, history)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const completeParallelRegions = (
|
|
109
|
+
model: Model,
|
|
110
|
+
active: Set<string>,
|
|
111
|
+
entered: Set<string>,
|
|
112
|
+
history: ReadonlyMap<string, HistoryRecord>
|
|
113
|
+
): void => {
|
|
114
|
+
for (const state of model.states.values()) {
|
|
115
|
+
if (state.type !== "parallel" || !active.has(state.path)) continue
|
|
116
|
+
state.children.forEach((child) => {
|
|
117
|
+
if (!active.has(child)) enter(model, child, active, entered, history)
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const snapshot = (
|
|
123
|
+
model: Model,
|
|
124
|
+
activePaths: Iterable<string>,
|
|
125
|
+
history: ReadonlyMap<string, HistoryRecord>
|
|
126
|
+
): InternalSnapshot => ({
|
|
127
|
+
activePaths: ordered(model, activePaths),
|
|
128
|
+
history: new Map(history)
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
const publicSnapshot = (value: InternalSnapshot): MachineWalkthrough.Snapshot => ({
|
|
132
|
+
activePaths: value.activePaths
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
const makeSession = (
|
|
136
|
+
document: MachineDocument.MachineDocument,
|
|
137
|
+
cursor: number,
|
|
138
|
+
frames: ReadonlyArray<InternalFrame>
|
|
139
|
+
): MachineWalkthrough.Session =>
|
|
140
|
+
({
|
|
141
|
+
[SessionTypeId]: SessionTypeId,
|
|
142
|
+
document,
|
|
143
|
+
cursor,
|
|
144
|
+
frames
|
|
145
|
+
}) as SessionImpl
|
|
146
|
+
|
|
147
|
+
const session = (self: MachineWalkthrough.Session): SessionImpl => self as SessionImpl
|
|
148
|
+
|
|
149
|
+
const initialSnapshot = (document: MachineDocument.MachineDocument, model: Model): InternalSnapshot => {
|
|
150
|
+
if (document.snapshot !== null) return snapshot(model, document.snapshot.activePaths, new Map())
|
|
151
|
+
const active = new Set<string>()
|
|
152
|
+
const entered = new Set<string>()
|
|
153
|
+
const targetAncestors = ancestors(model, document.initial.target)
|
|
154
|
+
targetAncestors.slice(0, -1).forEach((path) => add(active, entered, path))
|
|
155
|
+
enter(model, document.initial.target, active, entered, new Map())
|
|
156
|
+
return snapshot(model, active, new Map())
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** @internal */
|
|
160
|
+
export const start = (document: MachineDocument.MachineDocument): MachineWalkthrough.Session => {
|
|
161
|
+
const model = makeModel(document)
|
|
162
|
+
const after = initialSnapshot(document, model)
|
|
163
|
+
const frame: MachineWalkthrough.Frame = {
|
|
164
|
+
step: 0,
|
|
165
|
+
choice: null,
|
|
166
|
+
before: { activePaths: [] },
|
|
167
|
+
after: publicSnapshot(after),
|
|
168
|
+
exitPaths: [],
|
|
169
|
+
entryPaths: after.activePaths,
|
|
170
|
+
changed: after.activePaths.length > 0
|
|
171
|
+
}
|
|
172
|
+
return makeSession(document, 0, [{ public: frame, snapshot: after }])
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/** @internal */
|
|
176
|
+
export const current = (self: MachineWalkthrough.Session): MachineWalkthrough.Frame => {
|
|
177
|
+
const value = session(self)
|
|
178
|
+
return value.frames[value.cursor]!.public
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** @internal */
|
|
182
|
+
export const timeline = (self: MachineWalkthrough.Session): ReadonlyArray<MachineWalkthrough.Frame> =>
|
|
183
|
+
session(self).frames.map((frame) => frame.public)
|
|
184
|
+
|
|
185
|
+
/** @internal */
|
|
186
|
+
export const cursor = (self: MachineWalkthrough.Session): number => session(self).cursor
|
|
187
|
+
|
|
188
|
+
const decisions = (
|
|
189
|
+
transition: MachineDocument.Transition,
|
|
190
|
+
branch: MachineDocument.Branch
|
|
191
|
+
): ReadonlyArray<MachineWalkthrough.Decision> => {
|
|
192
|
+
const values = new Set<MachineWalkthrough.Decision>()
|
|
193
|
+
if (branch.type === "branch") values.add("conditional-branch")
|
|
194
|
+
if (transition.acceptance === "declinable") values.add("declinable-transition")
|
|
195
|
+
if (transition.trigger.type === "invoke") values.add("invoke-outcome")
|
|
196
|
+
else if (transition.trigger.type !== "event") values.add("automatic-trigger")
|
|
197
|
+
return [...values]
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const unavailableReason = (
|
|
201
|
+
branch: MachineDocument.Branch,
|
|
202
|
+
history: ReadonlyMap<string, HistoryRecord>
|
|
203
|
+
): MachineWalkthrough.UnavailableReason | null => {
|
|
204
|
+
if (branch.selection.kind === "history" && (branch.target === null || !history.has(branch.target))) {
|
|
205
|
+
return "history-unavailable"
|
|
206
|
+
}
|
|
207
|
+
if (
|
|
208
|
+
branch.target === null &&
|
|
209
|
+
branch.selection.kind !== "none" &&
|
|
210
|
+
branch.selection.kind !== "update"
|
|
211
|
+
) return "runtime-target"
|
|
212
|
+
return null
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/** @internal */
|
|
216
|
+
export const choices = (self: MachineWalkthrough.Session): ReadonlyArray<MachineWalkthrough.Choice> => {
|
|
217
|
+
const value = session(self)
|
|
218
|
+
const frame = value.frames[value.cursor]!
|
|
219
|
+
const active = new Set(frame.snapshot.activePaths)
|
|
220
|
+
const eventInputs = new Map(value.document.inputs.events.map(({ event, schema }) => [event, schema]))
|
|
221
|
+
return value.document.transitions.flatMap((transition): ReadonlyArray<MachineWalkthrough.Choice> => {
|
|
222
|
+
if (!active.has(transition.source)) return []
|
|
223
|
+
return transition.branches.map((branch, branchIndex) => ({
|
|
224
|
+
id: branch.id,
|
|
225
|
+
transitionId: transition.id,
|
|
226
|
+
branchId: branch.id,
|
|
227
|
+
branchIndex,
|
|
228
|
+
branchKey: branch.type === "branch" ? branch.key : null,
|
|
229
|
+
title: branch.type === "branch" ? branch.title : null,
|
|
230
|
+
source: transition.source,
|
|
231
|
+
trigger: transition.trigger,
|
|
232
|
+
target: branch.target,
|
|
233
|
+
selection: branch.selection,
|
|
234
|
+
updates: branch.updates,
|
|
235
|
+
decisions: decisions(transition, branch),
|
|
236
|
+
unavailableReason: unavailableReason(branch, frame.snapshot.history),
|
|
237
|
+
input: transition.trigger.type === "event" ? eventInputs.get(transition.trigger.event) ?? null : null
|
|
238
|
+
}))
|
|
239
|
+
})
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const recordHistory = (
|
|
243
|
+
document: MachineDocument.MachineDocument,
|
|
244
|
+
model: Model,
|
|
245
|
+
before: ReadonlySet<string>,
|
|
246
|
+
exited: ReadonlySet<string>,
|
|
247
|
+
history: Map<string, HistoryRecord>
|
|
248
|
+
): void => {
|
|
249
|
+
for (const state of document.states) {
|
|
250
|
+
if (state.type !== "history" || state.parent === null || !exited.has(state.parent)) continue
|
|
251
|
+
const paths = state.history === "deep"
|
|
252
|
+
? [...before].filter((path) => {
|
|
253
|
+
const node = model.states.get(path)
|
|
254
|
+
return isDescendant(model, path, state.parent!) && node?.type !== "history" && node?.type !== "choice"
|
|
255
|
+
})
|
|
256
|
+
: [...before].filter((path) => model.states.get(path)?.parent === state.parent)
|
|
257
|
+
if (paths.length > 0) {
|
|
258
|
+
history.set(state.path, {
|
|
259
|
+
mode: state.history === "deep" ? "deep" : "shallow",
|
|
260
|
+
paths: ordered(model, paths)
|
|
261
|
+
})
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const advance = (
|
|
267
|
+
value: SessionImpl,
|
|
268
|
+
choice: MachineWalkthrough.Choice
|
|
269
|
+
): {
|
|
270
|
+
readonly snapshot: InternalSnapshot
|
|
271
|
+
readonly exited: ReadonlyArray<string>
|
|
272
|
+
readonly entered: ReadonlyArray<string>
|
|
273
|
+
} => {
|
|
274
|
+
const frame = value.frames[value.cursor]!
|
|
275
|
+
const model = makeModel(value.document)
|
|
276
|
+
if (choice.target === null) {
|
|
277
|
+
return { snapshot: frame.snapshot, exited: [], entered: [] }
|
|
278
|
+
}
|
|
279
|
+
const transition = value.document.transitions.find(({ id }) => id === choice.transitionId)!
|
|
280
|
+
const naturalBoundary = leastCommonAncestor(model, transition.source, choice.target)
|
|
281
|
+
const sourceParent = model.states.get(transition.source)?.parent ?? null
|
|
282
|
+
const boundary = transition.reenter
|
|
283
|
+
? sourceParent === null || naturalBoundary === null
|
|
284
|
+
? null
|
|
285
|
+
: ancestors(model, naturalBoundary).length <= ancestors(model, sourceParent).length
|
|
286
|
+
? naturalBoundary
|
|
287
|
+
: sourceParent
|
|
288
|
+
: naturalBoundary
|
|
289
|
+
const before = new Set(frame.snapshot.activePaths)
|
|
290
|
+
const active = new Set(frame.snapshot.activePaths)
|
|
291
|
+
const exited = new Set(
|
|
292
|
+
frame.snapshot.activePaths.filter((path) => boundary === null || isDescendant(model, path, boundary))
|
|
293
|
+
)
|
|
294
|
+
const history = new Map(frame.snapshot.history)
|
|
295
|
+
recordHistory(value.document, model, before, exited, history)
|
|
296
|
+
exited.forEach((path) => active.delete(path))
|
|
297
|
+
|
|
298
|
+
const entered = new Set<string>()
|
|
299
|
+
const targetAncestors = ancestors(model, choice.target)
|
|
300
|
+
targetAncestors.slice(0, -1).forEach((path) => {
|
|
301
|
+
if (boundary === null || path === boundary || isDescendant(model, path, boundary)) add(active, entered, path)
|
|
302
|
+
})
|
|
303
|
+
enter(model, choice.target, active, entered, history)
|
|
304
|
+
completeParallelRegions(model, active, entered, history)
|
|
305
|
+
return {
|
|
306
|
+
snapshot: snapshot(model, active, history),
|
|
307
|
+
exited: ordered(model, exited),
|
|
308
|
+
entered: ordered(model, entered)
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/** @internal */
|
|
313
|
+
export const take = (api: PublicApi) =>
|
|
314
|
+
(
|
|
315
|
+
self: MachineWalkthrough.Session,
|
|
316
|
+
choiceId: string
|
|
317
|
+
): Result.Result<
|
|
318
|
+
MachineWalkthrough.Session,
|
|
319
|
+
MachineWalkthrough.ChoiceNotFound | MachineWalkthrough.ChoiceUnavailable
|
|
320
|
+
> => {
|
|
321
|
+
const value = session(self)
|
|
322
|
+
const choice = choices(self).find(({ id }) => id === choiceId)
|
|
323
|
+
if (choice === undefined) return Result.fail(new api.ChoiceNotFound({ choiceId }))
|
|
324
|
+
if (choice.unavailableReason !== null) {
|
|
325
|
+
return Result.fail(new api.ChoiceUnavailable({ choiceId, reason: choice.unavailableReason }))
|
|
326
|
+
}
|
|
327
|
+
const beforeFrame = value.frames[value.cursor]!
|
|
328
|
+
const next = advance(value, choice)
|
|
329
|
+
const before = publicSnapshot(beforeFrame.snapshot)
|
|
330
|
+
const after = publicSnapshot(next.snapshot)
|
|
331
|
+
const frame: MachineWalkthrough.Frame = {
|
|
332
|
+
step: value.cursor + 1,
|
|
333
|
+
choice,
|
|
334
|
+
before,
|
|
335
|
+
after,
|
|
336
|
+
exitPaths: next.exited,
|
|
337
|
+
entryPaths: next.entered,
|
|
338
|
+
changed: next.exited.length > 0 || next.entered.length > 0
|
|
339
|
+
}
|
|
340
|
+
const frames = [...value.frames.slice(0, value.cursor + 1), { public: frame, snapshot: next.snapshot }]
|
|
341
|
+
return Result.succeed(makeSession(value.document, frames.length - 1, frames))
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/** @internal */
|
|
345
|
+
export const seek = (api: PublicApi) =>
|
|
346
|
+
(
|
|
347
|
+
self: MachineWalkthrough.Session,
|
|
348
|
+
step: number
|
|
349
|
+
): Result.Result<MachineWalkthrough.Session, MachineWalkthrough.StepNotFound> => {
|
|
350
|
+
const value = session(self)
|
|
351
|
+
if (!Number.isInteger(step) || step < 0 || step >= value.frames.length) {
|
|
352
|
+
return Result.fail(new api.StepNotFound({ step }))
|
|
353
|
+
}
|
|
354
|
+
return Result.succeed(makeSession(value.document, step, value.frames))
|
|
355
|
+
}
|
|
@@ -39,14 +39,8 @@ interface EvaluationResponse {
|
|
|
39
39
|
readonly results: ReadonlyArray<unknown>
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
readonly root: string
|
|
45
|
-
readonly request: DevToolsProtocol.SimulationRequest
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
type WorkerRequest = EvaluationRequest | SimulationWorkerRequest
|
|
49
|
-
type WorkerResponse = EvaluationResponse | DevToolsProtocol.SimulationResult
|
|
42
|
+
type WorkerRequest = EvaluationRequest
|
|
43
|
+
type WorkerResponse = EvaluationResponse
|
|
50
44
|
|
|
51
45
|
const scriptKind = (file: string): ts.ScriptKind => {
|
|
52
46
|
if (file.endsWith(".tsx")) return ts.ScriptKind.TSX
|
|
@@ -229,27 +223,6 @@ const evaluate = (
|
|
|
229
223
|
)
|
|
230
224
|
}
|
|
231
225
|
|
|
232
|
-
const simulate = (
|
|
233
|
-
api: PublicApi,
|
|
234
|
-
request: DevToolsProtocol.SimulationRequest,
|
|
235
|
-
options: Pick<ProjectInspector.InspectOptions, "root">
|
|
236
|
-
): Effect.Effect<DevToolsProtocol.SimulationResult, ProjectInspector.EvaluationError> =>
|
|
237
|
-
runWorker({ _tag: "Simulate", root: options.root, request }).pipe(
|
|
238
|
-
Effect.timeout("10 seconds"),
|
|
239
|
-
Effect.flatMap((response) => {
|
|
240
|
-
if (response._tag === "InspectedMachines") {
|
|
241
|
-
return Effect.fail(new Error("The isolated planner returned an inspection response"))
|
|
242
|
-
}
|
|
243
|
-
return Schema.decodeUnknownEffect(DevToolsProtocol.SimulationResult)(response)
|
|
244
|
-
}),
|
|
245
|
-
Effect.mapError((cause) =>
|
|
246
|
-
new api.EvaluationError({
|
|
247
|
-
message: "The isolated machine planner failed",
|
|
248
|
-
cause
|
|
249
|
-
})
|
|
250
|
-
)
|
|
251
|
-
)
|
|
252
|
-
|
|
253
226
|
const make = (api: PublicApi) =>
|
|
254
227
|
Effect.gen(function*() {
|
|
255
228
|
const discover = yield* makeDiscovery(api)
|
|
@@ -258,8 +231,7 @@ const make = (api: PublicApi) =>
|
|
|
258
231
|
return api.ProjectInspector.of({
|
|
259
232
|
discover,
|
|
260
233
|
evaluate: (candidates, options) => evaluate(api, candidates, options),
|
|
261
|
-
inspect
|
|
262
|
-
simulate: (request, options) => simulate(api, request, options)
|
|
234
|
+
inspect
|
|
263
235
|
})
|
|
264
236
|
})
|
|
265
237
|
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Side-effect-free, best-effort simulation over a machine document.
|
|
3
|
-
*
|
|
4
|
-
* @since 0.23.0
|
|
5
|
-
*/
|
|
6
|
-
import * as Schema from "effect/Schema";
|
|
7
|
-
import type * as MachineDocument from "./MachineDocument.js";
|
|
8
|
-
/**
|
|
9
|
-
* Serializable state of a simulation session.
|
|
10
|
-
*
|
|
11
|
-
* @category schemas
|
|
12
|
-
* @since 0.23.0
|
|
13
|
-
*/
|
|
14
|
-
export declare const Snapshot: Schema.Struct<{
|
|
15
|
-
readonly step: Schema.Natural;
|
|
16
|
-
readonly activePaths: Schema.$Array<Schema.String>;
|
|
17
|
-
readonly candidateEvents: Schema.$Array<Schema.String>;
|
|
18
|
-
}>;
|
|
19
|
-
/**
|
|
20
|
-
* @category models
|
|
21
|
-
* @since 0.23.0
|
|
22
|
-
*/
|
|
23
|
-
export type Snapshot = Schema.Schema.Type<typeof Snapshot>;
|
|
24
|
-
/**
|
|
25
|
-
* Opaque simulation state paired with its source document.
|
|
26
|
-
*
|
|
27
|
-
* @category models
|
|
28
|
-
* @since 0.23.0
|
|
29
|
-
*/
|
|
30
|
-
export interface Session {
|
|
31
|
-
readonly document: MachineDocument.MachineDocument;
|
|
32
|
-
readonly snapshot: Snapshot;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Runtime behavior deliberately skipped by a best-effort step.
|
|
36
|
-
*
|
|
37
|
-
* @category schemas
|
|
38
|
-
* @since 0.23.0
|
|
39
|
-
*/
|
|
40
|
-
export declare const Note: Schema.Literals<readonly ["runtime-effects-skipped", "state-updates-skipped", "reentry-lifecycles-skipped", "automatic-transitions-skipped"]>;
|
|
41
|
-
/**
|
|
42
|
-
* @category models
|
|
43
|
-
* @since 0.23.0
|
|
44
|
-
*/
|
|
45
|
-
export type Note = Schema.Schema.Type<typeof Note>;
|
|
46
|
-
/**
|
|
47
|
-
* A topologically deterministic step.
|
|
48
|
-
*
|
|
49
|
-
* @category schemas
|
|
50
|
-
* @since 0.23.0
|
|
51
|
-
*/
|
|
52
|
-
export declare const Applied: Schema.Struct<{
|
|
53
|
-
readonly _tag: Schema.tag<"Applied">;
|
|
54
|
-
readonly notes: Schema.$Array<Schema.Literals<readonly ["runtime-effects-skipped", "state-updates-skipped", "reentry-lifecycles-skipped", "automatic-transitions-skipped"]>>;
|
|
55
|
-
readonly event: Schema.String;
|
|
56
|
-
readonly transitionIds: Schema.$Array<Schema.String>;
|
|
57
|
-
readonly session: Schema.Struct<{
|
|
58
|
-
readonly step: Schema.Natural;
|
|
59
|
-
readonly activePaths: Schema.$Array<Schema.String>;
|
|
60
|
-
readonly candidateEvents: Schema.$Array<Schema.String>;
|
|
61
|
-
}>;
|
|
62
|
-
}>;
|
|
63
|
-
/**
|
|
64
|
-
* @category models
|
|
65
|
-
* @since 0.23.0
|
|
66
|
-
*/
|
|
67
|
-
export type Applied = Schema.Schema.Type<typeof Applied>;
|
|
68
|
-
/**
|
|
69
|
-
* An event with no registration in the current active configuration.
|
|
70
|
-
*
|
|
71
|
-
* @category schemas
|
|
72
|
-
* @since 0.23.0
|
|
73
|
-
*/
|
|
74
|
-
export declare const Blocked: Schema.Struct<{
|
|
75
|
-
readonly _tag: Schema.tag<"Blocked">;
|
|
76
|
-
readonly reason: Schema.Literal<"event-not-enabled">;
|
|
77
|
-
readonly event: Schema.String;
|
|
78
|
-
readonly transitionIds: Schema.$Array<Schema.String>;
|
|
79
|
-
readonly session: Schema.Struct<{
|
|
80
|
-
readonly step: Schema.Natural;
|
|
81
|
-
readonly activePaths: Schema.$Array<Schema.String>;
|
|
82
|
-
readonly candidateEvents: Schema.$Array<Schema.String>;
|
|
83
|
-
}>;
|
|
84
|
-
}>;
|
|
85
|
-
/**
|
|
86
|
-
* @category models
|
|
87
|
-
* @since 0.23.0
|
|
88
|
-
*/
|
|
89
|
-
export type Blocked = Schema.Schema.Type<typeof Blocked>;
|
|
90
|
-
/**
|
|
91
|
-
* A step whose topology depends on runtime behavior the document cannot safely
|
|
92
|
-
* evaluate.
|
|
93
|
-
*
|
|
94
|
-
* @category schemas
|
|
95
|
-
* @since 0.23.0
|
|
96
|
-
*/
|
|
97
|
-
export declare const Indeterminate: Schema.Struct<{
|
|
98
|
-
readonly _tag: Schema.tag<"Indeterminate">;
|
|
99
|
-
readonly reason: Schema.Literals<readonly ["multiple-transitions", "declinable-transition", "conditional-branches", "history-target", "choice-target", "missing-target"]>;
|
|
100
|
-
readonly event: Schema.String;
|
|
101
|
-
readonly transitionIds: Schema.$Array<Schema.String>;
|
|
102
|
-
readonly session: Schema.Struct<{
|
|
103
|
-
readonly step: Schema.Natural;
|
|
104
|
-
readonly activePaths: Schema.$Array<Schema.String>;
|
|
105
|
-
readonly candidateEvents: Schema.$Array<Schema.String>;
|
|
106
|
-
}>;
|
|
107
|
-
}>;
|
|
108
|
-
/**
|
|
109
|
-
* @category models
|
|
110
|
-
* @since 0.23.0
|
|
111
|
-
*/
|
|
112
|
-
export type Indeterminate = Schema.Schema.Type<typeof Indeterminate>;
|
|
113
|
-
/**
|
|
114
|
-
* @category schemas
|
|
115
|
-
* @since 0.23.0
|
|
116
|
-
*/
|
|
117
|
-
export declare const StepResult: Schema.Union<readonly [Schema.Struct<{
|
|
118
|
-
readonly _tag: Schema.tag<"Applied">;
|
|
119
|
-
readonly notes: Schema.$Array<Schema.Literals<readonly ["runtime-effects-skipped", "state-updates-skipped", "reentry-lifecycles-skipped", "automatic-transitions-skipped"]>>;
|
|
120
|
-
readonly event: Schema.String;
|
|
121
|
-
readonly transitionIds: Schema.$Array<Schema.String>;
|
|
122
|
-
readonly session: Schema.Struct<{
|
|
123
|
-
readonly step: Schema.Natural;
|
|
124
|
-
readonly activePaths: Schema.$Array<Schema.String>;
|
|
125
|
-
readonly candidateEvents: Schema.$Array<Schema.String>;
|
|
126
|
-
}>;
|
|
127
|
-
}>, Schema.Struct<{
|
|
128
|
-
readonly _tag: Schema.tag<"Blocked">;
|
|
129
|
-
readonly reason: Schema.Literal<"event-not-enabled">;
|
|
130
|
-
readonly event: Schema.String;
|
|
131
|
-
readonly transitionIds: Schema.$Array<Schema.String>;
|
|
132
|
-
readonly session: Schema.Struct<{
|
|
133
|
-
readonly step: Schema.Natural;
|
|
134
|
-
readonly activePaths: Schema.$Array<Schema.String>;
|
|
135
|
-
readonly candidateEvents: Schema.$Array<Schema.String>;
|
|
136
|
-
}>;
|
|
137
|
-
}>, Schema.Struct<{
|
|
138
|
-
readonly _tag: Schema.tag<"Indeterminate">;
|
|
139
|
-
readonly reason: Schema.Literals<readonly ["multiple-transitions", "declinable-transition", "conditional-branches", "history-target", "choice-target", "missing-target"]>;
|
|
140
|
-
readonly event: Schema.String;
|
|
141
|
-
readonly transitionIds: Schema.$Array<Schema.String>;
|
|
142
|
-
readonly session: Schema.Struct<{
|
|
143
|
-
readonly step: Schema.Natural;
|
|
144
|
-
readonly activePaths: Schema.$Array<Schema.String>;
|
|
145
|
-
readonly candidateEvents: Schema.$Array<Schema.String>;
|
|
146
|
-
}>;
|
|
147
|
-
}>]>;
|
|
148
|
-
/**
|
|
149
|
-
* @category models
|
|
150
|
-
* @since 0.23.0
|
|
151
|
-
*/
|
|
152
|
-
export type StepResult = Schema.Schema.Type<typeof StepResult>;
|
|
153
|
-
/**
|
|
154
|
-
* Starts from the captured snapshot when present, otherwise from the static
|
|
155
|
-
* initial topology.
|
|
156
|
-
*
|
|
157
|
-
* @category constructors
|
|
158
|
-
* @since 0.23.0
|
|
159
|
-
*/
|
|
160
|
-
export declare const start: (document: MachineDocument.MachineDocument) => Session;
|
|
161
|
-
/**
|
|
162
|
-
* Sends an event without running user code. `Applied` means the active topology
|
|
163
|
-
* is statically known; its notes list runtime behavior that was skipped.
|
|
164
|
-
*
|
|
165
|
-
* @category combinators
|
|
166
|
-
* @since 0.23.0
|
|
167
|
-
*/
|
|
168
|
-
export declare const send: (session: Session, event: string) => StepResult;
|
|
169
|
-
//# sourceMappingURL=MachineSimulator.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MachineSimulator.d.ts","sourceRoot":"","sources":["../src/MachineSimulator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,KAAK,eAAe,MAAM,sBAAsB,CAAA;AAE5D;;;;;GAKG;AACH,eAAO,MAAM,QAAQ;;;;EAInB,CAAA;AAEF;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,QAAQ,CAAC,CAAA;AAE1D;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC,eAAe,CAAA;IAClD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAC5B;AAED;;;;;GAKG;AACH,eAAO,MAAM,IAAI,+IAKf,CAAA;AAEF;;;GAGG;AACH,MAAM,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAA;AAQlD;;;;;GAKG;AACH,eAAO,MAAM,OAAO;;;;;;;;;;EAIlB,CAAA;AAEF;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,OAAO,CAAC,CAAA;AAExD;;;;;GAKG;AACH,eAAO,MAAM,OAAO;;;;;;;;;;EAIlB,CAAA;AAEF;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,OAAO,CAAC,CAAA;AAExD;;;;;;GAMG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;EAWxB,CAAA;AAEF;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,aAAa,CAAC,CAAA;AAEpE;;;GAGG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAAkD,CAAA;AAEzE;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,UAAU,CAAC,CAAA;AAE9D;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,EAAE,CAAC,QAAQ,EAAE,eAAe,CAAC,eAAe,KAAK,OAAwB,CAAA;AAE3F;;;;;;GAMG;AACH,eAAO,MAAM,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,UAA0B,CAAA"}
|
package/dist/MachineSimulator.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Side-effect-free, best-effort simulation over a machine document.
|
|
3
|
-
*
|
|
4
|
-
* @since 0.23.0
|
|
5
|
-
*/
|
|
6
|
-
import * as Schema from "effect/Schema";
|
|
7
|
-
import * as internal from "./internal/machineSimulator.js";
|
|
8
|
-
/**
|
|
9
|
-
* Serializable state of a simulation session.
|
|
10
|
-
*
|
|
11
|
-
* @category schemas
|
|
12
|
-
* @since 0.23.0
|
|
13
|
-
*/
|
|
14
|
-
export const Snapshot = Schema.Struct({
|
|
15
|
-
step: Schema.Natural,
|
|
16
|
-
activePaths: Schema.Array(Schema.String),
|
|
17
|
-
candidateEvents: Schema.Array(Schema.String)
|
|
18
|
-
});
|
|
19
|
-
/**
|
|
20
|
-
* Runtime behavior deliberately skipped by a best-effort step.
|
|
21
|
-
*
|
|
22
|
-
* @category schemas
|
|
23
|
-
* @since 0.23.0
|
|
24
|
-
*/
|
|
25
|
-
export const Note = Schema.Literals([
|
|
26
|
-
"runtime-effects-skipped",
|
|
27
|
-
"state-updates-skipped",
|
|
28
|
-
"reentry-lifecycles-skipped",
|
|
29
|
-
"automatic-transitions-skipped"
|
|
30
|
-
]);
|
|
31
|
-
const ResultFields = {
|
|
32
|
-
event: Schema.String,
|
|
33
|
-
transitionIds: Schema.Array(Schema.String),
|
|
34
|
-
session: Snapshot
|
|
35
|
-
};
|
|
36
|
-
/**
|
|
37
|
-
* A topologically deterministic step.
|
|
38
|
-
*
|
|
39
|
-
* @category schemas
|
|
40
|
-
* @since 0.23.0
|
|
41
|
-
*/
|
|
42
|
-
export const Applied = Schema.Struct({
|
|
43
|
-
...ResultFields,
|
|
44
|
-
_tag: Schema.tag("Applied"),
|
|
45
|
-
notes: Schema.Array(Note)
|
|
46
|
-
});
|
|
47
|
-
/**
|
|
48
|
-
* An event with no registration in the current active configuration.
|
|
49
|
-
*
|
|
50
|
-
* @category schemas
|
|
51
|
-
* @since 0.23.0
|
|
52
|
-
*/
|
|
53
|
-
export const Blocked = Schema.Struct({
|
|
54
|
-
...ResultFields,
|
|
55
|
-
_tag: Schema.tag("Blocked"),
|
|
56
|
-
reason: Schema.Literal("event-not-enabled")
|
|
57
|
-
});
|
|
58
|
-
/**
|
|
59
|
-
* A step whose topology depends on runtime behavior the document cannot safely
|
|
60
|
-
* evaluate.
|
|
61
|
-
*
|
|
62
|
-
* @category schemas
|
|
63
|
-
* @since 0.23.0
|
|
64
|
-
*/
|
|
65
|
-
export const Indeterminate = Schema.Struct({
|
|
66
|
-
...ResultFields,
|
|
67
|
-
_tag: Schema.tag("Indeterminate"),
|
|
68
|
-
reason: Schema.Literals([
|
|
69
|
-
"multiple-transitions",
|
|
70
|
-
"declinable-transition",
|
|
71
|
-
"conditional-branches",
|
|
72
|
-
"history-target",
|
|
73
|
-
"choice-target",
|
|
74
|
-
"missing-target"
|
|
75
|
-
])
|
|
76
|
-
});
|
|
77
|
-
/**
|
|
78
|
-
* @category schemas
|
|
79
|
-
* @since 0.23.0
|
|
80
|
-
*/
|
|
81
|
-
export const StepResult = Schema.Union([Applied, Blocked, Indeterminate]);
|
|
82
|
-
/**
|
|
83
|
-
* Starts from the captured snapshot when present, otherwise from the static
|
|
84
|
-
* initial topology.
|
|
85
|
-
*
|
|
86
|
-
* @category constructors
|
|
87
|
-
* @since 0.23.0
|
|
88
|
-
*/
|
|
89
|
-
export const start = internal.start;
|
|
90
|
-
/**
|
|
91
|
-
* Sends an event without running user code. `Applied` means the active topology
|
|
92
|
-
* is statically known; its notes list runtime behavior that was skipped.
|
|
93
|
-
*
|
|
94
|
-
* @category combinators
|
|
95
|
-
* @since 0.23.0
|
|
96
|
-
*/
|
|
97
|
-
export const send = internal.send;
|
|
98
|
-
//# sourceMappingURL=MachineSimulator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MachineSimulator.js","sourceRoot":"","sources":["../src/MachineSimulator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,QAAQ,MAAM,gCAAgC,CAAA;AAG1D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC,OAAO;IACpB,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;IACxC,eAAe,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;CAC7C,CAAC,CAAA;AAmBF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC;IAClC,yBAAyB;IACzB,uBAAuB;IACvB,4BAA4B;IAC5B,+BAA+B;CAChC,CAAC,CAAA;AAQF,MAAM,YAAY,GAAG;IACnB,KAAK,EAAE,MAAM,CAAC,MAAM;IACpB,aAAa,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;IAC1C,OAAO,EAAE,QAAQ;CAClB,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC;IACnC,GAAG,YAAY;IACf,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;CAC1B,CAAC,CAAA;AAQF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC;IACnC,GAAG,YAAY;IACf,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC;CAC5C,CAAC,CAAA;AAQF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC;IACzC,GAAG,YAAY;IACf,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC;QACtB,sBAAsB;QACtB,uBAAuB;QACvB,sBAAsB;QACtB,gBAAgB;QAChB,eAAe;QACf,gBAAgB;KACjB,CAAC;CACH,CAAC,CAAA;AAQF;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAA;AAQzE;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,KAAK,GAA2D,QAAQ,CAAC,KAAK,CAAA;AAE3F;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,IAAI,GAAoD,QAAQ,CAAC,IAAI,CAAA"}
|