@doeixd/machine 0.0.17 → 0.0.19

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.
@@ -0,0 +1,500 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/extract.ts
21
+ var extract_exports = {};
22
+ __export(extract_exports, {
23
+ ADVANCED_CONFIG_EXAMPLES: () => ADVANCED_CONFIG_EXAMPLES,
24
+ _typeToJson: () => _typeToJson,
25
+ extractMachine: () => extractMachine,
26
+ extractMachines: () => extractMachines,
27
+ generateChart: () => generateChart
28
+ });
29
+ module.exports = __toCommonJS(extract_exports);
30
+ var import_ts_morph = require("ts-morph");
31
+ function _typeToJson(type, verbose = false) {
32
+ const symbol = type.getSymbol();
33
+ if (symbol && symbol.getDeclarations().some(import_ts_morph.Node.isClassDeclaration)) {
34
+ return symbol.getName();
35
+ }
36
+ if (type.isStringLiteral()) return type.getLiteralValue();
37
+ if (type.isNumberLiteral()) return type.getLiteralValue();
38
+ if (type.isBooleanLiteral()) return type.getLiteralValue();
39
+ if (type.isString()) return "string";
40
+ if (type.isNumber()) return "number";
41
+ if (type.isBoolean()) return "boolean";
42
+ if (type.isArray()) {
43
+ const elementType = type.getArrayElementTypeOrThrow();
44
+ return [_typeToJson(elementType, verbose)];
45
+ }
46
+ if (type.isObject() || type.isIntersection()) {
47
+ const obj = {};
48
+ const properties = type.getProperties();
49
+ for (const prop of properties) {
50
+ const propName = prop.getName();
51
+ if (propName.startsWith("__@")) continue;
52
+ const declaration = prop.getValueDeclaration();
53
+ if (!declaration) continue;
54
+ try {
55
+ obj[propName] = _typeToJson(declaration.getType(), verbose);
56
+ } catch (e) {
57
+ if (verbose) console.error(` Warning: Failed to serialize property ${propName}:`, e);
58
+ obj[propName] = "unknown";
59
+ }
60
+ }
61
+ return Object.keys(obj).length > 0 ? obj : null;
62
+ }
63
+ if (verbose) {
64
+ console.error(` Unhandled type: ${type.getText()}`);
65
+ }
66
+ return "unknown";
67
+ }
68
+ function resolveClassName(node) {
69
+ if (import_ts_morph.Node.isIdentifier(node)) {
70
+ return node.getText();
71
+ }
72
+ if (import_ts_morph.Node.isTypeOfExpression(node)) {
73
+ return node.getExpression().getText();
74
+ }
75
+ return "unknown";
76
+ }
77
+ function parseObjectLiteral(obj) {
78
+ if (!import_ts_morph.Node.isObjectLiteralExpression(obj)) {
79
+ return {};
80
+ }
81
+ const result = {};
82
+ for (const prop of obj.getProperties()) {
83
+ if (import_ts_morph.Node.isPropertyAssignment(prop)) {
84
+ const name = prop.getName();
85
+ const init = prop.getInitializer();
86
+ if (init) {
87
+ if (import_ts_morph.Node.isStringLiteral(init)) {
88
+ result[name] = init.getLiteralValue();
89
+ } else if (import_ts_morph.Node.isNumericLiteral(init)) {
90
+ result[name] = init.getLiteralValue();
91
+ } else if (init.getText() === "true" || init.getText() === "false") {
92
+ result[name] = init.getText() === "true";
93
+ } else if (import_ts_morph.Node.isIdentifier(init)) {
94
+ result[name] = init.getText();
95
+ } else if (import_ts_morph.Node.isObjectLiteralExpression(init)) {
96
+ result[name] = parseObjectLiteral(init);
97
+ } else if (import_ts_morph.Node.isArrayLiteralExpression(init)) {
98
+ result[name] = init.getElements().map((el) => {
99
+ if (import_ts_morph.Node.isObjectLiteralExpression(el)) {
100
+ return parseObjectLiteral(el);
101
+ }
102
+ return el.getText();
103
+ });
104
+ }
105
+ }
106
+ }
107
+ }
108
+ return result;
109
+ }
110
+ function parseInvokeService(obj) {
111
+ if (!import_ts_morph.Node.isObjectLiteralExpression(obj)) {
112
+ return {};
113
+ }
114
+ const service = {};
115
+ for (const prop of obj.getProperties()) {
116
+ if (import_ts_morph.Node.isPropertyAssignment(prop)) {
117
+ const name = prop.getName();
118
+ const init = prop.getInitializer();
119
+ if (!init) continue;
120
+ if (name === "onDone" || name === "onError") {
121
+ service[name] = resolveClassName(init);
122
+ } else if (import_ts_morph.Node.isStringLiteral(init)) {
123
+ service[name] = init.getLiteralValue();
124
+ } else if (import_ts_morph.Node.isIdentifier(init)) {
125
+ service[name] = init.getText();
126
+ }
127
+ }
128
+ }
129
+ return service;
130
+ }
131
+ function extractFromCallExpression(call, verbose = false) {
132
+ if (!import_ts_morph.Node.isCallExpression(call)) {
133
+ return null;
134
+ }
135
+ const expression = call.getExpression();
136
+ const fnName = import_ts_morph.Node.isIdentifier(expression) ? expression.getText() : null;
137
+ if (!fnName) {
138
+ return null;
139
+ }
140
+ const metadata = {};
141
+ const args = call.getArguments();
142
+ switch (fnName) {
143
+ case "transitionTo":
144
+ if (args[0]) {
145
+ metadata.target = resolveClassName(args[0]);
146
+ }
147
+ break;
148
+ case "describe":
149
+ if (args[0] && import_ts_morph.Node.isStringLiteral(args[0])) {
150
+ metadata.description = args[0].getLiteralValue();
151
+ }
152
+ if (args[1] && import_ts_morph.Node.isCallExpression(args[1])) {
153
+ const nested = extractFromCallExpression(args[1], verbose);
154
+ if (nested) {
155
+ Object.assign(metadata, nested);
156
+ }
157
+ }
158
+ break;
159
+ case "guarded":
160
+ if (args[0]) {
161
+ const guard = parseObjectLiteral(args[0]);
162
+ if (Object.keys(guard).length > 0) {
163
+ metadata.guards = [guard];
164
+ }
165
+ }
166
+ if (args[1] && import_ts_morph.Node.isCallExpression(args[1])) {
167
+ const nested = extractFromCallExpression(args[1], verbose);
168
+ if (nested) {
169
+ Object.assign(metadata, nested);
170
+ }
171
+ }
172
+ break;
173
+ case "invoke":
174
+ if (args[0]) {
175
+ const service = parseInvokeService(args[0]);
176
+ if (Object.keys(service).length > 0) {
177
+ metadata.invoke = service;
178
+ }
179
+ }
180
+ break;
181
+ case "action":
182
+ if (args[0]) {
183
+ const actionMeta = parseObjectLiteral(args[0]);
184
+ if (Object.keys(actionMeta).length > 0) {
185
+ metadata.actions = [actionMeta];
186
+ }
187
+ }
188
+ if (args[1] && import_ts_morph.Node.isCallExpression(args[1])) {
189
+ const nested = extractFromCallExpression(args[1], verbose);
190
+ if (nested) {
191
+ Object.assign(metadata, nested);
192
+ }
193
+ }
194
+ break;
195
+ case "guard":
196
+ if (args[2]) {
197
+ const options = parseObjectLiteral(args[2]);
198
+ if (options.description) {
199
+ metadata.description = options.description;
200
+ }
201
+ }
202
+ metadata.guards = [{ name: "runtime_guard", description: metadata.description || "Synchronous condition check" }];
203
+ if (args[1] && import_ts_morph.Node.isCallExpression(args[1])) {
204
+ const nested = extractFromCallExpression(args[1], verbose);
205
+ if (nested) {
206
+ Object.assign(metadata, nested);
207
+ }
208
+ }
209
+ break;
210
+ case "guardAsync":
211
+ if (args[2]) {
212
+ const options = parseObjectLiteral(args[2]);
213
+ if (options.description) {
214
+ metadata.description = options.description;
215
+ }
216
+ }
217
+ metadata.guards = [{ name: "runtime_guard_async", description: metadata.description || "Asynchronous condition check" }];
218
+ if (args[1] && import_ts_morph.Node.isCallExpression(args[1])) {
219
+ const nested = extractFromCallExpression(args[1], verbose);
220
+ if (nested) {
221
+ Object.assign(metadata, nested);
222
+ }
223
+ }
224
+ break;
225
+ default:
226
+ return null;
227
+ }
228
+ return Object.keys(metadata).length > 0 ? metadata : null;
229
+ }
230
+ function extractMetaFromMember(member, verbose = false) {
231
+ if (!import_ts_morph.Node.isPropertyDeclaration(member)) {
232
+ if (verbose) console.error(` āš ļø Not a property declaration`);
233
+ return null;
234
+ }
235
+ const initializer = member.getInitializer();
236
+ if (!initializer) {
237
+ if (verbose) console.error(` āš ļø No initializer`);
238
+ return null;
239
+ }
240
+ if (!import_ts_morph.Node.isCallExpression(initializer)) {
241
+ if (verbose) console.error(` āš ļø Initializer is not a call expression`);
242
+ return null;
243
+ }
244
+ const metadata = extractFromCallExpression(initializer, verbose);
245
+ if (metadata && verbose) {
246
+ console.error(` āœ… Extracted metadata:`, JSON.stringify(metadata, null, 2));
247
+ }
248
+ return metadata;
249
+ }
250
+ function analyzeStateNode(classSymbol, verbose = false) {
251
+ const chartNode = { on: {} };
252
+ const classDeclaration = classSymbol.getDeclarations()[0];
253
+ if (!classDeclaration || !import_ts_morph.Node.isClassDeclaration(classDeclaration)) {
254
+ if (verbose) {
255
+ console.error(`āš ļø Warning: Could not get class declaration for ${classSymbol.getName()}`);
256
+ }
257
+ return chartNode;
258
+ }
259
+ const className = classSymbol.getName();
260
+ if (verbose) {
261
+ console.error(` Analyzing state: ${className}`);
262
+ }
263
+ for (const member of classDeclaration.getInstanceMembers()) {
264
+ const memberName = member.getName();
265
+ if (verbose) {
266
+ console.error(` Checking member: ${memberName}`);
267
+ }
268
+ const meta = extractMetaFromMember(member, verbose);
269
+ if (!meta) continue;
270
+ if (verbose) {
271
+ console.error(` Found transition: ${memberName}`);
272
+ }
273
+ const { invoke, actions, guards, ...onEntry } = meta;
274
+ if (invoke) {
275
+ if (!chartNode.invoke) chartNode.invoke = [];
276
+ chartNode.invoke.push({
277
+ src: invoke.src,
278
+ onDone: { target: invoke.onDone },
279
+ onError: { target: invoke.onError },
280
+ description: invoke.description
281
+ });
282
+ if (verbose) {
283
+ console.error(` → Invoke: ${invoke.src}`);
284
+ }
285
+ }
286
+ if (onEntry.target) {
287
+ const transition = { target: onEntry.target };
288
+ if (onEntry.description) {
289
+ transition.description = onEntry.description;
290
+ }
291
+ if (guards) {
292
+ transition.cond = guards.map((g) => g.name).join(" && ");
293
+ if (verbose) {
294
+ console.error(` → Guard: ${transition.cond}`);
295
+ }
296
+ }
297
+ if (actions && actions.length > 0) {
298
+ transition.actions = actions.map((a) => a.name);
299
+ if (verbose) {
300
+ console.error(` → Actions: ${transition.actions.join(", ")}`);
301
+ }
302
+ }
303
+ chartNode.on[memberName] = transition;
304
+ if (verbose) {
305
+ console.error(` → Target: ${onEntry.target}`);
306
+ }
307
+ }
308
+ }
309
+ return chartNode;
310
+ }
311
+ function analyzeStateNodeWithNesting(className, classSymbol, sourceFile, childConfig, verbose = false) {
312
+ const stateNode = analyzeStateNode(classSymbol, verbose);
313
+ if (childConfig) {
314
+ if (verbose) {
315
+ console.error(` šŸ‘Ŗ Analyzing children for state: ${className}`);
316
+ }
317
+ stateNode.initial = childConfig.initialState;
318
+ stateNode.states = {};
319
+ for (const childClassName of childConfig.classes) {
320
+ const childClassDeclaration = sourceFile.getClass(childClassName);
321
+ if (childClassDeclaration) {
322
+ const childSymbol = childClassDeclaration.getSymbolOrThrow();
323
+ stateNode.states[childClassName] = analyzeStateNode(childSymbol, verbose);
324
+ } else {
325
+ console.warn(`āš ļø Warning: Child class '${childClassName}' not found.`);
326
+ }
327
+ }
328
+ }
329
+ return stateNode;
330
+ }
331
+ function extractMachine(config, project, verbose = false) {
332
+ if (verbose) {
333
+ console.error(`
334
+ šŸ” Analyzing machine: ${config.id}`);
335
+ console.error(` Source: ${config.input}`);
336
+ }
337
+ const sourceFile = project.getSourceFile(config.input);
338
+ if (!sourceFile) {
339
+ throw new Error(`Source file not found: ${config.input}`);
340
+ }
341
+ if (config.parallel) {
342
+ if (verbose) {
343
+ console.error(` ā¹ļø Parallel machine detected. Analyzing regions.`);
344
+ }
345
+ const parallelChart = {
346
+ id: config.id,
347
+ type: "parallel",
348
+ states: {}
349
+ };
350
+ if (config.description) {
351
+ parallelChart.description = config.description;
352
+ }
353
+ for (const region of config.parallel.regions) {
354
+ if (verbose) {
355
+ console.error(` šŸ“ Analyzing region: ${region.name}`);
356
+ }
357
+ const regionStates = {};
358
+ for (const className of region.classes) {
359
+ const classDeclaration = sourceFile.getClass(className);
360
+ if (classDeclaration) {
361
+ const classSymbol = classDeclaration.getSymbolOrThrow();
362
+ regionStates[className] = analyzeStateNode(classSymbol, verbose);
363
+ } else {
364
+ console.warn(`āš ļø Warning: Class '${className}' not found for region '${region.name}'.`);
365
+ }
366
+ }
367
+ parallelChart.states[region.name] = {
368
+ initial: region.initialState,
369
+ states: regionStates
370
+ };
371
+ }
372
+ if (verbose) {
373
+ console.error(` āœ… Extracted ${config.parallel.regions.length} parallel regions`);
374
+ }
375
+ return parallelChart;
376
+ }
377
+ if (!config.initialState || !config.classes) {
378
+ throw new Error(`Machine config for '${config.id}' must have either 'parallel' or 'initialState'/'classes'.`);
379
+ }
380
+ const fullChart = {
381
+ id: config.id,
382
+ initial: config.initialState,
383
+ states: {}
384
+ };
385
+ if (config.description) {
386
+ fullChart.description = config.description;
387
+ }
388
+ for (const className of config.classes) {
389
+ const classDeclaration = sourceFile.getClass(className);
390
+ if (!classDeclaration) {
391
+ console.warn(`āš ļø Warning: Class '${className}' not found in '${config.input}'. Skipping.`);
392
+ continue;
393
+ }
394
+ const classSymbol = classDeclaration.getSymbolOrThrow();
395
+ const hasChildren = className === config.initialState && config.children;
396
+ const stateNode = analyzeStateNodeWithNesting(
397
+ className,
398
+ classSymbol,
399
+ sourceFile,
400
+ hasChildren ? config.children : void 0,
401
+ verbose
402
+ );
403
+ fullChart.states[className] = stateNode;
404
+ }
405
+ if (verbose) {
406
+ console.error(` āœ… Extracted ${config.classes.length} states`);
407
+ }
408
+ return fullChart;
409
+ }
410
+ function extractMachines(config) {
411
+ var _a;
412
+ const verbose = (_a = config.verbose) != null ? _a : false;
413
+ if (verbose) {
414
+ console.error(`
415
+ šŸ“Š Starting statechart extraction`);
416
+ console.error(` Machines to extract: ${config.machines.length}`);
417
+ }
418
+ const project = new import_ts_morph.Project();
419
+ project.addSourceFilesAtPaths("src/**/*.ts");
420
+ project.addSourceFilesAtPaths("examples/**/*.ts");
421
+ const results = [];
422
+ for (const machineConfig of config.machines) {
423
+ try {
424
+ const chart = extractMachine(machineConfig, project, verbose);
425
+ results.push(chart);
426
+ } catch (error) {
427
+ console.error(`āŒ Error extracting machine '${machineConfig.id}':`, error);
428
+ if (!verbose) {
429
+ console.error(` Run with --verbose for more details`);
430
+ }
431
+ }
432
+ }
433
+ if (verbose) {
434
+ console.error(`
435
+ āœ… Extraction complete: ${results.length}/${config.machines.length} machines extracted`);
436
+ }
437
+ return results;
438
+ }
439
+ function generateChart() {
440
+ const config = {
441
+ input: "examples/authMachine.ts",
442
+ classes: [
443
+ "LoggedOutMachine",
444
+ "LoggingInMachine",
445
+ "LoggedInMachine",
446
+ "SessionExpiredMachine",
447
+ "ErrorMachine"
448
+ ],
449
+ id: "auth",
450
+ initialState: "LoggedOutMachine",
451
+ description: "Authentication state machine"
452
+ };
453
+ console.error("šŸ” Using legacy generateChart function");
454
+ console.error("āš ļø Consider using extractMachines() with a config file instead\n");
455
+ const project = new import_ts_morph.Project();
456
+ project.addSourceFilesAtPaths("src/**/*.ts");
457
+ project.addSourceFilesAtPaths("examples/**/*.ts");
458
+ try {
459
+ const chart = extractMachine(config, project, true);
460
+ console.log(JSON.stringify(chart, null, 2));
461
+ } catch (error) {
462
+ console.error(`āŒ Error:`, error);
463
+ process.exit(1);
464
+ }
465
+ }
466
+ var ADVANCED_CONFIG_EXAMPLES = {
467
+ hierarchical: {
468
+ input: "examples/dashboardMachine.ts",
469
+ id: "dashboard",
470
+ classes: ["DashboardMachine", "LoggedOutMachine"],
471
+ initialState: "DashboardMachine",
472
+ children: {
473
+ contextProperty: "child",
474
+ initialState: "ViewingChildMachine",
475
+ classes: ["ViewingChildMachine", "EditingChildMachine"]
476
+ }
477
+ },
478
+ parallel: {
479
+ input: "examples/editorMachine.ts",
480
+ id: "editor",
481
+ parallel: {
482
+ regions: [
483
+ {
484
+ name: "fontWeight",
485
+ initialState: "NormalWeight",
486
+ classes: ["NormalWeight", "BoldWeight"]
487
+ },
488
+ {
489
+ name: "textDecoration",
490
+ initialState: "NoDecoration",
491
+ classes: ["NoDecoration", "UnderlineState"]
492
+ }
493
+ ]
494
+ }
495
+ }
496
+ };
497
+ if (require.main === module) {
498
+ generateChart();
499
+ }
500
+ //# sourceMappingURL=extract.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/extract.ts"],
4
+ "sourcesContent": ["/**\n * @file Static Statechart Extractor for @doeixd/machine\n * @description\n * This build-time script uses the TypeScript Compiler API via `ts-morph` to analyze\n * your machine source code. It reads the \"type-level metadata\" encoded by the\n * primitives (`transitionTo`, `guarded`, etc.) and generates a formal, JSON-serializable\n * statechart definition compatible with tools like Stately Viz.\n *\n * This script does NOT execute your code. It performs a purely static analysis of the types.\n *\n * @usage\n * 1. Ensure you have `ts-node` and `ts-morph` installed: `npm install -D ts-node ts-morph`\n * 2. Create a configuration object or use .statechart.config.ts\n * 3. Run the script from your project root: `npx ts-node ./scripts/extract-statechart.ts`\n */\n\nimport { Project, Type, Node } from 'ts-morph';\n\n// =============================================================================\n// SECTION: CONFIGURATION TYPES\n// =============================================================================\n\n/**\n * Configuration for a parallel region\n */\nexport interface ParallelRegionConfig {\n /** A unique name for this region (e.g., 'fontStyle') */\n name: string;\n /** The initial state class for this region */\n initialState: string;\n /** All reachable state classes within this region */\n classes: string[];\n}\n\n/**\n * Configuration for child states in a hierarchical machine\n */\nexport interface ChildStatesConfig {\n /** The property in the parent's context that holds the child machine */\n contextProperty: string;\n /** An array of all possible child state class names */\n classes: string[];\n /** The initial child state */\n initialState: string;\n}\n\n/**\n * Configuration for a single machine to extract\n */\nexport interface MachineConfig {\n /** Path to the source file containing the machine */\n input: string;\n /** Output file path (optional, defaults to stdout) */\n output?: string;\n /** Top-level ID for the statechart */\n id: string;\n /** Optional description of the machine */\n description?: string;\n\n // EITHER `initialState` and `classes` for an FSM...\n /** Array of class names that represent states (for simple FSM) */\n classes?: string[];\n /** Name of the class that represents the initial state (for simple FSM) */\n initialState?: string;\n\n // OR `parallel` for a parallel machine.\n /** Configuration for parallel regions (mutually exclusive with initialState/classes) */\n parallel?: {\n regions: ParallelRegionConfig[];\n };\n\n /** Configuration for hierarchical/nested states */\n children?: ChildStatesConfig;\n}\n\n/**\n * Global extraction configuration\n */\nexport interface ExtractionConfig {\n /** Array of machines to extract */\n machines: MachineConfig[];\n /** Validate output against XState JSON schema (optional) */\n validate?: boolean;\n /** Output format (json, mermaid, or both) */\n format?: 'json' | 'mermaid' | 'both';\n /** Watch mode - auto-regenerate on file changes */\n watch?: boolean;\n /** Verbose logging */\n verbose?: boolean;\n}\n\n// =============================================================================\n// SECTION: CORE ANALYSIS LOGIC\n// =============================================================================\n\n/**\n * Recursively traverses a `ts-morph` Type object and serializes it into a\n * plain JSON-compatible value. It's smart enough to resolve class constructor\n * types into their string names.\n *\n * Note: This function is kept for future extensibility but is not currently used\n * as the AST-based extraction approach (via extractFromCallExpression) is preferred.\n *\n * @param type - The `ts-morph` Type object to serialize.\n * @param verbose - Enable debug logging\n * @returns A JSON-compatible value (string, number, object, array).\n * @internal\n */\n\nexport function _typeToJson(type: Type, verbose = false): any {\n // --- Terminal Types ---\n const symbol = type.getSymbol();\n if (symbol && symbol.getDeclarations().some(Node.isClassDeclaration)) {\n return symbol.getName(); // Resolve class types to their string name\n }\n if (type.isStringLiteral()) return type.getLiteralValue();\n if (type.isNumberLiteral()) return type.getLiteralValue();\n if (type.isBooleanLiteral()) return type.getLiteralValue();\n if (type.isString()) return 'string';\n if (type.isNumber()) return 'number';\n if (type.isBoolean()) return 'boolean';\n\n // --- Recursive Types ---\n if (type.isArray()) {\n const elementType = type.getArrayElementTypeOrThrow();\n return [_typeToJson(elementType, verbose)];\n }\n\n // --- Object Types ---\n if (type.isObject() || type.isIntersection()) {\n const obj: { [key: string]: any } = {};\n const properties = type.getProperties();\n\n // Filter out symbol properties and internal properties\n for (const prop of properties) {\n const propName = prop.getName();\n\n // Skip symbol properties (those starting with \"__@\")\n if (propName.startsWith('__@')) continue;\n\n const declaration = prop.getValueDeclaration();\n if (!declaration) continue;\n\n try {\n obj[propName] = _typeToJson(declaration.getType(), verbose);\n } catch (e) {\n if (verbose) console.error(` Warning: Failed to serialize property ${propName}:`, e);\n obj[propName] = 'unknown';\n }\n }\n\n // If we got an empty object, return null (no metadata)\n return Object.keys(obj).length > 0 ? obj : null;\n }\n\n if (verbose) {\n console.error(` Unhandled type: ${type.getText()}`);\n }\n\n return 'unknown'; // Fallback for unhandled types\n}\n\n// =============================================================================\n// SECTION: AST-BASED METADATA EXTRACTION\n// =============================================================================\n\n/**\n * Resolves a class name from an AST node (handles identifiers and typeof expressions)\n */\nfunction resolveClassName(node: Node): string {\n // Handle: LoggingInMachine\n if (Node.isIdentifier(node)) {\n return node.getText();\n }\n\n // Handle: typeof LoggingInMachine\n if (Node.isTypeOfExpression(node)) {\n return node.getExpression().getText();\n }\n\n return 'unknown';\n}\n\n/**\n * Parses an object literal expression into a plain JavaScript object\n */\nfunction parseObjectLiteral(obj: Node): any {\n if (!Node.isObjectLiteralExpression(obj)) {\n return {};\n }\n\n const result: any = {};\n\n for (const prop of obj.getProperties()) {\n if (Node.isPropertyAssignment(prop)) {\n const name = prop.getName();\n const init = prop.getInitializer();\n\n if (init) {\n if (Node.isStringLiteral(init)) {\n result[name] = init.getLiteralValue();\n } else if (Node.isNumericLiteral(init)) {\n result[name] = init.getLiteralValue();\n } else if (init.getText() === 'true' || init.getText() === 'false') {\n result[name] = init.getText() === 'true';\n } else if (Node.isIdentifier(init)) {\n result[name] = init.getText();\n } else if (Node.isObjectLiteralExpression(init)) {\n result[name] = parseObjectLiteral(init);\n } else if (Node.isArrayLiteralExpression(init)) {\n result[name] = init.getElements().map(el => {\n if (Node.isObjectLiteralExpression(el)) {\n return parseObjectLiteral(el);\n }\n return el.getText();\n });\n }\n }\n }\n }\n\n return result;\n}\n\n/**\n * Parses an invoke service configuration, resolving class names for onDone/onError\n */\nfunction parseInvokeService(obj: Node): any {\n if (!Node.isObjectLiteralExpression(obj)) {\n return {};\n }\n\n const service: any = {};\n\n for (const prop of obj.getProperties()) {\n if (Node.isPropertyAssignment(prop)) {\n const name = prop.getName();\n const init = prop.getInitializer();\n\n if (!init) continue;\n\n if (name === 'onDone' || name === 'onError') {\n // Resolve class names for state targets\n service[name] = resolveClassName(init);\n } else if (Node.isStringLiteral(init)) {\n service[name] = init.getLiteralValue();\n } else if (Node.isIdentifier(init)) {\n service[name] = init.getText();\n }\n }\n }\n\n return service;\n}\n\n/**\n * Recursively extracts metadata from a call expression chain\n * Handles nested DSL primitive calls like: describe(text, guarded(guard, transitionTo(...)))\n */\nfunction extractFromCallExpression(call: Node, verbose = false): any | null {\n if (!Node.isCallExpression(call)) {\n return null;\n }\n\n const expression = call.getExpression();\n const fnName = Node.isIdentifier(expression) ? expression.getText() : null;\n\n if (!fnName) {\n return null;\n }\n\n const metadata: any = {};\n const args = call.getArguments();\n\n switch (fnName) {\n case 'transitionTo':\n // Args: (target, implementation)\n if (args[0]) {\n metadata.target = resolveClassName(args[0]);\n }\n // The second argument might be another call expression, but we don't recurse there\n // because transitionTo is the innermost wrapper\n break;\n\n case 'describe':\n // Args: (description, transition)\n if (args[0] && Node.isStringLiteral(args[0])) {\n metadata.description = args[0].getLiteralValue();\n }\n // Recurse into wrapped transition\n if (args[1] && Node.isCallExpression(args[1])) {\n const nested = extractFromCallExpression(args[1], verbose);\n if (nested) {\n Object.assign(metadata, nested);\n }\n }\n break;\n\n case 'guarded':\n // Args: (guard, transition)\n if (args[0]) {\n const guard = parseObjectLiteral(args[0]);\n if (Object.keys(guard).length > 0) {\n metadata.guards = [guard];\n }\n }\n // Recurse into wrapped transition\n if (args[1] && Node.isCallExpression(args[1])) {\n const nested = extractFromCallExpression(args[1], verbose);\n if (nested) {\n Object.assign(metadata, nested);\n }\n }\n break;\n\n case 'invoke':\n // Args: (service, implementation)\n if (args[0]) {\n const service = parseInvokeService(args[0]);\n if (Object.keys(service).length > 0) {\n metadata.invoke = service;\n }\n }\n break;\n\n case 'action':\n // Args: (action, transition)\n if (args[0]) {\n const actionMeta = parseObjectLiteral(args[0]);\n if (Object.keys(actionMeta).length > 0) {\n metadata.actions = [actionMeta];\n }\n }\n // Recurse into wrapped transition\n if (args[1] && Node.isCallExpression(args[1])) {\n const nested = extractFromCallExpression(args[1], verbose);\n if (nested) {\n Object.assign(metadata, nested);\n }\n }\n break;\n\n case 'guard':\n // Args: (condition, transition, options?)\n // Extract description from options object (third argument)\n if (args[2]) {\n const options = parseObjectLiteral(args[2]);\n if (options.description) {\n metadata.description = options.description;\n }\n }\n // Add a generic guard condition for static analysis\n metadata.guards = [{ name: 'runtime_guard', description: metadata.description || 'Synchronous condition check' }];\n // Recurse into the transition (second argument)\n if (args[1] && Node.isCallExpression(args[1])) {\n const nested = extractFromCallExpression(args[1], verbose);\n if (nested) {\n Object.assign(metadata, nested);\n }\n }\n break;\n\n case 'guardAsync':\n // Args: (condition, transition, options?)\n // Extract description from options object (third argument)\n if (args[2]) {\n const options = parseObjectLiteral(args[2]);\n if (options.description) {\n metadata.description = options.description;\n }\n }\n // Add a generic guard condition for static analysis\n metadata.guards = [{ name: 'runtime_guard_async', description: metadata.description || 'Asynchronous condition check' }];\n // Recurse into the transition (second argument)\n if (args[1] && Node.isCallExpression(args[1])) {\n const nested = extractFromCallExpression(args[1], verbose);\n if (nested) {\n Object.assign(metadata, nested);\n }\n }\n break;\n\n default:\n // Not a DSL primitive we recognize\n return null;\n }\n\n return Object.keys(metadata).length > 0 ? metadata : null;\n}\n\n/**\n * Extracts metadata by parsing the AST of DSL primitive calls.\n * This is the new approach that solves the generic type parameter resolution problem.\n *\n * @param member - The class member (property declaration) to analyze\n * @param verbose - Enable debug logging\n * @returns The extracted metadata object, or `null` if no metadata is found.\n */\nfunction extractMetaFromMember(member: Node, verbose = false): any | null {\n // Only process property declarations (methods with initializers)\n if (!Node.isPropertyDeclaration(member)) {\n if (verbose) console.error(` āš ļø Not a property declaration`);\n return null;\n }\n\n const initializer = member.getInitializer();\n if (!initializer) {\n if (verbose) console.error(` āš ļø No initializer`);\n return null;\n }\n\n // Check if it's a call expression (DSL primitive call)\n if (!Node.isCallExpression(initializer)) {\n if (verbose) console.error(` āš ļø Initializer is not a call expression`);\n return null;\n }\n\n // Extract metadata by parsing the call chain\n const metadata = extractFromCallExpression(initializer, verbose);\n\n if (metadata && verbose) {\n console.error(` āœ… Extracted metadata:`, JSON.stringify(metadata, null, 2));\n }\n\n return metadata;\n}\n\n/**\n * Analyzes a single class symbol to find all annotated transitions and effects,\n * building a state node definition for the final statechart.\n *\n * @param classSymbol - The `ts-morph` Symbol for the class to analyze.\n * @param verbose - Enable verbose logging\n * @returns A state node object (e.g., `{ on: {...}, invoke: [...] }`).\n */\nfunction analyzeStateNode(classSymbol: any, verbose = false): object {\n const chartNode: any = { on: {} };\n const classDeclaration = classSymbol.getDeclarations()[0];\n if (!classDeclaration || !Node.isClassDeclaration(classDeclaration)) {\n if (verbose) {\n console.error(`āš ļø Warning: Could not get class declaration for ${classSymbol.getName()}`);\n }\n return chartNode;\n }\n\n const className = classSymbol.getName();\n if (verbose) {\n console.error(` Analyzing state: ${className}`);\n }\n\n for (const member of classDeclaration.getInstanceMembers()) {\n const memberName = member.getName();\n if (verbose) {\n console.error(` Checking member: ${memberName}`);\n }\n\n // NEW: Use AST-based extraction instead of type-based\n const meta = extractMetaFromMember(member, verbose);\n if (!meta) continue;\n\n if (verbose) {\n console.error(` Found transition: ${memberName}`);\n }\n\n // Separate `invoke` metadata from standard `on` transitions, as it's a\n // special property of a state node in XState/Stately syntax.\n const { invoke, actions, guards, ...onEntry } = meta;\n\n if (invoke) {\n if (!chartNode.invoke) chartNode.invoke = [];\n chartNode.invoke.push({\n src: invoke.src,\n onDone: { target: invoke.onDone },\n onError: { target: invoke.onError },\n description: invoke.description,\n });\n if (verbose) {\n console.error(` → Invoke: ${invoke.src}`);\n }\n }\n\n // If there's a target, it's a standard event transition.\n if (onEntry.target) {\n const transition: any = { target: onEntry.target };\n\n // Add description if present\n if (onEntry.description) {\n transition.description = onEntry.description;\n }\n\n // Add guards as 'cond' property\n if (guards) {\n transition.cond = guards.map((g: any) => g.name).join(' && ');\n if (verbose) {\n console.error(` → Guard: ${transition.cond}`);\n }\n }\n\n // Add actions array\n if (actions && actions.length > 0) {\n transition.actions = actions.map((a: any) => a.name);\n if (verbose) {\n console.error(` → Actions: ${transition.actions.join(', ')}`);\n }\n }\n\n chartNode.on[memberName] = transition;\n if (verbose) {\n console.error(` → Target: ${onEntry.target}`);\n }\n }\n }\n\n return chartNode;\n}\n\n// =============================================================================\n// SECTION: MAIN ORCHESTRATOR\n// =============================================================================\n\n/**\n * Helper function to analyze a state node with optional nesting support\n */\nfunction analyzeStateNodeWithNesting(\n className: string,\n classSymbol: any,\n sourceFile: any,\n childConfig: ChildStatesConfig | undefined,\n verbose = false\n): any {\n const stateNode = analyzeStateNode(classSymbol, verbose) as any;\n\n // If this state has children, analyze them recursively\n if (childConfig) {\n if (verbose) {\n console.error(` šŸ‘Ŗ Analyzing children for state: ${className}`);\n }\n stateNode.initial = childConfig.initialState;\n stateNode.states = {};\n\n // Recursively analyze each child state\n for (const childClassName of childConfig.classes) {\n const childClassDeclaration = sourceFile.getClass(childClassName);\n if (childClassDeclaration) {\n const childSymbol = childClassDeclaration.getSymbolOrThrow();\n stateNode.states[childClassName] = analyzeStateNode(childSymbol, verbose);\n } else {\n console.warn(`āš ļø Warning: Child class '${childClassName}' not found.`);\n }\n }\n }\n\n return stateNode;\n}\n\n/**\n * Extracts a single machine configuration to a statechart\n *\n * @param config - Machine configuration\n * @param project - ts-morph Project instance\n * @param verbose - Enable verbose logging\n * @returns The generated statechart object\n */\nexport function extractMachine(\n config: MachineConfig,\n project: Project,\n verbose = false\n): any {\n if (verbose) {\n console.error(`\\nšŸ” Analyzing machine: ${config.id}`);\n console.error(` Source: ${config.input}`);\n }\n\n const sourceFile = project.getSourceFile(config.input);\n if (!sourceFile) {\n throw new Error(`Source file not found: ${config.input}`);\n }\n\n // Handle parallel machine configuration\n if (config.parallel) {\n if (verbose) {\n console.error(` ā¹ļø Parallel machine detected. Analyzing regions.`);\n }\n\n const parallelChart: any = {\n id: config.id,\n type: 'parallel',\n states: {},\n };\n\n if (config.description) {\n parallelChart.description = config.description;\n }\n\n for (const region of config.parallel.regions) {\n if (verbose) {\n console.error(` šŸ“ Analyzing region: ${region.name}`);\n }\n\n const regionStates: any = {};\n for (const className of region.classes) {\n const classDeclaration = sourceFile.getClass(className);\n if (classDeclaration) {\n const classSymbol = classDeclaration.getSymbolOrThrow();\n regionStates[className] = analyzeStateNode(classSymbol, verbose);\n } else {\n console.warn(`āš ļø Warning: Class '${className}' not found for region '${region.name}'.`);\n }\n }\n\n parallelChart.states[region.name] = {\n initial: region.initialState,\n states: regionStates,\n };\n }\n\n if (verbose) {\n console.error(` āœ… Extracted ${config.parallel.regions.length} parallel regions`);\n }\n\n return parallelChart;\n }\n\n // Handle standard FSM configuration\n if (!config.initialState || !config.classes) {\n throw new Error(`Machine config for '${config.id}' must have either 'parallel' or 'initialState'/'classes'.`);\n }\n\n const fullChart: any = {\n id: config.id,\n initial: config.initialState,\n states: {},\n };\n\n if (config.description) {\n fullChart.description = config.description;\n }\n\n for (const className of config.classes) {\n const classDeclaration = sourceFile.getClass(className);\n if (!classDeclaration) {\n console.warn(`āš ļø Warning: Class '${className}' not found in '${config.input}'. Skipping.`);\n continue;\n }\n const classSymbol = classDeclaration.getSymbolOrThrow();\n\n // Check if this is the initial state and has children configuration\n const hasChildren = className === config.initialState && config.children;\n const stateNode = analyzeStateNodeWithNesting(\n className,\n classSymbol,\n sourceFile,\n hasChildren ? config.children : undefined,\n verbose\n );\n\n fullChart.states[className] = stateNode;\n }\n\n if (verbose) {\n console.error(` āœ… Extracted ${config.classes.length} states`);\n }\n\n return fullChart;\n}\n\n/**\n * Extracts multiple machines based on configuration\n *\n * @param config - Full extraction configuration\n * @returns Array of generated statecharts\n */\nexport function extractMachines(config: ExtractionConfig): any[] {\n const verbose = config.verbose ?? false;\n\n if (verbose) {\n console.error(`\\nšŸ“Š Starting statechart extraction`);\n console.error(` Machines to extract: ${config.machines.length}`);\n }\n\n const project = new Project();\n project.addSourceFilesAtPaths(\"src/**/*.ts\");\n project.addSourceFilesAtPaths(\"examples/**/*.ts\");\n\n const results: any[] = [];\n\n for (const machineConfig of config.machines) {\n try {\n const chart = extractMachine(machineConfig, project, verbose);\n results.push(chart);\n } catch (error) {\n console.error(`āŒ Error extracting machine '${machineConfig.id}':`, error);\n if (!verbose) {\n console.error(` Run with --verbose for more details`);\n }\n }\n }\n\n if (verbose) {\n console.error(`\\nāœ… Extraction complete: ${results.length}/${config.machines.length} machines extracted`);\n }\n\n return results;\n}\n\n/**\n * Legacy function for backwards compatibility\n * Extracts a single hardcoded machine configuration\n * @deprecated Use extractMachine or extractMachines instead\n */\nexport function generateChart() {\n // --- šŸŽØ CONFIGURATION šŸŽØ ---\n // Adjust these settings to match your project structure.\n\n const config: MachineConfig = {\n input: \"examples/authMachine.ts\",\n classes: [\n \"LoggedOutMachine\",\n \"LoggingInMachine\",\n \"LoggedInMachine\",\n \"SessionExpiredMachine\",\n \"ErrorMachine\"\n ],\n id: \"auth\",\n initialState: \"LoggedOutMachine\",\n description: \"Authentication state machine\"\n };\n\n // --- End Configuration ---\n\n console.error(\"šŸ” Using legacy generateChart function\");\n console.error(\"āš ļø Consider using extractMachines() with a config file instead\\n\");\n\n const project = new Project();\n project.addSourceFilesAtPaths(\"src/**/*.ts\");\n project.addSourceFilesAtPaths(\"examples/**/*.ts\");\n\n try {\n const chart = extractMachine(config, project, true);\n console.log(JSON.stringify(chart, null, 2));\n } catch (error) {\n console.error(`āŒ Error:`, error);\n process.exit(1);\n }\n}\n\n/**\n * Example configuration demonstrating hierarchical and parallel machines.\n * This is not used by default but serves as documentation.\n */\nexport const ADVANCED_CONFIG_EXAMPLES = {\n hierarchical: {\n input: 'examples/dashboardMachine.ts',\n id: 'dashboard',\n classes: ['DashboardMachine', 'LoggedOutMachine'],\n initialState: 'DashboardMachine',\n children: {\n contextProperty: 'child',\n initialState: 'ViewingChildMachine',\n classes: ['ViewingChildMachine', 'EditingChildMachine'],\n },\n } as MachineConfig,\n\n parallel: {\n input: 'examples/editorMachine.ts',\n id: 'editor',\n parallel: {\n regions: [\n {\n name: 'fontWeight',\n initialState: 'NormalWeight',\n classes: ['NormalWeight', 'BoldWeight'],\n },\n {\n name: 'textDecoration',\n initialState: 'NoDecoration',\n classes: ['NoDecoration', 'UnderlineState'],\n },\n ],\n },\n } as MachineConfig,\n};\n\n// This allows the script to be executed directly from the command line.\nif (require.main === module) {\n generateChart();\n}"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,sBAAoC;AA6F7B,SAAS,YAAY,MAAY,UAAU,OAAY;AAE5D,QAAM,SAAS,KAAK,UAAU;AAC9B,MAAI,UAAU,OAAO,gBAAgB,EAAE,KAAK,qBAAK,kBAAkB,GAAG;AACpE,WAAO,OAAO,QAAQ;AAAA,EACxB;AACA,MAAI,KAAK,gBAAgB,EAAG,QAAO,KAAK,gBAAgB;AACxD,MAAI,KAAK,gBAAgB,EAAG,QAAO,KAAK,gBAAgB;AACxD,MAAI,KAAK,iBAAiB,EAAG,QAAO,KAAK,gBAAgB;AACzD,MAAI,KAAK,SAAS,EAAG,QAAO;AAC5B,MAAI,KAAK,SAAS,EAAG,QAAO;AAC5B,MAAI,KAAK,UAAU,EAAG,QAAO;AAG7B,MAAI,KAAK,QAAQ,GAAG;AAClB,UAAM,cAAc,KAAK,2BAA2B;AACpD,WAAO,CAAC,YAAY,aAAa,OAAO,CAAC;AAAA,EAC3C;AAGA,MAAI,KAAK,SAAS,KAAK,KAAK,eAAe,GAAG;AAC5C,UAAM,MAA8B,CAAC;AACrC,UAAM,aAAa,KAAK,cAAc;AAGtC,eAAW,QAAQ,YAAY;AAC7B,YAAM,WAAW,KAAK,QAAQ;AAG9B,UAAI,SAAS,WAAW,KAAK,EAAG;AAEhC,YAAM,cAAc,KAAK,oBAAoB;AAC7C,UAAI,CAAC,YAAa;AAElB,UAAI;AACF,YAAI,QAAQ,IAAI,YAAY,YAAY,QAAQ,GAAG,OAAO;AAAA,MAC5D,SAAS,GAAG;AACV,YAAI,QAAS,SAAQ,MAAM,+CAA+C,QAAQ,KAAK,CAAC;AACxF,YAAI,QAAQ,IAAI;AAAA,MAClB;AAAA,IACF;AAGA,WAAO,OAAO,KAAK,GAAG,EAAE,SAAS,IAAI,MAAM;AAAA,EAC7C;AAEA,MAAI,SAAS;AACX,YAAQ,MAAM,yBAAyB,KAAK,QAAQ,CAAC,EAAE;AAAA,EACzD;AAEA,SAAO;AACT;AASA,SAAS,iBAAiB,MAAoB;AAE5C,MAAI,qBAAK,aAAa,IAAI,GAAG;AAC3B,WAAO,KAAK,QAAQ;AAAA,EACtB;AAGA,MAAI,qBAAK,mBAAmB,IAAI,GAAG;AACjC,WAAO,KAAK,cAAc,EAAE,QAAQ;AAAA,EACtC;AAEA,SAAO;AACT;AAKA,SAAS,mBAAmB,KAAgB;AAC1C,MAAI,CAAC,qBAAK,0BAA0B,GAAG,GAAG;AACxC,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,SAAc,CAAC;AAErB,aAAW,QAAQ,IAAI,cAAc,GAAG;AACtC,QAAI,qBAAK,qBAAqB,IAAI,GAAG;AACnC,YAAM,OAAO,KAAK,QAAQ;AAC1B,YAAM,OAAO,KAAK,eAAe;AAEjC,UAAI,MAAM;AACR,YAAI,qBAAK,gBAAgB,IAAI,GAAG;AAC9B,iBAAO,IAAI,IAAI,KAAK,gBAAgB;AAAA,QACtC,WAAW,qBAAK,iBAAiB,IAAI,GAAG;AACtC,iBAAO,IAAI,IAAI,KAAK,gBAAgB;AAAA,QACtC,WAAW,KAAK,QAAQ,MAAM,UAAU,KAAK,QAAQ,MAAM,SAAS;AAClE,iBAAO,IAAI,IAAI,KAAK,QAAQ,MAAM;AAAA,QACpC,WAAW,qBAAK,aAAa,IAAI,GAAG;AAClC,iBAAO,IAAI,IAAI,KAAK,QAAQ;AAAA,QAC9B,WAAW,qBAAK,0BAA0B,IAAI,GAAG;AAC/C,iBAAO,IAAI,IAAI,mBAAmB,IAAI;AAAA,QACxC,WAAW,qBAAK,yBAAyB,IAAI,GAAG;AAC9C,iBAAO,IAAI,IAAI,KAAK,YAAY,EAAE,IAAI,QAAM;AAC1C,gBAAI,qBAAK,0BAA0B,EAAE,GAAG;AACtC,qBAAO,mBAAmB,EAAE;AAAA,YAC9B;AACA,mBAAO,GAAG,QAAQ;AAAA,UACpB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,mBAAmB,KAAgB;AAC1C,MAAI,CAAC,qBAAK,0BAA0B,GAAG,GAAG;AACxC,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,UAAe,CAAC;AAEtB,aAAW,QAAQ,IAAI,cAAc,GAAG;AACtC,QAAI,qBAAK,qBAAqB,IAAI,GAAG;AACnC,YAAM,OAAO,KAAK,QAAQ;AAC1B,YAAM,OAAO,KAAK,eAAe;AAEjC,UAAI,CAAC,KAAM;AAEX,UAAI,SAAS,YAAY,SAAS,WAAW;AAE3C,gBAAQ,IAAI,IAAI,iBAAiB,IAAI;AAAA,MACvC,WAAW,qBAAK,gBAAgB,IAAI,GAAG;AACrC,gBAAQ,IAAI,IAAI,KAAK,gBAAgB;AAAA,MACvC,WAAW,qBAAK,aAAa,IAAI,GAAG;AAClC,gBAAQ,IAAI,IAAI,KAAK,QAAQ;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,0BAA0B,MAAY,UAAU,OAAmB;AAC1E,MAAI,CAAC,qBAAK,iBAAiB,IAAI,GAAG;AAChC,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,KAAK,cAAc;AACtC,QAAM,SAAS,qBAAK,aAAa,UAAU,IAAI,WAAW,QAAQ,IAAI;AAEtE,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAEA,QAAM,WAAgB,CAAC;AACvB,QAAM,OAAO,KAAK,aAAa;AAE/B,UAAQ,QAAQ;AAAA,IACd,KAAK;AAEH,UAAI,KAAK,CAAC,GAAG;AACX,iBAAS,SAAS,iBAAiB,KAAK,CAAC,CAAC;AAAA,MAC5C;AAGA;AAAA,IAEF,KAAK;AAEH,UAAI,KAAK,CAAC,KAAK,qBAAK,gBAAgB,KAAK,CAAC,CAAC,GAAG;AAC5C,iBAAS,cAAc,KAAK,CAAC,EAAE,gBAAgB;AAAA,MACjD;AAEA,UAAI,KAAK,CAAC,KAAK,qBAAK,iBAAiB,KAAK,CAAC,CAAC,GAAG;AAC7C,cAAM,SAAS,0BAA0B,KAAK,CAAC,GAAG,OAAO;AACzD,YAAI,QAAQ;AACV,iBAAO,OAAO,UAAU,MAAM;AAAA,QAChC;AAAA,MACF;AACA;AAAA,IAEF,KAAK;AAEH,UAAI,KAAK,CAAC,GAAG;AACX,cAAM,QAAQ,mBAAmB,KAAK,CAAC,CAAC;AACxC,YAAI,OAAO,KAAK,KAAK,EAAE,SAAS,GAAG;AACjC,mBAAS,SAAS,CAAC,KAAK;AAAA,QAC1B;AAAA,MACF;AAEA,UAAI,KAAK,CAAC,KAAK,qBAAK,iBAAiB,KAAK,CAAC,CAAC,GAAG;AAC7C,cAAM,SAAS,0BAA0B,KAAK,CAAC,GAAG,OAAO;AACzD,YAAI,QAAQ;AACV,iBAAO,OAAO,UAAU,MAAM;AAAA,QAChC;AAAA,MACF;AACA;AAAA,IAEF,KAAK;AAEH,UAAI,KAAK,CAAC,GAAG;AACX,cAAM,UAAU,mBAAmB,KAAK,CAAC,CAAC;AAC1C,YAAI,OAAO,KAAK,OAAO,EAAE,SAAS,GAAG;AACnC,mBAAS,SAAS;AAAA,QACpB;AAAA,MACF;AACA;AAAA,IAEF,KAAK;AAEH,UAAI,KAAK,CAAC,GAAG;AACX,cAAM,aAAa,mBAAmB,KAAK,CAAC,CAAC;AAC7C,YAAI,OAAO,KAAK,UAAU,EAAE,SAAS,GAAG;AACtC,mBAAS,UAAU,CAAC,UAAU;AAAA,QAChC;AAAA,MACF;AAEA,UAAI,KAAK,CAAC,KAAK,qBAAK,iBAAiB,KAAK,CAAC,CAAC,GAAG;AAC7C,cAAM,SAAS,0BAA0B,KAAK,CAAC,GAAG,OAAO;AACzD,YAAI,QAAQ;AACV,iBAAO,OAAO,UAAU,MAAM;AAAA,QAChC;AAAA,MACF;AACA;AAAA,IAEF,KAAK;AAGH,UAAI,KAAK,CAAC,GAAG;AACX,cAAM,UAAU,mBAAmB,KAAK,CAAC,CAAC;AAC1C,YAAI,QAAQ,aAAa;AACvB,mBAAS,cAAc,QAAQ;AAAA,QACjC;AAAA,MACF;AAEA,eAAS,SAAS,CAAC,EAAE,MAAM,iBAAiB,aAAa,SAAS,eAAe,8BAA8B,CAAC;AAEhH,UAAI,KAAK,CAAC,KAAK,qBAAK,iBAAiB,KAAK,CAAC,CAAC,GAAG;AAC7C,cAAM,SAAS,0BAA0B,KAAK,CAAC,GAAG,OAAO;AACzD,YAAI,QAAQ;AACV,iBAAO,OAAO,UAAU,MAAM;AAAA,QAChC;AAAA,MACF;AACA;AAAA,IAEF,KAAK;AAGH,UAAI,KAAK,CAAC,GAAG;AACX,cAAM,UAAU,mBAAmB,KAAK,CAAC,CAAC;AAC1C,YAAI,QAAQ,aAAa;AACvB,mBAAS,cAAc,QAAQ;AAAA,QACjC;AAAA,MACF;AAEA,eAAS,SAAS,CAAC,EAAE,MAAM,uBAAuB,aAAa,SAAS,eAAe,+BAA+B,CAAC;AAEvH,UAAI,KAAK,CAAC,KAAK,qBAAK,iBAAiB,KAAK,CAAC,CAAC,GAAG;AAC7C,cAAM,SAAS,0BAA0B,KAAK,CAAC,GAAG,OAAO;AACzD,YAAI,QAAQ;AACV,iBAAO,OAAO,UAAU,MAAM;AAAA,QAChC;AAAA,MACF;AACA;AAAA,IAEF;AAEE,aAAO;AAAA,EACX;AAEA,SAAO,OAAO,KAAK,QAAQ,EAAE,SAAS,IAAI,WAAW;AACvD;AAUA,SAAS,sBAAsB,QAAc,UAAU,OAAmB;AAExE,MAAI,CAAC,qBAAK,sBAAsB,MAAM,GAAG;AACvC,QAAI,QAAS,SAAQ,MAAM,qCAAqC;AAChE,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,OAAO,eAAe;AAC1C,MAAI,CAAC,aAAa;AAChB,QAAI,QAAS,SAAQ,MAAM,yBAAyB;AACpD,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,qBAAK,iBAAiB,WAAW,GAAG;AACvC,QAAI,QAAS,SAAQ,MAAM,+CAA+C;AAC1E,WAAO;AAAA,EACT;AAGA,QAAM,WAAW,0BAA0B,aAAa,OAAO;AAE/D,MAAI,YAAY,SAAS;AACvB,YAAQ,MAAM,+BAA+B,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,EAChF;AAEA,SAAO;AACT;AAUA,SAAS,iBAAiB,aAAkB,UAAU,OAAe;AACnE,QAAM,YAAiB,EAAE,IAAI,CAAC,EAAE;AAChC,QAAM,mBAAmB,YAAY,gBAAgB,EAAE,CAAC;AACxD,MAAI,CAAC,oBAAoB,CAAC,qBAAK,mBAAmB,gBAAgB,GAAG;AACnE,QAAI,SAAS;AACX,cAAQ,MAAM,mDAAmD,YAAY,QAAQ,CAAC,EAAE;AAAA,IAC1F;AACA,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,YAAY,QAAQ;AACtC,MAAI,SAAS;AACX,YAAQ,MAAM,sBAAsB,SAAS,EAAE;AAAA,EACjD;AAEA,aAAW,UAAU,iBAAiB,mBAAmB,GAAG;AAC1D,UAAM,aAAa,OAAO,QAAQ;AAClC,QAAI,SAAS;AACX,cAAQ,MAAM,wBAAwB,UAAU,EAAE;AAAA,IACpD;AAGA,UAAM,OAAO,sBAAsB,QAAQ,OAAO;AAClD,QAAI,CAAC,KAAM;AAEX,QAAI,SAAS;AACX,cAAQ,MAAM,yBAAyB,UAAU,EAAE;AAAA,IACrD;AAIA,UAAM,EAAE,QAAQ,SAAS,QAAQ,GAAG,QAAQ,IAAI;AAEhD,QAAI,QAAQ;AACV,UAAI,CAAC,UAAU,OAAQ,WAAU,SAAS,CAAC;AAC3C,gBAAU,OAAO,KAAK;AAAA,QACpB,KAAK,OAAO;AAAA,QACZ,QAAQ,EAAE,QAAQ,OAAO,OAAO;AAAA,QAChC,SAAS,EAAE,QAAQ,OAAO,QAAQ;AAAA,QAClC,aAAa,OAAO;AAAA,MACtB,CAAC;AACD,UAAI,SAAS;AACX,gBAAQ,MAAM,mBAAmB,OAAO,GAAG,EAAE;AAAA,MAC/C;AAAA,IACF;AAGA,QAAI,QAAQ,QAAQ;AAClB,YAAM,aAAkB,EAAE,QAAQ,QAAQ,OAAO;AAGjD,UAAI,QAAQ,aAAa;AACvB,mBAAW,cAAc,QAAQ;AAAA,MACnC;AAGA,UAAI,QAAQ;AACV,mBAAW,OAAO,OAAO,IAAI,CAAC,MAAW,EAAE,IAAI,EAAE,KAAK,MAAM;AAC5D,YAAI,SAAS;AACX,kBAAQ,MAAM,kBAAkB,WAAW,IAAI,EAAE;AAAA,QACnD;AAAA,MACF;AAGA,UAAI,WAAW,QAAQ,SAAS,GAAG;AACjC,mBAAW,UAAU,QAAQ,IAAI,CAAC,MAAW,EAAE,IAAI;AACnD,YAAI,SAAS;AACX,kBAAQ,MAAM,oBAAoB,WAAW,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,QACnE;AAAA,MACF;AAEA,gBAAU,GAAG,UAAU,IAAI;AAC3B,UAAI,SAAS;AACX,gBAAQ,MAAM,mBAAmB,QAAQ,MAAM,EAAE;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AASA,SAAS,4BACP,WACA,aACA,YACA,aACA,UAAU,OACL;AACL,QAAM,YAAY,iBAAiB,aAAa,OAAO;AAGvD,MAAI,aAAa;AACf,QAAI,SAAS;AACX,cAAQ,MAAM,sCAAsC,SAAS,EAAE;AAAA,IACjE;AACA,cAAU,UAAU,YAAY;AAChC,cAAU,SAAS,CAAC;AAGpB,eAAW,kBAAkB,YAAY,SAAS;AAChD,YAAM,wBAAwB,WAAW,SAAS,cAAc;AAChE,UAAI,uBAAuB;AACzB,cAAM,cAAc,sBAAsB,iBAAiB;AAC3D,kBAAU,OAAO,cAAc,IAAI,iBAAiB,aAAa,OAAO;AAAA,MAC1E,OAAO;AACL,gBAAQ,KAAK,4BAA4B,cAAc,cAAc;AAAA,MACvE;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAUO,SAAS,eACd,QACA,SACA,UAAU,OACL;AACL,MAAI,SAAS;AACX,YAAQ,MAAM;AAAA,wBAA2B,OAAO,EAAE,EAAE;AACpD,YAAQ,MAAM,aAAa,OAAO,KAAK,EAAE;AAAA,EAC3C;AAEA,QAAM,aAAa,QAAQ,cAAc,OAAO,KAAK;AACrD,MAAI,CAAC,YAAY;AACf,UAAM,IAAI,MAAM,0BAA0B,OAAO,KAAK,EAAE;AAAA,EAC1D;AAGA,MAAI,OAAO,UAAU;AACnB,QAAI,SAAS;AACX,cAAQ,MAAM,oDAAoD;AAAA,IACpE;AAEA,UAAM,gBAAqB;AAAA,MACzB,IAAI,OAAO;AAAA,MACX,MAAM;AAAA,MACN,QAAQ,CAAC;AAAA,IACX;AAEA,QAAI,OAAO,aAAa;AACtB,oBAAc,cAAc,OAAO;AAAA,IACrC;AAEA,eAAW,UAAU,OAAO,SAAS,SAAS;AAC5C,UAAI,SAAS;AACX,gBAAQ,MAAM,4BAA4B,OAAO,IAAI,EAAE;AAAA,MACzD;AAEA,YAAM,eAAoB,CAAC;AAC3B,iBAAW,aAAa,OAAO,SAAS;AACtC,cAAM,mBAAmB,WAAW,SAAS,SAAS;AACtD,YAAI,kBAAkB;AACpB,gBAAM,cAAc,iBAAiB,iBAAiB;AACtD,uBAAa,SAAS,IAAI,iBAAiB,aAAa,OAAO;AAAA,QACjE,OAAO;AACL,kBAAQ,KAAK,sBAAsB,SAAS,2BAA2B,OAAO,IAAI,IAAI;AAAA,QACxF;AAAA,MACF;AAEA,oBAAc,OAAO,OAAO,IAAI,IAAI;AAAA,QAClC,SAAS,OAAO;AAAA,QAChB,QAAQ;AAAA,MACV;AAAA,IACF;AAEA,QAAI,SAAS;AACX,cAAQ,MAAM,iBAAiB,OAAO,SAAS,QAAQ,MAAM,mBAAmB;AAAA,IAClF;AAEA,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,OAAO,gBAAgB,CAAC,OAAO,SAAS;AAC3C,UAAM,IAAI,MAAM,uBAAuB,OAAO,EAAE,4DAA4D;AAAA,EAC9G;AAEA,QAAM,YAAiB;AAAA,IACrB,IAAI,OAAO;AAAA,IACX,SAAS,OAAO;AAAA,IAChB,QAAQ,CAAC;AAAA,EACX;AAEA,MAAI,OAAO,aAAa;AACtB,cAAU,cAAc,OAAO;AAAA,EACjC;AAEA,aAAW,aAAa,OAAO,SAAS;AACtC,UAAM,mBAAmB,WAAW,SAAS,SAAS;AACtD,QAAI,CAAC,kBAAkB;AACrB,cAAQ,KAAK,sBAAsB,SAAS,mBAAmB,OAAO,KAAK,cAAc;AACzF;AAAA,IACF;AACA,UAAM,cAAc,iBAAiB,iBAAiB;AAGtD,UAAM,cAAc,cAAc,OAAO,gBAAgB,OAAO;AAChE,UAAM,YAAY;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc,OAAO,WAAW;AAAA,MAChC;AAAA,IACF;AAEA,cAAU,OAAO,SAAS,IAAI;AAAA,EAChC;AAEA,MAAI,SAAS;AACX,YAAQ,MAAM,iBAAiB,OAAO,QAAQ,MAAM,SAAS;AAAA,EAC/D;AAEA,SAAO;AACT;AAQO,SAAS,gBAAgB,QAAiC;AAhqBjE;AAiqBE,QAAM,WAAU,YAAO,YAAP,YAAkB;AAElC,MAAI,SAAS;AACX,YAAQ,MAAM;AAAA,kCAAqC;AACnD,YAAQ,MAAM,0BAA0B,OAAO,SAAS,MAAM,EAAE;AAAA,EAClE;AAEA,QAAM,UAAU,IAAI,wBAAQ;AAC5B,UAAQ,sBAAsB,aAAa;AAC3C,UAAQ,sBAAsB,kBAAkB;AAEhD,QAAM,UAAiB,CAAC;AAExB,aAAW,iBAAiB,OAAO,UAAU;AAC3C,QAAI;AACF,YAAM,QAAQ,eAAe,eAAe,SAAS,OAAO;AAC5D,cAAQ,KAAK,KAAK;AAAA,IACpB,SAAS,OAAO;AACd,cAAQ,MAAM,+BAA+B,cAAc,EAAE,MAAM,KAAK;AACxE,UAAI,CAAC,SAAS;AACZ,gBAAQ,MAAM,wCAAwC;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAS;AACX,YAAQ,MAAM;AAAA,yBAA4B,QAAQ,MAAM,IAAI,OAAO,SAAS,MAAM,qBAAqB;AAAA,EACzG;AAEA,SAAO;AACT;AAOO,SAAS,gBAAgB;AAI9B,QAAM,SAAwB;AAAA,IAC5B,OAAO;AAAA,IACP,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,IAAI;AAAA,IACJ,cAAc;AAAA,IACd,aAAa;AAAA,EACf;AAIA,UAAQ,MAAM,wCAAwC;AACtD,UAAQ,MAAM,kEAAkE;AAEhF,QAAM,UAAU,IAAI,wBAAQ;AAC5B,UAAQ,sBAAsB,aAAa;AAC3C,UAAQ,sBAAsB,kBAAkB;AAEhD,MAAI;AACF,UAAM,QAAQ,eAAe,QAAQ,SAAS,IAAI;AAClD,YAAQ,IAAI,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,EAC5C,SAAS,OAAO;AACd,YAAQ,MAAM,YAAY,KAAK;AAC/B,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAMO,IAAM,2BAA2B;AAAA,EACtC,cAAc;AAAA,IACZ,OAAO;AAAA,IACP,IAAI;AAAA,IACJ,SAAS,CAAC,oBAAoB,kBAAkB;AAAA,IAChD,cAAc;AAAA,IACd,UAAU;AAAA,MACR,iBAAiB;AAAA,MACjB,cAAc;AAAA,MACd,SAAS,CAAC,uBAAuB,qBAAqB;AAAA,IACxD;AAAA,EACF;AAAA,EAEA,UAAU;AAAA,IACR,OAAO;AAAA,IACP,IAAI;AAAA,IACJ,UAAU;AAAA,MACR,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,cAAc;AAAA,UACd,SAAS,CAAC,gBAAgB,YAAY;AAAA,QACxC;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,cAAc;AAAA,UACd,SAAS,CAAC,gBAAgB,gBAAgB;AAAA,QAC5C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAGA,IAAI,QAAQ,SAAS,QAAQ;AAC3B,gBAAc;AAChB;",
6
+ "names": []
7
+ }