@formspec/build 0.1.0-alpha.1

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 (45) hide show
  1. package/dist/__tests__/cli.test.d.ts +2 -0
  2. package/dist/__tests__/cli.test.d.ts.map +1 -0
  3. package/dist/__tests__/cli.test.js +178 -0
  4. package/dist/__tests__/cli.test.js.map +1 -0
  5. package/dist/__tests__/edge-cases.test.d.ts +7 -0
  6. package/dist/__tests__/edge-cases.test.d.ts.map +1 -0
  7. package/dist/__tests__/edge-cases.test.js +209 -0
  8. package/dist/__tests__/edge-cases.test.js.map +1 -0
  9. package/dist/__tests__/generator.test.d.ts +2 -0
  10. package/dist/__tests__/generator.test.d.ts.map +1 -0
  11. package/dist/__tests__/generator.test.js +208 -0
  12. package/dist/__tests__/generator.test.js.map +1 -0
  13. package/dist/__tests__/integration.test.d.ts +8 -0
  14. package/dist/__tests__/integration.test.d.ts.map +1 -0
  15. package/dist/__tests__/integration.test.js +163 -0
  16. package/dist/__tests__/integration.test.js.map +1 -0
  17. package/dist/__tests__/write-schemas.test.d.ts +2 -0
  18. package/dist/__tests__/write-schemas.test.d.ts.map +1 -0
  19. package/dist/__tests__/write-schemas.test.js +196 -0
  20. package/dist/__tests__/write-schemas.test.js.map +1 -0
  21. package/dist/cli.d.ts +17 -0
  22. package/dist/cli.d.ts.map +1 -0
  23. package/dist/cli.js +138 -0
  24. package/dist/cli.js.map +1 -0
  25. package/dist/index.d.ts +119 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +109 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/json-schema/generator.d.ts +32 -0
  30. package/dist/json-schema/generator.d.ts.map +1 -0
  31. package/dist/json-schema/generator.js +146 -0
  32. package/dist/json-schema/generator.js.map +1 -0
  33. package/dist/json-schema/types.d.ts +60 -0
  34. package/dist/json-schema/types.d.ts.map +1 -0
  35. package/dist/json-schema/types.js +7 -0
  36. package/dist/json-schema/types.js.map +1 -0
  37. package/dist/ui-schema/generator.d.ts +48 -0
  38. package/dist/ui-schema/generator.d.ts.map +1 -0
  39. package/dist/ui-schema/generator.js +150 -0
  40. package/dist/ui-schema/generator.js.map +1 -0
  41. package/dist/ui-schema/types.d.ts +87 -0
  42. package/dist/ui-schema/types.d.ts.map +1 -0
  43. package/dist/ui-schema/types.js +8 -0
  44. package/dist/ui-schema/types.js.map +1 -0
  45. package/package.json +41 -0
@@ -0,0 +1,119 @@
1
+ /**
2
+ * `@formspec/build` - Build tools for FormSpec
3
+ *
4
+ * This package provides generators to compile FormSpec forms into:
5
+ * - JSON Schema (for validation)
6
+ * - JSON Forms UI Schema (for rendering)
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { buildFormSchemas } from "@formspec/build";
11
+ * import { formspec, field, group } from "@formspec/dsl";
12
+ *
13
+ * const form = formspec(
14
+ * group("Customer",
15
+ * field.text("name", { label: "Name", required: true }),
16
+ * field.text("email", { label: "Email" }),
17
+ * ),
18
+ * );
19
+ *
20
+ * const { jsonSchema, uiSchema } = buildFormSchemas(form);
21
+ * ```
22
+ *
23
+ * @packageDocumentation
24
+ */
25
+ import type { FormElement, FormSpec } from "@formspec/core";
26
+ import type { JSONSchema7 } from "./json-schema/types.js";
27
+ import type { UISchema } from "./ui-schema/types.js";
28
+ export type { JSONSchema7, JSONSchemaType, } from "./json-schema/types.js";
29
+ export type { UISchema, UISchemaElement, UISchemaElementType, ControlElement, VerticalLayout, HorizontalLayout, GroupLayout, Rule, RuleEffect, SchemaBasedCondition, } from "./ui-schema/types.js";
30
+ export { generateJsonSchema } from "./json-schema/generator.js";
31
+ export { generateUiSchema } from "./ui-schema/generator.js";
32
+ /**
33
+ * Result of building form schemas.
34
+ */
35
+ export interface BuildResult {
36
+ /** JSON Schema for validation */
37
+ readonly jsonSchema: JSONSchema7;
38
+ /** JSON Forms UI Schema for rendering */
39
+ readonly uiSchema: UISchema;
40
+ }
41
+ /**
42
+ * Builds both JSON Schema and UI Schema from a FormSpec.
43
+ *
44
+ * This is a convenience function that combines `generateJsonSchema`
45
+ * and `generateUiSchema`.
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * const form = formspec(
50
+ * field.text("name", { required: true }),
51
+ * field.number("age", { min: 0 }),
52
+ * );
53
+ *
54
+ * const { jsonSchema, uiSchema } = buildFormSchemas(form);
55
+ *
56
+ * // Use with JSON Forms renderer
57
+ * <JsonForms
58
+ * schema={jsonSchema}
59
+ * uischema={uiSchema}
60
+ * data={formData}
61
+ * renderers={materialRenderers}
62
+ * />
63
+ * ```
64
+ *
65
+ * @param form - The FormSpec to build schemas from
66
+ * @returns Object containing both jsonSchema and uiSchema
67
+ */
68
+ export declare function buildFormSchemas<E extends readonly FormElement[]>(form: FormSpec<E>): BuildResult;
69
+ /**
70
+ * Options for writing schemas to disk.
71
+ */
72
+ export interface WriteSchemasOptions {
73
+ /** Output directory for the schema files */
74
+ readonly outDir: string;
75
+ /** Base name for the output files (without extension). Defaults to "schema" */
76
+ readonly name?: string;
77
+ /** Number of spaces for JSON indentation. Defaults to 2 */
78
+ readonly indent?: number;
79
+ }
80
+ /**
81
+ * Result of writing schemas to disk.
82
+ */
83
+ export interface WriteSchemasResult {
84
+ /** Path to the generated JSON Schema file */
85
+ readonly jsonSchemaPath: string;
86
+ /** Path to the generated UI Schema file */
87
+ readonly uiSchemaPath: string;
88
+ }
89
+ /**
90
+ * Builds and writes both JSON Schema and UI Schema files to disk.
91
+ *
92
+ * This is a convenience function for build-time schema generation.
93
+ * It creates the output directory if it doesn't exist.
94
+ *
95
+ * @example
96
+ * ```typescript
97
+ * import { formspec, field } from "formspec";
98
+ * import { writeSchemas } from "@formspec/build";
99
+ *
100
+ * const ProductForm = formspec(
101
+ * field.text("name", { required: true }),
102
+ * field.enum("status", ["draft", "active"]),
103
+ * );
104
+ *
105
+ * // Write schemas to ./generated/product-schema.json and ./generated/product-uischema.json
106
+ * const { jsonSchemaPath, uiSchemaPath } = writeSchemas(ProductForm, {
107
+ * outDir: "./generated",
108
+ * name: "product",
109
+ * });
110
+ *
111
+ * console.log(`Generated: ${jsonSchemaPath}, ${uiSchemaPath}`);
112
+ * ```
113
+ *
114
+ * @param form - The FormSpec to build schemas from
115
+ * @param options - Output options (directory, file name, indentation)
116
+ * @returns Object containing paths to the generated files
117
+ */
118
+ export declare function writeSchemas<E extends readonly FormElement[]>(form: FormSpec<E>, options: WriteSchemasOptions): WriteSchemasResult;
119
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAKrD,YAAY,EACV,WAAW,EACX,cAAc,GACf,MAAM,wBAAwB,CAAC;AAEhC,YAAY,EACV,QAAQ,EACR,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,IAAI,EACJ,UAAU,EACV,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,iCAAiC;IACjC,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC;IACjC,yCAAyC;IACzC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,SAAS,WAAW,EAAE,EAC/D,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,GAChB,WAAW,CAKb;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,6CAA6C;IAC7C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,2CAA2C;IAC3C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,SAAS,WAAW,EAAE,EAC3D,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,EACjB,OAAO,EAAE,mBAAmB,GAC3B,kBAAkB,CAmBpB"}
package/dist/index.js ADDED
@@ -0,0 +1,109 @@
1
+ /**
2
+ * `@formspec/build` - Build tools for FormSpec
3
+ *
4
+ * This package provides generators to compile FormSpec forms into:
5
+ * - JSON Schema (for validation)
6
+ * - JSON Forms UI Schema (for rendering)
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { buildFormSchemas } from "@formspec/build";
11
+ * import { formspec, field, group } from "@formspec/dsl";
12
+ *
13
+ * const form = formspec(
14
+ * group("Customer",
15
+ * field.text("name", { label: "Name", required: true }),
16
+ * field.text("email", { label: "Email" }),
17
+ * ),
18
+ * );
19
+ *
20
+ * const { jsonSchema, uiSchema } = buildFormSchemas(form);
21
+ * ```
22
+ *
23
+ * @packageDocumentation
24
+ */
25
+ import { generateJsonSchema } from "./json-schema/generator.js";
26
+ import { generateUiSchema } from "./ui-schema/generator.js";
27
+ import * as fs from "node:fs";
28
+ import * as path from "node:path";
29
+ // Re-export individual generators
30
+ export { generateJsonSchema } from "./json-schema/generator.js";
31
+ export { generateUiSchema } from "./ui-schema/generator.js";
32
+ /**
33
+ * Builds both JSON Schema and UI Schema from a FormSpec.
34
+ *
35
+ * This is a convenience function that combines `generateJsonSchema`
36
+ * and `generateUiSchema`.
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * const form = formspec(
41
+ * field.text("name", { required: true }),
42
+ * field.number("age", { min: 0 }),
43
+ * );
44
+ *
45
+ * const { jsonSchema, uiSchema } = buildFormSchemas(form);
46
+ *
47
+ * // Use with JSON Forms renderer
48
+ * <JsonForms
49
+ * schema={jsonSchema}
50
+ * uischema={uiSchema}
51
+ * data={formData}
52
+ * renderers={materialRenderers}
53
+ * />
54
+ * ```
55
+ *
56
+ * @param form - The FormSpec to build schemas from
57
+ * @returns Object containing both jsonSchema and uiSchema
58
+ */
59
+ export function buildFormSchemas(form) {
60
+ return {
61
+ jsonSchema: generateJsonSchema(form),
62
+ uiSchema: generateUiSchema(form),
63
+ };
64
+ }
65
+ /**
66
+ * Builds and writes both JSON Schema and UI Schema files to disk.
67
+ *
68
+ * This is a convenience function for build-time schema generation.
69
+ * It creates the output directory if it doesn't exist.
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * import { formspec, field } from "formspec";
74
+ * import { writeSchemas } from "@formspec/build";
75
+ *
76
+ * const ProductForm = formspec(
77
+ * field.text("name", { required: true }),
78
+ * field.enum("status", ["draft", "active"]),
79
+ * );
80
+ *
81
+ * // Write schemas to ./generated/product-schema.json and ./generated/product-uischema.json
82
+ * const { jsonSchemaPath, uiSchemaPath } = writeSchemas(ProductForm, {
83
+ * outDir: "./generated",
84
+ * name: "product",
85
+ * });
86
+ *
87
+ * console.log(`Generated: ${jsonSchemaPath}, ${uiSchemaPath}`);
88
+ * ```
89
+ *
90
+ * @param form - The FormSpec to build schemas from
91
+ * @param options - Output options (directory, file name, indentation)
92
+ * @returns Object containing paths to the generated files
93
+ */
94
+ export function writeSchemas(form, options) {
95
+ const { outDir, name = "schema", indent = 2 } = options;
96
+ // Build schemas
97
+ const { jsonSchema, uiSchema } = buildFormSchemas(form);
98
+ // Ensure output directory exists
99
+ if (!fs.existsSync(outDir)) {
100
+ fs.mkdirSync(outDir, { recursive: true });
101
+ }
102
+ // Write files
103
+ const jsonSchemaPath = path.join(outDir, `${name}-schema.json`);
104
+ const uiSchemaPath = path.join(outDir, `${name}-uischema.json`);
105
+ fs.writeFileSync(jsonSchemaPath, JSON.stringify(jsonSchema, null, indent));
106
+ fs.writeFileSync(uiSchemaPath, JSON.stringify(uiSchema, null, indent));
107
+ return { jsonSchemaPath, uiSchemaPath };
108
+ }
109
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAG5D,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAqBlC,kCAAkC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAY5D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAiB;IAEjB,OAAO;QACL,UAAU,EAAE,kBAAkB,CAAC,IAAI,CAAC;QACpC,QAAQ,EAAE,gBAAgB,CAAC,IAAI,CAAC;KACjC,CAAC;AACJ,CAAC;AAwBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAiB,EACjB,OAA4B;IAE5B,MAAM,EAAE,MAAM,EAAE,IAAI,GAAG,QAAQ,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC;IAExD,gBAAgB;IAChB,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAExD,iCAAiC;IACjC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,cAAc;IACd,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,cAAc,CAAC,CAAC;IAChE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,gBAAgB,CAAC,CAAC;IAEhE,EAAE,CAAC,aAAa,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3E,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAEvE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * JSON Schema generator for FormSpec forms.
3
+ */
4
+ import type { FormElement, FormSpec } from "@formspec/core";
5
+ import type { JSONSchema7 } from "./types.js";
6
+ /**
7
+ * Generates a JSON Schema from a FormSpec.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const form = formspec(
12
+ * field.text("name", { label: "Name", required: true }),
13
+ * field.number("age", { min: 0 }),
14
+ * );
15
+ *
16
+ * const schema = generateJsonSchema(form);
17
+ * // {
18
+ * // $schema: "https://json-schema.org/draft-07/schema#",
19
+ * // type: "object",
20
+ * // properties: {
21
+ * // name: { type: "string", title: "Name" },
22
+ * // age: { type: "number", minimum: 0 }
23
+ * // },
24
+ * // required: ["name"]
25
+ * // }
26
+ * ```
27
+ *
28
+ * @param form - The FormSpec to convert
29
+ * @returns A JSON Schema object
30
+ */
31
+ export declare function generateJsonSchema<E extends readonly FormElement[]>(form: FormSpec<E>): JSONSchema7;
32
+ //# sourceMappingURL=generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/json-schema/generator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,QAAQ,EAMT,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAyI9C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,SAAS,WAAW,EAAE,EACjE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,GAChB,WAAW,CAYb"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * JSON Schema generator for FormSpec forms.
3
+ */
4
+ /**
5
+ * Generates JSON Schema for nested elements (used for array items and object properties).
6
+ */
7
+ function generateNestedSchema(elements) {
8
+ const properties = {};
9
+ const required = [];
10
+ collectFields(elements, properties, required);
11
+ return {
12
+ type: "object",
13
+ properties,
14
+ ...(required.length > 0 && { required }),
15
+ };
16
+ }
17
+ /**
18
+ * Converts a single field to its JSON Schema representation.
19
+ */
20
+ function fieldToJsonSchema(field) {
21
+ const base = {};
22
+ if (field.label !== undefined) {
23
+ base.title = field.label;
24
+ }
25
+ switch (field._field) {
26
+ case "text":
27
+ return { ...base, type: "string" };
28
+ case "number":
29
+ return {
30
+ ...base,
31
+ type: "number",
32
+ ...(field.min !== undefined && { minimum: field.min }),
33
+ ...(field.max !== undefined && { maximum: field.max }),
34
+ };
35
+ case "boolean":
36
+ return { ...base, type: "boolean" };
37
+ case "enum":
38
+ return { ...base, type: "string", enum: field.options };
39
+ case "dynamic_enum":
40
+ // Dynamic enums are strings at the schema level
41
+ // The actual options are resolved at runtime
42
+ // x-formspec-source indicates the data source key
43
+ // x-formspec-params indicates dependent field names for fetching options
44
+ return {
45
+ ...base,
46
+ type: "string",
47
+ "x-formspec-source": field.source,
48
+ ...(field.params !== undefined &&
49
+ field.params.length > 0 && { "x-formspec-params": field.params }),
50
+ };
51
+ case "dynamic_schema":
52
+ // Dynamic schemas are objects with unknown properties
53
+ // x-formspec-schemaSource indicates where to load the schema from
54
+ return {
55
+ ...base,
56
+ type: "object",
57
+ additionalProperties: true,
58
+ "x-formspec-schemaSource": field.schemaSource,
59
+ };
60
+ case "array": {
61
+ const arrayField = field;
62
+ return {
63
+ ...base,
64
+ type: "array",
65
+ items: generateNestedSchema(arrayField.items),
66
+ ...(arrayField.minItems !== undefined && { minItems: arrayField.minItems }),
67
+ ...(arrayField.maxItems !== undefined && { maxItems: arrayField.maxItems }),
68
+ };
69
+ }
70
+ case "object": {
71
+ const objectField = field;
72
+ const nestedSchema = generateNestedSchema(objectField.properties);
73
+ return {
74
+ ...base,
75
+ ...nestedSchema,
76
+ };
77
+ }
78
+ default: {
79
+ // Exhaustiveness check
80
+ const _exhaustive = field;
81
+ return _exhaustive;
82
+ }
83
+ }
84
+ }
85
+ /**
86
+ * Visits all elements in a form tree, collecting fields and required fields.
87
+ */
88
+ function collectFields(elements, properties, required) {
89
+ for (const element of elements) {
90
+ switch (element._type) {
91
+ case "field":
92
+ properties[element.name] = fieldToJsonSchema(element);
93
+ if (element.required === true) {
94
+ required.push(element.name);
95
+ }
96
+ break;
97
+ case "group":
98
+ // Groups don't affect schema structure, just collect their children
99
+ collectFields(element.elements, properties, required);
100
+ break;
101
+ case "conditional":
102
+ // Conditional fields are still part of the schema
103
+ // They're just hidden/shown in the UI
104
+ collectFields(element
105
+ .elements, properties, required);
106
+ break;
107
+ }
108
+ }
109
+ }
110
+ /**
111
+ * Generates a JSON Schema from a FormSpec.
112
+ *
113
+ * @example
114
+ * ```typescript
115
+ * const form = formspec(
116
+ * field.text("name", { label: "Name", required: true }),
117
+ * field.number("age", { min: 0 }),
118
+ * );
119
+ *
120
+ * const schema = generateJsonSchema(form);
121
+ * // {
122
+ * // $schema: "https://json-schema.org/draft-07/schema#",
123
+ * // type: "object",
124
+ * // properties: {
125
+ * // name: { type: "string", title: "Name" },
126
+ * // age: { type: "number", minimum: 0 }
127
+ * // },
128
+ * // required: ["name"]
129
+ * // }
130
+ * ```
131
+ *
132
+ * @param form - The FormSpec to convert
133
+ * @returns A JSON Schema object
134
+ */
135
+ export function generateJsonSchema(form) {
136
+ const properties = {};
137
+ const required = [];
138
+ collectFields(form.elements, properties, required);
139
+ return {
140
+ $schema: "https://json-schema.org/draft-07/schema#",
141
+ type: "object",
142
+ properties,
143
+ ...(required.length > 0 && { required }),
144
+ };
145
+ }
146
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/json-schema/generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * JSON Schema Draft-07 type definitions.
3
+ *
4
+ * These types are a subset of JSON Schema sufficient for form generation.
5
+ */
6
+ /**
7
+ * JSON Schema primitive types.
8
+ */
9
+ export type JSONSchemaType = "string" | "number" | "integer" | "boolean" | "object" | "array" | "null";
10
+ /**
11
+ * A JSON Schema definition (draft-07 subset).
12
+ */
13
+ export interface JSONSchema7 {
14
+ $schema?: string;
15
+ $id?: string;
16
+ $ref?: string;
17
+ title?: string;
18
+ description?: string;
19
+ type?: JSONSchemaType | JSONSchemaType[];
20
+ minLength?: number;
21
+ maxLength?: number;
22
+ pattern?: string;
23
+ minimum?: number;
24
+ maximum?: number;
25
+ exclusiveMinimum?: number;
26
+ exclusiveMaximum?: number;
27
+ enum?: readonly (string | number | boolean | null)[];
28
+ const?: string | number | boolean | null;
29
+ properties?: Record<string, JSONSchema7>;
30
+ required?: string[];
31
+ additionalProperties?: boolean | JSONSchema7;
32
+ items?: JSONSchema7 | JSONSchema7[];
33
+ minItems?: number;
34
+ maxItems?: number;
35
+ allOf?: JSONSchema7[];
36
+ anyOf?: JSONSchema7[];
37
+ oneOf?: JSONSchema7[];
38
+ not?: JSONSchema7;
39
+ if?: JSONSchema7;
40
+ then?: JSONSchema7;
41
+ else?: JSONSchema7;
42
+ format?: string;
43
+ default?: unknown;
44
+ /**
45
+ * Data source key for dynamic enum fields.
46
+ * Indicates that options should be fetched from a registered resolver.
47
+ */
48
+ "x-formspec-source"?: string;
49
+ /**
50
+ * Field names whose values are needed to fetch dynamic enum options.
51
+ * Used for dependent/cascading dropdowns.
52
+ */
53
+ "x-formspec-params"?: readonly string[];
54
+ /**
55
+ * Schema source identifier for dynamic schema fields.
56
+ * Indicates that the schema should be loaded dynamically at runtime.
57
+ */
58
+ "x-formspec-schemaSource"?: string;
59
+ }
60
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/json-schema/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,SAAS,GACT,QAAQ,GACR,OAAO,GACP,MAAM,CAAC;AAEX;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IAGd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,IAAI,CAAC,EAAE,cAAc,GAAG,cAAc,EAAE,CAAC;IAGzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAG1B,IAAI,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC;IACrD,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IAGzC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,oBAAoB,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC;IAG7C,KAAK,CAAC,EAAE,WAAW,GAAG,WAAW,EAAE,CAAC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;IACtB,GAAG,CAAC,EAAE,WAAW,CAAC;IAGlB,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,IAAI,CAAC,EAAE,WAAW,CAAC;IAGnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAGhB,OAAO,CAAC,EAAE,OAAO,CAAC;IAMlB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAExC;;;OAGG;IACH,yBAAyB,CAAC,EAAE,MAAM,CAAC;CACpC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * JSON Schema Draft-07 type definitions.
3
+ *
4
+ * These types are a subset of JSON Schema sufficient for form generation.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/json-schema/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * JSON Forms UI Schema generator for FormSpec forms.
3
+ */
4
+ import type { FormElement, FormSpec } from "@formspec/core";
5
+ import type { UISchema } from "./types.js";
6
+ /**
7
+ * Generates a JSON Forms UI Schema from a FormSpec.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const form = formspec(
12
+ * group("Customer",
13
+ * field.text("name", { label: "Name" }),
14
+ * ),
15
+ * when("status", "draft",
16
+ * field.text("notes", { label: "Notes" }),
17
+ * ),
18
+ * );
19
+ *
20
+ * const uiSchema = generateUiSchema(form);
21
+ * // {
22
+ * // type: "VerticalLayout",
23
+ * // elements: [
24
+ * // {
25
+ * // type: "Group",
26
+ * // label: "Customer",
27
+ * // elements: [
28
+ * // { type: "Control", scope: "#/properties/name", label: "Name" }
29
+ * // ]
30
+ * // },
31
+ * // {
32
+ * // type: "Control",
33
+ * // scope: "#/properties/notes",
34
+ * // label: "Notes",
35
+ * // rule: {
36
+ * // effect: "SHOW",
37
+ * // condition: { scope: "#/properties/status", schema: { const: "draft" } }
38
+ * // }
39
+ * // }
40
+ * // ]
41
+ * // }
42
+ * ```
43
+ *
44
+ * @param form - The FormSpec to convert
45
+ * @returns A JSON Forms UI Schema
46
+ */
47
+ export declare function generateUiSchema<E extends readonly FormElement[]>(form: FormSpec<E>): UISchema;
48
+ //# sourceMappingURL=generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/ui-schema/generator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,QAAQ,EAGT,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAEV,QAAQ,EAIT,MAAM,YAAY,CAAC;AA2HpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,SAAS,WAAW,EAAE,EAC/D,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,GAChB,QAAQ,CAKV"}