@formspec/cli 0.1.0-alpha.10

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 (38) hide show
  1. package/README.md +480 -0
  2. package/dist/__tests__/analyzer.test.d.ts +8 -0
  3. package/dist/__tests__/analyzer.test.d.ts.map +1 -0
  4. package/dist/__tests__/analyzer.test.js +70 -0
  5. package/dist/__tests__/analyzer.test.js.map +1 -0
  6. package/dist/__tests__/codegen.test.d.ts +8 -0
  7. package/dist/__tests__/codegen.test.d.ts.map +1 -0
  8. package/dist/__tests__/codegen.test.js +51 -0
  9. package/dist/__tests__/codegen.test.js.map +1 -0
  10. package/dist/__tests__/edge-cases.test.d.ts +12 -0
  11. package/dist/__tests__/edge-cases.test.d.ts.map +1 -0
  12. package/dist/__tests__/edge-cases.test.js +169 -0
  13. package/dist/__tests__/edge-cases.test.js.map +1 -0
  14. package/dist/__tests__/fixtures/edge-cases.d.ts +110 -0
  15. package/dist/__tests__/fixtures/edge-cases.d.ts.map +1 -0
  16. package/dist/__tests__/fixtures/edge-cases.js +137 -0
  17. package/dist/__tests__/fixtures/edge-cases.js.map +1 -0
  18. package/dist/__tests__/fixtures/sample-forms.d.ts +55 -0
  19. package/dist/__tests__/fixtures/sample-forms.d.ts.map +1 -0
  20. package/dist/__tests__/fixtures/sample-forms.js +78 -0
  21. package/dist/__tests__/fixtures/sample-forms.js.map +1 -0
  22. package/dist/__tests__/integration.test.d.ts +5 -0
  23. package/dist/__tests__/integration.test.d.ts.map +1 -0
  24. package/dist/__tests__/integration.test.js +186 -0
  25. package/dist/__tests__/integration.test.js.map +1 -0
  26. package/dist/index.d.ts +19 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +374 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/output/writer.d.ts +82 -0
  31. package/dist/output/writer.d.ts.map +1 -0
  32. package/dist/output/writer.js +152 -0
  33. package/dist/output/writer.js.map +1 -0
  34. package/dist/runtime/formspec-loader.d.ts +80 -0
  35. package/dist/runtime/formspec-loader.d.ts.map +1 -0
  36. package/dist/runtime/formspec-loader.js +152 -0
  37. package/dist/runtime/formspec-loader.js.map +1 -0
  38. package/package.json +47 -0
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Integration tests for the CLI workflow.
3
+ */
4
+ import { describe, it, expect, beforeAll, afterAll } from "vitest";
5
+ import * as fs from "node:fs";
6
+ import * as path from "node:path";
7
+ import { createProgramContext, findClassByName, analyzeClass, generateClassSchemas, generateMethodSchemas, collectFormSpecReferences, } from "@formspec/build/internals";
8
+ import { loadFormSpecs, isFormSpec } from "../runtime/formspec-loader.js";
9
+ import { writeClassSchemas, writeFormSpecSchemas } from "../output/writer.js";
10
+ const fixturesDir = path.join(__dirname, "fixtures");
11
+ const sampleFormsPath = path.join(fixturesDir, "sample-forms.ts");
12
+ const compiledPath = path.join(fixturesDir, "sample-forms.js");
13
+ const testOutputDir = path.join(__dirname, "__test_output__");
14
+ // Check if compiled fixture exists (may need to be built)
15
+ const hasCompiledFixture = fs.existsSync(compiledPath);
16
+ /**
17
+ * Converts FormSpecSchemas from loader to LoadedFormSpecSchemas for build API.
18
+ */
19
+ function toLoadedSchemas(formSpecs) {
20
+ const result = new Map();
21
+ for (const [name, schemas] of formSpecs) {
22
+ result.set(name, {
23
+ name: schemas.name,
24
+ jsonSchema: schemas.jsonSchema,
25
+ uiSchema: schemas.uiSchema,
26
+ });
27
+ }
28
+ return result;
29
+ }
30
+ describe("generators", () => {
31
+ it("generates class schemas from static analysis", () => {
32
+ const ctx = createProgramContext(sampleFormsPath);
33
+ const classDecl = findClassByName(ctx.sourceFile, "SimpleProduct");
34
+ if (!classDecl)
35
+ throw new Error("SimpleProduct class not found");
36
+ const analysis = analyzeClass(classDecl, ctx.checker);
37
+ const schemas = generateClassSchemas(analysis, ctx.checker);
38
+ // JSON Schema
39
+ expect(schemas.jsonSchema.type).toBe("object");
40
+ expect(schemas.jsonSchema.properties).toBeDefined();
41
+ expect(schemas.jsonSchema.properties?.["name"]).toBeDefined();
42
+ expect(schemas.jsonSchema.properties?.["price"]).toBeDefined();
43
+ expect(schemas.jsonSchema.required).toContain("name");
44
+ expect(schemas.jsonSchema.required).toContain("active");
45
+ expect(schemas.jsonSchema.required).not.toContain("price");
46
+ // UI Schema
47
+ expect(schemas.uiSchema.elements).toHaveLength(4);
48
+ const nameElement = schemas.uiSchema.elements.find((e) => e.id === "name");
49
+ expect(nameElement?._field).toBe("text");
50
+ expect(nameElement?.required).toBe(true);
51
+ });
52
+ it("collects FormSpec references from methods", () => {
53
+ const ctx = createProgramContext(sampleFormsPath);
54
+ const classDecl = findClassByName(ctx.sourceFile, "InstallmentPlan");
55
+ if (!classDecl)
56
+ throw new Error("InstallmentPlan class not found");
57
+ const analysis = analyzeClass(classDecl, ctx.checker);
58
+ const refs = collectFormSpecReferences([
59
+ ...analysis.instanceMethods,
60
+ ...analysis.staticMethods,
61
+ ]);
62
+ expect(refs.size).toBe(2);
63
+ expect(refs.has("ActivateParams")).toBe(true);
64
+ expect(refs.has("CancelParams")).toBe(true);
65
+ });
66
+ it("generates method schemas without FormSpec (static only)", () => {
67
+ const ctx = createProgramContext(sampleFormsPath);
68
+ const classDecl = findClassByName(ctx.sourceFile, "SimpleProduct");
69
+ if (!classDecl)
70
+ throw new Error("SimpleProduct class not found");
71
+ const analysis = analyzeClass(classDecl, ctx.checker);
72
+ const updateMethod = analysis.instanceMethods[0];
73
+ if (!updateMethod)
74
+ throw new Error("updateMethod not found");
75
+ const methodSchemas = generateMethodSchemas(updateMethod, ctx.checker, new Map());
76
+ expect(methodSchemas.name).toBe("update");
77
+ expect(methodSchemas.params).not.toBeNull();
78
+ expect(methodSchemas.params?.jsonSchema.type).toBe("object");
79
+ expect(methodSchemas.params?.uiSchema).toBeNull();
80
+ expect(methodSchemas.returnType.type).toBe("boolean");
81
+ });
82
+ });
83
+ describe("isFormSpec", () => {
84
+ it("detects valid FormSpec-like objects", () => {
85
+ const validFormSpec = {
86
+ elements: [{ _type: "field", _field: "text", name: "test" }],
87
+ };
88
+ expect(isFormSpec(validFormSpec)).toBe(true);
89
+ });
90
+ it("rejects invalid objects", () => {
91
+ expect(isFormSpec(null)).toBe(false);
92
+ expect(isFormSpec(undefined)).toBe(false);
93
+ expect(isFormSpec({})).toBe(false);
94
+ expect(isFormSpec({ elements: "not-array" })).toBe(false);
95
+ expect(isFormSpec({ elements: [{ noType: true }] })).toBe(false);
96
+ });
97
+ });
98
+ describe.skipIf(!hasCompiledFixture)("runtime loading", () => {
99
+ it("loads FormSpec exports from compiled module", async () => {
100
+ const { formSpecs, module } = await loadFormSpecs(compiledPath);
101
+ // Should find our exported FormSpecs
102
+ expect(formSpecs.size).toBeGreaterThan(0);
103
+ expect(formSpecs.has("UserRegistrationForm")).toBe(true);
104
+ expect(formSpecs.has("ProductConfigForm")).toBe(true);
105
+ expect(formSpecs.has("ActivateParams")).toBe(true);
106
+ expect(formSpecs.has("CancelParams")).toBe(true);
107
+ // Check generated schemas
108
+ const userForm = formSpecs.get("UserRegistrationForm");
109
+ if (!userForm)
110
+ throw new Error("UserRegistrationForm not found");
111
+ expect(userForm.jsonSchema).toBeDefined();
112
+ expect(userForm.uiSchema).toBeDefined();
113
+ // Module should have the class exports too
114
+ expect(module["InstallmentPlan"]).toBeDefined();
115
+ });
116
+ it("generates method schemas with FormSpec params", async () => {
117
+ const ctx = createProgramContext(sampleFormsPath);
118
+ const classDecl = findClassByName(ctx.sourceFile, "InstallmentPlan");
119
+ if (!classDecl)
120
+ throw new Error("InstallmentPlan class not found");
121
+ const analysis = analyzeClass(classDecl, ctx.checker);
122
+ // Load FormSpecs at runtime
123
+ const { formSpecs } = await loadFormSpecs(compiledPath);
124
+ const loadedSchemas = toLoadedSchemas(formSpecs);
125
+ // Generate method schemas
126
+ const activateMethod = analysis.instanceMethods.find((m) => m.name === "activate");
127
+ if (!activateMethod)
128
+ throw new Error("activate method not found");
129
+ const methodSchemas = generateMethodSchemas(activateMethod, ctx.checker, loadedSchemas);
130
+ expect(methodSchemas.name).toBe("activate");
131
+ expect(methodSchemas.params).not.toBeNull();
132
+ expect(methodSchemas.params?.formSpecExport).toBe("ActivateParams");
133
+ // Should have UI Schema from the FormSpec
134
+ expect(methodSchemas.params?.uiSchema).not.toBeNull();
135
+ });
136
+ });
137
+ describe.skipIf(!hasCompiledFixture)("output writer", () => {
138
+ beforeAll(() => {
139
+ // Clean up test output directory
140
+ if (fs.existsSync(testOutputDir)) {
141
+ fs.rmSync(testOutputDir, { recursive: true });
142
+ }
143
+ });
144
+ afterAll(() => {
145
+ // Clean up test output directory
146
+ if (fs.existsSync(testOutputDir)) {
147
+ fs.rmSync(testOutputDir, { recursive: true });
148
+ }
149
+ });
150
+ it("writes class schemas to output directory", async () => {
151
+ const ctx = createProgramContext(sampleFormsPath);
152
+ const classDecl = findClassByName(ctx.sourceFile, "InstallmentPlan");
153
+ if (!classDecl)
154
+ throw new Error("InstallmentPlan class not found");
155
+ const analysis = analyzeClass(classDecl, ctx.checker);
156
+ // Load FormSpecs
157
+ const { formSpecs } = await loadFormSpecs(compiledPath);
158
+ const loadedSchemas = toLoadedSchemas(formSpecs);
159
+ // Generate schemas
160
+ const classSchemas = generateClassSchemas(analysis, ctx.checker);
161
+ const instanceMethodSchemas = analysis.instanceMethods.map((m) => generateMethodSchemas(m, ctx.checker, loadedSchemas));
162
+ const staticMethodSchemas = analysis.staticMethods.map((m) => generateMethodSchemas(m, ctx.checker, loadedSchemas));
163
+ // Write output
164
+ const result = writeClassSchemas(analysis.name, classSchemas, instanceMethodSchemas, staticMethodSchemas, { outDir: testOutputDir });
165
+ // Verify directory structure
166
+ expect(fs.existsSync(result.dir)).toBe(true);
167
+ expect(fs.existsSync(path.join(result.dir, "schema.json"))).toBe(true);
168
+ expect(fs.existsSync(path.join(result.dir, "ui_schema.json"))).toBe(true);
169
+ expect(fs.existsSync(path.join(result.dir, "instance_methods", "activate", "params.schema.json"))).toBe(true);
170
+ expect(fs.existsSync(path.join(result.dir, "instance_methods", "activate", "params.ui_schema.json"))).toBe(true);
171
+ expect(fs.existsSync(path.join(result.dir, "static_methods", "createStandard", "return_type.schema.json"))).toBe(true);
172
+ // Verify JSON content
173
+ const schemaContent = JSON.parse(fs.readFileSync(path.join(result.dir, "schema.json"), "utf-8"));
174
+ expect(schemaContent.type).toBe("object");
175
+ expect(schemaContent.properties).toBeDefined();
176
+ });
177
+ it("writes FormSpec schemas to output directory", async () => {
178
+ const { formSpecs } = await loadFormSpecs(compiledPath);
179
+ const result = writeFormSpecSchemas(formSpecs, { outDir: testOutputDir });
180
+ expect(fs.existsSync(result.dir)).toBe(true);
181
+ expect(fs.existsSync(path.join(result.dir, "UserRegistrationForm", "schema.json"))).toBe(true);
182
+ expect(fs.existsSync(path.join(result.dir, "UserRegistrationForm", "ui_schema.json"))).toBe(true);
183
+ expect(fs.existsSync(path.join(result.dir, "ProductConfigForm", "schema.json"))).toBe(true);
184
+ });
185
+ });
186
+ //# sourceMappingURL=integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration.test.js","sourceRoot":"","sources":["../../src/__tests__/integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * FormSpec CLI - Generate JSON Schema and FormSpec from TypeScript
4
+ *
5
+ * Usage:
6
+ * formspec generate <file> [className] [-o <outDir>]
7
+ *
8
+ * Examples:
9
+ * # Generate schemas from a class with decorators
10
+ * formspec generate ./src/forms.ts InstallmentPlan -o ./generated
11
+ *
12
+ * # Generate schemas from all FormSpec exports in a file (chain DSL)
13
+ * formspec generate ./src/forms.ts -o ./generated
14
+ *
15
+ * # Generate schemas from both classes and FormSpec exports
16
+ * formspec generate ./src/forms.ts MyClass -o ./generated
17
+ */
18
+ export {};
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG"}
package/dist/index.js ADDED
@@ -0,0 +1,374 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * FormSpec CLI - Generate JSON Schema and FormSpec from TypeScript
4
+ *
5
+ * Usage:
6
+ * formspec generate <file> [className] [-o <outDir>]
7
+ *
8
+ * Examples:
9
+ * # Generate schemas from a class with decorators
10
+ * formspec generate ./src/forms.ts InstallmentPlan -o ./generated
11
+ *
12
+ * # Generate schemas from all FormSpec exports in a file (chain DSL)
13
+ * formspec generate ./src/forms.ts -o ./generated
14
+ *
15
+ * # Generate schemas from both classes and FormSpec exports
16
+ * formspec generate ./src/forms.ts MyClass -o ./generated
17
+ */
18
+ import { runCodegen } from "@formspec/build";
19
+ import { createProgramContext, findClassByName, analyzeClass, generateClassSchemas, generateMethodSchemas, collectFormSpecReferences, } from "@formspec/build/internals";
20
+ import { loadFormSpecs, loadNamedFormSpecs, resolveCompiledPath, } from "./runtime/formspec-loader.js";
21
+ import { writeClassSchemas, writeFormSpecSchemas } from "./output/writer.js";
22
+ /**
23
+ * Parses codegen command arguments.
24
+ */
25
+ function parseCodegenArgs(args) {
26
+ const files = [];
27
+ let output = "./__formspec_types__.ts";
28
+ for (let i = 0; i < args.length; i++) {
29
+ const arg = args[i];
30
+ if (!arg)
31
+ continue;
32
+ if (arg === "-o" || arg === "--output") {
33
+ const nextArg = args[++i];
34
+ if (nextArg)
35
+ output = nextArg;
36
+ }
37
+ else if (arg.startsWith("-")) {
38
+ console.error(`Unknown option: ${arg}`);
39
+ process.exit(1);
40
+ }
41
+ else {
42
+ files.push(arg);
43
+ }
44
+ }
45
+ if (files.length === 0) {
46
+ console.error("Error: No source files provided");
47
+ console.error("Usage: formspec codegen <files...> [-o <output>]");
48
+ process.exit(1);
49
+ }
50
+ return { command: "codegen", files, output };
51
+ }
52
+ /**
53
+ * Parses command line arguments.
54
+ */
55
+ function parseArgs(args) {
56
+ const [command, ...rest] = args;
57
+ if (!command || command === "--help" || command === "-h") {
58
+ printHelp();
59
+ process.exit(0);
60
+ }
61
+ // Handle codegen command
62
+ if (command === "codegen") {
63
+ // Check for --help on subcommand
64
+ if (rest.includes("--help") || rest.includes("-h")) {
65
+ printCodegenHelp();
66
+ process.exit(0);
67
+ }
68
+ return parseCodegenArgs(rest);
69
+ }
70
+ // Accept both "generate" (primary) and "analyze" (alias for backwards compatibility)
71
+ if (command !== "generate" && command !== "analyze") {
72
+ console.error(`Unknown command: ${command}`);
73
+ console.error('Use "formspec generate" or "formspec codegen"');
74
+ process.exit(1);
75
+ }
76
+ // Check for --help on subcommand
77
+ if (rest.includes("--help") || rest.includes("-h")) {
78
+ printGenerateHelp();
79
+ process.exit(0);
80
+ }
81
+ let filePath;
82
+ let className;
83
+ let outDir = "./generated";
84
+ let compiledPath;
85
+ for (let i = 0; i < rest.length; i++) {
86
+ const arg = rest[i];
87
+ if (!arg)
88
+ continue;
89
+ if (arg === "-o" || arg === "--output") {
90
+ const nextArg = rest[++i];
91
+ if (nextArg)
92
+ outDir = nextArg;
93
+ }
94
+ else if (arg === "--compiled" || arg === "-c") {
95
+ const nextArg = rest[++i];
96
+ if (nextArg)
97
+ compiledPath = nextArg;
98
+ }
99
+ else if (arg.startsWith("-")) {
100
+ console.error(`Unknown option: ${arg}`);
101
+ process.exit(1);
102
+ }
103
+ else if (!filePath) {
104
+ filePath = arg;
105
+ }
106
+ else {
107
+ className ??= arg;
108
+ }
109
+ }
110
+ if (!filePath) {
111
+ console.error("Error: No file path provided");
112
+ console.error("Usage: formspec generate <file> [className] [-o <outDir>]");
113
+ process.exit(1);
114
+ }
115
+ return {
116
+ command,
117
+ filePath,
118
+ className,
119
+ outDir,
120
+ compiledPath,
121
+ };
122
+ }
123
+ /**
124
+ * Prints help message.
125
+ */
126
+ function printHelp() {
127
+ console.log(`
128
+ FormSpec CLI - Generate JSON Schema and FormSpec from TypeScript
129
+
130
+ COMMANDS:
131
+ generate Generate JSON Schema and UI Schema files from TypeScript
132
+ codegen Generate type metadata file for runtime schema generation
133
+
134
+ USAGE:
135
+ formspec generate <file> [className] [options]
136
+ formspec codegen <files...> [-o <output>]
137
+
138
+ Use 'formspec <command> --help' for more information about a command.
139
+ `);
140
+ }
141
+ /**
142
+ * Prints help for the generate command.
143
+ */
144
+ function printGenerateHelp() {
145
+ console.log(`
146
+ formspec generate - Generate JSON Schema and UI Schema files from TypeScript
147
+
148
+ USAGE:
149
+ formspec generate <file> [className] [options]
150
+
151
+ ARGUMENTS:
152
+ <file> Path to TypeScript source file (.ts)
153
+ [className] Optional class name to analyze
154
+
155
+ OPTIONS:
156
+ -o, --output <dir> Output directory (default: ./generated)
157
+ -c, --compiled <path> Path to compiled JS file (auto-detected if omitted)
158
+ -h, --help Show this help message
159
+
160
+ EXAMPLES:
161
+ # Generate from a decorated class (static analysis only)
162
+ formspec generate ./src/forms.ts UserForm -o ./generated
163
+
164
+ # Generate from FormSpec exports (requires compiled JS)
165
+ # First compile using your build tool (tsc, esbuild, swc, etc.)
166
+ formspec generate ./src/forms.ts -o ./generated
167
+
168
+ HOW IT WORKS:
169
+ The CLI performs static analysis of TypeScript source files using the
170
+ TypeScript Compiler API. It reads decorator metadata and type information
171
+ directly from the AST - no compiled output needed for class analysis.
172
+
173
+ For FormSpec chain DSL exports (formspec(...)), the CLI needs to import
174
+ the compiled JavaScript to generate schemas at runtime. Compile your
175
+ TypeScript using your project's build process, or use the --compiled
176
+ flag to specify the JS path explicitly.
177
+ `);
178
+ }
179
+ /**
180
+ * Prints help for the codegen command.
181
+ */
182
+ function printCodegenHelp() {
183
+ console.log(`
184
+ formspec codegen - Generate type metadata for runtime schema generation
185
+
186
+ USAGE:
187
+ formspec codegen <files...> [options]
188
+
189
+ ARGUMENTS:
190
+ <files...> TypeScript source files to analyze
191
+
192
+ OPTIONS:
193
+ -o, --output <file> Output file (default: ./__formspec_types__.ts)
194
+ -h, --help Show this help message
195
+
196
+ EXAMPLES:
197
+ formspec codegen ./src/forms.ts -o ./src/__formspec_types__.ts
198
+ formspec codegen ./src/**/*.ts -o ./src/__formspec_types__.ts
199
+
200
+ USAGE IN CODE:
201
+ After generating the type metadata file:
202
+
203
+ // Import once at application entry point
204
+ import './__formspec_types__';
205
+
206
+ // Then use the generated accessor functions
207
+ import { getUserFormFormSpec } from './__formspec_types__';
208
+
209
+ const spec = getUserFormFormSpec();
210
+ // Use \`spec\` with your preferred schema builder or form renderer.
211
+
212
+ Alternatively, use generateSchemasFromClass() for static analysis
213
+ without codegen:
214
+
215
+ import { generateSchemasFromClass } from '@formspec/build';
216
+
217
+ const { jsonSchema, uiSchema } = generateSchemasFromClass({
218
+ filePath: './src/forms.ts',
219
+ className: 'UserForm',
220
+ });
221
+
222
+ HOW IT WORKS:
223
+ TypeScript erases type information at runtime. This command extracts
224
+ type metadata (field types, enum values, optional/nullable flags) from
225
+ your decorated classes and generates a file that patches them with
226
+ a __formspec_types__ property and accessor functions.
227
+
228
+ Without codegen, use generateSchemasFromClass() from @formspec/build
229
+ for purely static analysis (no runtime metadata needed).
230
+ `);
231
+ }
232
+ /**
233
+ * Converts FormSpecSchemas to LoadedFormSpecSchemas for the build package API.
234
+ */
235
+ function toLoadedSchemas(formSpecs) {
236
+ const result = new Map();
237
+ for (const [name, schemas] of formSpecs) {
238
+ result.set(name, {
239
+ name: schemas.name,
240
+ jsonSchema: schemas.jsonSchema,
241
+ uiSchema: schemas.uiSchema,
242
+ });
243
+ }
244
+ return result;
245
+ }
246
+ /**
247
+ * Main CLI entry point.
248
+ */
249
+ async function main() {
250
+ const args = process.argv.slice(2);
251
+ const options = parseArgs(args);
252
+ // Handle codegen command
253
+ if (options.command === "codegen") {
254
+ const codegenOptions = options;
255
+ runCodegen({
256
+ files: codegenOptions.files,
257
+ output: codegenOptions.output,
258
+ });
259
+ return;
260
+ }
261
+ // Handle generate command
262
+ const generateOptions = options;
263
+ console.log(`Generating schemas from: ${generateOptions.filePath}`);
264
+ if (generateOptions.className) {
265
+ console.log(`Class: ${generateOptions.className}`);
266
+ }
267
+ console.log(`Output: ${generateOptions.outDir}`);
268
+ console.log();
269
+ try {
270
+ // Step 1: Static analysis with TypeScript
271
+ const ctx = createProgramContext(generateOptions.filePath);
272
+ console.log("✓ Created TypeScript program");
273
+ // Step 2: Resolve compiled JS path for runtime loading
274
+ const compiledPath = generateOptions.compiledPath ?? resolveCompiledPath(generateOptions.filePath);
275
+ // Step 3: Load all FormSpec exports from compiled module
276
+ let loadedFormSpecs = new Map();
277
+ let loadError;
278
+ try {
279
+ const { formSpecs } = await loadFormSpecs(compiledPath);
280
+ loadedFormSpecs = formSpecs;
281
+ console.log(`✓ Loaded ${String(formSpecs.size)} FormSpec export(s) from module`);
282
+ }
283
+ catch (error) {
284
+ // Track load errors for better messaging later
285
+ // Runtime loading is only needed for chain DSL exports and method parameters
286
+ if (error instanceof Error && error.message.includes("Cannot find module")) {
287
+ loadError = `Compiled file not found at: ${compiledPath}`;
288
+ }
289
+ }
290
+ // Step 4: If className specified, analyze the class
291
+ if (!generateOptions.className && loadedFormSpecs.size === 0) {
292
+ // No class name and no FormSpec exports - provide context-aware error
293
+ console.warn("⚠️ No class name specified and no FormSpec exports found.");
294
+ console.warn();
295
+ if (loadError) {
296
+ // Compiled file doesn't exist - suggest building first
297
+ console.warn(" For chain DSL forms, compile your TypeScript first:");
298
+ console.warn(` ${loadError}`);
299
+ console.warn();
300
+ console.warn(" Run your build tool (tsc, esbuild, swc, etc.) then try again.");
301
+ console.warn(" Or use -c/--compiled to specify the JS path explicitly:");
302
+ console.warn(` npx formspec generate ${generateOptions.filePath} -c ./dist/forms.js -o ${generateOptions.outDir}`);
303
+ }
304
+ else {
305
+ // Compiled file exists but no FormSpec exports found
306
+ console.warn(" For decorated classes, specify the class name:");
307
+ console.warn(` npx formspec generate ${generateOptions.filePath} <ClassName> -o ${generateOptions.outDir}`);
308
+ console.warn();
309
+ console.warn(" For chain DSL, export a FormSpec from your file:");
310
+ console.warn(" export const MyForm = formspec(...);");
311
+ }
312
+ console.warn();
313
+ process.exit(1);
314
+ }
315
+ if (generateOptions.className) {
316
+ const classDecl = findClassByName(ctx.sourceFile, generateOptions.className);
317
+ if (!classDecl) {
318
+ console.error(`Error: Class "${generateOptions.className}" not found in ${generateOptions.filePath}`);
319
+ process.exit(1);
320
+ }
321
+ // Analyze class
322
+ const analysis = analyzeClass(classDecl, ctx.checker);
323
+ console.log(`✓ Analyzed class "${analysis.name}" with ${String(analysis.fields.length)} field(s)`);
324
+ console.log(` Instance methods: ${String(analysis.instanceMethods.length)}`);
325
+ console.log(` Static methods: ${String(analysis.staticMethods.length)}`);
326
+ // Collect FormSpec references from methods
327
+ const allMethods = [...analysis.instanceMethods, ...analysis.staticMethods];
328
+ const formSpecRefs = collectFormSpecReferences(allMethods);
329
+ if (formSpecRefs.size > 0) {
330
+ console.log(` FormSpec refs: ${Array.from(formSpecRefs).join(", ")}`);
331
+ // Load specific FormSpecs if not already loaded
332
+ const missing = Array.from(formSpecRefs).filter((name) => !loadedFormSpecs.has(name));
333
+ if (missing.length > 0) {
334
+ try {
335
+ const namedFormSpecs = await loadNamedFormSpecs(compiledPath, missing);
336
+ for (const [name, schemas] of namedFormSpecs) {
337
+ loadedFormSpecs.set(name, schemas);
338
+ }
339
+ }
340
+ catch {
341
+ // Already warned about module loading
342
+ }
343
+ }
344
+ }
345
+ // Generate class schemas
346
+ const classSchemas = generateClassSchemas(analysis, ctx.checker);
347
+ // Generate method schemas
348
+ const loadedSchemasMap = toLoadedSchemas(loadedFormSpecs);
349
+ const instanceMethodSchemas = analysis.instanceMethods.map((m) => generateMethodSchemas(m, ctx.checker, loadedSchemasMap));
350
+ const staticMethodSchemas = analysis.staticMethods.map((m) => generateMethodSchemas(m, ctx.checker, loadedSchemasMap));
351
+ // Write class output
352
+ const classResult = writeClassSchemas(analysis.name, classSchemas, instanceMethodSchemas, staticMethodSchemas, { outDir: generateOptions.outDir });
353
+ console.log(`✓ Wrote ${String(classResult.files.length)} file(s) to ${classResult.dir}`);
354
+ }
355
+ // Step 5: Write standalone FormSpec exports (chain DSL)
356
+ if (loadedFormSpecs.size > 0) {
357
+ const formSpecResult = writeFormSpecSchemas(loadedFormSpecs, {
358
+ outDir: generateOptions.outDir,
359
+ });
360
+ if (formSpecResult.files.length > 0) {
361
+ console.log(`✓ Wrote ${String(formSpecResult.files.length)} FormSpec file(s) to ${formSpecResult.dir}`);
362
+ }
363
+ }
364
+ console.log();
365
+ console.log("Done!");
366
+ }
367
+ catch (error) {
368
+ console.error("Error:", error instanceof Error ? error.message : error);
369
+ process.exit(1);
370
+ }
371
+ }
372
+ // Run CLI
373
+ void main();
374
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,mBAAmB,GAEpB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAsB7E;;GAEG;AACH,SAAS,gBAAgB,CAAC,IAAc;IACtC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,GAAG,yBAAyB,CAAC;IAEvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,CAAC,GAAG;YAAE,SAAS;QAEnB,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;YACvC,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1B,IAAI,OAAO;gBAAE,MAAM,GAAG,OAAO,CAAC;QAChC,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,KAAK,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAC;YACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACjD,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAEhC,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACzD,SAAS,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,yBAAyB;IACzB,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,iCAAiC;QACjC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,gBAAgB,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAED,qFAAqF;IACrF,IAAI,OAAO,KAAK,UAAU,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QACpD,OAAO,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;QAC7C,OAAO,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;QAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,iCAAiC;IACjC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,iBAAiB,EAAE,CAAC;QACpB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,QAA4B,CAAC;IACjC,IAAI,SAA6B,CAAC;IAClC,IAAI,MAAM,GAAG,aAAa,CAAC;IAC3B,IAAI,YAAgC,CAAC;IAErC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,CAAC,GAAG;YAAE,SAAS;QAEnB,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;YACvC,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1B,IAAI,OAAO;gBAAE,MAAM,GAAG,OAAO,CAAC;QAChC,CAAC;aAAM,IAAI,GAAG,KAAK,YAAY,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YAChD,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1B,IAAI,OAAO;gBAAE,YAAY,GAAG,OAAO,CAAC;QACtC,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,KAAK,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAC;YACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;aAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YACrB,QAAQ,GAAG,GAAG,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,SAAS,KAAK,GAAG,CAAC;QACpB,CAAC;IACH,CAAC;IAED,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAC9C,OAAO,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAC3E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO;QACL,OAAO;QACP,QAAQ;QACR,SAAS;QACT,MAAM;QACN,YAAY;KACb,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;CAYb,CAAC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB;IACxB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCb,CAAC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB;IACvB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+Cb,CAAC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CACtB,SAAuC;IAEvC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAiC,CAAC;IACxD,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,SAAS,EAAE,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE;YACf,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B,CAAC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAEhC,yBAAyB;IACzB,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,cAAc,GAAG,OAA4B,CAAC;QACpD,UAAU,CAAC;YACT,KAAK,EAAE,cAAc,CAAC,KAAK;YAC3B,MAAM,EAAE,cAAc,CAAC,MAAM;SAC9B,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,0BAA0B;IAC1B,MAAM,eAAe,GAAG,OAAqB,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,4BAA4B,eAAe,CAAC,QAAQ,EAAE,CAAC,CAAC;IACpE,IAAI,eAAe,CAAC,SAAS,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,UAAU,eAAe,CAAC,SAAS,EAAE,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,WAAW,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,IAAI,CAAC;QACH,0CAA0C;QAC1C,MAAM,GAAG,GAAG,oBAAoB,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;QAE5C,uDAAuD;QACvD,MAAM,YAAY,GAChB,eAAe,CAAC,YAAY,IAAI,mBAAmB,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QAEhF,yDAAyD;QACzD,IAAI,eAAe,GAAG,IAAI,GAAG,EAA2B,CAAC;QACzD,IAAI,SAA6B,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,aAAa,CAAC,YAAY,CAAC,CAAC;YACxD,eAAe,GAAG,SAAS,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;QACnF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,+CAA+C;YAC/C,6EAA6E;YAC7E,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC;gBAC3E,SAAS,GAAG,+BAA+B,YAAY,EAAE,CAAC;YAC5D,CAAC;QACH,CAAC;QAED,oDAAoD;QACpD,IAAI,CAAC,eAAe,CAAC,SAAS,IAAI,eAAe,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC7D,sEAAsE;YACtE,OAAO,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;YAC3E,OAAO,CAAC,IAAI,EAAE,CAAC;YAEf,IAAI,SAAS,EAAE,CAAC;gBACd,uDAAuD;gBACvD,OAAO,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAC;gBACvE,OAAO,CAAC,IAAI,CAAC,QAAQ,SAAS,EAAE,CAAC,CAAC;gBAClC,OAAO,CAAC,IAAI,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;gBACjF,OAAO,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;gBAC3E,OAAO,CAAC,IAAI,CACV,8BAA8B,eAAe,CAAC,QAAQ,0BAA0B,eAAe,CAAC,MAAM,EAAE,CACzG,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,qDAAqD;gBACrD,OAAO,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;gBAClE,OAAO,CAAC,IAAI,CACV,8BAA8B,eAAe,CAAC,QAAQ,mBAAmB,eAAe,CAAC,MAAM,EAAE,CAClG,CAAC;gBACF,OAAO,CAAC,IAAI,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;gBACpE,OAAO,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;YAC5D,CAAC;YACD,OAAO,CAAC,IAAI,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,eAAe,CAAC,SAAS,EAAE,CAAC;YAC9B,MAAM,SAAS,GAAG,eAAe,CAAC,GAAG,CAAC,UAAU,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC;YAE7E,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CACX,iBAAiB,eAAe,CAAC,SAAS,kBAAkB,eAAe,CAAC,QAAQ,EAAE,CACvF,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAED,gBAAgB;YAChB,MAAM,QAAQ,GAAG,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YACtD,OAAO,CAAC,GAAG,CACT,qBAAqB,QAAQ,CAAC,IAAI,UAAU,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CACtF,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,uBAAuB,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC9E,OAAO,CAAC,GAAG,CAAC,qBAAqB,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAE1E,2CAA2C;YAC3C,MAAM,UAAU,GAAG,CAAC,GAAG,QAAQ,CAAC,eAAe,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC;YAC5E,MAAM,YAAY,GAAG,yBAAyB,CAAC,UAAU,CAAC,CAAC;YAE3D,IAAI,YAAY,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAEvE,gDAAgD;gBAChD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;gBACtF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACvB,IAAI,CAAC;wBACH,MAAM,cAAc,GAAG,MAAM,kBAAkB,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;wBACvE,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,cAAc,EAAE,CAAC;4BAC7C,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;wBACrC,CAAC;oBACH,CAAC;oBAAC,MAAM,CAAC;wBACP,sCAAsC;oBACxC,CAAC;gBACH,CAAC;YACH,CAAC;YAED,yBAAyB;YACzB,MAAM,YAAY,GAAG,oBAAoB,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YAEjE,0BAA0B;YAC1B,MAAM,gBAAgB,GAAG,eAAe,CAAC,eAAe,CAAC,CAAC;YAC1D,MAAM,qBAAqB,GAAG,QAAQ,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAC/D,qBAAqB,CAAC,CAAC,EAAE,GAAG,CAAC,OAAO,EAAE,gBAAgB,CAAC,CACxD,CAAC;YACF,MAAM,mBAAmB,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAC3D,qBAAqB,CAAC,CAAC,EAAE,GAAG,CAAC,OAAO,EAAE,gBAAgB,CAAC,CACxD,CAAC;YAEF,qBAAqB;YACrB,MAAM,WAAW,GAAG,iBAAiB,CACnC,QAAQ,CAAC,IAAI,EACb,YAAY,EACZ,qBAAqB,EACrB,mBAAmB,EACnB,EAAE,MAAM,EAAE,eAAe,CAAC,MAAM,EAAE,CACnC,CAAC;YAEF,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,eAAe,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC;QAC3F,CAAC;QAED,wDAAwD;QACxD,IAAI,eAAe,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,cAAc,GAAG,oBAAoB,CAAC,eAAe,EAAE;gBAC3D,MAAM,EAAE,eAAe,CAAC,MAAM;aAC/B,CAAC,CAAC;YAEH,IAAI,cAAc,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpC,OAAO,CAAC,GAAG,CACT,WAAW,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,wBAAwB,cAAc,CAAC,GAAG,EAAE,CAC3F,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,UAAU;AACV,KAAK,IAAI,EAAE,CAAC"}