@form-engine-ts/core 4.7.0 → 5.0.0

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 CHANGED
@@ -52,6 +52,9 @@ Required locales cover every source text that exists on the form, its fields, op
52
52
  safe maximum-length corrections while purging unregistered locale content. Pass
53
53
  `{ policy: { allowedLocales, maxLocales } }` to `populateSchemaTranslations` to reject inadmissible targets before the
54
54
  translation adapter runs.
55
+ `normalizeLocale(locale)` returns the canonical BCP 47 tag, accepts underscore-separated compatibility input such as
56
+ `ja_JP`, and returns `null` for invalid tags. Schema validation, sanitization, locale policy checks, and translation
57
+ slot lookup use this same normalization so equivalent locale spellings cannot bypass constraints.
55
58
 
56
59
  Fields can use a `displayRule` with nested `all`/`any` condition groups and `show` or `hide` actions. Supported
57
60
  operators include equality, containment, emptiness, and numeric comparisons; the legacy `displayCondition` and
@@ -96,6 +99,11 @@ const i18nextAdapter: TranslationAdapter = {
96
99
  };
97
100
  ```
98
101
 
102
+ Core also exports the fully typed `FormEngineTranslationKey` union, `JA_MESSAGES`, `EN_MESSAGES`, and
103
+ `createFormEngineTranslator`. The built-in translator defaults to Japanese, falls back to English, accepts partial
104
+ custom catalogs, formats `{{placeholder}}` values, and returns an empty string for an unresolved key instead of
105
+ exposing the key itself.
106
+
99
107
  Translation callbacks receive `nodeMetadata` and `existingTranslationMetadata` separately. The deprecated `metadata`
100
108
  slot property remains an alias for `nodeMetadata` during migration.
101
109
 
@@ -120,6 +128,23 @@ const submissions = await storage.listSubmissions("contact", 1, range);
120
128
 
121
129
  Results are ordered by `submittedAt`, then submission ID. Both boundaries are inclusive.
122
130
 
131
+ Submission metadata can be strongly typed at the application boundary:
132
+
133
+ ```ts
134
+ import { createSubmission, validateSubmission } from "@form-engine-ts/core";
135
+
136
+ const submission = createSubmission<{ deckId: string; piiConfirmed: boolean }>({
137
+ formId: "guide",
138
+ formVersion: 1,
139
+ answers: { title: "Welcome" },
140
+ metadata: { deckId: "deck_123", piiConfirmed: false }
141
+ });
142
+ submission.metadata.deckId;
143
+ const validation = validateSubmission(schema, submission, { privacyEngine });
144
+ ```
145
+
146
+ `validateSubmission` returns one serializable result containing field errors, form errors, and optional PII findings.
147
+
123
148
  ## Versioning, incremental analytics, and paged storage
124
149
 
125
150
  `cloneVersionToDraft`, asynchronous `publishDraft`, and `deleteDraft` implement revision-checked version transitions as
@@ -150,6 +175,13 @@ may push supported nodes to their native query language while preserving identic
150
175
  implement `listTextAnswerPage` expose stable cursor pagination over individual text answers.
151
176
  `TextAnswerPageQueryOptions.fieldIds` can select multiple free-text fields for item-level paging.
152
177
 
178
+ The `paginateWithFilter` helper in `@form-engine-ts/storage` continues fetching native pages until `pageSize` matching
179
+ items are collected or the source is exhausted. `totalScannedCount` makes post-filter work observable and
180
+ `maxScanPages` bounds low-density scans.
181
+
182
+ `commitVersionTransition` accepts a typed `domainData` value and carries it through optional before/after hooks and the
183
+ persistence adapter without interpreting or modifying it.
184
+
153
185
  `iterateSubmissionPages(adapter, formId, query, options)` safely traverses every page as an async generator. It supports
154
186
  `pageSize`, `maxItems`, and `AbortSignal`, continues through empty pages with a next cursor, and rejects missing or cyclic
155
187
  cursors instead of looping indefinitely. Publish transition validation also rejects mismatched form IDs, non-Published