@formspec/build 0.1.0-alpha.2 → 0.1.0-alpha.21

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 (177) hide show
  1. package/README.md +120 -0
  2. package/dist/__tests__/alias-chain-propagation.test.d.ts +9 -0
  3. package/dist/__tests__/alias-chain-propagation.test.d.ts.map +1 -0
  4. package/dist/__tests__/chain-dsl-canonicalizer.test.d.ts +2 -0
  5. package/dist/__tests__/chain-dsl-canonicalizer.test.d.ts.map +1 -0
  6. package/dist/__tests__/class-schema.test.d.ts +2 -0
  7. package/dist/__tests__/class-schema.test.d.ts.map +1 -0
  8. package/dist/__tests__/constraint-validator.test.d.ts +2 -0
  9. package/dist/__tests__/constraint-validator.test.d.ts.map +1 -0
  10. package/dist/__tests__/date-extension.integration.test.d.ts +2 -0
  11. package/dist/__tests__/date-extension.integration.test.d.ts.map +1 -0
  12. package/dist/__tests__/extension-api.test.d.ts +2 -0
  13. package/dist/__tests__/extension-api.test.d.ts.map +1 -0
  14. package/dist/__tests__/extension-runtime.integration.test.d.ts +2 -0
  15. package/dist/__tests__/extension-runtime.integration.test.d.ts.map +1 -0
  16. package/dist/__tests__/fixtures/alias-chains.d.ts +37 -0
  17. package/dist/__tests__/fixtures/alias-chains.d.ts.map +1 -0
  18. package/dist/__tests__/fixtures/class-schema-regressions.d.ts +86 -0
  19. package/dist/__tests__/fixtures/class-schema-regressions.d.ts.map +1 -0
  20. package/dist/__tests__/fixtures/edge-cases.d.ts +132 -0
  21. package/dist/__tests__/fixtures/edge-cases.d.ts.map +1 -0
  22. package/dist/__tests__/fixtures/example-a-builtins.d.ts +31 -0
  23. package/dist/__tests__/fixtures/example-a-builtins.d.ts.map +1 -0
  24. package/dist/__tests__/fixtures/example-date-extension.d.ts +12 -0
  25. package/dist/__tests__/fixtures/example-date-extension.d.ts.map +1 -0
  26. package/dist/__tests__/fixtures/example-interface-types.d.ts +107 -0
  27. package/dist/__tests__/fixtures/example-interface-types.d.ts.map +1 -0
  28. package/dist/__tests__/fixtures/example-numeric-extension.d.ts +20 -0
  29. package/dist/__tests__/fixtures/example-numeric-extension.d.ts.map +1 -0
  30. package/dist/__tests__/fixtures/extension-forms.d.ts +7 -0
  31. package/dist/__tests__/fixtures/extension-forms.d.ts.map +1 -0
  32. package/dist/__tests__/fixtures/mixed-authoring-shipping-address.d.ts +31 -0
  33. package/dist/__tests__/fixtures/mixed-authoring-shipping-address.d.ts.map +1 -0
  34. package/dist/__tests__/fixtures/named-primitive-aliases.d.ts +15 -0
  35. package/dist/__tests__/fixtures/named-primitive-aliases.d.ts.map +1 -0
  36. package/dist/__tests__/fixtures/nested-array-path-constraints.d.ts +14 -0
  37. package/dist/__tests__/fixtures/nested-array-path-constraints.d.ts.map +1 -0
  38. package/dist/__tests__/fixtures/sample-forms.d.ts +65 -0
  39. package/dist/__tests__/fixtures/sample-forms.d.ts.map +1 -0
  40. package/dist/__tests__/generate-schemas.test.d.ts +2 -0
  41. package/dist/__tests__/generate-schemas.test.d.ts.map +1 -0
  42. package/dist/__tests__/guards.test.d.ts +2 -0
  43. package/dist/__tests__/guards.test.d.ts.map +1 -0
  44. package/dist/__tests__/ir-analyzer.test.d.ts +11 -0
  45. package/dist/__tests__/ir-analyzer.test.d.ts.map +1 -0
  46. package/dist/__tests__/ir-jsdoc-constraints.test.d.ts +12 -0
  47. package/dist/__tests__/ir-jsdoc-constraints.test.d.ts.map +1 -0
  48. package/dist/__tests__/ir-json-schema-generator.test.d.ts +11 -0
  49. package/dist/__tests__/ir-json-schema-generator.test.d.ts.map +1 -0
  50. package/dist/__tests__/ir-ui-schema-generator.test.d.ts +2 -0
  51. package/dist/__tests__/ir-ui-schema-generator.test.d.ts.map +1 -0
  52. package/dist/__tests__/mixed-authoring.test.d.ts +2 -0
  53. package/dist/__tests__/mixed-authoring.test.d.ts.map +1 -0
  54. package/dist/__tests__/numeric-extension.integration.test.d.ts +2 -0
  55. package/dist/__tests__/numeric-extension.integration.test.d.ts.map +1 -0
  56. package/dist/__tests__/parity/fixtures/address/chain-dsl.d.ts +9 -0
  57. package/dist/__tests__/parity/fixtures/address/chain-dsl.d.ts.map +1 -0
  58. package/dist/__tests__/parity/fixtures/address/expected-ir.d.ts +9 -0
  59. package/dist/__tests__/parity/fixtures/address/expected-ir.d.ts.map +1 -0
  60. package/dist/__tests__/parity/fixtures/address/tsdoc.d.ts +19 -0
  61. package/dist/__tests__/parity/fixtures/address/tsdoc.d.ts.map +1 -0
  62. package/dist/__tests__/parity/fixtures/plan-status/chain-dsl.d.ts +19 -0
  63. package/dist/__tests__/parity/fixtures/plan-status/chain-dsl.d.ts.map +1 -0
  64. package/dist/__tests__/parity/fixtures/plan-status/expected-ir.d.ts +6 -0
  65. package/dist/__tests__/parity/fixtures/plan-status/expected-ir.d.ts.map +1 -0
  66. package/dist/__tests__/parity/fixtures/plan-status/tsdoc.d.ts +17 -0
  67. package/dist/__tests__/parity/fixtures/plan-status/tsdoc.d.ts.map +1 -0
  68. package/dist/__tests__/parity/fixtures/product-config/chain-dsl.d.ts +13 -0
  69. package/dist/__tests__/parity/fixtures/product-config/chain-dsl.d.ts.map +1 -0
  70. package/dist/__tests__/parity/fixtures/product-config/expected-ir.d.ts +9 -0
  71. package/dist/__tests__/parity/fixtures/product-config/expected-ir.d.ts.map +1 -0
  72. package/dist/__tests__/parity/fixtures/product-config/tsdoc.d.ts +28 -0
  73. package/dist/__tests__/parity/fixtures/product-config/tsdoc.d.ts.map +1 -0
  74. package/dist/__tests__/parity/fixtures/usd-cents/chain-dsl.d.ts +9 -0
  75. package/dist/__tests__/parity/fixtures/usd-cents/chain-dsl.d.ts.map +1 -0
  76. package/dist/__tests__/parity/fixtures/usd-cents/expected-ir.d.ts +6 -0
  77. package/dist/__tests__/parity/fixtures/usd-cents/expected-ir.d.ts.map +1 -0
  78. package/dist/__tests__/parity/fixtures/usd-cents/tsdoc.d.ts +19 -0
  79. package/dist/__tests__/parity/fixtures/usd-cents/tsdoc.d.ts.map +1 -0
  80. package/dist/__tests__/parity/fixtures/user-registration/chain-dsl.d.ts +12 -0
  81. package/dist/__tests__/parity/fixtures/user-registration/chain-dsl.d.ts.map +1 -0
  82. package/dist/__tests__/parity/fixtures/user-registration/expected-ir.d.ts +9 -0
  83. package/dist/__tests__/parity/fixtures/user-registration/expected-ir.d.ts.map +1 -0
  84. package/dist/__tests__/parity/fixtures/user-registration/tsdoc.d.ts +19 -0
  85. package/dist/__tests__/parity/fixtures/user-registration/tsdoc.d.ts.map +1 -0
  86. package/dist/__tests__/parity/parity.test.d.ts +18 -0
  87. package/dist/__tests__/parity/parity.test.d.ts.map +1 -0
  88. package/dist/__tests__/parity/utils.d.ts +152 -0
  89. package/dist/__tests__/parity/utils.d.ts.map +1 -0
  90. package/dist/__tests__/path-target-parser.test.d.ts +9 -0
  91. package/dist/__tests__/path-target-parser.test.d.ts.map +1 -0
  92. package/dist/analyzer/class-analyzer.d.ts +100 -0
  93. package/dist/analyzer/class-analyzer.d.ts.map +1 -0
  94. package/dist/analyzer/jsdoc-constraints.d.ts +53 -0
  95. package/dist/analyzer/jsdoc-constraints.d.ts.map +1 -0
  96. package/dist/analyzer/program.d.ts +68 -0
  97. package/dist/analyzer/program.d.ts.map +1 -0
  98. package/dist/analyzer/tsdoc-parser.d.ts +123 -0
  99. package/dist/analyzer/tsdoc-parser.d.ts.map +1 -0
  100. package/dist/browser.cjs +1294 -0
  101. package/dist/browser.cjs.map +1 -0
  102. package/dist/browser.d.ts +73 -0
  103. package/dist/browser.d.ts.map +1 -0
  104. package/dist/browser.js +1245 -0
  105. package/dist/browser.js.map +1 -0
  106. package/dist/build.d.ts +1144 -0
  107. package/dist/canonicalize/chain-dsl-canonicalizer.d.ts +18 -0
  108. package/dist/canonicalize/chain-dsl-canonicalizer.d.ts.map +1 -0
  109. package/dist/canonicalize/index.d.ts +8 -0
  110. package/dist/canonicalize/index.d.ts.map +1 -0
  111. package/dist/canonicalize/tsdoc-canonicalizer.d.ts +34 -0
  112. package/dist/canonicalize/tsdoc-canonicalizer.d.ts.map +1 -0
  113. package/dist/cli.cjs +3859 -0
  114. package/dist/cli.cjs.map +1 -0
  115. package/dist/cli.js +3823 -103
  116. package/dist/cli.js.map +1 -1
  117. package/dist/extensions/index.d.ts +8 -0
  118. package/dist/extensions/index.d.ts.map +1 -0
  119. package/dist/extensions/registry.d.ts +83 -0
  120. package/dist/extensions/registry.d.ts.map +1 -0
  121. package/dist/generators/class-schema.d.ts +111 -0
  122. package/dist/generators/class-schema.d.ts.map +1 -0
  123. package/dist/generators/method-schema.d.ts +65 -0
  124. package/dist/generators/method-schema.d.ts.map +1 -0
  125. package/dist/generators/mixed-authoring.d.ts +51 -0
  126. package/dist/generators/mixed-authoring.d.ts.map +1 -0
  127. package/dist/index.cjs +3624 -0
  128. package/dist/index.cjs.map +1 -0
  129. package/dist/index.d.ts +45 -8
  130. package/dist/index.d.ts.map +1 -1
  131. package/dist/index.js +3584 -106
  132. package/dist/index.js.map +1 -1
  133. package/dist/internals.cjs +3368 -0
  134. package/dist/internals.cjs.map +1 -0
  135. package/dist/internals.d.ts +30 -0
  136. package/dist/internals.d.ts.map +1 -0
  137. package/dist/internals.js +3342 -0
  138. package/dist/internals.js.map +1 -0
  139. package/dist/json-schema/generator.d.ts +20 -5
  140. package/dist/json-schema/generator.d.ts.map +1 -1
  141. package/dist/json-schema/ir-generator.d.ts +114 -0
  142. package/dist/json-schema/ir-generator.d.ts.map +1 -0
  143. package/dist/json-schema/schema.d.ts +23 -0
  144. package/dist/json-schema/schema.d.ts.map +1 -0
  145. package/dist/json-schema/types.d.ts +45 -2
  146. package/dist/json-schema/types.d.ts.map +1 -1
  147. package/dist/ui-schema/generator.d.ts +7 -0
  148. package/dist/ui-schema/generator.d.ts.map +1 -1
  149. package/dist/ui-schema/ir-generator.d.ts +53 -0
  150. package/dist/ui-schema/ir-generator.d.ts.map +1 -0
  151. package/dist/ui-schema/schema.d.ts +434 -0
  152. package/dist/ui-schema/schema.d.ts.map +1 -0
  153. package/dist/ui-schema/types.d.ts +10 -73
  154. package/dist/ui-schema/types.d.ts.map +1 -1
  155. package/dist/validate/constraint-validator.d.ts +23 -0
  156. package/dist/validate/constraint-validator.d.ts.map +1 -0
  157. package/dist/validate/index.d.ts +9 -0
  158. package/dist/validate/index.d.ts.map +1 -0
  159. package/package.json +27 -7
  160. package/dist/__tests__/cli.test.js +0 -178
  161. package/dist/__tests__/cli.test.js.map +0 -1
  162. package/dist/__tests__/edge-cases.test.js +0 -217
  163. package/dist/__tests__/edge-cases.test.js.map +0 -1
  164. package/dist/__tests__/generator.test.js +0 -225
  165. package/dist/__tests__/generator.test.js.map +0 -1
  166. package/dist/__tests__/integration.test.js +0 -163
  167. package/dist/__tests__/integration.test.js.map +0 -1
  168. package/dist/__tests__/write-schemas.test.js +0 -196
  169. package/dist/__tests__/write-schemas.test.js.map +0 -1
  170. package/dist/json-schema/generator.js +0 -161
  171. package/dist/json-schema/generator.js.map +0 -1
  172. package/dist/json-schema/types.js +0 -7
  173. package/dist/json-schema/types.js.map +0 -1
  174. package/dist/ui-schema/generator.js +0 -150
  175. package/dist/ui-schema/generator.js.map +0 -1
  176. package/dist/ui-schema/types.js +0 -8
  177. package/dist/ui-schema/types.js.map +0 -1
@@ -1,178 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
- import * as fs from "node:fs";
3
- import * as path from "node:path";
4
- import * as os from "node:os";
5
- import { execSync } from "node:child_process";
6
- describe("CLI", () => {
7
- let tempDir;
8
- const cliPath = path.join(__dirname, "..", "..", "dist", "cli.js");
9
- beforeEach(() => {
10
- tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "formspec-cli-test-"));
11
- });
12
- afterEach(() => {
13
- if (fs.existsSync(tempDir)) {
14
- fs.rmSync(tempDir, { recursive: true });
15
- }
16
- });
17
- function runCli(args) {
18
- try {
19
- const stdout = execSync(`node ${cliPath} ${args.join(" ")}`, {
20
- encoding: "utf-8",
21
- cwd: tempDir,
22
- stdio: ["pipe", "pipe", "pipe"],
23
- });
24
- return { stdout, exitCode: 0 };
25
- }
26
- catch (error) {
27
- const execError = error;
28
- return {
29
- stdout: execError.stdout || execError.stderr || "",
30
- exitCode: execError.status || 1,
31
- };
32
- }
33
- }
34
- function createFormFile(filename, content) {
35
- const filepath = path.join(tempDir, filename);
36
- fs.writeFileSync(filepath, content);
37
- return filepath;
38
- }
39
- describe("help", () => {
40
- it("should show help with --help flag", () => {
41
- const result = runCli(["--help"]);
42
- expect(result.stdout).toContain("FormSpec Build CLI");
43
- expect(result.stdout).toContain("Usage:");
44
- expect(result.stdout).toContain("--out-dir");
45
- expect(result.stdout).toContain("--name");
46
- });
47
- it("should show help with -h flag", () => {
48
- const result = runCli(["-h"]);
49
- expect(result.stdout).toContain("FormSpec Build CLI");
50
- });
51
- });
52
- describe("argument parsing", () => {
53
- it("should fail when no input file provided", () => {
54
- const result = runCli([]);
55
- expect(result.exitCode).not.toBe(0);
56
- // Shows help which includes Usage information
57
- expect(result.stdout).toContain("Usage:");
58
- });
59
- it("should fail for unknown option", () => {
60
- const formFile = createFormFile("form.js", `
61
- export default { elements: [] };
62
- `);
63
- const result = runCli([formFile, "--unknown-option"]);
64
- expect(result.exitCode).not.toBe(0);
65
- expect(result.stdout).toContain("Unknown option");
66
- });
67
- it("should fail when --out-dir has no value", () => {
68
- const formFile = createFormFile("form.js", `
69
- export default { elements: [] };
70
- `);
71
- const result = runCli([formFile, "--out-dir"]);
72
- expect(result.exitCode).not.toBe(0);
73
- expect(result.stdout).toContain("--out-dir requires a value");
74
- });
75
- it("should fail when --name has no value", () => {
76
- const formFile = createFormFile("form.js", `
77
- export default { elements: [] };
78
- `);
79
- const result = runCli([formFile, "--name"]);
80
- expect(result.exitCode).not.toBe(0);
81
- expect(result.stdout).toContain("--name requires a value");
82
- });
83
- });
84
- describe("file handling", () => {
85
- it("should fail when input file doesn't exist", () => {
86
- const result = runCli(["nonexistent.js"]);
87
- expect(result.exitCode).not.toBe(0);
88
- expect(result.stdout).toContain("Error");
89
- });
90
- it("should fail when file has no form export", () => {
91
- const formFile = createFormFile("no-export.js", `
92
- const notExported = { foo: "bar" };
93
- `);
94
- const result = runCli([formFile]);
95
- expect(result.exitCode).not.toBe(0);
96
- expect(result.stdout).toContain("Error");
97
- });
98
- it("should fail when export is not a FormSpec", () => {
99
- const formFile = createFormFile("not-formspec.js", `
100
- export default { notAForm: true };
101
- `);
102
- const result = runCli([formFile]);
103
- expect(result.exitCode).not.toBe(0);
104
- expect(result.stdout).toContain("FormSpec");
105
- });
106
- });
107
- describe("successful generation", () => {
108
- it("should generate schemas from default export", () => {
109
- const formFile = createFormFile("form-default.js", `
110
- export default {
111
- elements: [
112
- { _type: "field", _field: "text", name: "name" }
113
- ]
114
- };
115
- `);
116
- const outDir = path.join(tempDir, "output");
117
- const result = runCli([formFile, "-o", outDir, "-n", "test"]);
118
- expect(result.exitCode).toBe(0);
119
- expect(result.stdout).toContain("Generated");
120
- expect(fs.existsSync(path.join(outDir, "test-schema.json"))).toBe(true);
121
- expect(fs.existsSync(path.join(outDir, "test-uischema.json"))).toBe(true);
122
- });
123
- it("should generate schemas from named 'form' export", () => {
124
- const formFile = createFormFile("form-named.js", `
125
- export const form = {
126
- elements: [
127
- { _type: "field", _field: "text", name: "title" }
128
- ]
129
- };
130
- `);
131
- const outDir = path.join(tempDir, "output");
132
- const result = runCli([formFile, "-o", outDir, "-n", "test"]);
133
- expect(result.exitCode).toBe(0);
134
- expect(fs.existsSync(path.join(outDir, "test-schema.json"))).toBe(true);
135
- });
136
- it("should derive name from input filename when not specified", () => {
137
- const formFile = createFormFile("my-form.js", `
138
- export default {
139
- elements: [
140
- { _type: "field", _field: "text", name: "name" }
141
- ]
142
- };
143
- `);
144
- const outDir = path.join(tempDir, "output");
145
- const result = runCli([formFile, "-o", outDir]);
146
- expect(result.exitCode).toBe(0);
147
- expect(fs.existsSync(path.join(outDir, "my-form-schema.json"))).toBe(true);
148
- expect(fs.existsSync(path.join(outDir, "my-form-uischema.json"))).toBe(true);
149
- });
150
- it("should use default output directory when not specified", () => {
151
- const formFile = createFormFile("form.js", `
152
- export default {
153
- elements: [
154
- { _type: "field", _field: "text", name: "name" }
155
- ]
156
- };
157
- `);
158
- const result = runCli([formFile, "-n", "test"]);
159
- expect(result.exitCode).toBe(0);
160
- // Default output is ./generated relative to cwd
161
- expect(fs.existsSync(path.join(tempDir, "generated", "test-schema.json"))).toBe(true);
162
- });
163
- it("should accept short flags -o and -n", () => {
164
- const formFile = createFormFile("form.js", `
165
- export default {
166
- elements: [
167
- { _type: "field", _field: "text", name: "name" }
168
- ]
169
- };
170
- `);
171
- const outDir = path.join(tempDir, "out");
172
- const result = runCli([formFile, "-o", outDir, "-n", "short"]);
173
- expect(result.exitCode).toBe(0);
174
- expect(fs.existsSync(path.join(outDir, "short-schema.json"))).toBe(true);
175
- });
176
- });
177
- });
178
- //# sourceMappingURL=cli.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.test.js","sourceRoot":"","sources":["../../src/__tests__/cli.test.ts"],"names":[],"mappings":"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"}
@@ -1,217 +0,0 @@
1
- /**
2
- * Edge case and error handling tests.
3
- *
4
- * These tests verify correct behavior in unusual or boundary situations.
5
- */
6
- import { describe, it, expect } from "vitest";
7
- import { buildFormSchemas, generateJsonSchema, generateUiSchema } from "../index.js";
8
- import { formspec, field, group, when, is } from "@formspec/dsl";
9
- describe("Edge cases: Empty and minimal forms", () => {
10
- it("should handle form with no fields", () => {
11
- const emptyForm = formspec();
12
- const { jsonSchema, uiSchema } = buildFormSchemas(emptyForm);
13
- expect(jsonSchema.type).toBe("object");
14
- expect(jsonSchema.properties).toEqual({});
15
- expect(jsonSchema.required).toBeUndefined();
16
- expect(uiSchema.type).toBe("VerticalLayout");
17
- expect(uiSchema.elements).toEqual([]);
18
- });
19
- it("should handle empty group", () => {
20
- const form = formspec(group("Empty Group"));
21
- const { jsonSchema, uiSchema } = buildFormSchemas(form);
22
- expect(jsonSchema.properties).toEqual({});
23
- expect(uiSchema.elements).toHaveLength(1);
24
- expect(uiSchema.elements[0]).toMatchObject({
25
- type: "Group",
26
- label: "Empty Group",
27
- elements: [],
28
- });
29
- });
30
- it("should handle empty conditional", () => {
31
- const form = formspec(field.enum("type", ["a", "b"]), when(is("type", "a")));
32
- const { jsonSchema, uiSchema } = buildFormSchemas(form);
33
- // Only the enum field should exist
34
- expect(Object.keys(jsonSchema.properties ?? {})).toEqual(["type"]);
35
- expect(uiSchema.elements).toHaveLength(1);
36
- });
37
- it("should handle empty array field", () => {
38
- const form = formspec(field.array("items"));
39
- const { jsonSchema } = buildFormSchemas(form);
40
- expect(jsonSchema.properties?.["items"]).toMatchObject({
41
- type: "array",
42
- items: {
43
- type: "object",
44
- properties: {},
45
- },
46
- });
47
- });
48
- it("should handle empty object field", () => {
49
- const form = formspec(field.object("data"));
50
- const { jsonSchema } = buildFormSchemas(form);
51
- expect(jsonSchema.properties?.["data"]).toMatchObject({
52
- type: "object",
53
- properties: {},
54
- });
55
- });
56
- });
57
- describe("Edge cases: Field names", () => {
58
- it("should handle field names with special characters", () => {
59
- const form = formspec(field.text("field_with_underscore"), field.text("field-with-dash"), field.text("field123"));
60
- const { jsonSchema, uiSchema } = buildFormSchemas(form);
61
- expect(jsonSchema.properties?.["field_with_underscore"]).toBeDefined();
62
- expect(jsonSchema.properties?.["field-with-dash"]).toBeDefined();
63
- expect(jsonSchema.properties?.["field123"]).toBeDefined();
64
- // All scopes should be properly formed
65
- expect(uiSchema.elements[0]).toMatchObject({
66
- scope: "#/properties/field_with_underscore",
67
- });
68
- expect(uiSchema.elements[1]).toMatchObject({
69
- scope: "#/properties/field-with-dash",
70
- });
71
- });
72
- it("should handle single character field names", () => {
73
- const form = formspec(field.text("a"), field.number("b"), field.boolean("c"));
74
- const { jsonSchema } = buildFormSchemas(form);
75
- expect(Object.keys(jsonSchema.properties ?? {})).toEqual(["a", "b", "c"]);
76
- });
77
- });
78
- describe("Edge cases: Number constraints", () => {
79
- it("should handle zero as min/max", () => {
80
- const form = formspec(field.number("zeroMin", { min: 0 }), field.number("zeroMax", { max: 0 }), field.number("zeroRange", { min: 0, max: 0 }));
81
- const { jsonSchema } = buildFormSchemas(form);
82
- expect(jsonSchema.properties?.["zeroMin"]).toMatchObject({
83
- type: "number",
84
- minimum: 0,
85
- });
86
- expect(jsonSchema.properties?.["zeroMax"]).toMatchObject({
87
- type: "number",
88
- maximum: 0,
89
- });
90
- expect(jsonSchema.properties?.["zeroRange"]).toMatchObject({
91
- type: "number",
92
- minimum: 0,
93
- maximum: 0,
94
- });
95
- });
96
- it("should handle negative min/max", () => {
97
- const form = formspec(field.number("temperature", { min: -273, max: 1000000 }));
98
- const { jsonSchema } = buildFormSchemas(form);
99
- expect(jsonSchema.properties?.["temperature"]).toMatchObject({
100
- type: "number",
101
- minimum: -273,
102
- maximum: 1000000,
103
- });
104
- });
105
- });
106
- describe("Edge cases: Enum options", () => {
107
- it("should handle single option enum", () => {
108
- const form = formspec(field.enum("singleOption", ["only"]));
109
- const { jsonSchema } = buildFormSchemas(form);
110
- expect(jsonSchema.properties?.["singleOption"]).toMatchObject({
111
- type: "string",
112
- enum: ["only"],
113
- });
114
- });
115
- it("should handle single object option enum", () => {
116
- const form = formspec(field.enum("singleObj", [{ id: "only", label: "Only Option" }]));
117
- const { jsonSchema } = buildFormSchemas(form);
118
- expect(jsonSchema.properties?.["singleObj"]).toMatchObject({
119
- type: "string",
120
- oneOf: [{ const: "only", title: "Only Option" }],
121
- });
122
- });
123
- it("should handle enum with empty string option", () => {
124
- const form = formspec(field.enum("withEmpty", ["", "value"]));
125
- const { jsonSchema } = buildFormSchemas(form);
126
- expect(jsonSchema.properties?.["withEmpty"]).toMatchObject({
127
- type: "string",
128
- enum: ["", "value"],
129
- });
130
- });
131
- });
132
- describe("Edge cases: Conditional values", () => {
133
- it("should handle boolean conditional value", () => {
134
- const form = formspec(field.boolean("enabled"), when(is("enabled", true), field.text("config")));
135
- const { uiSchema } = buildFormSchemas(form);
136
- const conditionalField = uiSchema.elements.find((el) => el.type === "Control" && "scope" in el && el.scope === "#/properties/config");
137
- expect(conditionalField?.rule?.condition.schema).toMatchObject({
138
- const: true,
139
- });
140
- });
141
- it("should handle null conditional value", () => {
142
- const form = formspec(field.text("optional"), when(is("optional", null), field.text("fallback")));
143
- const { uiSchema } = buildFormSchemas(form);
144
- const conditionalField = uiSchema.elements.find((el) => el.type === "Control" && "scope" in el && el.scope === "#/properties/fallback");
145
- expect(conditionalField?.rule?.condition.schema).toMatchObject({
146
- const: null,
147
- });
148
- });
149
- it("should handle number conditional value", () => {
150
- const form = formspec(field.number("quantity"), when(is("quantity", 0), field.text("zeroReason", { label: "Why zero?" })));
151
- const { uiSchema } = buildFormSchemas(form);
152
- const conditionalField = uiSchema.elements.find((el) => el.type === "Control" && "scope" in el && el.scope === "#/properties/zeroReason");
153
- expect(conditionalField?.rule?.condition.schema).toMatchObject({
154
- const: 0,
155
- });
156
- });
157
- });
158
- describe("Edge cases: Array min/max items", () => {
159
- it("should handle minItems of 0", () => {
160
- const form = formspec(field.arrayWithConfig("items", { minItems: 0 }, field.text("name")));
161
- const { jsonSchema } = buildFormSchemas(form);
162
- expect(jsonSchema.properties?.["items"]).toMatchObject({
163
- type: "array",
164
- minItems: 0,
165
- });
166
- });
167
- it("should handle minItems equal to maxItems", () => {
168
- const form = formspec(field.arrayWithConfig("exactFive", { minItems: 5, maxItems: 5 }, field.text("item")));
169
- const { jsonSchema } = buildFormSchemas(form);
170
- expect(jsonSchema.properties?.["exactFive"]).toMatchObject({
171
- type: "array",
172
- minItems: 5,
173
- maxItems: 5,
174
- });
175
- });
176
- });
177
- describe("Edge cases: Deeply nested structures", () => {
178
- it("should handle 3+ levels of nesting", () => {
179
- const form = formspec(field.object("level1", field.object("level2", field.object("level3", field.text("deepValue")))));
180
- const { jsonSchema } = buildFormSchemas(form);
181
- expect(jsonSchema.properties?.["level1"]).toMatchObject({
182
- type: "object",
183
- properties: {
184
- level2: {
185
- type: "object",
186
- properties: {
187
- level3: {
188
- type: "object",
189
- properties: {
190
- deepValue: { type: "string" },
191
- },
192
- },
193
- },
194
- },
195
- },
196
- });
197
- });
198
- it("should handle conditionals inside groups inside conditionals", () => {
199
- const form = formspec(field.enum("outer", ["a", "b"]), when(is("outer", "a"), group("Inner Group", field.enum("inner", ["x", "y"]), when(is("inner", "x"), field.text("deepest")))));
200
- const { jsonSchema, uiSchema } = buildFormSchemas(form);
201
- // All fields should be in schema
202
- expect(Object.keys(jsonSchema.properties ?? {})).toContain("outer");
203
- expect(Object.keys(jsonSchema.properties ?? {})).toContain("inner");
204
- expect(Object.keys(jsonSchema.properties ?? {})).toContain("deepest");
205
- // Find the deepest field and verify it has combined rules
206
- const deepestControl = uiSchema.elements.find((el) => {
207
- if (el.type === "Group") {
208
- return el.elements.some((inner) => inner.type === "Control" &&
209
- "scope" in inner &&
210
- inner.scope === "#/properties/deepest");
211
- }
212
- return false;
213
- });
214
- expect(deepestControl).toBeDefined();
215
- });
216
- });
217
- //# sourceMappingURL=edge-cases.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"edge-cases.test.js","sourceRoot":"","sources":["../../src/__tests__/edge-cases.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AAEjE,QAAQ,CAAC,qCAAqC,EAAE,GAAG,EAAE;IACnD,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,SAAS,GAAG,QAAQ,EAAE,CAAC;QAE7B,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAE7D,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC1C,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,aAAa,EAAE,CAAC;QAE5C,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC7C,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,IAAI,GAAG,QAAQ,CACnB,KAAK,CAAC,aAAa,CAAC,CACrB,CAAC;QAEF,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAExD,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC1C,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;YACzC,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,aAAa;YACpB,QAAQ,EAAE,EAAE;SACb,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,IAAI,GAAG,QAAQ,CACnB,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,CAAU,CAAC,EACvC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CACtB,CAAC;QAEF,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAExD,mCAAmC;QACnC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QACnE,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,IAAI,GAAG,QAAQ,CACnB,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CACrB,CAAC;QAEF,MAAM,EAAE,UAAU,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAE9C,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC;YACrD,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE,EAAE;aACf;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,IAAI,GAAG,QAAQ,CACnB,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CACrB,CAAC;QAEF,MAAM,EAAE,UAAU,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAE9C,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC;YACpD,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,EAAE;SACf,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,IAAI,GAAG,QAAQ,CACnB,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,EACnC,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAC7B,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CACvB,CAAC;QAEF,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAExD,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,uBAAuB,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QACvE,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QACjE,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAE1D,uCAAuC;QACvC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;YACzC,KAAK,EAAE,oCAAoC;SAC5C,CAAC,CAAC;QACH,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;YACzC,KAAK,EAAE,8BAA8B;SACtC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,IAAI,GAAG,QAAQ,CACnB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EACf,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EACjB,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CACnB,CAAC;QAEF,MAAM,EAAE,UAAU,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAE9C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,IAAI,GAAG,QAAQ,CACnB,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EACnC,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EACnC,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAC9C,CAAC;QAEF,MAAM,EAAE,UAAU,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAE9C,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC;YACvD,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,CAAC;SACX,CAAC,CAAC;QACH,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC;YACvD,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,CAAC;SACX,CAAC,CAAC;QACH,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC;YACzD,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,CAAC;SACX,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,IAAI,GAAG,QAAQ,CACnB,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CACzD,CAAC;QAEF,MAAM,EAAE,UAAU,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAE9C,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC;YAC3D,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,CAAC,GAAG;YACb,OAAO,EAAE,OAAO;SACjB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,IAAI,GAAG,QAAQ,CACnB,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,MAAM,CAAU,CAAC,CAC9C,CAAC;QAEF,MAAM,EAAE,UAAU,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAE9C,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,aAAa,CAAC;YAC5D,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,MAAM,CAAC;SACf,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,IAAI,GAAG,QAAQ,CACnB,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,CAAU,CAAC,CACzE,CAAC;QAEF,MAAM,EAAE,UAAU,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAE9C,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC;YACzD,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;SACjD,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,IAAI,GAAG,QAAQ,CACnB,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,EAAE,OAAO,CAAU,CAAC,CAChD,CAAC;QAEF,MAAM,EAAE,UAAU,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAE9C,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC;YACzD,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,EAAE,EAAE,OAAO,CAAC;SACpB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,IAAI,GAAG,QAAQ,CACnB,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EACxB,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,EACtB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CACrB,CACF,CAAC;QAEF,MAAM,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAE5C,MAAM,gBAAgB,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAC7C,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,EAAE,IAAI,EAAE,CAAC,KAAK,KAAK,qBAAqB,CACrF,CAAC;QACF,MAAM,CAAC,gBAAgB,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC;YAC7D,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,IAAI,GAAG,QAAQ,CACnB,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EACtB,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,EACvB,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CACvB,CACF,CAAC;QAEF,MAAM,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAE5C,MAAM,gBAAgB,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAC7C,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,EAAE,IAAI,EAAE,CAAC,KAAK,KAAK,uBAAuB,CACvF,CAAC;QACF,MAAM,CAAC,gBAAgB,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC;YAC7D,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,IAAI,GAAG,QAAQ,CACnB,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,EACxB,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC,EACpB,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CACjD,CACF,CAAC;QAEF,MAAM,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAE5C,MAAM,gBAAgB,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAC7C,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,EAAE,IAAI,EAAE,CAAC,KAAK,KAAK,yBAAyB,CACzF,CAAC;QACF,MAAM,CAAC,gBAAgB,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC;YAC7D,KAAK,EAAE,CAAC;SACT,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAC/C,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,IAAI,GAAG,QAAQ,CACnB,KAAK,CAAC,eAAe,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,EAC5C,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CACnB,CACF,CAAC;QAEF,MAAM,EAAE,UAAU,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAE9C,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC;YACrD,IAAI,EAAE,OAAO;YACb,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,IAAI,GAAG,QAAQ,CACnB,KAAK,CAAC,eAAe,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,EAC7D,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CACnB,CACF,CAAC;QAEF,MAAM,EAAE,UAAU,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAE9C,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC;YACzD,IAAI,EAAE,OAAO;YACb,QAAQ,EAAE,CAAC;YACX,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;IACpD,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,IAAI,GAAG,QAAQ,CACnB,KAAK,CAAC,MAAM,CAAC,QAAQ,EACnB,KAAK,CAAC,MAAM,CAAC,QAAQ,EACnB,KAAK,CAAC,MAAM,CAAC,QAAQ,EACnB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CACxB,CACF,CACF,CACF,CAAC;QAEF,MAAM,EAAE,UAAU,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAE9C,MAAM,CACJ,UAAU,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,CAClC,CAAC,aAAa,CAAC;YACd,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,MAAM,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,MAAM,EAAE;4BACN,IAAI,EAAE,QAAQ;4BACd,UAAU,EAAE;gCACV,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;6BAC9B;yBACF;qBACF;iBACF;aACF;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,MAAM,IAAI,GAAG,QAAQ,CACnB,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,CAAU,CAAC,EACxC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,EACnB,KAAK,CAAC,aAAa,EACjB,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,CAAU,CAAC,EACxC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,EACnB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CACtB,CACF,CACF,CACF,CAAC;QAEF,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAExD,iCAAiC;QACjC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACpE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACpE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAEtE,0DAA0D;QAC1D,MAAM,cAAc,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE;YACnD,IAAI,EAAE,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBACxB,OAAO,EAAE,CAAC,QAAQ,CAAC,IAAI,CACrB,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,IAAI,KAAK,SAAS;oBACxB,OAAO,IAAI,KAAK;oBAChB,KAAK,CAAC,KAAK,KAAK,sBAAsB,CACzC,CAAC;YACJ,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,cAAc,CAAC,CAAC,WAAW,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,225 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { buildFormSchemas, generateJsonSchema, generateUiSchema } from "../index.js";
3
- import { formspec, field, group, when, is } from "@formspec/dsl";
4
- describe("generateJsonSchema", () => {
5
- it("should generate schema for basic fields", () => {
6
- const form = formspec(field.text("name", { label: "Name" }), field.number("age", { min: 0, max: 150 }), field.boolean("active"));
7
- const schema = generateJsonSchema(form);
8
- expect(schema.$schema).toBe("https://json-schema.org/draft-07/schema#");
9
- expect(schema.type).toBe("object");
10
- expect(schema.properties).toEqual({
11
- name: { type: "string", title: "Name" },
12
- age: { type: "number", minimum: 0, maximum: 150 },
13
- active: { type: "boolean" },
14
- });
15
- });
16
- it("should generate schema for enum fields", () => {
17
- const form = formspec(field.enum("status", ["draft", "sent", "paid"], { label: "Status" }));
18
- const schema = generateJsonSchema(form);
19
- expect(schema.properties?.["status"]).toEqual({
20
- type: "string",
21
- title: "Status",
22
- enum: ["draft", "sent", "paid"],
23
- });
24
- });
25
- it("should generate schema for enum fields with object options", () => {
26
- const form = formspec(field.enum("priority", [
27
- { id: "low", label: "Low Priority" },
28
- { id: "medium", label: "Medium Priority" },
29
- { id: "high", label: "High Priority" },
30
- ], { label: "Priority" }));
31
- const schema = generateJsonSchema(form);
32
- expect(schema.properties?.["priority"]).toEqual({
33
- type: "string",
34
- title: "Priority",
35
- oneOf: [
36
- { const: "low", title: "Low Priority" },
37
- { const: "medium", title: "Medium Priority" },
38
- { const: "high", title: "High Priority" },
39
- ],
40
- });
41
- });
42
- it("should handle required fields", () => {
43
- const form = formspec(field.text("name", { required: true }), field.text("optional"));
44
- const schema = generateJsonSchema(form);
45
- expect(schema.required).toEqual(["name"]);
46
- });
47
- it("should extract fields from groups", () => {
48
- const form = formspec(group("Customer", field.text("name"), field.text("email")));
49
- const schema = generateJsonSchema(form);
50
- expect(Object.keys(schema.properties ?? {})).toEqual(["name", "email"]);
51
- });
52
- it("should extract fields from conditionals", () => {
53
- const form = formspec(field.enum("type", ["a", "b"]), when(is("type", "a"), field.text("extra")));
54
- const schema = generateJsonSchema(form);
55
- expect(Object.keys(schema.properties ?? {})).toEqual(["type", "extra"]);
56
- });
57
- it("should include x-formspec-source for dynamic enum fields", () => {
58
- const form = formspec(field.dynamicEnum("country", "countries", { label: "Country" }));
59
- const schema = generateJsonSchema(form);
60
- expect(schema.properties?.["country"]).toMatchObject({
61
- type: "string",
62
- title: "Country",
63
- "x-formspec-source": "countries",
64
- });
65
- });
66
- it("should include x-formspec-params for dynamic enum with dependencies", () => {
67
- const form = formspec(field.dynamicEnum("city", "cities", {
68
- label: "City",
69
- params: ["country", "state"],
70
- }));
71
- const schema = generateJsonSchema(form);
72
- expect(schema.properties?.["city"]).toMatchObject({
73
- type: "string",
74
- "x-formspec-source": "cities",
75
- "x-formspec-params": ["country", "state"],
76
- });
77
- });
78
- it("should include x-formspec-schemaSource for dynamic schema fields", () => {
79
- const form = formspec(field.dynamicSchema("paymentDetails", "stripe-payment-form", {
80
- label: "Payment Details",
81
- }));
82
- const schema = generateJsonSchema(form);
83
- expect(schema.properties?.["paymentDetails"]).toMatchObject({
84
- type: "object",
85
- title: "Payment Details",
86
- additionalProperties: true,
87
- "x-formspec-schemaSource": "stripe-payment-form",
88
- });
89
- });
90
- });
91
- describe("generateUiSchema", () => {
92
- it("should generate vertical layout for basic fields", () => {
93
- const form = formspec(field.text("name", { label: "Name" }));
94
- const uiSchema = generateUiSchema(form);
95
- expect(uiSchema.type).toBe("VerticalLayout");
96
- expect(uiSchema.elements).toHaveLength(1);
97
- expect(uiSchema.elements[0]).toEqual({
98
- type: "Control",
99
- scope: "#/properties/name",
100
- label: "Name",
101
- });
102
- });
103
- it("should generate groups", () => {
104
- const form = formspec(group("Customer Info", field.text("name")));
105
- const uiSchema = generateUiSchema(form);
106
- expect(uiSchema.elements[0]).toMatchObject({
107
- type: "Group",
108
- label: "Customer Info",
109
- elements: [
110
- { type: "Control", scope: "#/properties/name" },
111
- ],
112
- });
113
- });
114
- it("should generate rules for conditionals", () => {
115
- const form = formspec(field.enum("status", ["draft", "sent"]), when(is("status", "draft"), field.text("notes", { label: "Notes" })));
116
- const uiSchema = generateUiSchema(form);
117
- // First element is the status control
118
- expect(uiSchema.elements[0]).toMatchObject({
119
- type: "Control",
120
- scope: "#/properties/status",
121
- });
122
- // Second element is the notes control with a rule
123
- expect(uiSchema.elements[1]).toMatchObject({
124
- type: "Control",
125
- scope: "#/properties/notes",
126
- label: "Notes",
127
- rule: {
128
- effect: "SHOW",
129
- condition: {
130
- scope: "#/properties/status",
131
- schema: { const: "draft" },
132
- },
133
- },
134
- });
135
- });
136
- });
137
- describe("generateJsonSchema - array fields", () => {
138
- it("should generate schema for array fields", () => {
139
- const form = formspec(field.array("addresses", field.text("street"), field.text("city")));
140
- const schema = generateJsonSchema(form);
141
- expect(schema.properties?.["addresses"]).toEqual({
142
- type: "array",
143
- items: {
144
- type: "object",
145
- properties: {
146
- street: { type: "string" },
147
- city: { type: "string" },
148
- },
149
- },
150
- });
151
- });
152
- it("should handle array fields with min/max items", () => {
153
- const form = formspec(field.arrayWithConfig("items", { label: "Line Items", minItems: 1, maxItems: 10 }, field.text("description"), field.number("quantity")));
154
- const schema = generateJsonSchema(form);
155
- expect(schema.properties?.["items"]).toMatchObject({
156
- type: "array",
157
- title: "Line Items",
158
- minItems: 1,
159
- maxItems: 10,
160
- items: {
161
- type: "object",
162
- properties: {
163
- description: { type: "string" },
164
- quantity: { type: "number" },
165
- },
166
- },
167
- });
168
- });
169
- });
170
- describe("generateJsonSchema - object fields", () => {
171
- it("should generate schema for object fields", () => {
172
- const form = formspec(field.object("address", field.text("street"), field.text("city"), field.text("zip")));
173
- const schema = generateJsonSchema(form);
174
- expect(schema.properties?.["address"]).toEqual({
175
- type: "object",
176
- properties: {
177
- street: { type: "string" },
178
- city: { type: "string" },
179
- zip: { type: "string" },
180
- },
181
- });
182
- });
183
- it("should handle required fields within object fields", () => {
184
- const form = formspec(field.object("address", field.text("street", { required: true }), field.text("city", { required: true }), field.text("zip")));
185
- const schema = generateJsonSchema(form);
186
- expect(schema.properties?.["address"]).toMatchObject({
187
- type: "object",
188
- properties: {
189
- street: { type: "string" },
190
- city: { type: "string" },
191
- zip: { type: "string" },
192
- },
193
- required: ["street", "city"],
194
- });
195
- });
196
- });
197
- describe("generateUiSchema - nested conditionals", () => {
198
- it("should combine rules for nested conditionals", () => {
199
- const form = formspec(field.enum("country", ["US", "CA"]), field.enum("paymentMethod", ["card", "bank"]), when(is("country", "US"), when(is("paymentMethod", "bank"), field.text("routingNumber", { label: "Routing Number" }))));
200
- const uiSchema = generateUiSchema(form);
201
- // Find the routingNumber control
202
- const routingControl = uiSchema.elements.find((el) => el.type === "Control" && "scope" in el && el.scope === "#/properties/routingNumber");
203
- expect(routingControl).toBeDefined();
204
- expect(routingControl?.rule).toBeDefined();
205
- // The combined rule should use allOf to require both conditions
206
- expect(routingControl?.rule?.condition.schema.allOf).toHaveLength(2);
207
- expect(routingControl?.rule?.condition.schema.allOf?.[0]).toMatchObject({
208
- properties: { country: { const: "US" } },
209
- });
210
- expect(routingControl?.rule?.condition.schema.allOf?.[1]).toMatchObject({
211
- properties: { paymentMethod: { const: "bank" } },
212
- });
213
- });
214
- });
215
- describe("buildFormSchemas", () => {
216
- it("should return both schemas", () => {
217
- const form = formspec(field.text("name"));
218
- const result = buildFormSchemas(form);
219
- expect(result.jsonSchema).toBeDefined();
220
- expect(result.jsonSchema.$schema).toBe("https://json-schema.org/draft-07/schema#");
221
- expect(result.uiSchema).toBeDefined();
222
- expect(result.uiSchema.type).toBe("VerticalLayout");
223
- });
224
- });
225
- //# sourceMappingURL=generator.test.js.map