@f1studio/form-spec 5.0.0-alpha.101

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 (225) hide show
  1. package/Designer.d.ts +89 -0
  2. package/FormSpec.TS/Components/HelloComponent.js +68 -0
  3. package/FormSpec.TS/Components/HelloComponent.js.map +1 -0
  4. package/FormSpec.TS/Components/HelloComponent.ts.map +1 -0
  5. package/FormSpec.TS/Designer.js +526 -0
  6. package/FormSpec.TS/Designer.js.map +1 -0
  7. package/FormSpec.TS/Designer.ts.map +1 -0
  8. package/FormSpec.TS/FormSpec.js +5400 -0
  9. package/FormSpec.TS/FormSpec.js.map +1 -0
  10. package/FormSpec.TS/FormSpec.ts.map +1 -0
  11. package/FormSpec.TS/FormSpecHelpers.js +382 -0
  12. package/FormSpec.TS/FormSpecHelpers.js.map +1 -0
  13. package/FormSpec.TS/FormSpecHelpers.ts.map +1 -0
  14. package/FormSpec.TS/Helpers.js +732 -0
  15. package/FormSpec.TS/Helpers.js.map +1 -0
  16. package/FormSpec.TS/Helpers.ts.map +1 -0
  17. package/FormSpec.TS/Interfaces.js +257 -0
  18. package/FormSpec.TS/Interfaces.js.map +1 -0
  19. package/FormSpec.TS/Interfaces.ts.map +1 -0
  20. package/FormSpec.TS/Interop/FormSpec.Api.Helpers.js +854 -0
  21. package/FormSpec.TS/Interop/FormSpec.Api.Helpers.js.map +1 -0
  22. package/FormSpec.TS/Interop/FormSpec.Api.Helpers.ts.map +1 -0
  23. package/FormSpec.TS/Interop/FormSpec.Api.Option.js +1961 -0
  24. package/FormSpec.TS/Interop/FormSpec.Api.Option.js.map +1 -0
  25. package/FormSpec.TS/Interop/FormSpec.Api.Option.ts.map +1 -0
  26. package/FormSpec.TS/Interop/FormSpec.Values.Api.Option.js +1367 -0
  27. package/FormSpec.TS/Interop/FormSpec.Values.Api.Option.js.map +1 -0
  28. package/FormSpec.TS/Interop/FormSpec.Values.Api.Option.ts.map +1 -0
  29. package/FormSpec.TS/Logging/LogTypes.js +347 -0
  30. package/FormSpec.TS/Logging/LogTypes.js.map +1 -0
  31. package/FormSpec.TS/Logging/LogTypes.ts.map +1 -0
  32. package/FormSpec.TS/Migrator.js +230 -0
  33. package/FormSpec.TS/Migrator.js.map +1 -0
  34. package/FormSpec.TS/Migrator.ts.map +1 -0
  35. package/FormSpec.TS/PathwayDataExtractor.js +361 -0
  36. package/FormSpec.TS/PathwayDataExtractor.js.map +1 -0
  37. package/FormSpec.TS/PathwayDataExtractor.ts.map +1 -0
  38. package/FormSpec.TS/PathwayExecutor.js +1321 -0
  39. package/FormSpec.TS/PathwayExecutor.js.map +1 -0
  40. package/FormSpec.TS/PathwayExecutor.ts.map +1 -0
  41. package/FormSpec.TS/PathwayValidator.js +346 -0
  42. package/FormSpec.TS/PathwayValidator.js.map +1 -0
  43. package/FormSpec.TS/PathwayValidator.ts.map +1 -0
  44. package/FormSpec.TS/PluginInterface.js +171 -0
  45. package/FormSpec.TS/PluginInterface.js.map +1 -0
  46. package/FormSpec.TS/PluginInterface.ts.map +1 -0
  47. package/FormSpec.TS/Prelude.js +59 -0
  48. package/FormSpec.TS/Prelude.js.map +1 -0
  49. package/FormSpec.TS/Prelude.ts.map +1 -0
  50. package/FormSpec.TS/Renderers/FormSpecMarkdownRenderer.js +958 -0
  51. package/FormSpec.TS/Renderers/FormSpecMarkdownRenderer.js.map +1 -0
  52. package/FormSpec.TS/Renderers/FormSpecMarkdownRenderer.ts.map +1 -0
  53. package/FormSpec.TS/Renderers/MermaidRenderer.js +228 -0
  54. package/FormSpec.TS/Renderers/MermaidRenderer.js.map +1 -0
  55. package/FormSpec.TS/Renderers/MermaidRenderer.ts.map +1 -0
  56. package/FormSpec.TS/Renderers/PathwayRenderers.js +190 -0
  57. package/FormSpec.TS/Renderers/PathwayRenderers.js.map +1 -0
  58. package/FormSpec.TS/Renderers/PathwayRenderers.ts.map +1 -0
  59. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Base.fs +511 -0
  60. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Base.fs.js +437 -0
  61. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Base.fs.js.map +1 -0
  62. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Base.fs.ts.map +1 -0
  63. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Error.fs +16 -0
  64. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Error.fs.js +73 -0
  65. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Error.fs.js.map +1 -0
  66. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Error.fs.ts.map +1 -0
  67. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Extensions.fs +50 -0
  68. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Extensions.fs.js +72 -0
  69. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Extensions.fs.js.map +1 -0
  70. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Extensions.fs.ts.map +1 -0
  71. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Fable.Form.fableproj +28 -0
  72. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Field.fs +24 -0
  73. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Field.fs.js +56 -0
  74. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Field.fs.js.map +1 -0
  75. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Field.fs.ts.map +1 -0
  76. package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Fable.Form.Simple.fableproj +31 -0
  77. package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Form.fs +178 -0
  78. package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Form.fs.js +464 -0
  79. package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Form.fs.js.map +1 -0
  80. package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Form.fs.ts.map +1 -0
  81. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Extensions.fs +17 -0
  82. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Hooks.fs +152 -0
  83. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Hooks.fs.js +25 -0
  84. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Hooks.fs.js.map +1 -0
  85. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Hooks.fs.ts.map +1 -0
  86. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Types.fableproj +28 -0
  87. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.fs +218 -0
  88. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.fs.js +37 -0
  89. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.fs.js.map +1 -0
  90. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.fs.ts.map +1 -0
  91. package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.Types.fableproj +27 -0
  92. package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.fs +82 -0
  93. package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.fs.js +7 -0
  94. package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.fs.js.map +1 -0
  95. package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.fs.ts.map +1 -0
  96. package/FormSpec.TS/fable_modules/Feliz.2.7.0/BorderStyle.fs +59 -0
  97. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Colors.fs +154 -0
  98. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Colors.fs.js +32 -0
  99. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Colors.fs.js.map +1 -0
  100. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Colors.fs.ts.map +1 -0
  101. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Feliz.fableproj +42 -0
  102. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Fonts.fs +240 -0
  103. package/FormSpec.TS/fable_modules/Feliz.2.7.0/GridTypes.fs +24 -0
  104. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Html.fs +826 -0
  105. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Interop.fs +83 -0
  106. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Interop.fs.js +292 -0
  107. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Interop.fs.js.map +1 -0
  108. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Interop.fs.ts.map +1 -0
  109. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Key.fs +65 -0
  110. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Key.fs.js +229 -0
  111. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Key.fs.js.map +1 -0
  112. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Key.fs.ts.map +1 -0
  113. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Length.fs +91 -0
  114. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Locale.fs +876 -0
  115. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Properties.fs +4080 -0
  116. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Properties.fs.js +133 -0
  117. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Properties.fs.js.map +1 -0
  118. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Properties.fs.ts.map +1 -0
  119. package/FormSpec.TS/fable_modules/Feliz.2.7.0/React.fs +656 -0
  120. package/FormSpec.TS/fable_modules/Feliz.2.7.0/React.fs.js +561 -0
  121. package/FormSpec.TS/fable_modules/Feliz.2.7.0/React.fs.js.map +1 -0
  122. package/FormSpec.TS/fable_modules/Feliz.2.7.0/React.fs.ts.map +1 -0
  123. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactDOM.fs +25 -0
  124. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactDOM.fs.js +46 -0
  125. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactDOM.fs.js.map +1 -0
  126. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactDOM.fs.ts.map +1 -0
  127. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactInterop.js +63 -0
  128. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactInterop.js.map +1 -0
  129. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactTypes.fs +41 -0
  130. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactTypes.fs.js +7 -0
  131. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactTypes.fs.js.map +1 -0
  132. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactTypes.fs.ts.map +1 -0
  133. package/FormSpec.TS/fable_modules/Feliz.2.7.0/StyleTypes.fs +53 -0
  134. package/FormSpec.TS/fable_modules/Feliz.2.7.0/StyleTypes.fs.js +7 -0
  135. package/FormSpec.TS/fable_modules/Feliz.2.7.0/StyleTypes.fs.js.map +1 -0
  136. package/FormSpec.TS/fable_modules/Feliz.2.7.0/StyleTypes.fs.ts.map +1 -0
  137. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Styles.fs +5740 -0
  138. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Svg.fs +1455 -0
  139. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Svg.fs.js +39 -0
  140. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Svg.fs.js.map +1 -0
  141. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Svg.fs.ts.map +1 -0
  142. package/FormSpec.TS/fable_modules/Feliz.2.7.0/TextDecorationLine.fs +13 -0
  143. package/FormSpec.TS/fable_modules/Feliz.2.7.0/TextDecorationStyle.fs +33 -0
  144. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Transform.fs +181 -0
  145. package/FormSpec.TS/fable_modules/Feliz.2.7.0/TransformOrigin.fs +17 -0
  146. package/FormSpec.TS/fable_modules/Feliz.2.7.0/TransitionProperty.fs +162 -0
  147. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Types.fs +13 -0
  148. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Types.fs.js +7 -0
  149. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Types.fs.js.map +1 -0
  150. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Types.fs.ts.map +1 -0
  151. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Decode.fs +1768 -0
  152. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Decode.fs.js +2337 -0
  153. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Decode.fs.js.map +1 -0
  154. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Decode.fs.ts.map +1 -0
  155. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs +811 -0
  156. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs.js +465 -0
  157. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs.js.map +1 -0
  158. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs.ts.map +1 -0
  159. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Extra.fs +47 -0
  160. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Extra.fs.js +18 -0
  161. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Extra.fs.js.map +1 -0
  162. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Extra.fs.ts.map +1 -0
  163. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Thoth.Json.fableproj +34 -0
  164. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Types.fs +68 -0
  165. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Types.fs.js +355 -0
  166. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Types.fs.js.map +1 -0
  167. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Types.fs.ts.map +1 -0
  168. package/FormSpec.TS/fable_modules/project_cracked.json +1 -0
  169. package/FormSpec.d.ts +1257 -0
  170. package/FormSpecHelpers.d.ts +50 -0
  171. package/Helpers.d.ts +147 -0
  172. package/Interfaces.d.ts +70 -0
  173. package/Interop/FormSpec.Api.Helpers.d.ts +247 -0
  174. package/Interop/FormSpec.Api.Helpers.d.ts.map +1 -0
  175. package/Interop/FormSpec.Api.Option.d.ts +384 -0
  176. package/Interop/FormSpec.Api.Option.d.ts.map +1 -0
  177. package/Interop/FormSpec.Values.Api.Option.d.ts +324 -0
  178. package/Interop/FormSpec.Values.Api.Option.d.ts.map +1 -0
  179. package/Migrator.d.ts +59 -0
  180. package/PathwayDataExtractor.d.ts +19 -0
  181. package/PathwayExecutor.d.ts +210 -0
  182. package/PathwayValidator.d.ts +52 -0
  183. package/PluginInterface.d.ts +36 -0
  184. package/Prelude.d.ts +11 -0
  185. package/README.TS.md +622 -0
  186. package/README.md +85 -0
  187. package/package.json +39 -0
  188. package/src/Components/HelloComponent.ts +48 -0
  189. package/src/Components/HelloComponent.ts.map +1 -0
  190. package/src/Designer.ts +389 -0
  191. package/src/Designer.ts.map +1 -0
  192. package/src/FormSpec.ts +3114 -0
  193. package/src/FormSpec.ts.map +1 -0
  194. package/src/FormSpecHelpers.ts +374 -0
  195. package/src/FormSpecHelpers.ts.map +1 -0
  196. package/src/Helpers.ts +765 -0
  197. package/src/Helpers.ts.map +1 -0
  198. package/src/Interfaces.ts +166 -0
  199. package/src/Interfaces.ts.map +1 -0
  200. package/src/Interop/FormSpec.Api.Helpers.ts +872 -0
  201. package/src/Interop/FormSpec.Api.Helpers.ts.map +1 -0
  202. package/src/Interop/FormSpec.Api.Option.ts +1618 -0
  203. package/src/Interop/FormSpec.Api.Option.ts.map +1 -0
  204. package/src/Interop/FormSpec.Values.Api.Option.ts +1214 -0
  205. package/src/Interop/FormSpec.Values.Api.Option.ts.map +1 -0
  206. package/src/Logging/LogTypes.ts +212 -0
  207. package/src/Logging/LogTypes.ts.map +1 -0
  208. package/src/Migrator.ts +156 -0
  209. package/src/Migrator.ts.map +1 -0
  210. package/src/PathwayDataExtractor.ts +290 -0
  211. package/src/PathwayDataExtractor.ts.map +1 -0
  212. package/src/PathwayExecutor.ts +1102 -0
  213. package/src/PathwayExecutor.ts.map +1 -0
  214. package/src/PathwayValidator.ts +244 -0
  215. package/src/PathwayValidator.ts.map +1 -0
  216. package/src/PluginInterface.ts +79 -0
  217. package/src/PluginInterface.ts.map +1 -0
  218. package/src/Prelude.ts +21 -0
  219. package/src/Prelude.ts.map +1 -0
  220. package/src/Renderers/FormSpecMarkdownRenderer.ts +874 -0
  221. package/src/Renderers/FormSpecMarkdownRenderer.ts.map +1 -0
  222. package/src/Renderers/MermaidRenderer.ts +218 -0
  223. package/src/Renderers/MermaidRenderer.ts.map +1 -0
  224. package/src/Renderers/PathwayRenderers.ts +200 -0
  225. package/src/Renderers/PathwayRenderers.ts.map +1 -0
package/README.TS.md ADDED
@@ -0,0 +1,622 @@
1
+ # FormSpec TypeScript API Documentation
2
+
3
+ ## 🚀 F# to TypeScript Interop for Form Specifications
4
+
5
+ The FormSpec TypeScript API provides a type-safe, validated bridge between F# domain models and TypeScript applications. Built with Fable and Thoth.Json, it enables seamless form specification management across the F#/TypeScript boundary.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ # From Verdaccio local registry
11
+ npm install @f1studio/form-spec@5.0.0-alpha.13 --registry http://localhost:4873
12
+ # or
13
+ pnpm add @f1studio/form-spec@5.0.0-alpha.13 --registry http://localhost:4873
14
+ # or
15
+ yarn add @f1studio/form-spec@5.0.0-alpha.13 --registry http://localhost:4873
16
+ ```
17
+
18
+ ## Core Concepts
19
+
20
+ ### FableResult Type
21
+ All validation functions return a `FableResult<T, E>` - a TypeScript-friendly tagged union:
22
+
23
+ ```typescript
24
+ type FableResult<T, E> =
25
+ | { result: "fableOk"; Item: T }
26
+ | { result: "fableError"; Item: E }
27
+ ```
28
+
29
+ This enables safe pattern matching in TypeScript:
30
+
31
+ ```typescript
32
+ const result = validateFormSpec(unknownData);
33
+
34
+ switch (result.result) {
35
+ case "fableOk":
36
+ console.log("Valid FormSpec:", result.Item);
37
+ break;
38
+ case "fableError":
39
+ console.error("Validation failed:", result.Item);
40
+ break;
41
+ }
42
+ ```
43
+
44
+ ## Quick Start
45
+
46
+ ### 1. Validate Unknown Data
47
+
48
+ ```typescript
49
+ import {
50
+ Api_validateFormSpec,
51
+ Api_validateAndConvertFormSpec
52
+ } from '@f1studio/form-spec/Interop/FormSpec.Api';
53
+
54
+ // Validate JSON data from an API
55
+ async function loadFormSpec(url: string) {
56
+ const response = await fetch(url);
57
+ const data = await response.json();
58
+
59
+ // Validate to TypeScript-friendly types
60
+ const result = Api_validateFormSpec()(data);
61
+
62
+ if (result.result === "fableOk") {
63
+ return result.Item; // Fully typed FormSpecTS
64
+ } else {
65
+ throw new Error(result.Item);
66
+ }
67
+ }
68
+
69
+ // Validate AND convert to F# domain types
70
+ const domainResult = Api_validateAndConvertFormSpec()(data);
71
+ ```
72
+
73
+ ### 2. Create Forms with Builders
74
+
75
+ ```typescript
76
+ import {
77
+ Api_createFormSpec,
78
+ Api_createTextField,
79
+ Api_createCheckboxField,
80
+ Api_createDropdownField,
81
+ Api_createFieldOption,
82
+ Builders_formField,
83
+ Builders_formStep,
84
+ Builders_formSpec
85
+ } from '@f1studio/form-spec/Interop/FormSpec.Api';
86
+
87
+ // Create a new empty FormSpec
88
+ const emptySpec = Api_createFormSpec();
89
+
90
+ // Build a complete form specification
91
+ function createPatientIntakeForm() {
92
+ // Create field options
93
+ const genderOptions = [
94
+ Api_createFieldOption("Male", "male"),
95
+ Api_createFieldOption("Female", "female"),
96
+ Api_createFieldOption("Other", "other")
97
+ ];
98
+
99
+ // Create fields
100
+ const nameField = Builders_formField(
101
+ "Patient Name",
102
+ Api_createTextField(null)
103
+ )
104
+ .WithOrder(1)
105
+ .AsOptional()
106
+ .Build();
107
+
108
+ const genderField = Builders_formField(
109
+ "Gender",
110
+ Api_createDropdownField(genderOptions)
111
+ )
112
+ .WithOrder(2)
113
+ .Build();
114
+
115
+ const consentField = Builders_formField(
116
+ "I consent to treatment",
117
+ Api_createCheckboxField(false, null)
118
+ )
119
+ .WithOrder(3)
120
+ .Build();
121
+
122
+ // Create form step
123
+ const demographicsStep = Builders_formStep("Demographics")
124
+ .WithOrder(1)
125
+ .AddField(nameField)
126
+ .AddField(genderField)
127
+ .AddField(consentField)
128
+ .Build();
129
+
130
+ // Create complete FormSpec
131
+ const formSpec = Builders_formSpec("Patient Intake Form")
132
+ .WithCode("INTAKE-001")
133
+ .WithAbstract("Standard patient intake and consent form")
134
+ .WithVersion("2.0.0")
135
+ .AddStep(demographicsStep)
136
+ .WithTags(["intake", "patient", "consent"])
137
+ .RequiresReview()
138
+ .Build();
139
+
140
+ return formSpec;
141
+ }
142
+ ```
143
+
144
+ ### 3. Field Types
145
+
146
+ The API supports all standard HTML input types plus specialized medical fields:
147
+
148
+ ```typescript
149
+ import {
150
+ Api_createTextField,
151
+ Api_createTextArea,
152
+ Api_createEmailField,
153
+ Api_createPasswordField,
154
+ Api_createNumberField,
155
+ Api_createDateField,
156
+ Api_createTimeField,
157
+ Api_createCheckboxField,
158
+ Api_createRadioField,
159
+ Api_createDropdownField,
160
+ Api_createMultiChoiceField,
161
+ Api_createMessageField,
162
+ Types_MessageTypeTS
163
+ } from '@f1studio/form-spec/Interop/FormSpec.Api';
164
+
165
+ // Text inputs
166
+ const textField = Api_createTextField("default value");
167
+ const emailField = Api_createEmailField(null);
168
+ const numberField = Api_createNumberField("42");
169
+
170
+ // Date/Time inputs
171
+ const dateField = Api_createDateField("2024-01-01");
172
+ const timeField = Api_createTimeField("14:30");
173
+
174
+ // Choice inputs
175
+ const options = [
176
+ Api_createFieldOption("Option 1", "opt1"),
177
+ Api_createFieldOption("Option 2", "opt2")
178
+ ];
179
+ const radioField = Api_createRadioField(options);
180
+ const dropdownField = Api_createDropdownField(options);
181
+ const multiChoiceField = Api_createMultiChoiceField(options);
182
+
183
+ // Informational
184
+ const messageField = Api_createMessageField(
185
+ "Important Notice",
186
+ "Please read carefully before proceeding",
187
+ Types_MessageTypeTS.Warning
188
+ );
189
+ ```
190
+
191
+ ### 4. Field Dependencies
192
+
193
+ Create conditional field visibility based on other field values:
194
+
195
+ ```typescript
196
+ import {
197
+ Types_EvaluatorTS,
198
+ Api_createFieldKey
199
+ } from '@f1studio/form-spec/Interop/FormSpec.Api';
200
+
201
+ const hasAllergyField = Builders_formField(
202
+ "Do you have allergies?",
203
+ Api_createCheckboxField(false, null)
204
+ )
205
+ .WithOrder(1)
206
+ .Build();
207
+
208
+ const allergyDetailsField = Builders_formField(
209
+ "Please describe your allergies",
210
+ Api_createTextField(null)
211
+ )
212
+ .WithOrder(2)
213
+ .WithDependency({
214
+ FieldKey: hasAllergyField.FieldKey,
215
+ FieldValue: "true",
216
+ Evaluator: Types_EvaluatorTS.Equals
217
+ })
218
+ .Build();
219
+ ```
220
+
221
+ ### 5. Serialization
222
+
223
+ ```typescript
224
+ import {
225
+ Api_serializeFormSpec,
226
+ Api_deserializeFormSpec
227
+ } from '@f1studio/form-spec/Interop/FormSpec.Api';
228
+
229
+ // Convert FormSpec to JSON string
230
+ const formSpec = createPatientIntakeForm();
231
+ const json = Api_serializeFormSpec(formSpec);
232
+ localStorage.setItem('formSpec', json);
233
+
234
+ // Deserialize from JSON string
235
+ const savedJson = localStorage.getItem('formSpec');
236
+ const result = Api_deserializeFormSpec(savedJson);
237
+
238
+ if (result.result === "fableOk") {
239
+ const restoredSpec = result.Item;
240
+ console.log("Loaded form:", restoredSpec.Title);
241
+ }
242
+ ```
243
+
244
+ ### 6. Query and Utility Functions
245
+
246
+ ```typescript
247
+ import {
248
+ Api_getFieldKeys,
249
+ Api_findFieldByKey,
250
+ Api_getFieldsByType,
251
+ Api_isValidFormSpec,
252
+ Api_getFormSpecSummary
253
+ } from '@f1studio/form-spec/Interop/FormSpec.Api';
254
+
255
+ const formSpec = createPatientIntakeForm();
256
+
257
+ // Get all field keys
258
+ const fieldKeys = Api_getFieldKeys(formSpec);
259
+ console.log(`Form has ${fieldKeys.length} fields`);
260
+
261
+ // Find a specific field
262
+ const field = Api_findFieldByKey(formSpec, fieldKeys[0]);
263
+ if (field) {
264
+ console.log("Found field:", field.Label);
265
+ }
266
+
267
+ // Get all text fields
268
+ const textFields = Api_getFieldsByType(formSpec, "Text");
269
+ console.log(`Found ${textFields.length} text fields`);
270
+
271
+ // Validate structure
272
+ if (Api_isValidFormSpec(formSpec)) {
273
+ console.log("FormSpec is valid");
274
+ }
275
+
276
+ // Get summary information
277
+ const summary = Api_getFormSpecSummary(formSpec);
278
+ console.log(summary);
279
+ // Output: { Id, Title, Version, StepCount, FieldCount, RequiresReview, RequiresApproval }
280
+ ```
281
+
282
+ ### 7. Scoring System
283
+
284
+ Add scoring ranges for assessments and evaluations:
285
+
286
+ ```typescript
287
+ import {
288
+ Types_ScoreColorTS,
289
+ Api_createScoreRange
290
+ } from '@f1studio/form-spec/Interop/FormSpec.Api';
291
+
292
+ const scoreRanges = [
293
+ {
294
+ Id: "550e8400-e29b-41d4-a716-446655440001",
295
+ Min: 0,
296
+ Max: 10,
297
+ Label: "Low Risk",
298
+ Tag: Types_ScoreColorTS.Success
299
+ },
300
+ {
301
+ Id: "550e8400-e29b-41d4-a716-446655440002",
302
+ Min: 11,
303
+ Max: 20,
304
+ Label: "Medium Risk",
305
+ Tag: Types_ScoreColorTS.Warning
306
+ },
307
+ {
308
+ Id: "550e8400-e29b-41d4-a716-446655440003",
309
+ Min: 21,
310
+ Max: 30,
311
+ Label: "High Risk",
312
+ Tag: Types_ScoreColorTS.Danger
313
+ }
314
+ ];
315
+
316
+ const formWithScore = Builders_formSpec("Risk Assessment")
317
+ .WithScore({
318
+ MaxScore: 30,
319
+ ScoreRanges: scoreRanges
320
+ })
321
+ .Build();
322
+ ```
323
+
324
+ ### 8. Matrix/Likert Scale Fields
325
+
326
+ Create matrix questions for surveys and assessments:
327
+
328
+ ```typescript
329
+ const satisfactionItems = [
330
+ Api_createFieldOption("Wait time", "wait_time"),
331
+ Api_createFieldOption("Staff friendliness", "staff"),
332
+ Api_createFieldOption("Cleanliness", "clean"),
333
+ ];
334
+
335
+ const ratingScale = [
336
+ Api_createFieldOption("Very Dissatisfied", "1"),
337
+ Api_createFieldOption("Dissatisfied", "2"),
338
+ Api_createFieldOption("Neutral", "3"),
339
+ Api_createFieldOption("Satisfied", "4"),
340
+ Api_createFieldOption("Very Satisfied", "5"),
341
+ ];
342
+
343
+ const matrixField = Builders_formField(
344
+ "Please rate your experience",
345
+ {
346
+ Type: "Matrix",
347
+ MatrixInfo: {
348
+ Items: satisfactionItems,
349
+ Options: ratingScale
350
+ },
351
+ // ... other properties set to null
352
+ }
353
+ ).Build();
354
+ ```
355
+
356
+ ## Advanced Usage
357
+
358
+ ### Type Guards and Validation
359
+
360
+ ```typescript
361
+ import { FormSpecTS } from '@f1studio/form-spec/Interop/FormSpec.Api';
362
+
363
+ // Type guard for FormSpec
364
+ function isFormSpec(obj: any): obj is FormSpecTS {
365
+ const result = Api_validateFormSpec()(obj);
366
+ return result.result === "fableOk";
367
+ }
368
+
369
+ // Use in your code
370
+ function processForm(data: unknown) {
371
+ if (isFormSpec(data)) {
372
+ // data is now typed as FormSpecTS
373
+ console.log(data.Title);
374
+ data.Steps.forEach(step => {
375
+ console.log(step.StepLabel);
376
+ });
377
+ }
378
+ }
379
+ ```
380
+
381
+ ### Batch Validation
382
+
383
+ ```typescript
384
+ import { Api_validateFormSpecs } from '@f1studio/form-spec/Interop/FormSpec.Api';
385
+
386
+ async function validateMultipleForms(urls: string[]) {
387
+ const responses = await Promise.all(
388
+ urls.map(url => fetch(url).then(r => r.json()))
389
+ );
390
+
391
+ const result = Api_validateFormSpecs(responses);
392
+
393
+ if (result.result === "fableOk") {
394
+ return result.Item; // FormSpecTS[]
395
+ } else {
396
+ throw new Error(`Validation failed: ${result.Item}`);
397
+ }
398
+ }
399
+ ```
400
+
401
+ ### Working with GUIDs
402
+
403
+ All keys in the system use GUIDs wrapped in typed objects:
404
+
405
+ ```typescript
406
+ import {
407
+ Api_createFieldKey,
408
+ Api_createStateKey,
409
+ Api_createTransitionKey
410
+ } from '@f1studio/form-spec/Interop/FormSpec.Api';
411
+
412
+ // Generate new keys
413
+ const fieldKey = Api_createFieldKey(); // { Value: "uuid..." }
414
+ const stateKey = Api_createStateKey(); // { Value: "uuid..." }
415
+ const transitionKey = Api_createTransitionKey(); // { Value: "uuid..." }
416
+
417
+ // Keys are automatically generated when using builders
418
+ const field = Builders_formField("Name", Api_createTextField(null))
419
+ .Build();
420
+ console.log(field.FieldKey.Value); // UUID string
421
+ ```
422
+
423
+ ## React Integration Example
424
+
425
+ ```typescript
426
+ import React, { useState, useEffect } from 'react';
427
+ import {
428
+ FormSpecTS,
429
+ Api_validateFormSpec,
430
+ Api_getFieldsByType
431
+ } from '@f1studio/form-spec/Interop/FormSpec.Api';
432
+
433
+ function FormRenderer({ formData }: { formData: unknown }) {
434
+ const [formSpec, setFormSpec] = useState<FormSpecTS | null>(null);
435
+ const [error, setError] = useState<string | null>(null);
436
+
437
+ useEffect(() => {
438
+ const result = Api_validateFormSpec()(formData);
439
+
440
+ if (result.result === "fableOk") {
441
+ setFormSpec(result.Item);
442
+ setError(null);
443
+ } else {
444
+ setError(result.Item);
445
+ setFormSpec(null);
446
+ }
447
+ }, [formData]);
448
+
449
+ if (error) {
450
+ return <div className="error">Invalid form: {error}</div>;
451
+ }
452
+
453
+ if (!formSpec) {
454
+ return <div>Loading...</div>;
455
+ }
456
+
457
+ return (
458
+ <div className="form-renderer">
459
+ <h1>{formSpec.Title}</h1>
460
+ <p>{formSpec.Abstract}</p>
461
+
462
+ {formSpec.Steps.map((step, stepIdx) => (
463
+ <div key={stepIdx} className="form-step">
464
+ <h2>{step.StepLabel}</h2>
465
+ {step.Fields.map((field, fieldIdx) => (
466
+ <div key={field.FieldKey.Value} className="form-field">
467
+ <label>{field.Label}</label>
468
+ {/* Render appropriate input based on field.FieldType.Type */}
469
+ </div>
470
+ ))}
471
+ </div>
472
+ ))}
473
+ </div>
474
+ );
475
+ }
476
+ ```
477
+
478
+ ## Type Definitions
479
+
480
+ ### Core Types
481
+
482
+ ```typescript
483
+ interface FormSpecTS {
484
+ Id: string;
485
+ Code?: string;
486
+ Title: string;
487
+ Abstract: string;
488
+ Version: string;
489
+ FormSpecVersion: string;
490
+ Steps: FormStepTS[];
491
+ CategoryTags: string[];
492
+ Score?: ScoreTS;
493
+ AssociatedCodes: string[];
494
+ RequiresReview: boolean;
495
+ RequiresReviewAndApproval: boolean;
496
+ ClinicalPathway?: ClinicalPathwaySpecTS;
497
+ }
498
+
499
+ interface FormStepTS {
500
+ StepOrder: number;
501
+ StepLabel: string;
502
+ Fields: FormFieldTS[];
503
+ }
504
+
505
+ interface FormFieldTS {
506
+ FieldOrder: number;
507
+ FieldKey: FieldKeyTS;
508
+ Label: string;
509
+ DependsOn?: DependsOnTS;
510
+ IsOptional: boolean;
511
+ IsDeprecated: boolean;
512
+ FieldType: FieldTypeTS;
513
+ }
514
+
515
+ interface FieldTypeTS {
516
+ Type: string; // "Text", "Checkbox", "Radio", etc.
517
+ TextInfo?: TextInfoTS;
518
+ BooleanInfo?: BooleanInfoTS;
519
+ SingleChoiceInfo?: SingleChoiceInfoTS;
520
+ MultiChoiceInfo?: MultiChoiceInfoTS;
521
+ MessageInfo?: MessageInfoTS;
522
+ MatrixInfo?: MatrixInfoTS;
523
+ SignatureInfo?: SignatureInfoTS;
524
+ PluginConfig?: PluginFieldConfigTS;
525
+ }
526
+ ```
527
+
528
+ ## Best Practices
529
+
530
+ 1. **Always Validate External Data**: Never trust data from APIs, files, or user input without validation
531
+ 2. **Use Builders for Type Safety**: Builders ensure all required fields are set correctly
532
+ 3. **Handle Both Result Cases**: Always handle both `fableOk` and `fableError` cases
533
+ 4. **Leverage TypeScript Types**: Import type definitions for IntelliSense and compile-time checking
534
+ 5. **Store GUIDs as Strings**: When persisting to databases, use the `Value` property of key types
535
+
536
+ ## Migration from Legacy Forms
537
+
538
+ If you have existing form data in a different format:
539
+
540
+ ```typescript
541
+ function migrateOldForm(oldForm: any): FormSpecTS {
542
+ const builder = Builders_formSpec(oldForm.title || "Untitled Form")
543
+ .WithVersion(oldForm.version || "1.0.0");
544
+
545
+ // Map old fields to new structure
546
+ oldForm.questions?.forEach((q: any, idx: number) => {
547
+ const field = Builders_formField(
548
+ q.text,
549
+ mapOldFieldType(q.type, q.options)
550
+ )
551
+ .WithOrder(idx + 1)
552
+ .Build();
553
+
554
+ // Add to step...
555
+ });
556
+
557
+ return builder.Build();
558
+ }
559
+
560
+ function mapOldFieldType(type: string, options?: any[]): FieldTypeTS {
561
+ switch(type) {
562
+ case 'text': return Api_createTextField(null);
563
+ case 'select': return Api_createDropdownField(
564
+ options?.map(o => Api_createFieldOption(o.label, o.value)) || []
565
+ );
566
+ // ... map other types
567
+ default: return Api_createTextField(null);
568
+ }
569
+ }
570
+ ```
571
+
572
+ ## Troubleshooting
573
+
574
+ ### Common Issues
575
+
576
+ **Issue**: Validation fails with "Invalid GUID for FieldKey"
577
+ **Solution**: Ensure you're using the key creation functions or builders which generate valid GUIDs
578
+
579
+ **Issue**: TypeScript can't find types
580
+ **Solution**: Import from the specific path: `@f1studio/form-spec/Interop/FormSpec.Api`
581
+
582
+ **Issue**: FableResult is not being recognized in switch statements
583
+ **Solution**: Check the discriminator property is exactly `result` (lowercase)
584
+
585
+ ## API Reference
586
+
587
+ ### Validation Functions
588
+ - `Api_validateFormSpec(input: any): FableResult<FormSpecTS, string>` - Validate unknown data to FormSpecTS
589
+ - `Api_validateAndConvertFormSpec(input: any): FableResult<FormSpec, string>` - Validate and convert to F# domain type
590
+ - `Api_validateFormField(input: any): FableResult<FormFieldTS, string>` - Validate a single field
591
+ - `Api_validateFormStep(input: any): FableResult<FormStepTS, string>` - Validate a form step
592
+ - `Api_validateFieldType(input: any): FableResult<FieldTypeTS, string>` - Validate a field type
593
+
594
+ ### Builder Functions
595
+ - `Api_createFormSpec(): FormSpecTS` - Create empty FormSpec
596
+ - `Api_createFieldKey(): FieldKeyTS` - Generate new field key
597
+ - `Api_createFieldOption(description: string, value: string): FieldOptionTS` - Create field option
598
+ - `Api_createTextField(value: string | null): FieldTypeTS` - Create text field
599
+ - `Api_createCheckboxField(defaultValue: boolean | null, selection: boolean | null): FieldTypeTS` - Create checkbox
600
+ - `Api_createRadioField(options: FieldOptionTS[]): FieldTypeTS` - Create radio button group
601
+ - `Api_createDropdownField(options: FieldOptionTS[]): FieldTypeTS` - Create dropdown
602
+
603
+ ### Serialization Functions
604
+ - `Api_serializeFormSpec(spec: FormSpecTS): string` - Convert to JSON string
605
+ - `Api_deserializeFormSpec(json: string): FableResult<FormSpecTS, string>` - Parse from JSON
606
+
607
+ ### Query Functions
608
+ - `Api_getFieldKeys(spec: FormSpecTS): FieldKeyTS[]` - Get all field keys
609
+ - `Api_findFieldByKey(spec: FormSpecTS, key: FieldKeyTS): FormFieldTS | undefined` - Find field by key
610
+ - `Api_getFieldsByType(spec: FormSpecTS, type: string): FormFieldTS[]` - Get fields of specific type
611
+ - `Api_isValidFormSpec(spec: FormSpecTS): boolean` - Check if spec is valid
612
+ - `Api_getFormSpecSummary(spec: FormSpecTS): object` - Get spec summary
613
+
614
+ ## Support
615
+
616
+ For issues, questions, or contributions:
617
+ - GitHub: https://github.com/f1-studio/f1-monorepo
618
+ - Documentation: https://f1studio.ai/docs
619
+
620
+ ## License
621
+
622
+ MIT © F1 Studio
package/README.md ADDED
@@ -0,0 +1,85 @@
1
+ # FormSpec – Build & Publish
2
+
3
+ TypeScript package generated from F# via Fable. Runtime uses external `@fable-org/fable-library-js`.
4
+
5
+ ## Build & Publish (Unified Script)
6
+
7
+ From `packages/core/form-spec`:
8
+
9
+ ```bash
10
+ # Publish to Verdaccio (local testing)
11
+ ./build-and-publish.sh none --verdaccio
12
+
13
+ # Publish to npm (public registry)
14
+ ./build-and-publish.sh none --npm
15
+
16
+ # Publish to both registries
17
+ ./build-and-publish.sh none --both
18
+
19
+ # Bump version and publish
20
+ ./build-and-publish.sh alpha --npm # or beta, rc, release
21
+ ```
22
+
23
+ The unified script handles:
24
+ 1. **Version bumping** (if requested)
25
+ 2. **.NET build** (NuGet package)
26
+ 3. **Fable compilation** (F# → TypeScript with `--fableLib` flag)
27
+ 4. **JS artifact creation** (TypeScript → JavaScript via SWC, type declarations)
28
+ 5. **NPM packaging** (creates `dist/package.json`)
29
+ 6. **Publishing to selected registry** (Verdaccio, npm, or both)
30
+ 7. **Verification** (checks package availability, JS files, exports)
31
+ 8. **Reporting** (version, install instructions, artifact list)
32
+
33
+ **📖 For complete publishing documentation, see [docs/PUBLISHING.md](./docs/PUBLISHING.md)**
34
+
35
+ Outputs to `dist/` with:
36
+ - JS: `FormSpec.TS/Interop/*.js` (compiled JavaScript)
37
+ - d.ts: `Interop/*.d.ts` (TypeScript definitions)
38
+ - Exports map for all interop modules
39
+ - Source maps and original TS under `dist/src/`
40
+
41
+ Notes:
42
+ - SWC is used for TS→JS; tsc declaration step may emit non-fatal TS errors from generated Thoth.Json TS (ignored in script).
43
+ - The `--fableLib` flag externalizes fable-library dependencies (critical for packaging).
44
+
45
+ ## Install (consumer)
46
+
47
+ ### From Verdaccio (local testing)
48
+ ```bash
49
+ npm install @f1studio/form-spec@<version> --registry http://localhost:4873
50
+ pnpm add @f1studio/form-spec@<version> --registry http://localhost:4873
51
+ bun add @f1studio/form-spec@<version> --registry http://localhost:4873
52
+ ```
53
+
54
+ ### From npm (public registry)
55
+ ```bash
56
+ npm install @f1studio/form-spec@<version>
57
+ pnpm add @f1studio/form-spec@<version>
58
+ bun add @f1studio/form-spec@<version>
59
+ ```
60
+
61
+ Entry points:
62
+ - Main: `@f1studio/form-spec` → `FormSpec.TS/Interop/FormSpec.Api.Option.js` (main API)
63
+ - Types: `@f1studio/form-spec/Interop/FormSpec.Api.Option` (d.ts + js)
64
+ - Result: `@f1studio/form-spec/Interop/FormSpec.Api.Result` (d.ts + js)
65
+ - TryCatch: `@f1studio/form-spec/Interop/FormSpec.Api.TryCatch` (d.ts + js)
66
+ - Values: `@f1studio/form-spec/Interop/FormSpec.Values.Api.Option` (d.ts + js)
67
+
68
+ ## Quick JS usage
69
+
70
+ ```ts
71
+ import { FormSpec_create, FormSpec_validate, FormSpec_tryFromJson } from '@f1studio/form-spec';
72
+ import { FormSpec_Values_create } from '@f1studio/form-spec/Interop/FormSpec.Values.Api.Option';
73
+
74
+ const form = FormSpec_create({
75
+ title: 'Example',
76
+ steps: [{ label: 'Step 1', fields: [] }],
77
+ });
78
+
79
+ const res = FormSpec_validate(form);
80
+ if (!res.success) throw new Error(res.errors[0].message);
81
+ ```
82
+
83
+ ## Runtime dependency
84
+ - `@fable-org/fable-library-js@1.11.0` (exact version; external; not bundled)
85
+