@frt-platform/report-core 1.2.0 → 1.2.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.
- package/README.md +193 -49
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `@frt-platform/report-core`
|
|
2
2
|
|
|
3
|
-
Core engine for building, validating, and migrating **report templates** – plus validating **report responses**.
|
|
3
|
+
Core engine for building, validating, and migrating **report templates** – plus validating **report responses** and exporting **JSON Schema**.
|
|
4
4
|
|
|
5
5
|
This package is:
|
|
6
6
|
|
|
@@ -15,9 +15,12 @@ It gives you:
|
|
|
15
15
|
* **Legacy schema migration** (flat `fields` → `sections`, old type names, etc.)
|
|
16
16
|
* **Normalization** helpers to ensure safe IDs & consistent structure
|
|
17
17
|
* **Field defaults** and **ID utilities** you can use to build your own UI
|
|
18
|
-
* **Response validation** based on templates (`
|
|
19
|
-
* **
|
|
18
|
+
* **Response validation** based on templates (`validateReportResponse`)
|
|
19
|
+
* **Conditional logic** for fields (`visibleIf` / `requiredIf`)
|
|
20
|
+
* **Template diffing** (`diffTemplates`) to compare template versions (including ordering)
|
|
20
21
|
* **Type-level response inference** (`InferResponse`) for fully typed responses
|
|
22
|
+
* **Field registry** (`FieldRegistry`) for custom / extensible field types
|
|
23
|
+
* **JSON Schema export** (`exportJSONSchema`) for integration with OpenAPI / external validators
|
|
21
24
|
|
|
22
25
|
It’s the core that powers a flexible incident/report builder, but it’s generic enough to be reused in any app.
|
|
23
26
|
|
|
@@ -27,13 +30,13 @@ It’s the core that powers a flexible incident/report builder, but it’s gener
|
|
|
27
30
|
|
|
28
31
|
```bash
|
|
29
32
|
# npm
|
|
30
|
-
npm install @frt/report-core zod
|
|
33
|
+
npm install @frt-platform/report-core zod
|
|
31
34
|
|
|
32
35
|
# yarn
|
|
33
|
-
yarn add @frt/report-core zod
|
|
36
|
+
yarn add @frt-platform/report-core zod
|
|
34
37
|
|
|
35
38
|
# pnpm
|
|
36
|
-
pnpm add @frt/report-core zod
|
|
39
|
+
pnpm add @frt-platform/report-core zod
|
|
37
40
|
```
|
|
38
41
|
|
|
39
42
|
`zod` is a peer dependency and is used for schema validation & parsing.
|
|
@@ -47,11 +50,12 @@ The core model looks like this:
|
|
|
47
50
|
* A **template** contains multiple **sections**
|
|
48
51
|
* A **section** contains multiple **fields**
|
|
49
52
|
* A **field** has a `type` (short text, long text, number, select, etc.) and optional constraints
|
|
53
|
+
* Fields can have **conditional logic** (`visibleIf`, `requiredIf`)
|
|
50
54
|
|
|
51
55
|
Supported field types:
|
|
52
56
|
|
|
53
57
|
```ts
|
|
54
|
-
import { REPORT_TEMPLATE_FIELD_TYPES } from "@frt/report-core";
|
|
58
|
+
import { REPORT_TEMPLATE_FIELD_TYPES } from "@frt-platform/report-core";
|
|
55
59
|
|
|
56
60
|
console.log(REPORT_TEMPLATE_FIELD_TYPES);
|
|
57
61
|
// [
|
|
@@ -62,9 +66,12 @@ console.log(REPORT_TEMPLATE_FIELD_TYPES);
|
|
|
62
66
|
// "checkbox",
|
|
63
67
|
// "singleSelect",
|
|
64
68
|
// "multiSelect",
|
|
69
|
+
// "repeatGroup", // reserved for repeating groups / fieldsets
|
|
65
70
|
// ]
|
|
66
71
|
```
|
|
67
72
|
|
|
73
|
+
> `repeatGroup` is reserved for repeating fieldsets (e.g. multiple injured people); the core schema knows about it and provides defaults, and the full runtime semantics can be layered on top in your app/React package.
|
|
74
|
+
|
|
68
75
|
---
|
|
69
76
|
|
|
70
77
|
## Quick Start
|
|
@@ -74,7 +81,7 @@ console.log(REPORT_TEMPLATE_FIELD_TYPES);
|
|
|
74
81
|
You can define templates statically or load them from DB / API:
|
|
75
82
|
|
|
76
83
|
```ts
|
|
77
|
-
import type { ReportTemplateSchema } from "@frt/report-core";
|
|
84
|
+
import type { ReportTemplateSchema } from "@frt-platform/report-core";
|
|
78
85
|
|
|
79
86
|
const templateJson: ReportTemplateSchema = {
|
|
80
87
|
version: 1,
|
|
@@ -114,14 +121,14 @@ Use the helpers to safely parse and normalize unknown input:
|
|
|
114
121
|
import {
|
|
115
122
|
parseReportTemplateSchema,
|
|
116
123
|
normalizeReportTemplateSchema,
|
|
117
|
-
} from "@frt/report-core";
|
|
124
|
+
} from "@frt-platform/report-core";
|
|
118
125
|
|
|
119
126
|
const raw = /* from DB, file, API, etc. */ templateJson;
|
|
120
127
|
|
|
121
128
|
// 1) parse + validate (throws on invalid input)
|
|
122
129
|
const parsed = parseReportTemplateSchema(raw);
|
|
123
130
|
|
|
124
|
-
// 2) optional extra normalization step (IDs, trimming, etc.)
|
|
131
|
+
// 2) optional extra normalization step (IDs, trimming, de-duplication, etc.)
|
|
125
132
|
const normalized = normalizeReportTemplateSchema(parsed);
|
|
126
133
|
|
|
127
134
|
console.log(normalized.sections[0].fields[0].id);
|
|
@@ -131,7 +138,7 @@ console.log(normalized.sections[0].fields[0].id);
|
|
|
131
138
|
### 3. Serialize for storage
|
|
132
139
|
|
|
133
140
|
```ts
|
|
134
|
-
import { serializeReportTemplateSchema } from "@frt/report-core";
|
|
141
|
+
import { serializeReportTemplateSchema } from "@frt-platform/report-core";
|
|
135
142
|
|
|
136
143
|
const jsonString = serializeReportTemplateSchema(normalized);
|
|
137
144
|
// ready to store in DB, file, etc.
|
|
@@ -144,7 +151,7 @@ const jsonString = serializeReportTemplateSchema(normalized);
|
|
|
144
151
|
If you have a JSON string (e.g. from a form textarea):
|
|
145
152
|
|
|
146
153
|
```ts
|
|
147
|
-
import { parseReportTemplateSchemaFromString } from "@frt/report-core";
|
|
154
|
+
import { parseReportTemplateSchemaFromString } from "@frt-platform/report-core";
|
|
148
155
|
|
|
149
156
|
try {
|
|
150
157
|
const template = parseReportTemplateSchemaFromString(userInputString);
|
|
@@ -160,33 +167,23 @@ try {
|
|
|
160
167
|
|
|
161
168
|
Once you have a template, you can validate **user-submitted responses** against it.
|
|
162
169
|
|
|
163
|
-
### Runtime
|
|
170
|
+
### Runtime validation
|
|
164
171
|
|
|
165
172
|
```ts
|
|
166
|
-
import {
|
|
167
|
-
buildResponseSchema,
|
|
168
|
-
validateReportResponse,
|
|
169
|
-
} from "@frt/report-core";
|
|
173
|
+
import { validateReportResponse } from "@frt-platform/report-core";
|
|
170
174
|
|
|
171
175
|
const template = /* a valid ReportTemplateSchema */ normalized;
|
|
172
176
|
|
|
173
|
-
// Build a Zod schema for responses
|
|
174
|
-
const responseSchema = buildResponseSchema(template);
|
|
175
|
-
|
|
176
|
-
// Example response object
|
|
177
177
|
const responseData = {
|
|
178
178
|
summary: "Student slipped in the hallway, no serious injuries.",
|
|
179
179
|
status: "Resolved",
|
|
180
180
|
};
|
|
181
181
|
|
|
182
182
|
// Validate (throws ZodError on failure)
|
|
183
|
-
const safeResponse =
|
|
184
|
-
|
|
185
|
-
// Or use the convenience helper:
|
|
186
|
-
const safeResponse2 = validateReportResponse(template, responseData);
|
|
183
|
+
const safeResponse = validateReportResponse(template, responseData);
|
|
187
184
|
```
|
|
188
185
|
|
|
189
|
-
`
|
|
186
|
+
`validateReportResponse` respects:
|
|
190
187
|
|
|
191
188
|
* `required` flags
|
|
192
189
|
* `minLength` / `maxLength` (short/long text)
|
|
@@ -194,6 +191,49 @@ const safeResponse2 = validateReportResponse(template, responseData);
|
|
|
194
191
|
* `minSelections` / `maxSelections` (multiSelect)
|
|
195
192
|
* `options` (singleSelect + multiSelect)
|
|
196
193
|
* `checkbox` semantics (required checkbox must be `true`)
|
|
194
|
+
* **Conditional logic**:
|
|
195
|
+
|
|
196
|
+
* `visibleIf`: if false, the field is treated as invisible and removed from the parsed output
|
|
197
|
+
* `requiredIf`: if true, the field is treated as required for this specific response
|
|
198
|
+
|
|
199
|
+
You can still build a raw schema yourself using the conditional builder:
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
import { buildResponseSchemaWithConditions } from "@frt-platform/report-core";
|
|
203
|
+
|
|
204
|
+
const responseSchema = buildResponseSchemaWithConditions(template, responseData);
|
|
205
|
+
const safeResponse = responseSchema.parse(responseData);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Conditional logic (`visibleIf` / `requiredIf`)
|
|
211
|
+
|
|
212
|
+
Fields can declare conditions that refer to other field values.
|
|
213
|
+
|
|
214
|
+
Example:
|
|
215
|
+
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"id": "injury_details",
|
|
219
|
+
"type": "longText",
|
|
220
|
+
"label": "Describe the injury",
|
|
221
|
+
"visibleIf": { "equals": { "injured": true } },
|
|
222
|
+
"requiredIf": { "equals": { "severity": "High" } }
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Supported condition shapes:
|
|
227
|
+
|
|
228
|
+
* `{"equals": { "fieldId": value } }`
|
|
229
|
+
* `{"any": [cond1, cond2, ...] }`
|
|
230
|
+
* `{"all": [cond1, cond2, ...] }`
|
|
231
|
+
* `{"not": cond }`
|
|
232
|
+
|
|
233
|
+
At runtime:
|
|
234
|
+
|
|
235
|
+
* If `visibleIf` is **false** → field is treated as **invisible**, becomes optional, and is stripped from the validated response.
|
|
236
|
+
* If `requiredIf` is **true** → field is treated as **required** for that specific response.
|
|
197
237
|
|
|
198
238
|
---
|
|
199
239
|
|
|
@@ -202,7 +242,7 @@ const safeResponse2 = validateReportResponse(template, responseData);
|
|
|
202
242
|
If you define templates statically (`as const`), you can get a fully-typed response type from the template:
|
|
203
243
|
|
|
204
244
|
```ts
|
|
205
|
-
import type { InferResponse } from "@frt/report-core";
|
|
245
|
+
import type { InferResponse } from "@frt-platform/report-core";
|
|
206
246
|
|
|
207
247
|
const incidentTemplate = {
|
|
208
248
|
version: 1,
|
|
@@ -278,7 +318,7 @@ import {
|
|
|
278
318
|
CORE_FIELD_DEFAULTS,
|
|
279
319
|
DEFAULT_FIELD_LABEL,
|
|
280
320
|
type ReportTemplateFieldType,
|
|
281
|
-
} from "@frt/report-core";
|
|
321
|
+
} from "@frt-platform/report-core";
|
|
282
322
|
|
|
283
323
|
function createDefaultField(type: ReportTemplateFieldType) {
|
|
284
324
|
const defaults = CORE_FIELD_DEFAULTS[type] ?? {};
|
|
@@ -293,16 +333,63 @@ function createDefaultField(type: ReportTemplateFieldType) {
|
|
|
293
333
|
const field = createDefaultField("shortText");
|
|
294
334
|
```
|
|
295
335
|
|
|
336
|
+
`CORE_FIELD_DEFAULTS` includes basic defaults for:
|
|
337
|
+
|
|
338
|
+
* `shortText`, `longText`, `number`, `date`, `checkbox`, `singleSelect`, `multiSelect`
|
|
339
|
+
* `repeatGroup` (with an empty `fields` array; your builder populates nested fields)
|
|
340
|
+
|
|
296
341
|
This is especially useful in a form builder UI when the user adds a new field of a given type.
|
|
297
342
|
|
|
298
343
|
---
|
|
299
344
|
|
|
345
|
+
## Field Registry (`FieldRegistry`)
|
|
346
|
+
|
|
347
|
+
You can register **custom field types** or override core types at runtime:
|
|
348
|
+
|
|
349
|
+
```ts
|
|
350
|
+
import { FieldRegistry } from "@frt-platform/report-core";
|
|
351
|
+
import { z } from "zod";
|
|
352
|
+
|
|
353
|
+
// Simple example: a "richText" field that behaves like a string
|
|
354
|
+
FieldRegistry.register("richText", {
|
|
355
|
+
defaults: {
|
|
356
|
+
label: "Details",
|
|
357
|
+
placeholder: "Write here...",
|
|
358
|
+
},
|
|
359
|
+
buildResponseSchema: (field) => {
|
|
360
|
+
let schema = z.string();
|
|
361
|
+
|
|
362
|
+
if (typeof field.minLength === "number") {
|
|
363
|
+
schema = schema.min(field.minLength);
|
|
364
|
+
}
|
|
365
|
+
if (typeof field.maxLength === "number") {
|
|
366
|
+
schema = schema.max(field.maxLength);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return field.required ? schema : schema.optional();
|
|
370
|
+
},
|
|
371
|
+
});
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
At validation time, `validateReportResponse` and `buildBaseFieldSchema` will:
|
|
375
|
+
|
|
376
|
+
1. Check the registry for a custom handler.
|
|
377
|
+
2. Use the built-in fallback if none is registered.
|
|
378
|
+
|
|
379
|
+
Use this for:
|
|
380
|
+
|
|
381
|
+
* App-specific field types (e.g. `fileUpload`, `signature`, `mapLocation`)
|
|
382
|
+
* Tenant-specific extensions in a multi-tenant platform
|
|
383
|
+
* Gradually introducing new field behaviors without changing the core package
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
300
387
|
## Generating unique IDs
|
|
301
388
|
|
|
302
389
|
The core package exposes a generic `createUniqueId` helper:
|
|
303
390
|
|
|
304
391
|
```ts
|
|
305
|
-
import { createUniqueId } from "@frt/report-core";
|
|
392
|
+
import { createUniqueId } from "@frt-platform/report-core";
|
|
306
393
|
|
|
307
394
|
const existingSectionIds = ["section-1", "section-2"];
|
|
308
395
|
const newId = createUniqueId("section", existingSectionIds);
|
|
@@ -326,7 +413,7 @@ you can pass them through the migration pipeline:
|
|
|
326
413
|
import {
|
|
327
414
|
migrateLegacySchema,
|
|
328
415
|
parseReportTemplateSchema,
|
|
329
|
-
} from "@frt/report-core";
|
|
416
|
+
} from "@frt-platform/report-core";
|
|
330
417
|
|
|
331
418
|
const legacy = {
|
|
332
419
|
title: "Old template",
|
|
@@ -356,10 +443,10 @@ const parsed = ReportTemplateSchemaValidator.parse(migrated);
|
|
|
356
443
|
|
|
357
444
|
## Diffing templates
|
|
358
445
|
|
|
359
|
-
When you version templates (e.g. editing in a UI), you might want to see what changed between versions. The core exposes a
|
|
446
|
+
When you version templates (e.g. editing in a UI), you might want to see what changed between versions. The core exposes a diff utility:
|
|
360
447
|
|
|
361
448
|
```ts
|
|
362
|
-
import { diffTemplates } from "@frt/report-core";
|
|
449
|
+
import { diffTemplates } from "@frt-platform/report-core";
|
|
363
450
|
|
|
364
451
|
const beforeTemplate = /* old template */;
|
|
365
452
|
const afterTemplate = /* updated template */;
|
|
@@ -368,14 +455,19 @@ const diff = diffTemplates(beforeTemplate, afterTemplate);
|
|
|
368
455
|
|
|
369
456
|
console.log(diff.addedSections);
|
|
370
457
|
console.log(diff.removedSections);
|
|
371
|
-
console.log(diff.
|
|
458
|
+
console.log(diff.reorderedSections);
|
|
459
|
+
console.log(diff.modifiedSections);
|
|
460
|
+
|
|
461
|
+
console.log(diff.addedFields);
|
|
462
|
+
console.log(diff.removedFields);
|
|
463
|
+
console.log(diff.reorderedFields);
|
|
464
|
+
console.log(diff.modifiedFields);
|
|
372
465
|
```
|
|
373
466
|
|
|
374
|
-
`diff.
|
|
467
|
+
`diff.modifiedFields` contains entries like:
|
|
375
468
|
|
|
376
469
|
```ts
|
|
377
470
|
{
|
|
378
|
-
type: "modified",
|
|
379
471
|
sectionId: "section-overview",
|
|
380
472
|
fieldId: "summary",
|
|
381
473
|
before: { label: "What happened?", required: false, ... },
|
|
@@ -392,6 +484,42 @@ Use this for:
|
|
|
392
484
|
* “Changes” tabs in your UI
|
|
393
485
|
* Migration & compatibility warnings
|
|
394
486
|
* Audit trails
|
|
487
|
+
* Showing ordered changes (section/field reorder is explicitly tracked)
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
## JSON Schema export
|
|
492
|
+
|
|
493
|
+
You can export a template as a **JSON Schema** object for use with OpenAPI, Swagger, Postman, or other runtimes that don’t speak TypeScript/Zod.
|
|
494
|
+
|
|
495
|
+
```ts
|
|
496
|
+
import { exportJSONSchema } from "@frt-platform/report-core";
|
|
497
|
+
|
|
498
|
+
const jsonSchema = exportJSONSchema(template);
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
Shape (simplified):
|
|
502
|
+
|
|
503
|
+
```json
|
|
504
|
+
{
|
|
505
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
506
|
+
"type": "object",
|
|
507
|
+
"properties": {
|
|
508
|
+
"summary": { "type": "string", "minLength": 10 },
|
|
509
|
+
"status": { "type": "string", "enum": ["Pending", "Resolved", "Escalated"] }
|
|
510
|
+
},
|
|
511
|
+
"required": ["summary", "status"],
|
|
512
|
+
"additionalProperties": false,
|
|
513
|
+
"x-frt-templateTitle": "Incident follow-up",
|
|
514
|
+
"x-frt-version": 1
|
|
515
|
+
}
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
Key points:
|
|
519
|
+
|
|
520
|
+
* String/number/boolean/array mapping matches the runtime validation semantics.
|
|
521
|
+
* `required` only includes **unconditionally required** fields (no `visibleIf` / `requiredIf`), but we expose conditional logic as vendor extensions.
|
|
522
|
+
* Extra metadata is available under `x-frt-*` keys, e.g. `x-frt-placeholder`, `x-frt-dataClassification`, `x-frt-visibleIf`, `x-frt-requiredIf`.
|
|
395
523
|
|
|
396
524
|
---
|
|
397
525
|
|
|
@@ -406,7 +534,7 @@ import type {
|
|
|
406
534
|
ReportTemplateField,
|
|
407
535
|
ReportTemplateFieldType,
|
|
408
536
|
InferResponse,
|
|
409
|
-
} from "@frt/report-core";
|
|
537
|
+
} from "@frt-platform/report-core";
|
|
410
538
|
```
|
|
411
539
|
|
|
412
540
|
* `ReportTemplateFieldType` – union of all field type strings
|
|
@@ -423,7 +551,7 @@ import {
|
|
|
423
551
|
REPORT_TEMPLATE_FIELD_TYPES,
|
|
424
552
|
DEFAULT_FIELD_LABEL,
|
|
425
553
|
CORE_FIELD_DEFAULTS,
|
|
426
|
-
} from "@frt/report-core";
|
|
554
|
+
} from "@frt-platform/report-core";
|
|
427
555
|
```
|
|
428
556
|
|
|
429
557
|
* `REPORT_TEMPLATE_VERSION: number`
|
|
@@ -442,13 +570,13 @@ import {
|
|
|
442
570
|
parseReportTemplateSchemaFromString,
|
|
443
571
|
normalizeReportTemplateSchema,
|
|
444
572
|
serializeReportTemplateSchema,
|
|
445
|
-
} from "@frt/report-core";
|
|
573
|
+
} from "@frt-platform/report-core";
|
|
446
574
|
```
|
|
447
575
|
|
|
448
576
|
Use the Zod schemas directly if you want:
|
|
449
577
|
|
|
450
578
|
```ts
|
|
451
|
-
import { ReportTemplateSchemaValidator } from "@frt/report-core";
|
|
579
|
+
import { ReportTemplateSchemaValidator } from "@frt-platform/report-core";
|
|
452
580
|
|
|
453
581
|
const result = ReportTemplateSchemaValidator.safeParse(raw);
|
|
454
582
|
if (!result.success) {
|
|
@@ -459,7 +587,7 @@ if (!result.success) {
|
|
|
459
587
|
### Migration
|
|
460
588
|
|
|
461
589
|
```ts
|
|
462
|
-
import { migrateLegacySchema } from "@frt/report-core";
|
|
590
|
+
import { migrateLegacySchema } from "@frt-platform/report-core";
|
|
463
591
|
```
|
|
464
592
|
|
|
465
593
|
Takes `unknown` legacy input and returns a shape better suited for current schema validation.
|
|
@@ -468,16 +596,28 @@ Takes `unknown` legacy input and returns a shape better suited for current schem
|
|
|
468
596
|
|
|
469
597
|
```ts
|
|
470
598
|
import {
|
|
471
|
-
buildResponseSchema,
|
|
472
599
|
validateReportResponse,
|
|
600
|
+
buildResponseSchemaWithConditions,
|
|
473
601
|
type InferResponse,
|
|
474
|
-
} from "@frt/report-core";
|
|
602
|
+
} from "@frt-platform/report-core";
|
|
475
603
|
```
|
|
476
604
|
|
|
477
605
|
### Template diffing
|
|
478
606
|
|
|
479
607
|
```ts
|
|
480
|
-
import { diffTemplates } from "@frt/report-core";
|
|
608
|
+
import { diffTemplates } from "@frt-platform/report-core";
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
### JSON Schema export
|
|
612
|
+
|
|
613
|
+
```ts
|
|
614
|
+
import { exportJSONSchema } from "@frt-platform/report-core";
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
### Field registry
|
|
618
|
+
|
|
619
|
+
```ts
|
|
620
|
+
import { FieldRegistry } from "@frt-platform/report-core";
|
|
481
621
|
```
|
|
482
622
|
|
|
483
623
|
---
|
|
@@ -497,6 +637,7 @@ This package is intentionally minimal. You can layer it into:
|
|
|
497
637
|
* Migrating old template shapes
|
|
498
638
|
* Ensuring consistent data before persisting to a DB
|
|
499
639
|
* Validating report responses before saving them
|
|
640
|
+
* Serving JSON Schema to other services
|
|
500
641
|
|
|
501
642
|
Typical pattern in a full stack app:
|
|
502
643
|
|
|
@@ -518,13 +659,14 @@ Typical pattern in a full stack app:
|
|
|
518
659
|
|
|
519
660
|
* Load templates from DB
|
|
520
661
|
* Use them to render dynamic forms
|
|
521
|
-
* Use `
|
|
662
|
+
* Use `validateReportResponse` / `buildResponseSchemaWithConditions` to validate and normalize responses
|
|
663
|
+
* Use `exportJSONSchema` for interoperability with other stacks
|
|
522
664
|
|
|
523
665
|
---
|
|
524
666
|
|
|
525
667
|
## Roadmap / Extensions (ideas)
|
|
526
668
|
|
|
527
|
-
Things you might add on top (in a separate package, e.g. `@frt/report-react`):
|
|
669
|
+
Things you might add on top (in a separate package, e.g. `@frt-platform/report-react`):
|
|
528
670
|
|
|
529
671
|
* React components for:
|
|
530
672
|
|
|
@@ -536,16 +678,18 @@ Things you might add on top (in a separate package, e.g. `@frt/report-react`):
|
|
|
536
678
|
* File uploads
|
|
537
679
|
* Signature pads
|
|
538
680
|
* Matrix / grid fields
|
|
539
|
-
*
|
|
681
|
+
* Fully-featured `repeatGroup` UI & runtime
|
|
682
|
+
* Richer conditional logic:
|
|
540
683
|
|
|
541
684
|
* `visibleIf`
|
|
542
685
|
* `requiredIf`
|
|
686
|
+
* multi-step branching
|
|
543
687
|
* Multi-language labels & descriptions
|
|
544
688
|
|
|
545
|
-
The core stays simple: **schema + validation + migration +
|
|
689
|
+
The core stays simple: **schema + validation + conditional logic + migration + diffing + registry + JSON Schema export**.
|
|
546
690
|
|
|
547
691
|
---
|
|
548
692
|
|
|
549
693
|
## License
|
|
550
694
|
|
|
551
|
-
MIT – use it in your projects, commercial or not. Contributions welcome.
|
|
695
|
+
MIT – use it in your projects, commercial or not. Contributions welcome.
|