@form-engine-ts/core 5.0.1 → 6.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
@@ -56,6 +56,11 @@ translation adapter runs.
56
56
  `ja_JP`, and returns `null` for invalid tags. Schema validation, sanitization, locale policy checks, and translation
57
57
  slot lookup use this same normalization so equivalent locale spellings cannot bypass constraints.
58
58
 
59
+ Submissions use `values` as their canonical answer property. `toFormSubmissionWire` and
60
+ `fromFormSubmissionWire` preserve the optional submission `locale` across validated wire payloads. Legacy payloads with
61
+ `answers` are isolated under `LegacyFormSubmission` and `fromLegacyFormSubmission` in the compatibility namespace.
62
+ `serializeSubmissionError` and `deserializeSubmissionError` provide the JSON boundary for `FormSubmissionError`.
63
+
59
64
  Fields can use a `displayRule` with nested `all`/`any` condition groups and `show` or `hide` actions. Supported
60
65
  operators include equality, containment, emptiness, and numeric comparisons; the legacy `displayCondition` and
61
66
  `not_empty` forms remain supported. `submissionSettings` can enable pre-submit confirmation and select its
package/dist/index.cjs CHANGED
@@ -22,6 +22,9 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  DEFAULT_FIELD_TYPE_DEFINITIONS: () => DEFAULT_FIELD_TYPE_DEFINITIONS,
24
24
  EN_MESSAGES: () => EN_MESSAGES,
25
+ FormSubmissionError: () => FormSubmissionError,
26
+ FormSubmissionMetadataSchema: () => FormSubmissionMetadataSchema,
27
+ FormSubmissionWireSchema: () => FormSubmissionWireSchema,
25
28
  JA_MESSAGES: () => JA_MESSAGES,
26
29
  aggregateResponses: () => aggregateResponses,
27
30
  applyTransitionPlan: () => applyTransitionPlan,
@@ -48,6 +51,7 @@ __export(index_exports, {
48
51
  decodeSubmissionCursor: () => decodeSubmissionCursor,
49
52
  decodeTextAnswerCursor: () => decodeTextAnswerCursor,
50
53
  deleteDraft: () => deleteDraft,
54
+ deserializeSubmissionError: () => deserializeSubmissionError,
51
55
  dispatchWebhook: () => dispatchWebhook,
52
56
  encodeStorageSubmissionCursor: () => encodeStorageSubmissionCursor,
53
57
  encodeStorageTextAnswerCursor: () => encodeStorageTextAnswerCursor,
@@ -56,6 +60,8 @@ __export(index_exports, {
56
60
  escapeCsvCell: () => escapeCsvCell,
57
61
  exportResponsesToCsv: () => exportResponsesToCsv,
58
62
  exportResponsesToCsvStream: () => exportResponsesToCsvStream,
63
+ fromFormSubmissionWire: () => fromFormSubmissionWire,
64
+ fromLegacyFormSubmission: () => fromLegacyFormSubmission,
59
65
  getTranslationStatus: () => getTranslationStatus,
60
66
  isDisplayConditionGroupSatisfied: () => isDisplayConditionGroupSatisfied,
61
67
  isDisplayConditionSatisfied: () => isDisplayConditionSatisfied,
@@ -77,6 +83,8 @@ __export(index_exports, {
77
83
  resolveLocalizedSchema: () => resolveLocalizedSchema,
78
84
  sanitizeSchema: () => sanitizeSchema,
79
85
  selectVisibleAnswers: () => selectVisibleAnswers,
86
+ serializeSubmissionError: () => serializeSubmissionError,
87
+ toFormSubmissionWire: () => toFormSubmissionWire,
80
88
  transformFieldType: () => transformFieldType,
81
89
  validateAnswers: () => validateAnswers,
82
90
  validateFormSchema: () => validateFormSchema,
@@ -1474,7 +1482,7 @@ function aggregateResponses(schema, submissions) {
1474
1482
  function responseValues(submission) {
1475
1483
  if (typeof submission !== "object" || submission === null) return void 0;
1476
1484
  if ("values" in submission) return submission.values;
1477
- return "answers" in submission ? submission.answers : void 0;
1485
+ return submission.answers;
1478
1486
  }
1479
1487
  function responseIdentifier(submission) {
1480
1488
  if (typeof submission !== "object" || submission === null) return "<unknown>";
@@ -1670,14 +1678,17 @@ function serializeValue(value) {
1670
1678
  }
1671
1679
  function asFormResponse(submission) {
1672
1680
  if (!("values" in submission)) return submission;
1681
+ const metadata = submission.metadata === void 0 ? void 0 : Object.fromEntries(
1682
+ Object.entries(submission.metadata).filter((entry) => entry[1] !== void 0)
1683
+ );
1673
1684
  return {
1674
1685
  responseId: submission.id,
1675
1686
  formId: submission.formId,
1676
- sourceLocale: submission.locale,
1687
+ ...submission.locale === void 0 ? {} : { sourceLocale: submission.locale },
1677
1688
  formVersion: submission.formVersion,
1678
1689
  answers: submission.values,
1679
1690
  submittedAt: submission.submittedAt,
1680
- ...submission.metadata === void 0 ? {} : { metadata: submission.metadata },
1691
+ ...metadata === void 0 ? {} : { metadata },
1681
1692
  ...submission.translationMetadata === void 0 ? {} : { translationMetadata: submission.translationMetadata }
1682
1693
  };
1683
1694
  }
@@ -1686,15 +1697,28 @@ function serializeUnknown(value) {
1686
1697
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
1687
1698
  return JSON.stringify(value);
1688
1699
  }
1700
+ function submissionWithMetadata(submission) {
1701
+ return { ...submission, metadata: submission.metadata ?? {} };
1702
+ }
1689
1703
  async function* exportResponsesToCsvStream(schema, submissions, options = {}) {
1690
1704
  assertValidFormSchema(schema);
1691
1705
  const includeDefaultColumns = options.includeDefaultColumns ?? true;
1692
1706
  const customColumns = options.columns ?? [];
1707
+ const contractColumns = options.customColumns ?? [];
1708
+ const includeLocale = options.includeLocale ?? true;
1709
+ const includePiiStatus = options.includePiiStatus ?? false;
1693
1710
  const headers = [
1694
- ...includeDefaultColumns ? ["submissionId", "submittedAt", "locale", ...schema.fields.map((field) => field.id)] : [],
1695
- ...customColumns.map((column) => column.header)
1711
+ ...includeDefaultColumns ? [
1712
+ "submissionId",
1713
+ "submittedAt",
1714
+ ...includeLocale ? ["locale"] : [],
1715
+ ...includePiiStatus ? ["piiStatus"] : [],
1716
+ ...schema.fields.map((field) => field.id)
1717
+ ] : [],
1718
+ ...customColumns.map((column) => column.header),
1719
+ ...contractColumns.map((column) => column.header)
1696
1720
  ];
1697
- const neutralizeFormulas = options.neutralizeFormulas ?? true;
1721
+ const neutralizeFormulas = options.preventFormulaInjection ?? options.neutralizeFormulas ?? true;
1698
1722
  const header = headers.map((value) => escapeCsvCell(value, neutralizeFormulas)).join(",");
1699
1723
  yield `${options.withBom ?? true ? "\uFEFF" : ""}${header}`;
1700
1724
  for await (const submission of submissions) {
@@ -1703,10 +1727,12 @@ async function* exportResponsesToCsvStream(schema, submissions, options = {}) {
1703
1727
  const response = asFormResponse(submission);
1704
1728
  const answers = response.answers;
1705
1729
  const visible = selectVisibleAnswers(schema, answers);
1730
+ const piiStatus = response.metadata?.piiConfirmed === true ? "confirmed" : "unconfirmed";
1706
1731
  const defaultCells = includeDefaultColumns ? [
1707
1732
  response.responseId,
1708
1733
  response.submittedAt,
1709
- response.sourceLocale ?? "",
1734
+ ...includeLocale ? [response.sourceLocale ?? ""] : [],
1735
+ ...includePiiStatus ? [piiStatus] : [],
1710
1736
  ...schema.fields.map((field) => serializeUnknown(visible[field.id]))
1711
1737
  ] : [];
1712
1738
  const context = {
@@ -1716,8 +1742,9 @@ async function* exportResponsesToCsvStream(schema, submissions, options = {}) {
1716
1742
  schema
1717
1743
  };
1718
1744
  const customCells = await Promise.all(customColumns.map((column) => column.getValue(context)));
1745
+ const contractCells = "values" in submission ? contractColumns.map((column) => column.getValue(submissionWithMetadata(submission), schema)) : contractColumns.map(() => void 0);
1719
1746
  yield `\r
1720
- ${[...defaultCells, ...customCells].map((value) => escapeCsvCell(value, neutralizeFormulas)).join(",")}`;
1747
+ ${[...defaultCells, ...customCells, ...contractCells].map((value) => escapeCsvCell(value, neutralizeFormulas)).join(",")}`;
1721
1748
  }
1722
1749
  }
1723
1750
  function isWebWritableStream(writable) {
@@ -1774,23 +1801,68 @@ function exportResponsesToCsv(schema, responses, options = {}) {
1774
1801
  throw new TypeError(`Submission ${response.id} does not match ${schema.id}@${schema.version}.`);
1775
1802
  }
1776
1803
  }
1804
+ const includeLocale = options.includeLocale ?? true;
1805
+ const includePiiStatus = options.includePiiStatus ?? false;
1806
+ const customColumns = options.customColumns ?? [];
1807
+ const headers = [
1808
+ "submissionId",
1809
+ "submittedAt",
1810
+ ...includeLocale ? ["locale"] : [],
1811
+ ...includePiiStatus ? ["piiStatus"] : [],
1812
+ ...schema.fields.map((field) => field.id),
1813
+ ...customColumns.map((column) => column.header)
1814
+ ];
1777
1815
  const rows = [
1778
- ["submissionId", "submittedAt", "locale", ...schema.fields.map((field) => field.id)],
1816
+ headers,
1779
1817
  ...responses.map((response) => {
1780
1818
  const visible = selectVisibleAnswers(schema, response.values);
1819
+ const piiStatus = response.metadata?.piiConfirmed === true ? "confirmed" : "unconfirmed";
1820
+ const submissionForCustomColumns = submissionWithMetadata(response);
1781
1821
  return [
1782
1822
  response.id,
1783
1823
  response.submittedAt,
1784
- response.locale,
1785
- ...schema.fields.map((field) => serializeValue(visible[field.id]))
1824
+ ...includeLocale ? [response.locale] : [],
1825
+ ...includePiiStatus ? [piiStatus] : [],
1826
+ ...schema.fields.map((field) => serializeValue(visible[field.id])),
1827
+ ...customColumns.map((column) => column.getValue(submissionForCustomColumns, schema))
1786
1828
  ];
1787
1829
  })
1788
1830
  ];
1789
- const neutralizeFormulas = options.neutralizeFormulas ?? true;
1831
+ const neutralizeFormulas = options.preventFormulaInjection ?? options.neutralizeFormulas ?? true;
1790
1832
  const csv = rows.map((row) => row.map((cell) => escapeCsvCell(cell, neutralizeFormulas)).join(",")).join("\r\n");
1791
- return options.withBom ?? true ? `\uFEFF${csv}` : csv;
1833
+ return options.useBom ?? options.withBom ?? true ? `\uFEFF${csv}` : csv;
1792
1834
  }
1793
1835
 
1836
+ // src/compat/legacy.ts
1837
+ var fromLegacyFormSubmission = (legacy) => {
1838
+ const { id, formId, formVersion, answers, locale, metadata, submittedAt, schemaRevision } = legacy;
1839
+ return {
1840
+ id,
1841
+ formId,
1842
+ formVersion,
1843
+ values: { ...answers },
1844
+ ...locale === void 0 ? {} : { locale },
1845
+ metadata,
1846
+ submittedAt,
1847
+ ...schemaRevision === void 0 ? {} : { schemaRevision }
1848
+ };
1849
+ };
1850
+
1851
+ // src/errors.ts
1852
+ var FormSubmissionError = class extends Error {
1853
+ payload;
1854
+ constructor(payload) {
1855
+ super(payload.messageKey);
1856
+ this.name = "FormSubmissionError";
1857
+ this.payload = payload;
1858
+ }
1859
+ toJSON() {
1860
+ return this.payload;
1861
+ }
1862
+ };
1863
+ var serializeSubmissionError = (error) => error.toJSON();
1864
+ var deserializeSubmissionError = (json) => new FormSubmissionError(json);
1865
+
1794
1866
  // src/events.ts
1795
1867
  function bytesToHex(bytes) {
1796
1868
  return [...new Uint8Array(bytes)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
@@ -2113,7 +2185,20 @@ var EN_MESSAGES = Object.freeze({
2113
2185
  "workspace.errors.maxLocalesExceeded": "The maximum number of locales ({{max}}) has been reached.",
2114
2186
  "workspace.errors.readOnly": "This workspace is read-only.",
2115
2187
  "workspace.errors.adapterNotConfigured": "A translation adapter is not configured.",
2116
- "workspace.errors.translationFailed": "Translation failed."
2188
+ "workspace.errors.translationFailed": "Translation failed.",
2189
+ "workspace.header.title": "Translation workspace",
2190
+ "workspace.header.sourceLocale": "Source language",
2191
+ "workspace.header.targetLocale": "Target language",
2192
+ "workspace.header.translateAll": "Translate all",
2193
+ "workspace.header.progress": "{{translated}}/{{total}} translated ({{percent}}%)",
2194
+ "workspace.slot.sourceText": "Source",
2195
+ "workspace.slot.translatedText": "Translation",
2196
+ "workspace.slot.translateSingle": "Translate this slot",
2197
+ "workspace.slot.revertManual": "Revert manual translation",
2198
+ "workspace.confirm.removeLocaleTitle": "Remove language?",
2199
+ "workspace.confirm.removeLocaleMessage": "This will remove {{locale}} and its translations.",
2200
+ "workspace.empty.noTargetLocales": "No target languages are configured.",
2201
+ "workspace.empty.noSlotsToTranslate": "There are no translation slots for this language."
2117
2202
  });
2118
2203
 
2119
2204
  // src/i18n/catalogs/ja.ts
@@ -2285,7 +2370,20 @@ var JA_MESSAGES = Object.freeze({
2285
2370
  "workspace.errors.maxLocalesExceeded": "\u767B\u9332\u53EF\u80FD\u306A\u6700\u5927\u8A00\u8A9E\u6570 ({{max}}) \u306B\u9054\u3057\u307E\u3057\u305F\u3002",
2286
2371
  "workspace.errors.readOnly": "\u8AAD\u307F\u53D6\u308A\u5C02\u7528\u30E2\u30FC\u30C9\u306E\u305F\u3081\u5909\u66F4\u3067\u304D\u307E\u305B\u3093\u3002",
2287
2372
  "workspace.errors.adapterNotConfigured": "\u7FFB\u8A33\u30A2\u30C0\u30D7\u30BF\u30FC\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002",
2288
- "workspace.errors.translationFailed": "\u7FFB\u8A33\u51E6\u7406\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002"
2373
+ "workspace.errors.translationFailed": "\u7FFB\u8A33\u51E6\u7406\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002",
2374
+ "workspace.header.title": "\u591A\u8A00\u8A9E\u7FFB\u8A33\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9",
2375
+ "workspace.header.sourceLocale": "\u5143\u8A00\u8A9E",
2376
+ "workspace.header.targetLocale": "\u7FFB\u8A33\u8A00\u8A9E",
2377
+ "workspace.header.translateAll": "\u4E00\u62EC\u81EA\u52D5\u7FFB\u8A33",
2378
+ "workspace.header.progress": "{{translated}}/{{total}} \u7FFB\u8A33\u6E08\u307F ({{percent}}%)",
2379
+ "workspace.slot.sourceText": "\u539F\u6587",
2380
+ "workspace.slot.translatedText": "\u7FFB\u8A33\u6587",
2381
+ "workspace.slot.translateSingle": "\u3053\u306E\u9805\u76EE\u3092\u7FFB\u8A33",
2382
+ "workspace.slot.revertManual": "\u624B\u52D5\u7FFB\u8A33\u3092\u5143\u306B\u623B\u3059",
2383
+ "workspace.confirm.removeLocaleTitle": "\u8A00\u8A9E\u3092\u524A\u9664\u3057\u307E\u3059\u304B\uFF1F",
2384
+ "workspace.confirm.removeLocaleMessage": "{{locale}} \u3068\u305D\u306E\u7FFB\u8A33\u3092\u524A\u9664\u3057\u307E\u3059\u3002",
2385
+ "workspace.empty.noTargetLocales": "\u7FFB\u8A33\u5148\u306E\u8A00\u8A9E\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002",
2386
+ "workspace.empty.noSlotsToTranslate": "\u3053\u306E\u8A00\u8A9E\u306B\u306F\u7FFB\u8A33\u9805\u76EE\u304C\u3042\u308A\u307E\u305B\u3093\u3002"
2289
2387
  });
2290
2388
 
2291
2389
  // src/i18n/translator.ts
@@ -2347,14 +2445,17 @@ async function paginateWithFilter(params) {
2347
2445
  return { items: collected, hasMore: false, totalScannedCount };
2348
2446
  }
2349
2447
  function asFormResponse2(submission) {
2448
+ const metadata = submission.metadata === void 0 ? void 0 : Object.fromEntries(
2449
+ Object.entries(submission.metadata).filter((entry) => entry[1] !== void 0)
2450
+ );
2350
2451
  return {
2351
2452
  responseId: submission.id,
2352
2453
  formId: submission.formId,
2353
2454
  formVersion: submission.formVersion,
2354
- sourceLocale: submission.locale,
2455
+ ...submission.locale === void 0 ? {} : { sourceLocale: submission.locale },
2355
2456
  answers: submission.values,
2356
2457
  submittedAt: submission.submittedAt,
2357
- ...submission.metadata === void 0 ? {} : { metadata: submission.metadata }
2458
+ ...metadata === void 0 ? {} : { metadata }
2358
2459
  };
2359
2460
  }
2360
2461
  async function* iterateSubmissionPages(adapter, formId, queryOptions = {}, options = {}) {
@@ -2574,6 +2675,20 @@ function matchesSubmissionPageFilters(submission, options) {
2574
2675
  );
2575
2676
  }
2576
2677
 
2678
+ // src/schemas/submission.zod.ts
2679
+ var import_zod = require("zod");
2680
+ var FormSubmissionMetadataSchema = import_zod.z.record(import_zod.z.string(), import_zod.z.unknown());
2681
+ var FormSubmissionWireSchema = import_zod.z.object({
2682
+ id: import_zod.z.string().min(1),
2683
+ formId: import_zod.z.string().min(1),
2684
+ formVersion: import_zod.z.number().int().positive(),
2685
+ values: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()),
2686
+ locale: import_zod.z.string().min(1).optional(),
2687
+ metadata: FormSubmissionMetadataSchema,
2688
+ submittedAt: import_zod.z.string().datetime(),
2689
+ schemaRevision: import_zod.z.number().int().optional()
2690
+ });
2691
+
2577
2692
  // src/validation.ts
2578
2693
  var DEFAULT_MESSAGES = {
2579
2694
  required: "validation.required",
@@ -2754,6 +2869,33 @@ function toFormValues(answers) {
2754
2869
  function isFormValue(value) {
2755
2870
  return value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || Array.isArray(value) && value.every((item) => typeof item === "string");
2756
2871
  }
2872
+ function toFormSubmissionWire(submission) {
2873
+ const { id, formId, formVersion, values, locale, metadata, submittedAt, schemaRevision } = submission;
2874
+ return {
2875
+ id,
2876
+ formId,
2877
+ formVersion,
2878
+ values: { ...values },
2879
+ ...locale === void 0 ? {} : { locale },
2880
+ metadata: { ...metadata ?? {} },
2881
+ submittedAt,
2882
+ ...schemaRevision === void 0 ? {} : { schemaRevision }
2883
+ };
2884
+ }
2885
+ function fromFormSubmissionWire(wire) {
2886
+ const { id, formId, formVersion, values, locale, metadata, submittedAt, schemaRevision } = wire;
2887
+ const canonicalMetadata = { ...metadata };
2888
+ return {
2889
+ id,
2890
+ formId,
2891
+ formVersion,
2892
+ values: { ...values },
2893
+ ...locale === void 0 ? {} : { locale },
2894
+ metadata: canonicalMetadata,
2895
+ submittedAt,
2896
+ ...schemaRevision === void 0 ? {} : { schemaRevision }
2897
+ };
2898
+ }
2757
2899
  function createSubmission(schemaOrInput, values, options) {
2758
2900
  if ("answers" in schemaOrInput) {
2759
2901
  const input = schemaOrInput;
@@ -2773,7 +2915,6 @@ function createSubmission(schemaOrInput, values, options) {
2773
2915
  formVersion: input.formVersion,
2774
2916
  locale: "",
2775
2917
  values: Object.freeze(cloneValues(toFormValues(answers))),
2776
- answers,
2777
2918
  metadata: input.metadata,
2778
2919
  submittedAt,
2779
2920
  ...input.schemaRevision === void 0 ? {} : { schemaRevision: input.schemaRevision }
@@ -2800,7 +2941,6 @@ function createSubmission(schemaOrInput, values, options) {
2800
2941
  formVersion: schema.version,
2801
2942
  locale: options.locale,
2802
2943
  values: Object.freeze(cloneValues(visibleValues)),
2803
- answers: Object.freeze({ ...visibleValues }),
2804
2944
  submittedAt: options.submittedAt,
2805
2945
  ...options.metadata === void 0 ? {} : { metadata: Object.freeze({ ...options.metadata }) },
2806
2946
  ...options.translationMetadata === void 0 ? {} : { translationMetadata: Object.freeze({ ...options.translationMetadata }) }
@@ -3177,18 +3317,20 @@ var migrateSchemaTranslationMetadata = (schema, migratorOrOptions) => {
3177
3317
  };
3178
3318
  };
3179
3319
  var removeLocaleFromSchema = (schema, localeToRemove) => {
3180
- if (localeToRemove === schema.defaultLocale) {
3320
+ const normalizedLocaleToRemove = normalizeLocale(localeToRemove) ?? localeToRemove;
3321
+ const normalizedDefaultLocale = schema.defaultLocale === void 0 ? void 0 : normalizeLocale(schema.defaultLocale) ?? schema.defaultLocale;
3322
+ if (normalizedLocaleToRemove === normalizedDefaultLocale) {
3181
3323
  throw new Error(`Cannot remove defaultLocale: ${localeToRemove}`);
3182
3324
  }
3183
- const form = removeLocalizedNodeLocale(schema, localeToRemove);
3325
+ const form = removeLocalizedNodeLocale(schema, normalizedLocaleToRemove);
3184
3326
  const fields = schema.fields.map((field) => {
3185
- const localizedField = removeLocalizedNodeLocale(field, localeToRemove);
3327
+ const localizedField = removeLocalizedNodeLocale(field, normalizedLocaleToRemove);
3186
3328
  if (!("options" in localizedField)) return localizedField;
3187
3329
  return {
3188
3330
  ...localizedField,
3189
3331
  options: localizedField.options.map((option) => {
3190
- const translations = removeLocaleRecord(option.translations, localeToRemove);
3191
- const translationMetadata = removeLocaleRecord(option.translationMetadata, localeToRemove);
3332
+ const translations = removeLocaleRecord(option.translations, normalizedLocaleToRemove);
3333
+ const translationMetadata = removeLocaleRecord(option.translationMetadata, normalizedLocaleToRemove);
3192
3334
  const { translations: _translations, translationMetadata: _translationMetadata, ...base } = option;
3193
3335
  return {
3194
3336
  ...base,
@@ -3198,10 +3340,12 @@ var removeLocaleFromSchema = (schema, localeToRemove) => {
3198
3340
  })
3199
3341
  };
3200
3342
  });
3201
- const pages = schema.pages?.map((page) => removeLocalizedNodeLocale(page, localeToRemove));
3343
+ const pages = schema.pages?.map((page) => removeLocalizedNodeLocale(page, normalizedLocaleToRemove));
3202
3344
  return {
3203
3345
  ...form,
3204
- supportedLocales: (schema.supportedLocales ?? []).filter((locale) => locale !== localeToRemove),
3346
+ supportedLocales: (schema.supportedLocales ?? []).filter(
3347
+ (locale) => (normalizeLocale(locale) ?? locale) !== normalizedLocaleToRemove
3348
+ ),
3205
3349
  fields,
3206
3350
  ...pages === void 0 ? {} : { pages }
3207
3351
  };
@@ -3660,6 +3804,9 @@ async function commitVersionTransition(options) {
3660
3804
  0 && (module.exports = {
3661
3805
  DEFAULT_FIELD_TYPE_DEFINITIONS,
3662
3806
  EN_MESSAGES,
3807
+ FormSubmissionError,
3808
+ FormSubmissionMetadataSchema,
3809
+ FormSubmissionWireSchema,
3663
3810
  JA_MESSAGES,
3664
3811
  aggregateResponses,
3665
3812
  applyTransitionPlan,
@@ -3686,6 +3833,7 @@ async function commitVersionTransition(options) {
3686
3833
  decodeSubmissionCursor,
3687
3834
  decodeTextAnswerCursor,
3688
3835
  deleteDraft,
3836
+ deserializeSubmissionError,
3689
3837
  dispatchWebhook,
3690
3838
  encodeStorageSubmissionCursor,
3691
3839
  encodeStorageTextAnswerCursor,
@@ -3694,6 +3842,8 @@ async function commitVersionTransition(options) {
3694
3842
  escapeCsvCell,
3695
3843
  exportResponsesToCsv,
3696
3844
  exportResponsesToCsvStream,
3845
+ fromFormSubmissionWire,
3846
+ fromLegacyFormSubmission,
3697
3847
  getTranslationStatus,
3698
3848
  isDisplayConditionGroupSatisfied,
3699
3849
  isDisplayConditionSatisfied,
@@ -3715,6 +3865,8 @@ async function commitVersionTransition(options) {
3715
3865
  resolveLocalizedSchema,
3716
3866
  sanitizeSchema,
3717
3867
  selectVisibleAnswers,
3868
+ serializeSubmissionError,
3869
+ toFormSubmissionWire,
3718
3870
  transformFieldType,
3719
3871
  validateAnswers,
3720
3872
  validateFormSchema,