@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.
- package/Designer.d.ts +89 -0
- package/FormSpec.TS/Components/HelloComponent.js +68 -0
- package/FormSpec.TS/Components/HelloComponent.js.map +1 -0
- package/FormSpec.TS/Components/HelloComponent.ts.map +1 -0
- package/FormSpec.TS/Designer.js +526 -0
- package/FormSpec.TS/Designer.js.map +1 -0
- package/FormSpec.TS/Designer.ts.map +1 -0
- package/FormSpec.TS/FormSpec.js +5400 -0
- package/FormSpec.TS/FormSpec.js.map +1 -0
- package/FormSpec.TS/FormSpec.ts.map +1 -0
- package/FormSpec.TS/FormSpecHelpers.js +382 -0
- package/FormSpec.TS/FormSpecHelpers.js.map +1 -0
- package/FormSpec.TS/FormSpecHelpers.ts.map +1 -0
- package/FormSpec.TS/Helpers.js +732 -0
- package/FormSpec.TS/Helpers.js.map +1 -0
- package/FormSpec.TS/Helpers.ts.map +1 -0
- package/FormSpec.TS/Interfaces.js +257 -0
- package/FormSpec.TS/Interfaces.js.map +1 -0
- package/FormSpec.TS/Interfaces.ts.map +1 -0
- package/FormSpec.TS/Interop/FormSpec.Api.Helpers.js +854 -0
- package/FormSpec.TS/Interop/FormSpec.Api.Helpers.js.map +1 -0
- package/FormSpec.TS/Interop/FormSpec.Api.Helpers.ts.map +1 -0
- package/FormSpec.TS/Interop/FormSpec.Api.Option.js +1961 -0
- package/FormSpec.TS/Interop/FormSpec.Api.Option.js.map +1 -0
- package/FormSpec.TS/Interop/FormSpec.Api.Option.ts.map +1 -0
- package/FormSpec.TS/Interop/FormSpec.Values.Api.Option.js +1367 -0
- package/FormSpec.TS/Interop/FormSpec.Values.Api.Option.js.map +1 -0
- package/FormSpec.TS/Interop/FormSpec.Values.Api.Option.ts.map +1 -0
- package/FormSpec.TS/Logging/LogTypes.js +347 -0
- package/FormSpec.TS/Logging/LogTypes.js.map +1 -0
- package/FormSpec.TS/Logging/LogTypes.ts.map +1 -0
- package/FormSpec.TS/Migrator.js +230 -0
- package/FormSpec.TS/Migrator.js.map +1 -0
- package/FormSpec.TS/Migrator.ts.map +1 -0
- package/FormSpec.TS/PathwayDataExtractor.js +361 -0
- package/FormSpec.TS/PathwayDataExtractor.js.map +1 -0
- package/FormSpec.TS/PathwayDataExtractor.ts.map +1 -0
- package/FormSpec.TS/PathwayExecutor.js +1321 -0
- package/FormSpec.TS/PathwayExecutor.js.map +1 -0
- package/FormSpec.TS/PathwayExecutor.ts.map +1 -0
- package/FormSpec.TS/PathwayValidator.js +346 -0
- package/FormSpec.TS/PathwayValidator.js.map +1 -0
- package/FormSpec.TS/PathwayValidator.ts.map +1 -0
- package/FormSpec.TS/PluginInterface.js +171 -0
- package/FormSpec.TS/PluginInterface.js.map +1 -0
- package/FormSpec.TS/PluginInterface.ts.map +1 -0
- package/FormSpec.TS/Prelude.js +59 -0
- package/FormSpec.TS/Prelude.js.map +1 -0
- package/FormSpec.TS/Prelude.ts.map +1 -0
- package/FormSpec.TS/Renderers/FormSpecMarkdownRenderer.js +958 -0
- package/FormSpec.TS/Renderers/FormSpecMarkdownRenderer.js.map +1 -0
- package/FormSpec.TS/Renderers/FormSpecMarkdownRenderer.ts.map +1 -0
- package/FormSpec.TS/Renderers/MermaidRenderer.js +228 -0
- package/FormSpec.TS/Renderers/MermaidRenderer.js.map +1 -0
- package/FormSpec.TS/Renderers/MermaidRenderer.ts.map +1 -0
- package/FormSpec.TS/Renderers/PathwayRenderers.js +190 -0
- package/FormSpec.TS/Renderers/PathwayRenderers.js.map +1 -0
- package/FormSpec.TS/Renderers/PathwayRenderers.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Base.fs +511 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Base.fs.js +437 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Base.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Base.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Error.fs +16 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Error.fs.js +73 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Error.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Error.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Extensions.fs +50 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Extensions.fs.js +72 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Extensions.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Extensions.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Fable.Form.fableproj +28 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Field.fs +24 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Field.fs.js +56 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Field.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Field.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Fable.Form.Simple.fableproj +31 -0
- package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Form.fs +178 -0
- package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Form.fs.js +464 -0
- package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Form.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Form.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Extensions.fs +17 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Hooks.fs +152 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Hooks.fs.js +25 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Hooks.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Hooks.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Types.fableproj +28 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.fs +218 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.fs.js +37 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.Types.fableproj +27 -0
- package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.fs +82 -0
- package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.fs.js +7 -0
- package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/BorderStyle.fs +59 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Colors.fs +154 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Colors.fs.js +32 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Colors.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Colors.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Feliz.fableproj +42 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Fonts.fs +240 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/GridTypes.fs +24 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Html.fs +826 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Interop.fs +83 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Interop.fs.js +292 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Interop.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Interop.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Key.fs +65 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Key.fs.js +229 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Key.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Key.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Length.fs +91 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Locale.fs +876 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Properties.fs +4080 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Properties.fs.js +133 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Properties.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Properties.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/React.fs +656 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/React.fs.js +561 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/React.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/React.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactDOM.fs +25 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactDOM.fs.js +46 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactDOM.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactDOM.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactInterop.js +63 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactInterop.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactTypes.fs +41 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactTypes.fs.js +7 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactTypes.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactTypes.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/StyleTypes.fs +53 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/StyleTypes.fs.js +7 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/StyleTypes.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/StyleTypes.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Styles.fs +5740 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Svg.fs +1455 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Svg.fs.js +39 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Svg.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Svg.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/TextDecorationLine.fs +13 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/TextDecorationStyle.fs +33 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Transform.fs +181 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/TransformOrigin.fs +17 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/TransitionProperty.fs +162 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Types.fs +13 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Types.fs.js +7 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Types.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Types.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Decode.fs +1768 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Decode.fs.js +2337 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Decode.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Decode.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs +811 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs.js +465 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Extra.fs +47 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Extra.fs.js +18 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Extra.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Extra.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Thoth.Json.fableproj +34 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Types.fs +68 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Types.fs.js +355 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Types.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Types.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/project_cracked.json +1 -0
- package/FormSpec.d.ts +1257 -0
- package/FormSpecHelpers.d.ts +50 -0
- package/Helpers.d.ts +147 -0
- package/Interfaces.d.ts +70 -0
- package/Interop/FormSpec.Api.Helpers.d.ts +247 -0
- package/Interop/FormSpec.Api.Helpers.d.ts.map +1 -0
- package/Interop/FormSpec.Api.Option.d.ts +384 -0
- package/Interop/FormSpec.Api.Option.d.ts.map +1 -0
- package/Interop/FormSpec.Values.Api.Option.d.ts +324 -0
- package/Interop/FormSpec.Values.Api.Option.d.ts.map +1 -0
- package/Migrator.d.ts +59 -0
- package/PathwayDataExtractor.d.ts +19 -0
- package/PathwayExecutor.d.ts +210 -0
- package/PathwayValidator.d.ts +52 -0
- package/PluginInterface.d.ts +36 -0
- package/Prelude.d.ts +11 -0
- package/README.TS.md +622 -0
- package/README.md +85 -0
- package/package.json +39 -0
- package/src/Components/HelloComponent.ts +48 -0
- package/src/Components/HelloComponent.ts.map +1 -0
- package/src/Designer.ts +389 -0
- package/src/Designer.ts.map +1 -0
- package/src/FormSpec.ts +3114 -0
- package/src/FormSpec.ts.map +1 -0
- package/src/FormSpecHelpers.ts +374 -0
- package/src/FormSpecHelpers.ts.map +1 -0
- package/src/Helpers.ts +765 -0
- package/src/Helpers.ts.map +1 -0
- package/src/Interfaces.ts +166 -0
- package/src/Interfaces.ts.map +1 -0
- package/src/Interop/FormSpec.Api.Helpers.ts +872 -0
- package/src/Interop/FormSpec.Api.Helpers.ts.map +1 -0
- package/src/Interop/FormSpec.Api.Option.ts +1618 -0
- package/src/Interop/FormSpec.Api.Option.ts.map +1 -0
- package/src/Interop/FormSpec.Values.Api.Option.ts +1214 -0
- package/src/Interop/FormSpec.Values.Api.Option.ts.map +1 -0
- package/src/Logging/LogTypes.ts +212 -0
- package/src/Logging/LogTypes.ts.map +1 -0
- package/src/Migrator.ts +156 -0
- package/src/Migrator.ts.map +1 -0
- package/src/PathwayDataExtractor.ts +290 -0
- package/src/PathwayDataExtractor.ts.map +1 -0
- package/src/PathwayExecutor.ts +1102 -0
- package/src/PathwayExecutor.ts.map +1 -0
- package/src/PathwayValidator.ts +244 -0
- package/src/PathwayValidator.ts.map +1 -0
- package/src/PluginInterface.ts +79 -0
- package/src/PluginInterface.ts.map +1 -0
- package/src/Prelude.ts +21 -0
- package/src/Prelude.ts.map +1 -0
- package/src/Renderers/FormSpecMarkdownRenderer.ts +874 -0
- package/src/Renderers/FormSpecMarkdownRenderer.ts.map +1 -0
- package/src/Renderers/MermaidRenderer.ts +218 -0
- package/src/Renderers/MermaidRenderer.ts.map +1 -0
- package/src/Renderers/PathwayRenderers.ts +200 -0
- 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
|
+
|