@formspec/cli 0.1.0-alpha.3

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 (66) hide show
  1. package/README.md +314 -0
  2. package/dist/__tests__/analyzer.test.d.ts +5 -0
  3. package/dist/__tests__/analyzer.test.d.ts.map +1 -0
  4. package/dist/__tests__/analyzer.test.js +141 -0
  5. package/dist/__tests__/analyzer.test.js.map +1 -0
  6. package/dist/__tests__/codegen.test.d.ts +5 -0
  7. package/dist/__tests__/codegen.test.d.ts.map +1 -0
  8. package/dist/__tests__/codegen.test.js +482 -0
  9. package/dist/__tests__/codegen.test.js.map +1 -0
  10. package/dist/__tests__/edge-cases.test.d.ts +14 -0
  11. package/dist/__tests__/edge-cases.test.d.ts.map +1 -0
  12. package/dist/__tests__/edge-cases.test.js +432 -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 +135 -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 +159 -0
  25. package/dist/__tests__/integration.test.js.map +1 -0
  26. package/dist/analyzer/class-analyzer.d.ts +75 -0
  27. package/dist/analyzer/class-analyzer.d.ts.map +1 -0
  28. package/dist/analyzer/class-analyzer.js +151 -0
  29. package/dist/analyzer/class-analyzer.js.map +1 -0
  30. package/dist/analyzer/decorator-extractor.d.ts +87 -0
  31. package/dist/analyzer/decorator-extractor.d.ts.map +1 -0
  32. package/dist/analyzer/decorator-extractor.js +193 -0
  33. package/dist/analyzer/decorator-extractor.js.map +1 -0
  34. package/dist/analyzer/program.d.ts +37 -0
  35. package/dist/analyzer/program.d.ts.map +1 -0
  36. package/dist/analyzer/program.js +89 -0
  37. package/dist/analyzer/program.js.map +1 -0
  38. package/dist/analyzer/type-converter.d.ts +97 -0
  39. package/dist/analyzer/type-converter.d.ts.map +1 -0
  40. package/dist/analyzer/type-converter.js +353 -0
  41. package/dist/analyzer/type-converter.js.map +1 -0
  42. package/dist/codegen/index.d.ts +74 -0
  43. package/dist/codegen/index.d.ts.map +1 -0
  44. package/dist/codegen/index.js +501 -0
  45. package/dist/codegen/index.js.map +1 -0
  46. package/dist/generators/class-schema.d.ts +43 -0
  47. package/dist/generators/class-schema.d.ts.map +1 -0
  48. package/dist/generators/class-schema.js +61 -0
  49. package/dist/generators/class-schema.js.map +1 -0
  50. package/dist/generators/method-schema.d.ts +57 -0
  51. package/dist/generators/method-schema.d.ts.map +1 -0
  52. package/dist/generators/method-schema.js +108 -0
  53. package/dist/generators/method-schema.js.map +1 -0
  54. package/dist/index.d.ts +19 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +282 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/output/writer.d.ts +82 -0
  59. package/dist/output/writer.d.ts.map +1 -0
  60. package/dist/output/writer.js +152 -0
  61. package/dist/output/writer.js.map +1 -0
  62. package/dist/runtime/formspec-loader.d.ts +80 -0
  63. package/dist/runtime/formspec-loader.d.ts.map +1 -0
  64. package/dist/runtime/formspec-loader.js +154 -0
  65. package/dist/runtime/formspec-loader.js.map +1 -0
  66. package/package.json +46 -0
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Edge case fixtures for testing type converter and analyzer.
3
+ *
4
+ * These test various TypeScript type patterns that might cause issues.
5
+ */
6
+ // ============================================================================
7
+ // Complex Union Types
8
+ // ============================================================================
9
+ /**
10
+ * Mixed type union (not just literals) - should produce oneOf.
11
+ */
12
+ export class MixedUnionTypes {
13
+ // string | number - incompatible union
14
+ mixedPrimitive;
15
+ // Complex union with object and primitive
16
+ complexUnion;
17
+ // Union of different object shapes
18
+ objectUnion;
19
+ }
20
+ // ============================================================================
21
+ // Nullable and Optional Patterns
22
+ // ============================================================================
23
+ /**
24
+ * Various nullable patterns.
25
+ */
26
+ export class NullablePatterns {
27
+ // Nullable string (T | null)
28
+ nullableString;
29
+ // Undefined union (T | undefined) - different from optional
30
+ undefinedString;
31
+ // Both nullable and optional
32
+ optionalNullable;
33
+ // Triple union (T | null | undefined)
34
+ tripleUnion;
35
+ // Nullable enum
36
+ nullableStatus;
37
+ }
38
+ // ============================================================================
39
+ // Array Edge Cases
40
+ // ============================================================================
41
+ /**
42
+ * Various array patterns.
43
+ */
44
+ export class ArrayEdgeCases {
45
+ // Array of primitives
46
+ strings;
47
+ // Array of unions
48
+ mixedArray;
49
+ // Nullable array
50
+ nullableArray;
51
+ // Array of objects
52
+ objectArray;
53
+ // Empty array type (any[])
54
+ anyArray;
55
+ // Nested arrays
56
+ nestedArray;
57
+ }
58
+ // ============================================================================
59
+ // Object Edge Cases
60
+ // ============================================================================
61
+ /**
62
+ * Various object type patterns.
63
+ */
64
+ export class ObjectEdgeCases {
65
+ // Empty object
66
+ emptyObject;
67
+ // Record type
68
+ stringRecord;
69
+ // Deeply nested object
70
+ deepNested;
71
+ // Object with optional properties
72
+ optionalProps;
73
+ }
74
+ // ============================================================================
75
+ // Special Types
76
+ // ============================================================================
77
+ /**
78
+ * Special TypeScript types.
79
+ */
80
+ export class SpecialTypes {
81
+ // any type (should handle gracefully)
82
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
83
+ anyField;
84
+ // unknown type
85
+ unknownField;
86
+ // never type (edge case)
87
+ // Note: never is not typically used as a property type
88
+ // void type
89
+ voidField;
90
+ // Date (built-in object)
91
+ dateField;
92
+ }
93
+ // ============================================================================
94
+ // Enum Variations
95
+ // ============================================================================
96
+ /**
97
+ * Various enum patterns.
98
+ */
99
+ export class EnumVariations {
100
+ // Single literal (degenerates to const)
101
+ singleLiteral;
102
+ // Number literal enum
103
+ numberEnum;
104
+ // Mixed literal types (should NOT be valid enum)
105
+ // Note: This is a union, not an enum
106
+ mixedLiterals;
107
+ // Large enum (many options)
108
+ largeEnum;
109
+ }
110
+ // ============================================================================
111
+ // Class without decorators (for testing analyzer handles undecorated classes)
112
+ // ============================================================================
113
+ /**
114
+ * Simple class with no decorators for testing analyzer edge cases.
115
+ */
116
+ export class NoDecoratorsClass {
117
+ // Regular string field
118
+ name;
119
+ // Optional number field
120
+ count;
121
+ // Boolean field
122
+ active;
123
+ }
124
+ // ============================================================================
125
+ // Invalid FormSpec-like Objects (for testing isFormSpec)
126
+ // ============================================================================
127
+ export const notFormSpec1 = null;
128
+ export const notFormSpec2 = undefined;
129
+ export const notFormSpec3 = "string";
130
+ export const notFormSpec4 = 123;
131
+ export const notFormSpec5 = { notElements: [] };
132
+ export const notFormSpec6 = { elements: "not-array" };
133
+ export const notFormSpec7 = { elements: [{ missingType: true }] };
134
+ export const notFormSpec8 = { elements: [null] };
135
+ //# sourceMappingURL=edge-cases.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edge-cases.js","sourceRoot":"","sources":["../../../src/__tests__/fixtures/edge-cases.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,+EAA+E;AAC/E,sBAAsB;AACtB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,OAAO,eAAe;IAC1B,uCAAuC;IACvC,cAAc,CAAmB;IAEjC,0CAA0C;IAC1C,YAAY,CAAgC;IAE5C,mCAAmC;IACnC,WAAW,CAAiE;CAC7E;AAED,+EAA+E;AAC/E,iCAAiC;AACjC,+EAA+E;AAE/E;;GAEG;AACH,MAAM,OAAO,gBAAgB;IAC3B,6BAA6B;IAC7B,cAAc,CAAiB;IAE/B,4DAA4D;IAC5D,eAAe,CAAsB;IAErC,6BAA6B;IAC7B,gBAAgB,CAAiB;IAEjC,sCAAsC;IACtC,WAAW,CAA6B;IAExC,gBAAgB;IAChB,cAAc,CAAgC;CAC/C;AAED,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,OAAO,cAAc;IACzB,sBAAsB;IACtB,OAAO,CAAY;IAEnB,kBAAkB;IAClB,UAAU,CAAuB;IAEjC,iBAAiB;IACjB,aAAa,CAAmB;IAEhC,mBAAmB;IACnB,WAAW,CAAuC;IAElD,2BAA2B;IAC3B,QAAQ,CAAa;IAErB,gBAAgB;IAChB,WAAW,CAAc;CAC1B;AAED,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,OAAO,eAAe;IAC1B,eAAe;IACf,WAAW,CAAM;IAEjB,cAAc;IACd,YAAY,CAA0B;IAEtC,uBAAuB;IACvB,UAAU,CAQR;IAEF,kCAAkC;IAClC,aAAa,CAGX;CACH;AAED,+EAA+E;AAC/E,gBAAgB;AAChB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,OAAO,YAAY;IACvB,sCAAsC;IACtC,8DAA8D;IAC9D,QAAQ,CAAO;IAEf,eAAe;IACf,YAAY,CAAW;IAEvB,yBAAyB;IACzB,uDAAuD;IAEvD,YAAY;IACZ,SAAS,CAAQ;IAEjB,yBAAyB;IACzB,SAAS,CAAQ;CAClB;AAED,+EAA+E;AAC/E,kBAAkB;AAClB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,OAAO,cAAc;IACzB,wCAAwC;IACxC,aAAa,CAAU;IAEvB,sBAAsB;IACtB,UAAU,CAAa;IAEvB,iDAAiD;IACjD,qCAAqC;IACrC,aAAa,CAAiB;IAE9B,4BAA4B;IAC5B,SAAS,CAEuB;CACjC;AAED,+EAA+E;AAC/E,8EAA8E;AAC9E,+EAA+E;AAE/E;;GAEG;AACH,MAAM,OAAO,iBAAiB;IAC5B,uBAAuB;IACvB,IAAI,CAAU;IAEd,wBAAwB;IACxB,KAAK,CAAU;IAEf,gBAAgB;IAChB,MAAM,CAAW;CAClB;AAED,+EAA+E;AAC/E,yDAAyD;AACzD,+EAA+E;AAE/E,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC;AACjC,MAAM,CAAC,MAAM,YAAY,GAAG,SAAS,CAAC;AACtC,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAC;AACrC,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAC;AAChC,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;AAChD,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AACtD,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AAClE,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Test fixture for CLI analyzer.
3
+ *
4
+ * Contains both:
5
+ * - Decorated classes (class + decorator DSL)
6
+ * - FormSpec exports (chain DSL)
7
+ */
8
+ import type { InferFormSchema } from "@formspec/dsl";
9
+ /**
10
+ * FormSpec for user registration.
11
+ */
12
+ export declare const UserRegistrationForm: import("@formspec/core").FormSpec<readonly [import("@formspec/core").TextField<"username">, import("@formspec/core").TextField<"email">, import("@formspec/core").TextField<"password">, import("@formspec/core").BooleanField<"acceptTerms">]>;
13
+ /**
14
+ * FormSpec for product configuration.
15
+ */
16
+ export declare const ProductConfigForm: import("@formspec/core").FormSpec<readonly [import("@formspec/core").TextField<"name">, import("@formspec/core").NumberField<"price">, import("@formspec/core").StaticEnumField<"status", readonly ["draft", "active", "archived"]>]>;
17
+ /**
18
+ * FormSpec for method parameters.
19
+ */
20
+ export declare const ActivateParams: import("@formspec/core").FormSpec<readonly [import("@formspec/core").NumberField<"amount">, import("@formspec/core").NumberField<"installments">]>;
21
+ export declare const CancelParams: import("@formspec/core").FormSpec<readonly [import("@formspec/core").StaticEnumField<"reason", readonly ["user_request", "fraud", "other"]>, import("@formspec/core").TextField<"notes">]>;
22
+ /**
23
+ * Sample class with decorated fields and methods.
24
+ */
25
+ export declare class InstallmentPlan {
26
+ status: "active" | "paused" | "canceled";
27
+ amount: number;
28
+ customerEmail?: string;
29
+ installments: number;
30
+ /**
31
+ * Activates the plan with the given parameters.
32
+ */
33
+ activate(params: InferFormSchema<typeof ActivateParams>): {
34
+ success: boolean;
35
+ };
36
+ /**
37
+ * Cancels the plan.
38
+ */
39
+ cancelPlan(params: InferFormSchema<typeof CancelParams>): void;
40
+ /**
41
+ * Static factory method.
42
+ */
43
+ static createStandard(name: string, amount: number): InstallmentPlan;
44
+ }
45
+ export declare class SimpleProduct {
46
+ name: string;
47
+ price?: number;
48
+ active: boolean;
49
+ tags?: string[];
50
+ update(data: {
51
+ name?: string;
52
+ price?: number;
53
+ }): boolean;
54
+ }
55
+ //# sourceMappingURL=sample-forms.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sample-forms.d.ts","sourceRoot":"","sources":["../../../src/__tests__/fixtures/sample-forms.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAMrD;;GAEG;AACH,eAAO,MAAM,oBAAoB,iPAKhC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,uOAM7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,oJAG1B,CAAC;AAEF,eAAO,MAAM,YAAY,4LAKxB,CAAC;AAMF;;GAEG;AACH,qBAAa,eAAe;IAC1B,MAAM,EAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;IAE1C,MAAM,EAAG,MAAM,CAAC;IAEhB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,YAAY,EAAG,MAAM,CAAC;IAEtB;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,cAAc,CAAC,GAAG;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE;IAK9E;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,YAAY,CAAC,GAAG,IAAI;IAI9D;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,eAAe;CAKrE;AAMD,qBAAa,aAAa;IACxB,IAAI,EAAG,MAAM,CAAC;IAEd,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,MAAM,EAAG,OAAO,CAAC;IAEjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB,MAAM,CAAC,IAAI,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO;CAKzD"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Test fixture for CLI analyzer.
3
+ *
4
+ * Contains both:
5
+ * - Decorated classes (class + decorator DSL)
6
+ * - FormSpec exports (chain DSL)
7
+ */
8
+ import { formspec, field } from "@formspec/dsl";
9
+ // ============================================================================
10
+ // Chain DSL FormSpecs (exported for runtime loading)
11
+ // ============================================================================
12
+ /**
13
+ * FormSpec for user registration.
14
+ */
15
+ export const UserRegistrationForm = formspec(field.text("username", { label: "Username", required: true }), field.text("email", { label: "Email Address", required: true }), field.text("password", { label: "Password", required: true }), field.boolean("acceptTerms", { label: "Accept Terms", required: true }));
16
+ /**
17
+ * FormSpec for product configuration.
18
+ */
19
+ export const ProductConfigForm = formspec(field.text("name", { label: "Product Name", required: true }), field.number("price", { label: "Price (cents)", min: 0 }), field.enum("status", ["draft", "active", "archived"], {
20
+ label: "Status",
21
+ }));
22
+ /**
23
+ * FormSpec for method parameters.
24
+ */
25
+ export const ActivateParams = formspec(field.number("amount", { label: "Amount (cents)", min: 100 }), field.number("installments", { label: "Number of Installments", min: 2, max: 12 }));
26
+ export const CancelParams = formspec(field.enum("reason", ["user_request", "fraud", "other"], {
27
+ label: "Cancellation Reason",
28
+ }), field.text("notes", { label: "Additional Notes" }));
29
+ // ============================================================================
30
+ // Decorated Class (class + decorator DSL)
31
+ // ============================================================================
32
+ /**
33
+ * Sample class with decorated fields and methods.
34
+ */
35
+ export class InstallmentPlan {
36
+ status;
37
+ amount;
38
+ customerEmail;
39
+ installments;
40
+ /**
41
+ * Activates the plan with the given parameters.
42
+ */
43
+ activate(params) {
44
+ console.log("Activating with", params);
45
+ return { success: true };
46
+ }
47
+ /**
48
+ * Cancels the plan.
49
+ */
50
+ cancelPlan(params) {
51
+ console.log("Canceling with reason:", params.reason);
52
+ }
53
+ /**
54
+ * Static factory method.
55
+ */
56
+ static createStandard(name, amount) {
57
+ const plan = new InstallmentPlan();
58
+ plan.amount = amount;
59
+ return plan;
60
+ }
61
+ }
62
+ // ============================================================================
63
+ // Simple class without FormSpec method params (for testing static analysis only)
64
+ // ============================================================================
65
+ export class SimpleProduct {
66
+ name;
67
+ price;
68
+ active;
69
+ tags;
70
+ update(data) {
71
+ if (data.name)
72
+ this.name = data.name;
73
+ if (data.price)
74
+ this.price = data.price;
75
+ return true;
76
+ }
77
+ }
78
+ //# sourceMappingURL=sample-forms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sample-forms.js","sourceRoot":"","sources":["../../../src/__tests__/fixtures/sample-forms.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAGhD,+EAA+E;AAC/E,qDAAqD;AACrD,+EAA+E;AAE/E;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,QAAQ,CAC1C,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAC7D,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAC/D,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAC7D,KAAK,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CACxE,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CACvC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAC7D,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EACzD,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAU,EAAE;IAC7D,KAAK,EAAE,QAAQ;CAChB,CAAC,CACH,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,QAAQ,CACpC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAC7D,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,wBAAwB,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CACnF,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAClC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,cAAc,EAAE,OAAO,EAAE,OAAO,CAAU,EAAE;IAChE,KAAK,EAAE,qBAAqB;CAC7B,CAAC,EACF,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CACnD,CAAC;AAEF,+EAA+E;AAC/E,0CAA0C;AAC1C,+EAA+E;AAE/E;;GAEG;AACH,MAAM,OAAO,eAAe;IAC1B,MAAM,CAAoC;IAE1C,MAAM,CAAU;IAEhB,aAAa,CAAU;IAEvB,YAAY,CAAU;IAEtB;;OAEG;IACH,QAAQ,CAAC,MAA8C;QACrD,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;QACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,MAA4C;QACrD,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACvD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,IAAY,EAAE,MAAc;QAChD,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED,+EAA+E;AAC/E,iFAAiF;AACjF,+EAA+E;AAE/E,MAAM,OAAO,aAAa;IACxB,IAAI,CAAU;IAEd,KAAK,CAAU;IAEf,MAAM,CAAW;IAEjB,IAAI,CAAY;IAEhB,MAAM,CAAC,IAAuC;QAC5C,IAAI,IAAI,CAAC,IAAI;YAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACrC,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Integration tests for the CLI workflow.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=integration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/integration.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,159 @@
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 } from "../analyzer/program.js";
8
+ import { analyzeClass } from "../analyzer/class-analyzer.js";
9
+ import { generateClassSchemas } from "../generators/class-schema.js";
10
+ import { generateMethodSchemas, collectFormSpecReferences, } from "../generators/method-schema.js";
11
+ import { loadFormSpecs, isFormSpec, } from "../runtime/formspec-loader.js";
12
+ import { writeClassSchemas, writeFormSpecSchemas } from "../output/writer.js";
13
+ const fixturesDir = path.join(__dirname, "fixtures");
14
+ const sampleFormsPath = path.join(fixturesDir, "sample-forms.ts");
15
+ const compiledPath = path.join(fixturesDir, "sample-forms.js");
16
+ const testOutputDir = path.join(__dirname, "__test_output__");
17
+ // Check if compiled fixture exists (may need to be built)
18
+ const hasCompiledFixture = fs.existsSync(compiledPath);
19
+ describe("generators", () => {
20
+ it("generates class schemas from static analysis", () => {
21
+ const ctx = createProgramContext(sampleFormsPath);
22
+ const classDecl = findClassByName(ctx.sourceFile, "SimpleProduct");
23
+ const analysis = analyzeClass(classDecl, ctx.checker);
24
+ const schemas = generateClassSchemas(analysis, ctx.checker);
25
+ // JSON Schema
26
+ expect(schemas.jsonSchema.type).toBe("object");
27
+ expect(schemas.jsonSchema.properties).toBeDefined();
28
+ expect(schemas.jsonSchema.properties?.["name"]).toBeDefined();
29
+ expect(schemas.jsonSchema.properties?.["price"]).toBeDefined();
30
+ expect(schemas.jsonSchema.required).toContain("name");
31
+ expect(schemas.jsonSchema.required).toContain("active");
32
+ expect(schemas.jsonSchema.required).not.toContain("price");
33
+ // UI Schema
34
+ expect(schemas.uxSpec.elements).toHaveLength(4);
35
+ const nameElement = schemas.uxSpec.elements.find((e) => e.id === "name");
36
+ expect(nameElement?._field).toBe("text");
37
+ expect(nameElement?.required).toBe(true);
38
+ });
39
+ it("collects FormSpec references from methods", () => {
40
+ const ctx = createProgramContext(sampleFormsPath);
41
+ const classDecl = findClassByName(ctx.sourceFile, "InstallmentPlan");
42
+ const analysis = analyzeClass(classDecl, ctx.checker);
43
+ const refs = collectFormSpecReferences([
44
+ ...analysis.instanceMethods,
45
+ ...analysis.staticMethods,
46
+ ]);
47
+ expect(refs.size).toBe(2);
48
+ expect(refs.has("ActivateParams")).toBe(true);
49
+ expect(refs.has("CancelParams")).toBe(true);
50
+ });
51
+ it("generates method schemas without FormSpec (static only)", () => {
52
+ const ctx = createProgramContext(sampleFormsPath);
53
+ const classDecl = findClassByName(ctx.sourceFile, "SimpleProduct");
54
+ const analysis = analyzeClass(classDecl, ctx.checker);
55
+ const updateMethod = analysis.instanceMethods[0];
56
+ const methodSchemas = generateMethodSchemas(updateMethod, ctx.checker, new Map());
57
+ expect(methodSchemas.name).toBe("update");
58
+ expect(methodSchemas.params).not.toBeNull();
59
+ expect(methodSchemas.params?.jsonSchema.type).toBe("object");
60
+ expect(methodSchemas.params?.uxSpec).toBeNull();
61
+ expect(methodSchemas.returnType.type).toBe("boolean");
62
+ });
63
+ });
64
+ describe("isFormSpec", () => {
65
+ it("detects valid FormSpec-like objects", () => {
66
+ const validFormSpec = {
67
+ elements: [
68
+ { _type: "field", _field: "text", name: "test" },
69
+ ],
70
+ };
71
+ expect(isFormSpec(validFormSpec)).toBe(true);
72
+ });
73
+ it("rejects invalid objects", () => {
74
+ expect(isFormSpec(null)).toBe(false);
75
+ expect(isFormSpec(undefined)).toBe(false);
76
+ expect(isFormSpec({})).toBe(false);
77
+ expect(isFormSpec({ elements: "not-array" })).toBe(false);
78
+ expect(isFormSpec({ elements: [{ noType: true }] })).toBe(false);
79
+ });
80
+ });
81
+ describe.skipIf(!hasCompiledFixture)("runtime loading", () => {
82
+ it("loads FormSpec exports from compiled module", async () => {
83
+ const { formSpecs, module } = await loadFormSpecs(compiledPath);
84
+ // Should find our exported FormSpecs
85
+ expect(formSpecs.size).toBeGreaterThan(0);
86
+ expect(formSpecs.has("UserRegistrationForm")).toBe(true);
87
+ expect(formSpecs.has("ProductConfigForm")).toBe(true);
88
+ expect(formSpecs.has("ActivateParams")).toBe(true);
89
+ expect(formSpecs.has("CancelParams")).toBe(true);
90
+ // Check generated schemas
91
+ const userForm = formSpecs.get("UserRegistrationForm");
92
+ expect(userForm.jsonSchema).toBeDefined();
93
+ expect(userForm.uiSchema).toBeDefined();
94
+ // Module should have the class exports too
95
+ expect(module["InstallmentPlan"]).toBeDefined();
96
+ });
97
+ it("generates method schemas with FormSpec params", async () => {
98
+ const ctx = createProgramContext(sampleFormsPath);
99
+ const classDecl = findClassByName(ctx.sourceFile, "InstallmentPlan");
100
+ const analysis = analyzeClass(classDecl, ctx.checker);
101
+ // Load FormSpecs at runtime
102
+ const { formSpecs } = await loadFormSpecs(compiledPath);
103
+ // Generate method schemas
104
+ const activateMethod = analysis.instanceMethods.find((m) => m.name === "activate");
105
+ const methodSchemas = generateMethodSchemas(activateMethod, ctx.checker, formSpecs);
106
+ expect(methodSchemas.name).toBe("activate");
107
+ expect(methodSchemas.params).not.toBeNull();
108
+ expect(methodSchemas.params?.formSpecExport).toBe("ActivateParams");
109
+ // Should have UI Schema from the FormSpec
110
+ expect(methodSchemas.params?.uxSpec).not.toBeNull();
111
+ });
112
+ });
113
+ describe.skipIf(!hasCompiledFixture)("output writer", () => {
114
+ beforeAll(() => {
115
+ // Clean up test output directory
116
+ if (fs.existsSync(testOutputDir)) {
117
+ fs.rmSync(testOutputDir, { recursive: true });
118
+ }
119
+ });
120
+ afterAll(() => {
121
+ // Clean up test output directory
122
+ if (fs.existsSync(testOutputDir)) {
123
+ fs.rmSync(testOutputDir, { recursive: true });
124
+ }
125
+ });
126
+ it("writes class schemas to output directory", async () => {
127
+ const ctx = createProgramContext(sampleFormsPath);
128
+ const classDecl = findClassByName(ctx.sourceFile, "InstallmentPlan");
129
+ const analysis = analyzeClass(classDecl, ctx.checker);
130
+ // Load FormSpecs
131
+ const { formSpecs } = await loadFormSpecs(compiledPath);
132
+ // Generate schemas
133
+ const classSchemas = generateClassSchemas(analysis, ctx.checker);
134
+ const instanceMethodSchemas = analysis.instanceMethods.map((m) => generateMethodSchemas(m, ctx.checker, formSpecs));
135
+ const staticMethodSchemas = analysis.staticMethods.map((m) => generateMethodSchemas(m, ctx.checker, formSpecs));
136
+ // Write output
137
+ const result = writeClassSchemas(analysis.name, classSchemas, instanceMethodSchemas, staticMethodSchemas, { outDir: testOutputDir });
138
+ // Verify directory structure
139
+ expect(fs.existsSync(result.dir)).toBe(true);
140
+ expect(fs.existsSync(path.join(result.dir, "schema.json"))).toBe(true);
141
+ expect(fs.existsSync(path.join(result.dir, "ux_spec.json"))).toBe(true);
142
+ expect(fs.existsSync(path.join(result.dir, "instance_methods", "activate", "params.schema.json"))).toBe(true);
143
+ expect(fs.existsSync(path.join(result.dir, "instance_methods", "activate", "params.ux_spec.json"))).toBe(true);
144
+ expect(fs.existsSync(path.join(result.dir, "static_methods", "createStandard", "return_type.schema.json"))).toBe(true);
145
+ // Verify JSON content
146
+ const schemaContent = JSON.parse(fs.readFileSync(path.join(result.dir, "schema.json"), "utf-8"));
147
+ expect(schemaContent.type).toBe("object");
148
+ expect(schemaContent.properties).toBeDefined();
149
+ });
150
+ it("writes FormSpec schemas to output directory", async () => {
151
+ const { formSpecs } = await loadFormSpecs(compiledPath);
152
+ const result = writeFormSpecSchemas(formSpecs, { outDir: testOutputDir });
153
+ expect(fs.existsSync(result.dir)).toBe(true);
154
+ expect(fs.existsSync(path.join(result.dir, "UserRegistrationForm", "schema.json"))).toBe(true);
155
+ expect(fs.existsSync(path.join(result.dir, "UserRegistrationForm", "ux_spec.json"))).toBe(true);
156
+ expect(fs.existsSync(path.join(result.dir, "ProductConfigForm", "schema.json"))).toBe(true);
157
+ });
158
+ });
159
+ //# 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,75 @@
1
+ /**
2
+ * Class analyzer for extracting fields, types, and decorators.
3
+ *
4
+ * Analyzes a TypeScript class declaration to extract:
5
+ * - Field names and TypeScript types
6
+ * - Decorator metadata (Label, Min, Max, etc.)
7
+ * - Field optionality
8
+ */
9
+ import * as ts from "typescript";
10
+ import { type DecoratorInfo } from "./decorator-extractor.js";
11
+ /**
12
+ * Analyzed field information from a class.
13
+ */
14
+ export interface FieldInfo {
15
+ /** Field name */
16
+ name: string;
17
+ /** TypeScript type node for the field */
18
+ typeNode: ts.TypeNode | undefined;
19
+ /** Resolved type from the type checker */
20
+ type: ts.Type;
21
+ /** Whether the field is optional (has ? modifier) */
22
+ optional: boolean;
23
+ /** Decorators applied to the field */
24
+ decorators: DecoratorInfo[];
25
+ }
26
+ /**
27
+ * Result of analyzing a class declaration.
28
+ */
29
+ export interface ClassAnalysis {
30
+ /** Class name */
31
+ name: string;
32
+ /** Analyzed fields */
33
+ fields: FieldInfo[];
34
+ /** Instance methods */
35
+ instanceMethods: MethodInfo[];
36
+ /** Static methods */
37
+ staticMethods: MethodInfo[];
38
+ }
39
+ /**
40
+ * Analyzed method information.
41
+ */
42
+ export interface MethodInfo {
43
+ /** Method name */
44
+ name: string;
45
+ /** Method parameters */
46
+ parameters: ParameterInfo[];
47
+ /** Return type node */
48
+ returnTypeNode: ts.TypeNode | undefined;
49
+ /** Resolved return type */
50
+ returnType: ts.Type;
51
+ }
52
+ /**
53
+ * Analyzed parameter information.
54
+ */
55
+ export interface ParameterInfo {
56
+ /** Parameter name */
57
+ name: string;
58
+ /** TypeScript type node */
59
+ typeNode: ts.TypeNode | undefined;
60
+ /** Resolved type */
61
+ type: ts.Type;
62
+ /** If this is InferSchema<typeof X>, the export name X */
63
+ formSpecExportName: string | null;
64
+ /** Whether the parameter is optional (has ? or default value) */
65
+ optional: boolean;
66
+ }
67
+ /**
68
+ * Analyzes a class declaration to extract fields and methods.
69
+ *
70
+ * @param classDecl - The class declaration to analyze
71
+ * @param checker - TypeScript type checker
72
+ * @returns Analysis result with fields and methods
73
+ */
74
+ export declare function analyzeClass(classDecl: ts.ClassDeclaration, checker: ts.TypeChecker): ClassAnalysis;
75
+ //# sourceMappingURL=class-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"class-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzer/class-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEjF;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,QAAQ,EAAE,EAAE,CAAC,QAAQ,GAAG,SAAS,CAAC;IAClC,0CAA0C;IAC1C,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;IACd,qDAAqD;IACrD,QAAQ,EAAE,OAAO,CAAC;IAClB,sCAAsC;IACtC,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,sBAAsB;IACtB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,uBAAuB;IACvB,eAAe,EAAE,UAAU,EAAE,CAAC;IAC9B,qBAAqB;IACrB,aAAa,EAAE,UAAU,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,kBAAkB;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,uBAAuB;IACvB,cAAc,EAAE,EAAE,CAAC,QAAQ,GAAG,SAAS,CAAC;IACxC,2BAA2B;IAC3B,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,2BAA2B;IAC3B,QAAQ,EAAE,EAAE,CAAC,QAAQ,GAAG,SAAS,CAAC;IAClC,oBAAoB;IACpB,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;IACd,0DAA0D;IAC1D,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,iEAAiE;IACjE,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,EAAE,CAAC,gBAAgB,EAC9B,OAAO,EAAE,EAAE,CAAC,WAAW,GACtB,aAAa,CAiCf"}