@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,150 @@
1
+ /**
2
+ * JSON Forms UI Schema generator for FormSpec forms.
3
+ */
4
+ /**
5
+ * Converts a field name to a JSON Pointer scope.
6
+ */
7
+ function fieldToScope(fieldName) {
8
+ return `#/properties/${fieldName}`;
9
+ }
10
+ /**
11
+ * Creates a rule for conditional visibility.
12
+ */
13
+ function createShowRule(fieldName, value) {
14
+ return {
15
+ effect: "SHOW",
16
+ condition: {
17
+ scope: fieldToScope(fieldName),
18
+ schema: { const: value },
19
+ },
20
+ };
21
+ }
22
+ /**
23
+ * Combines two rules into one using allOf.
24
+ *
25
+ * When elements are nested inside multiple conditionals, all conditions
26
+ * must be met for the element to be visible.
27
+ */
28
+ function combineRules(parentRule, childRule) {
29
+ // Both rules should have the same effect (SHOW)
30
+ // Combine conditions using allOf
31
+ const parentCondition = parentRule.condition;
32
+ const childCondition = childRule.condition;
33
+ return {
34
+ effect: "SHOW",
35
+ condition: {
36
+ scope: "#",
37
+ schema: {
38
+ allOf: [
39
+ {
40
+ properties: {
41
+ [parentCondition.scope.replace("#/properties/", "")]: parentCondition.schema,
42
+ },
43
+ },
44
+ {
45
+ properties: {
46
+ [childCondition.scope.replace("#/properties/", "")]: childCondition.schema,
47
+ },
48
+ },
49
+ ],
50
+ },
51
+ },
52
+ };
53
+ }
54
+ /**
55
+ * Converts form elements to UI Schema elements.
56
+ *
57
+ * @param elements - The form elements to convert
58
+ * @param parentRule - Optional rule inherited from parent conditional
59
+ * @returns Array of UI Schema elements
60
+ */
61
+ function elementsToUiSchema(elements, parentRule) {
62
+ const result = [];
63
+ for (const element of elements) {
64
+ switch (element._type) {
65
+ case "field": {
66
+ const control = {
67
+ type: "Control",
68
+ scope: fieldToScope(element.name),
69
+ ...(element.label !== undefined && { label: element.label }),
70
+ ...(parentRule !== undefined && { rule: parentRule }),
71
+ };
72
+ result.push(control);
73
+ break;
74
+ }
75
+ case "group": {
76
+ const groupElement = element;
77
+ const group = {
78
+ type: "Group",
79
+ label: groupElement.label,
80
+ elements: elementsToUiSchema(groupElement.elements, parentRule),
81
+ ...(parentRule !== undefined && { rule: parentRule }),
82
+ };
83
+ result.push(group);
84
+ break;
85
+ }
86
+ case "conditional": {
87
+ const conditionalElement = element;
88
+ // Create a rule for this conditional
89
+ const newRule = createShowRule(conditionalElement.field, conditionalElement.value);
90
+ // Combine with parent rule if present (for nested conditionals)
91
+ const combinedRule = parentRule !== undefined
92
+ ? combineRules(parentRule, newRule)
93
+ : newRule;
94
+ // Apply the combined rule to all children
95
+ const childElements = elementsToUiSchema(conditionalElement.elements, combinedRule);
96
+ result.push(...childElements);
97
+ break;
98
+ }
99
+ }
100
+ }
101
+ return result;
102
+ }
103
+ /**
104
+ * Generates a JSON Forms UI Schema from a FormSpec.
105
+ *
106
+ * @example
107
+ * ```typescript
108
+ * const form = formspec(
109
+ * group("Customer",
110
+ * field.text("name", { label: "Name" }),
111
+ * ),
112
+ * when("status", "draft",
113
+ * field.text("notes", { label: "Notes" }),
114
+ * ),
115
+ * );
116
+ *
117
+ * const uiSchema = generateUiSchema(form);
118
+ * // {
119
+ * // type: "VerticalLayout",
120
+ * // elements: [
121
+ * // {
122
+ * // type: "Group",
123
+ * // label: "Customer",
124
+ * // elements: [
125
+ * // { type: "Control", scope: "#/properties/name", label: "Name" }
126
+ * // ]
127
+ * // },
128
+ * // {
129
+ * // type: "Control",
130
+ * // scope: "#/properties/notes",
131
+ * // label: "Notes",
132
+ * // rule: {
133
+ * // effect: "SHOW",
134
+ * // condition: { scope: "#/properties/status", schema: { const: "draft" } }
135
+ * // }
136
+ * // }
137
+ * // ]
138
+ * // }
139
+ * ```
140
+ *
141
+ * @param form - The FormSpec to convert
142
+ * @returns A JSON Forms UI Schema
143
+ */
144
+ export function generateUiSchema(form) {
145
+ return {
146
+ type: "VerticalLayout",
147
+ elements: elementsToUiSchema(form.elements),
148
+ };
149
+ }
150
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/ui-schema/generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * JSON Forms UI Schema type definitions.
3
+ *
4
+ * These types define the UI layout structure for JSON Forms.
5
+ * See: https://jsonforms.io/docs/uischema/
6
+ */
7
+ /**
8
+ * UI Schema element types.
9
+ */
10
+ export type UISchemaElementType = "Control" | "VerticalLayout" | "HorizontalLayout" | "Group" | "Categorization" | "Category";
11
+ /**
12
+ * Rule effect types for conditional visibility.
13
+ */
14
+ export type RuleEffect = "SHOW" | "HIDE" | "ENABLE" | "DISABLE";
15
+ /**
16
+ * JSON Schema subset for rule conditions.
17
+ */
18
+ export interface RuleConditionSchema {
19
+ const?: unknown;
20
+ enum?: readonly unknown[];
21
+ type?: string;
22
+ minimum?: number;
23
+ maximum?: number;
24
+ properties?: Record<string, RuleConditionSchema>;
25
+ allOf?: RuleConditionSchema[];
26
+ }
27
+ /**
28
+ * Condition for a rule.
29
+ */
30
+ export interface SchemaBasedCondition {
31
+ scope: string;
32
+ schema: RuleConditionSchema;
33
+ }
34
+ /**
35
+ * Rule for conditional element visibility/enablement.
36
+ */
37
+ export interface Rule {
38
+ effect: RuleEffect;
39
+ condition: SchemaBasedCondition;
40
+ }
41
+ /**
42
+ * Base interface for all UI Schema elements.
43
+ */
44
+ export interface UISchemaElementBase {
45
+ type: UISchemaElementType;
46
+ rule?: Rule;
47
+ options?: Record<string, unknown>;
48
+ }
49
+ /**
50
+ * A Control element that binds to a JSON Schema property.
51
+ */
52
+ export interface ControlElement extends UISchemaElementBase {
53
+ type: "Control";
54
+ scope: string;
55
+ label?: string;
56
+ }
57
+ /**
58
+ * A vertical layout element.
59
+ */
60
+ export interface VerticalLayout extends UISchemaElementBase {
61
+ type: "VerticalLayout";
62
+ elements: UISchemaElement[];
63
+ }
64
+ /**
65
+ * A horizontal layout element.
66
+ */
67
+ export interface HorizontalLayout extends UISchemaElementBase {
68
+ type: "HorizontalLayout";
69
+ elements: UISchemaElement[];
70
+ }
71
+ /**
72
+ * A group element with a label.
73
+ */
74
+ export interface GroupLayout extends UISchemaElementBase {
75
+ type: "Group";
76
+ label: string;
77
+ elements: UISchemaElement[];
78
+ }
79
+ /**
80
+ * Union of all UI Schema element types.
81
+ */
82
+ export type UISchemaElement = ControlElement | VerticalLayout | HorizontalLayout | GroupLayout;
83
+ /**
84
+ * Root UI Schema (always a layout).
85
+ */
86
+ export type UISchema = VerticalLayout | HorizontalLayout | GroupLayout;
87
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ui-schema/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAC3B,SAAS,GACT,gBAAgB,GAChB,kBAAkB,GAClB,OAAO,GACP,gBAAgB,GAChB,UAAU,CAAC;AAEf;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IACjD,KAAK,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,mBAAmB,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,oBAAoB,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,mBAAmB;IACzD,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,mBAAmB;IACzD,IAAI,EAAE,gBAAgB,CAAC;IACvB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,mBAAmB;IAC3D,IAAI,EAAE,kBAAkB,CAAC;IACzB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,WAAY,SAAQ,mBAAmB;IACtD,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GACvB,cAAc,GACd,cAAc,GACd,gBAAgB,GAChB,WAAW,CAAC;AAEhB;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,cAAc,GAAG,gBAAgB,GAAG,WAAW,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * JSON Forms UI Schema type definitions.
3
+ *
4
+ * These types define the UI layout structure for JSON Forms.
5
+ * See: https://jsonforms.io/docs/uischema/
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/ui-schema/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@formspec/build",
3
+ "version": "0.1.0-alpha.1",
4
+ "description": "Build tools to compile FormSpec forms to JSON Schema and UI Schema",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/build.d.ts",
8
+ "bin": {
9
+ "formspec-build": "./dist/cli.js"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/build.d.ts",
14
+ "import": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "dependencies": {
21
+ "@formspec/core": "0.1.0-alpha.0"
22
+ },
23
+ "devDependencies": {
24
+ "vitest": "^3.0.0",
25
+ "@formspec/dsl": "0.1.0-alpha.0"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "keywords": [],
31
+ "license": "UNLICENSED",
32
+ "scripts": {
33
+ "build": "tsc",
34
+ "clean": "rm -rf dist temp",
35
+ "typecheck": "tsc --noEmit",
36
+ "test": "pnpm run build && vitest run",
37
+ "api-extractor": "api-extractor run",
38
+ "api-extractor:local": "api-extractor run --local",
39
+ "api-documenter": "api-documenter markdown -i temp -o docs"
40
+ }
41
+ }