@wix/bex-core 2.325.0 → 2.327.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.
Files changed (29) hide show
  1. package/dist/cjs/hooks/useImport.js +4 -0
  2. package/dist/cjs/hooks/useImport.js.map +1 -1
  3. package/dist/cjs/hooks/useImportConfig.js.map +1 -1
  4. package/dist/cjs/state/ImportState/ImportState.js +181 -10
  5. package/dist/cjs/state/ImportState/ImportState.js.map +1 -1
  6. package/dist/cjs/state/ImportState/detectFieldType.js +140 -0
  7. package/dist/cjs/state/ImportState/detectFieldType.js.map +1 -0
  8. package/dist/cjs/state/ImportState/index.js +6 -0
  9. package/dist/cjs/state/ImportState/index.js.map +1 -1
  10. package/dist/esm/hooks/useImport.js +4 -2
  11. package/dist/esm/hooks/useImport.js.map +1 -1
  12. package/dist/esm/hooks/useImportConfig.js.map +1 -1
  13. package/dist/esm/state/ImportState/ImportState.js +146 -10
  14. package/dist/esm/state/ImportState/ImportState.js.map +1 -1
  15. package/dist/esm/state/ImportState/detectFieldType.js +125 -0
  16. package/dist/esm/state/ImportState/detectFieldType.js.map +1 -0
  17. package/dist/esm/state/ImportState/index.js +1 -0
  18. package/dist/esm/state/ImportState/index.js.map +1 -1
  19. package/dist/types/hooks/useImport.d.ts +3 -1
  20. package/dist/types/hooks/useImport.d.ts.map +1 -1
  21. package/dist/types/hooks/useImportConfig.d.ts +2 -1
  22. package/dist/types/hooks/useImportConfig.d.ts.map +1 -1
  23. package/dist/types/state/ImportState/ImportState.d.ts +57 -2
  24. package/dist/types/state/ImportState/ImportState.d.ts.map +1 -1
  25. package/dist/types/state/ImportState/detectFieldType.d.ts +21 -0
  26. package/dist/types/state/ImportState/detectFieldType.d.ts.map +1 -0
  27. package/dist/types/state/ImportState/index.d.ts +1 -0
  28. package/dist/types/state/ImportState/index.d.ts.map +1 -1
  29. package/package.json +4 -4
@@ -10,6 +10,8 @@ function useCreateImport(params) {
10
10
  fields,
11
11
  bulkUploadItems,
12
12
  backup,
13
+ updateSchema,
14
+ detectColumnType,
13
15
  importModalState,
14
16
  batchSize
15
17
  } = params;
@@ -25,6 +27,8 @@ function useCreateImport(params) {
25
27
  fields,
26
28
  bulkUploadItems,
27
29
  backup,
30
+ updateSchema,
31
+ detectColumnType,
28
32
  collection,
29
33
  importModalState,
30
34
  batchSize,
@@ -1 +1 @@
1
- {"version":3,"names":["_react","require","_providers","_state","useCreateImport","params","fields","bulkUploadItems","backup","importModalState","batchSize","showToast","translate","errorHandler","window","useWixPatternsContainer","collection","useCollectionContext","useCallback","ImportState","downloadCsv","content","fileName","download","encodeURIComponent"],"sources":["../../../src/hooks/useImport.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useWixPatternsContainer, useCollectionContext } from '../providers';\nimport { ModalState, ImportState, BackupFn, BulkUploadItemsFn } from '../state';\nimport { CreateExportAsyncJobRequest } from '@wix/bex-utils/@wix/ambassador-fedinfra-exportservice-v1-export-async-job/types';\nimport { FiltersMap } from '../model';\n\nexport interface UseImportParams {\n fields: CreateExportAsyncJobRequest['fields'];\n bulkUploadItems: BulkUploadItemsFn;\n backup?: BackupFn;\n importModalState: ModalState;\n batchSize?: number;\n}\n\nexport function useCreateImport<T = unknown, F extends FiltersMap = FiltersMap>(params: UseImportParams) {\n const { fields, bulkUploadItems, backup, importModalState, batchSize } = params;\n const { showToast, translate, errorHandler, window } =\n useWixPatternsContainer();\n const collection = useCollectionContext<T, F>();\n\n return useCallback(() => {\n return new ImportState({\n fields,\n bulkUploadItems,\n backup,\n collection,\n importModalState,\n batchSize,\n showToast,\n translate,\n errorHandler,\n downloadCsv: (content, fileName) => {\n window.download(\n `data:text/csv;charset=utf-8,${encodeURIComponent(content)}`,\n fileName,\n );\n },\n });\n }, []);\n}\n"],"mappings":";;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,UAAA,GAAAD,OAAA;AACA,IAAAE,MAAA,GAAAF,OAAA;AAYO,SAASG,eAAeA,CAAiDC,MAAuB,EAAE;EACvG,MAAM;IAAEC,MAAM;IAAEC,eAAe;IAAEC,MAAM;IAAEC,gBAAgB;IAAEC;EAAU,CAAC,GAAGL,MAAM;EAC/E,MAAM;IAAEM,SAAS;IAAEC,SAAS;IAAEC,YAAY;IAAEC;EAAO,CAAC,GAClD,IAAAC,kCAAuB,EAAC,CAAC;EAC3B,MAAMC,UAAU,GAAG,IAAAC,+BAAoB,EAAO,CAAC;EAE/C,OAAO,IAAAC,kBAAW,EAAC,MAAM;IACvB,OAAO,IAAIC,kBAAW,CAAC;MACrBb,MAAM;MACNC,eAAe;MACfC,MAAM;MACNQ,UAAU;MACVP,gBAAgB;MAChBC,SAAS;MACTC,SAAS;MACTC,SAAS;MACTC,YAAY;MACZO,WAAW,EAAEA,CAACC,OAAO,EAAEC,QAAQ,KAAK;QAClCR,MAAM,CAACS,QAAQ,CACb,+BAA+BC,kBAAkB,CAACH,OAAO,CAAC,EAAE,EAC5DC,QACF,CAAC;MACH;IACF,CAAC,CAAC;EACJ,CAAC,EAAE,EAAE,CAAC;AACR","ignoreList":[]}
1
+ {"version":3,"names":["_react","require","_providers","_state","useCreateImport","params","fields","bulkUploadItems","backup","updateSchema","detectColumnType","importModalState","batchSize","showToast","translate","errorHandler","window","useWixPatternsContainer","collection","useCollectionContext","useCallback","ImportState","downloadCsv","content","fileName","download","encodeURIComponent"],"sources":["../../../src/hooks/useImport.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useWixPatternsContainer, useCollectionContext } from '../providers';\nimport {\n ModalState,\n ImportState,\n BackupFn,\n BulkUploadItemsFn,\n UpdateSchemaFn,\n DetectColumnType,\n} from '../state';\nimport { CreateExportAsyncJobRequest } from '@wix/bex-utils/@wix/ambassador-fedinfra-exportservice-v1-export-async-job/types';\nimport { FiltersMap } from '../model';\n\nexport interface UseImportParams {\n fields: CreateExportAsyncJobRequest['fields'];\n bulkUploadItems: BulkUploadItemsFn;\n backup?: BackupFn;\n updateSchema?: UpdateSchemaFn;\n detectColumnType?: DetectColumnType;\n importModalState: ModalState;\n batchSize?: number;\n}\n\nexport function useCreateImport<T = unknown, F extends FiltersMap = FiltersMap>(\n params: UseImportParams,\n) {\n const {\n fields,\n bulkUploadItems,\n backup,\n updateSchema,\n detectColumnType,\n importModalState,\n batchSize,\n } = params;\n const { showToast, translate, errorHandler, window } =\n useWixPatternsContainer();\n const collection = useCollectionContext<T, F>();\n\n return useCallback(() => {\n return new ImportState({\n fields,\n bulkUploadItems,\n backup,\n updateSchema,\n detectColumnType,\n collection,\n importModalState,\n batchSize,\n showToast,\n translate,\n errorHandler,\n downloadCsv: (content, fileName) => {\n window.download(\n `data:text/csv;charset=utf-8,${encodeURIComponent(content)}`,\n fileName,\n );\n },\n });\n }, []);\n}\n"],"mappings":";;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,UAAA,GAAAD,OAAA;AACA,IAAAE,MAAA,GAAAF,OAAA;AAqBO,SAASG,eAAeA,CAC7BC,MAAuB,EACvB;EACA,MAAM;IACJC,MAAM;IACNC,eAAe;IACfC,MAAM;IACNC,YAAY;IACZC,gBAAgB;IAChBC,gBAAgB;IAChBC;EACF,CAAC,GAAGP,MAAM;EACV,MAAM;IAAEQ,SAAS;IAAEC,SAAS;IAAEC,YAAY;IAAEC;EAAO,CAAC,GAClD,IAAAC,kCAAuB,EAAC,CAAC;EAC3B,MAAMC,UAAU,GAAG,IAAAC,+BAAoB,EAAO,CAAC;EAE/C,OAAO,IAAAC,kBAAW,EAAC,MAAM;IACvB,OAAO,IAAIC,kBAAW,CAAC;MACrBf,MAAM;MACNC,eAAe;MACfC,MAAM;MACNC,YAAY;MACZC,gBAAgB;MAChBQ,UAAU;MACVP,gBAAgB;MAChBC,SAAS;MACTC,SAAS;MACTC,SAAS;MACTC,YAAY;MACZO,WAAW,EAAEA,CAACC,OAAO,EAAEC,QAAQ,KAAK;QAClCR,MAAM,CAACS,QAAQ,CACb,+BAA+BC,kBAAkB,CAACH,OAAO,CAAC,EAAE,EAC5DC,QACF,CAAC;MACH;IACF,CAAC,CAAC;EACJ,CAAC,EAAE,EAAE,CAAC;AACR","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"names":["_react","require","useImportConfig","params","config","useState"],"sources":["../../../src/hooks/useImportConfig.ts"],"sourcesContent":["import { useState } from 'react';\nimport { CreateExportAsyncJobRequest } from '@wix/bex-utils/@wix/ambassador-fedinfra-exportservice-v1-export-async-job/types';\nimport { BackupFn, BulkUploadItemsFn } from '../state';\n\nexport interface UseImportConfigParams {\n fields: CreateExportAsyncJobRequest['fields'];\n bulkUploadItems: BulkUploadItemsFn;\n backup?: BackupFn;\n batchSize?: number;\n}\n\nexport function useImportConfig(params: UseImportConfigParams) {\n const [config] = useState(() => params);\n\n return config;\n}\n"],"mappings":";;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAWO,SAASC,eAAeA,CAACC,MAA6B,EAAE;EAC7D,MAAM,CAACC,MAAM,CAAC,GAAG,IAAAC,eAAQ,EAAC,MAAMF,MAAM,CAAC;EAEvC,OAAOC,MAAM;AACf","ignoreList":[]}
1
+ {"version":3,"names":["_react","require","useImportConfig","params","config","useState"],"sources":["../../../src/hooks/useImportConfig.ts"],"sourcesContent":["import { useState } from 'react';\nimport { CreateExportAsyncJobRequest } from '@wix/bex-utils/@wix/ambassador-fedinfra-exportservice-v1-export-async-job/types';\nimport { BackupFn, BulkUploadItemsFn, UpdateSchemaFn } from '../state';\n\nexport interface UseImportConfigParams {\n fields: CreateExportAsyncJobRequest['fields'];\n bulkUploadItems: BulkUploadItemsFn;\n backup?: BackupFn;\n updateSchema?: UpdateSchemaFn;\n batchSize?: number;\n}\n\nexport function useImportConfig(params: UseImportConfigParams) {\n const [config] = useState(() => params);\n\n return config;\n}\n"],"mappings":";;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAYO,SAASC,eAAeA,CAACC,MAA6B,EAAE;EAC7D,MAAM,CAACC,MAAM,CAAC,GAAG,IAAAC,eAAQ,EAAC,MAAMF,MAAM,CAAC;EAEvC,OAAOC,MAAM;AACf","ignoreList":[]}
@@ -8,7 +8,32 @@ var _mobx = require("mobx");
8
8
  var _model = require("../../model");
9
9
  var _ConditionalModalState = require("../ConditionalModalState");
10
10
  var _parseCsv = require("./parseCsv");
11
+ var _detectFieldType = require("./detectFieldType");
11
12
  var _set = _interopRequireDefault(require("lodash/set"));
13
+ // `NewFieldType`, `detectColumnType`, etc. are re-exported from the package via
14
+ // the `ImportState` barrel (`./index`), which also exports `./detectFieldType`.
15
+
16
+ // A new field to add to the collection schema during import. `key` is decided by
17
+ // Cairo (derived from the column header, deduped) and is also the key the
18
+ // column's values are written under, so the consumer must add the field under
19
+ // exactly this key.
20
+
21
+ /**
22
+ * Consumer-supplied callback that adds the given new fields to the collection
23
+ * schema in a single call, before the rows are uploaded. Mirrors the cm-import
24
+ * `beforeImport`/`updateSchema` flow: Cairo decides the fields (and their keys),
25
+ * the consumer performs one schema mutation (e.g. `updateSchema(collectionId,
26
+ * ...addField(key, config))`). Its presence is also the opt-in for the "create
27
+ * new field" default — see `getDefaultMapping`.
28
+ */
29
+
30
+ /**
31
+ * How a CSV column is mapped:
32
+ * - `existing` — into an existing collection field by id
33
+ * - `new` — into a new field created during import (always text for now)
34
+ * - `null` — don't import (skip)
35
+ */
36
+
12
37
  const DEFAULT_BATCH_SIZE = 100;
13
38
 
14
39
  // How long to keep the completed progress bar (100%) on screen before closing
@@ -19,6 +44,38 @@ const COMPLETION_LINGER_MS = 600;
19
44
  function normalize(value) {
20
45
  return value.trim().toLowerCase();
21
46
  }
47
+
48
+ // camelCase key for a field created from a column header
49
+ // (e.g. "Product Name" -> "productName").
50
+ function toFieldKey(header) {
51
+ const words = header.trim().split(/[^a-zA-Z0-9]+/).filter(Boolean);
52
+ if (words.length === 0) {
53
+ return 'field';
54
+ }
55
+ return words.map((word, index) => index === 0 ? word.charAt(0).toLowerCase() + word.slice(1) : word.charAt(0).toUpperCase() + word.slice(1)).join('');
56
+ }
57
+
58
+ // A display name + key for a field created from a column header, unique against
59
+ // both `usedNames` (existing field display names + names already assigned to
60
+ // earlier new columns) and `usedKeys` (existing field ids + keys already
61
+ // assigned). Mirrors cm-import `generateFieldNameAndKey`: when the name or its
62
+ // derived key collides, suffix the *display name* as `"<header>-<n>"` and
63
+ // re-derive the key from it — so the created field's name and key are both
64
+ // unique (otherwise two columns with the same header would create fields showing
65
+ // the same name).
66
+ function uniqueFieldNameAndKey(header, usedNames, usedKeys) {
67
+ let displayName = header;
68
+ for (let suffix = 1;; suffix++) {
69
+ const key = toFieldKey(displayName);
70
+ if (!usedNames.has(displayName) && !usedKeys.has(key)) {
71
+ return {
72
+ displayName,
73
+ key
74
+ };
75
+ }
76
+ displayName = `${header}-${suffix}`;
77
+ }
78
+ }
22
79
  function toMappedRows(rows, headers, mappingByHeader) {
23
80
  return rows.map(row => {
24
81
  const mapped = {};
@@ -37,6 +94,7 @@ class ImportState {
37
94
  (0, _defineProperty2.default)(this, "fields", void 0);
38
95
  (0, _defineProperty2.default)(this, "bulkUploadItems", void 0);
39
96
  (0, _defineProperty2.default)(this, "backup", void 0);
97
+ (0, _defineProperty2.default)(this, "updateSchema", void 0);
40
98
  (0, _defineProperty2.default)(this, "collection", void 0);
41
99
  (0, _defineProperty2.default)(this, "importModalState", void 0);
42
100
  (0, _defineProperty2.default)(this, "translate", void 0);
@@ -44,6 +102,7 @@ class ImportState {
44
102
  (0, _defineProperty2.default)(this, "showToast", void 0);
45
103
  (0, _defineProperty2.default)(this, "downloadCsv", void 0);
46
104
  (0, _defineProperty2.default)(this, "batchSize", void 0);
105
+ (0, _defineProperty2.default)(this, "_detectColumnType", void 0);
47
106
  (0, _defineProperty2.default)(this, "discardChangesModal", new _ConditionalModalState.ConditionalModalState());
48
107
  (0, _defineProperty2.default)(this, "currentStep", 'upload');
49
108
  (0, _defineProperty2.default)(this, "importStatus", {
@@ -73,6 +132,7 @@ class ImportState {
73
132
  this.fields = props.fields ?? [];
74
133
  this.bulkUploadItems = props.bulkUploadItems;
75
134
  this.backup = props.backup;
135
+ this.updateSchema = props.updateSchema;
76
136
  this.collection = props.collection;
77
137
  this.importModalState = props.importModalState;
78
138
  this.translate = props.translate;
@@ -80,6 +140,7 @@ class ImportState {
80
140
  this.showToast = props.showToast;
81
141
  this.downloadCsv = props.downloadCsv;
82
142
  this.batchSize = props.batchSize ?? DEFAULT_BATCH_SIZE;
143
+ this._detectColumnType = props.detectColumnType ?? _detectFieldType.detectColumnType;
83
144
  (0, _mobx.makeObservable)(this, {
84
145
  currentStep: _mobx.observable.ref,
85
146
  importStatus: _mobx.observable.ref,
@@ -96,10 +157,10 @@ class ImportState {
96
157
  hasMappings: _mobx.computed,
97
158
  hasNoMappedData: _mobx.computed,
98
159
  selectedFieldIds: _mobx.computed,
99
- mappedRows: _mobx.computed,
100
160
  onUploadContinue: _mobx.action.bound,
101
161
  goToUpload: _mobx.action.bound,
102
162
  setMapping: _mobx.action.bound,
163
+ setNewFieldMapping: _mobx.action.bound,
103
164
  close: _mobx.action.bound,
104
165
  onFileSelected: _mobx.action.bound,
105
166
  startImport: _mobx.action.bound,
@@ -136,10 +197,17 @@ class ImportState {
136
197
  return !this.csvRows.some(row => mappedIndices.some(index => (row[index] ?? '').trim() !== ''));
137
198
  }
138
199
  get selectedFieldIds() {
139
- return new Set(Object.values(this.mappingByHeader).filter(v => v != null));
200
+ return new Set(Object.values(this.mappingByHeader).filter(m => (m == null ? void 0 : m.kind) === 'existing').map(m => m.fieldId));
140
201
  }
141
- get mappedRows() {
142
- return toMappedRows(this.csvRows, this.csvHeaders, this.mappingByHeader);
202
+
203
+ /**
204
+ * Whether columns may be mapped to a brand-new field created during import.
205
+ * Driven purely by the presence of the `updateSchema` callback — providing the
206
+ * capability is the opt-in (see `getDefaultMapping`). Never changes after
207
+ * construction, so it isn't an observable.
208
+ */
209
+ get canCreateNewField() {
210
+ return this.updateSchema != null;
143
211
  }
144
212
  reset() {
145
213
  var _this$_abortControlle;
@@ -230,13 +298,33 @@ class ImportState {
230
298
  id: field.id ?? '',
231
299
  header: field.header ?? ''
232
300
  }));
233
- headers.forEach(header => {
301
+ headers.forEach((header, index) => {
234
302
  const normalizedHeader = normalize(header);
235
303
  const matched = fields.find(field => normalize(field.id) === normalizedHeader || normalize(field.header) === normalizedHeader);
236
- mapping[header] = (matched == null ? void 0 : matched.id) || null;
304
+ if (matched != null && matched.id) {
305
+ mapping[header] = {
306
+ kind: 'existing',
307
+ fieldId: matched.id
308
+ };
309
+ } else {
310
+ // Unmatched columns default to creating a new field (type inferred from
311
+ // the column's data) when the consumer supplied `updateSchema`;
312
+ // otherwise they default to skip.
313
+ mapping[header] = this.canCreateNewField ? {
314
+ kind: 'new',
315
+ fieldType: this._detectColumnType(this._columnValues(index))
316
+ } : null;
317
+ }
237
318
  });
238
319
  return mapping;
239
320
  }
321
+
322
+ // The column's values, capped at the detection sample size — detection only
323
+ // looks at the first `TYPE_SAMPLE_SIZE` values, so avoid copying the whole
324
+ // column (a wide CSV would otherwise allocate rows × columns strings).
325
+ _columnValues(columnIndex) {
326
+ return this.csvRows.slice(0, _detectFieldType.TYPE_SAMPLE_SIZE).map(row => row[columnIndex] ?? '');
327
+ }
240
328
  applyParsedCsv(fileName, parsedCsv) {
241
329
  this.fileName = fileName;
242
330
  this.csvHeaders = parsedCsv.headers;
@@ -339,7 +427,21 @@ class ImportState {
339
427
  setMapping(header, fieldId) {
340
428
  this.mappingByHeader = {
341
429
  ...this.mappingByHeader,
342
- [header]: fieldId
430
+ [header]: fieldId == null ? null : {
431
+ kind: 'existing',
432
+ fieldId
433
+ }
434
+ };
435
+ }
436
+ setNewFieldMapping(header) {
437
+ const index = this.csvHeaders.indexOf(header);
438
+ const fieldType = index >= 0 ? this._detectColumnType(this._columnValues(index)) : 'text';
439
+ this.mappingByHeader = {
440
+ ...this.mappingByHeader,
441
+ [header]: {
442
+ kind: 'new',
443
+ fieldType
444
+ }
343
445
  };
344
446
  }
345
447
  async _uploadBatches(batches) {
@@ -426,6 +528,50 @@ class ImportState {
426
528
  _lingerOnCompletion() {
427
529
  return new Promise(resolve => setTimeout(resolve, COMPLETION_LINGER_MS));
428
530
  }
531
+
532
+ /**
533
+ * Resolves every column to the final destination key used in the upload
534
+ * payload: an existing field id, a new field's (Cairo-decided) key, or `null`
535
+ * to skip. All new fields are added to the schema in a single `updateSchema`
536
+ * call before the rows upload — mirroring the cm-import `beforeImport` flow.
537
+ * `updateSchema` may throw — `startImport` surfaces that as the error state.
538
+ */
539
+ async _resolveFieldMapping() {
540
+ const resolved = {};
541
+ const newFields = [];
542
+ // Seed with existing field ids/display names so derived keys and names never
543
+ // collide with them or with each other.
544
+ const usedKeys = new Set(this.fields.map(field => field.id).filter(id => !!id));
545
+ const usedNames = new Set(this.fields.map(field => field.header).filter(header => !!header));
546
+ for (const header of this.csvHeaders) {
547
+ const mapping = this.mappingByHeader[header];
548
+ if (mapping == null) {
549
+ resolved[header] = null;
550
+ } else if (mapping.kind === 'existing') {
551
+ resolved[header] = mapping.fieldId;
552
+ } else if (this.updateSchema) {
553
+ const {
554
+ displayName,
555
+ key
556
+ } = uniqueFieldNameAndKey(header, usedNames, usedKeys);
557
+ usedKeys.add(key);
558
+ usedNames.add(displayName);
559
+ newFields.push({
560
+ key,
561
+ type: mapping.fieldType,
562
+ displayName
563
+ });
564
+ resolved[header] = key;
565
+ } else {
566
+ // "new" mapping without an `updateSchema` callback — nothing to map into.
567
+ resolved[header] = null;
568
+ }
569
+ }
570
+ if (newFields.length > 0 && this.updateSchema) {
571
+ await this.updateSchema(newFields);
572
+ }
573
+ return resolved;
574
+ }
429
575
  _createRowsBatches(rows) {
430
576
  return rows.reduce((acc, row, index) => {
431
577
  if (index % this.batchSize === 0) {
@@ -441,9 +587,10 @@ class ImportState {
441
587
  }
442
588
  this._cancelled = false;
443
589
  this._abortController = new AbortController();
444
- const rows = this.mappedRows;
445
- const totalCount = rows.length;
446
- const batches = this._createRowsBatches(rows);
590
+
591
+ // One mapped row is produced per CSV row, so the total is known up front and
592
+ // doesn't depend on field creation below.
593
+ const totalCount = this.csvRows.length;
447
594
  (0, _mobx.runInAction)(() => {
448
595
  this.currentStep = 'progress';
449
596
  this.totalCount = totalCount;
@@ -465,6 +612,30 @@ class ImportState {
465
612
  if (backupFailed) {
466
613
  return;
467
614
  }
615
+ if (this._cancelled) {
616
+ return;
617
+ }
618
+
619
+ // Create any new fields and resolve every column to its destination key
620
+ // before building the payload. A creation failure surfaces as the error
621
+ // state with a "Try again" CTA, like a first-batch upload failure.
622
+ let resolvedMapping;
623
+ try {
624
+ resolvedMapping = await this._resolveFieldMapping();
625
+ } catch (error) {
626
+ (0, _mobx.runInAction)(() => {
627
+ this.importStatus = {
628
+ ..._model.queryStatus.error,
629
+ error
630
+ };
631
+ });
632
+ return;
633
+ }
634
+ if (this._cancelled) {
635
+ return;
636
+ }
637
+ const rows = toMappedRows(this.csvRows, this.csvHeaders, resolvedMapping);
638
+ const batches = this._createRowsBatches(rows);
468
639
  const promise = this._uploadBatches(batches);
469
640
  this.importStatus = {
470
641
  ..._model.queryStatus.loading,
@@ -1 +1 @@
1
- {"version":3,"names":["_mobx","require","_model","_ConditionalModalState","_parseCsv","_set","_interopRequireDefault","DEFAULT_BATCH_SIZE","COMPLETION_LINGER_MS","normalize","value","trim","toLowerCase","toMappedRows","rows","headers","mappingByHeader","map","row","mapped","forEach","header","index","mappedField","set","ImportState","constructor","props","_defineProperty2","default","ConditionalModalState","queryStatus","idle","succeeded","failed","errors","fields","bulkUploadItems","backup","collection","importModalState","translate","errorHandler","showToast","downloadCsv","batchSize","makeObservable","currentStep","observable","ref","importStatus","fileName","csvHeaders","csvRows","processedCount","totalCount","result","isBackingUp","isRestoring","hasParsedRows","computed","hasMappings","hasNoMappedData","selectedFieldIds","mappedRows","onUploadContinue","action","bound","goToUpload","setMapping","close","onFileSelected","startImport","reset","init","undefined","length","Object","values","some","mappedIndices","reduce","indices","push","Set","filter","v","_this$_abortControlle","_abortController","abort","restoreFn","_cancelled","_failedRowIndices","_this$_abortControlle2","_restoreBackup","clearResultAndMoveToStart","force","restoreController","AbortController","signal","error","console","runInAction","discardAndGoBack","discardChangesModal","open","modal","promise","discardAndClose","getDefaultMapping","mapping","field","id","normalizedHeader","matched","find","applyParsedCsv","parsedCsv","file","bytes","_readFileBytes","_showFileReadErrorToast","content","_decodeUtf8","_rejectFile","parseCsv","name","arrayBuffer","e","TextDecoder","fatal","decode","messageKey","_this$showToast","call","type","message","_this$showToast2","text","onClick","removeToastOnClick","_showPartialSuccessToast","_this$showToast3","String","imported","_downloadFailedRows","_this$downloadCsv","failedRows","unparseCsv","fieldId","_uploadBatches","batches","processedRows","receivedOkResponse","failedRowIndices","batch","batchStart","batchResult","rowIndex","Math","min","_runBackup","restore","_lingerOnCompletion","Promise","resolve","setTimeout","_createRowsBatches","acc","backupFailed","loading","success","data","exports"],"sources":["../../../../src/state/ImportState/ImportState.ts"],"sourcesContent":["import {\n action,\n computed,\n makeObservable,\n observable,\n runInAction,\n} from 'mobx';\nimport {\n queryStatus,\n ShowToast,\n TaskStatus,\n PatternsErrorHandler,\n} from '../../model';\nimport { Translate, TranslationsKeys } from '../../services';\nimport { ModalState } from '../ModalState';\nimport { ConditionalModalState } from '../ConditionalModalState';\nimport { CreateExportAsyncJobRequest } from '@wix/bex-utils/@wix/ambassador-fedinfra-exportservice-v1-export-async-job/types';\nimport { ParseCsvResult, parseCsv, unparseCsv } from './parseCsv';\nimport set from 'lodash/set';\n\nexport interface ImportCollection {\n clearResultAndMoveToStart(params?: { force?: boolean }): void;\n}\n\nexport interface BulkUploadError {\n rowIndex: number;\n message?: string;\n code?: string;\n}\n\nexport interface BulkUploadResults {\n succeeded: number;\n failed: number;\n errors: BulkUploadError[];\n insertedIds?: string[];\n}\n\nexport type BulkUploadItemsFn = (\n items: Record<string, unknown>[],\n) => Promise<BulkUploadResults>;\n\nexport interface BackupResult {\n restore(signal: AbortSignal): Promise<void>;\n}\n\nexport type BackupFn = (signal: AbortSignal) => Promise<BackupResult | void>;\n\nexport type DownloadCsvFn = (content: string, fileName: string) => void;\n\nexport type ImportField = NonNullable<\n CreateExportAsyncJobRequest['fields']\n>[number];\n\nexport interface ImportStateProps {\n fields: CreateExportAsyncJobRequest['fields'];\n bulkUploadItems: BulkUploadItemsFn;\n backup?: BackupFn;\n collection: ImportCollection;\n importModalState: ModalState;\n translate: Translate;\n errorHandler: PatternsErrorHandler;\n showToast?: ShowToast;\n downloadCsv?: DownloadCsvFn;\n batchSize?: number;\n}\n\nexport type ImportStep = 'upload' | 'configuration' | 'progress';\n\nconst DEFAULT_BATCH_SIZE = 100;\n\n// How long to keep the completed progress bar (100%) on screen before closing\n// the modal on a clean import. Without it, an import of very few rows finishes\n// near-instantly and the modal appears to vanish without ever showing the bar\n// reaching completion.\nconst COMPLETION_LINGER_MS = 600;\n\nfunction normalize(value: string) {\n return value.trim().toLowerCase();\n}\n\nfunction toMappedRows(\n rows: string[][],\n headers: string[],\n mappingByHeader: Record<string, string | null | undefined>,\n) {\n return rows.map((row) => {\n const mapped: Record<string, unknown> = {};\n\n headers.forEach((header, index) => {\n const mappedField = mappingByHeader[header];\n if (mappedField == null) {\n return;\n }\n\n set(mapped, mappedField, row[index] ?? '');\n });\n\n return mapped;\n });\n}\n\nexport class ImportState {\n readonly fields: ImportField[];\n readonly bulkUploadItems: BulkUploadItemsFn;\n readonly backup?: BackupFn;\n readonly collection: ImportCollection;\n readonly importModalState: ModalState;\n readonly translate: Translate;\n readonly errorHandler: PatternsErrorHandler;\n readonly showToast?: ShowToast;\n readonly downloadCsv?: DownloadCsvFn;\n readonly batchSize: number;\n readonly discardChangesModal = new ConditionalModalState<\n 'goBack' | 'close'\n >();\n\n currentStep: ImportStep = 'upload';\n importStatus: TaskStatus<BulkUploadResults, unknown> = {\n ...queryStatus.idle,\n };\n fileName = '';\n csvHeaders: string[] = [];\n csvRows: string[][] = [];\n mappingByHeader: Record<string, string | null> = {};\n processedCount = 0;\n totalCount = 0;\n result: BulkUploadResults = {\n succeeded: 0,\n failed: 0,\n errors: [],\n };\n isBackingUp = false;\n isRestoring = false;\n private restoreFn: ((signal: AbortSignal) => Promise<void>) | null = null;\n private _cancelled = false;\n private _abortController: AbortController | null = null;\n // Global indices (into `csvRows`) of every row that was not imported: rows\n // the server rejected via a batch's returned `errors`, plus — when a batch\n // throws after some rows succeeded — the throwing batch and all un-attempted\n // rows. Offered to the user as a downloadable CSV via the partial toast.\n private _failedRowIndices: number[] = [];\n\n constructor(props: ImportStateProps) {\n this.fields = (props.fields ?? []) as ImportField[];\n this.bulkUploadItems = props.bulkUploadItems;\n this.backup = props.backup;\n this.collection = props.collection;\n this.importModalState = props.importModalState;\n this.translate = props.translate;\n this.errorHandler = props.errorHandler;\n this.showToast = props.showToast;\n this.downloadCsv = props.downloadCsv;\n this.batchSize = props.batchSize ?? DEFAULT_BATCH_SIZE;\n\n makeObservable(this, {\n currentStep: observable.ref,\n importStatus: observable.ref,\n fileName: observable.ref,\n csvHeaders: observable.ref,\n csvRows: observable.ref,\n mappingByHeader: observable.ref,\n processedCount: observable.ref,\n totalCount: observable.ref,\n result: observable.ref,\n isBackingUp: observable.ref,\n isRestoring: observable.ref,\n hasParsedRows: computed,\n hasMappings: computed,\n hasNoMappedData: computed,\n selectedFieldIds: computed,\n mappedRows: computed,\n onUploadContinue: action.bound,\n goToUpload: action.bound,\n setMapping: action.bound,\n close: action.bound,\n onFileSelected: action.bound,\n startImport: action.bound,\n reset: action.bound,\n });\n }\n\n init() {\n return () => undefined;\n }\n\n get hasParsedRows() {\n return this.csvHeaders.length > 0 && this.csvRows.length > 0;\n }\n\n get hasMappings() {\n return Object.values(this.mappingByHeader).some((value) => value != null);\n }\n\n /**\n * True when there are mappings but none of the mapped columns contain any\n * data in any row (including the case of zero data rows). Drives the\n * non-blocking \"no rows found\" warning in the configuration step. Returns\n * false when nothing is mapped yet — that case is handled by the disabled\n * import button instead.\n */\n get hasNoMappedData(): boolean {\n if (!this.hasMappings) {\n return false;\n }\n\n const mappedIndices = this.csvHeaders.reduce<number[]>(\n (indices, header, index) => {\n if (this.mappingByHeader[header] != null) {\n indices.push(index);\n }\n return indices;\n },\n [],\n );\n\n return !this.csvRows.some((row) =>\n mappedIndices.some((index) => (row[index] ?? '').trim() !== ''),\n );\n }\n\n get selectedFieldIds(): Set<string> {\n return new Set(\n Object.values(this.mappingByHeader).filter((v): v is string => v != null),\n );\n }\n\n get mappedRows() {\n return toMappedRows(this.csvRows, this.csvHeaders, this.mappingByHeader);\n }\n\n reset() {\n this._abortController?.abort();\n this._abortController = null;\n this.currentStep = 'upload';\n this.importStatus = {\n ...queryStatus.idle,\n };\n this.fileName = '';\n this.csvHeaders = [];\n this.csvRows = [];\n this.mappingByHeader = {};\n this.processedCount = 0;\n this.totalCount = 0;\n this.result = {\n succeeded: 0,\n failed: 0,\n errors: [],\n };\n this.isBackingUp = false;\n this.isRestoring = false;\n this.restoreFn = null;\n this._cancelled = false;\n this._failedRowIndices = [];\n }\n\n async close() {\n if (this.currentStep === 'progress') {\n this._cancelled = true;\n this._abortController?.abort();\n\n if (!this.isBackingUp) {\n await this._restoreBackup();\n }\n\n this.collection.clearResultAndMoveToStart({\n force: true,\n });\n }\n\n this.importModalState.close();\n }\n\n private async _restoreBackup() {\n const restoreFn = this.restoreFn;\n if (!restoreFn) {\n return;\n }\n\n const restoreController = new AbortController();\n this._abortController = restoreController;\n\n this.isRestoring = true;\n try {\n await restoreFn(restoreController.signal);\n } catch (error) {\n console.error('Restore failed', error);\n }\n runInAction(() => {\n this.isRestoring = false;\n this.restoreFn = null;\n });\n }\n\n goToUpload() {\n this.currentStep = 'upload';\n }\n\n async discardAndGoBack() {\n this.discardChangesModal.open('goBack');\n const { result } = await this.discardChangesModal.modal.promise();\n if (result === 'confirmed') {\n this.goToUpload();\n }\n }\n\n async discardAndClose() {\n this.discardChangesModal.open('close');\n const { result } = await this.discardChangesModal.modal.promise();\n if (result === 'confirmed') {\n this.close();\n }\n }\n\n onUploadContinue() {\n if (this.hasParsedRows) {\n this.currentStep = 'configuration';\n }\n }\n\n private getDefaultMapping(headers: string[]) {\n const mapping: Record<string, string | null> = {};\n const fields = this.fields.map((field) => ({\n id: field.id ?? '',\n header: field.header ?? '',\n }));\n\n headers.forEach((header) => {\n const normalizedHeader = normalize(header);\n const matched = fields.find(\n (field) =>\n normalize(field.id) === normalizedHeader ||\n normalize(field.header) === normalizedHeader,\n );\n\n mapping[header] = matched?.id || null;\n });\n\n return mapping;\n }\n\n private applyParsedCsv(fileName: string, parsedCsv: ParseCsvResult) {\n this.fileName = fileName;\n this.csvHeaders = parsedCsv.headers;\n this.csvRows = parsedCsv.rows;\n this.mappingByHeader = this.getDefaultMapping(parsedCsv.headers);\n this.currentStep = 'configuration';\n }\n\n async onFileSelected(file: File | null) {\n if (file == null) {\n return;\n }\n\n const bytes = await this._readFileBytes(file);\n if (bytes == null) {\n this._showFileReadErrorToast(file);\n return;\n }\n\n const content = this._decodeUtf8(bytes);\n if (content == null) {\n this._rejectFile(file, 'cairo.import.encodingFailed');\n return;\n }\n\n const parsedCsv = parseCsv(content);\n if ('code' in parsedCsv) {\n this._rejectFile(file, 'cairo.import.processFailed');\n return;\n }\n\n runInAction(() => {\n this.applyParsedCsv(file.name, parsedCsv);\n });\n }\n\n private async _readFileBytes(file: File): Promise<ArrayBuffer | null> {\n try {\n return await file.arrayBuffer();\n } catch (e) {\n console.error(e);\n return null;\n }\n }\n\n private _decodeUtf8(bytes: ArrayBuffer): string | null {\n try {\n // `fatal: true` throws on any byte sequence that isn't valid UTF-8,\n // so encoding is validated against the raw bytes before decoding —\n // unlike `File.text()`, which silently substitutes U+FFFD.\n return new TextDecoder('utf-8', { fatal: true }).decode(bytes);\n } catch (e) {\n console.error(e);\n return null;\n }\n }\n\n private _rejectFile(file: File, messageKey: TranslationsKeys) {\n runInAction(() => {\n this.fileName = file.name;\n this.csvHeaders = [];\n this.csvRows = [];\n this.mappingByHeader = {};\n this.currentStep = 'upload';\n });\n this.showToast?.({\n type: 'ERROR',\n message: this.translate(messageKey),\n });\n }\n\n private _showFileReadErrorToast(file: File) {\n this.showToast?.({\n type: 'ERROR',\n message: this.translate('cairo.import.fileReadFailed'),\n action: {\n text: this.translate('cairo.import.tryAgain'),\n onClick: () => this.onFileSelected(file),\n removeToastOnClick: true,\n },\n });\n }\n\n private _showPartialSuccessToast() {\n const failed = this._failedRowIndices.length;\n this.showToast?.({\n type: 'WARNING',\n message: this.translate('cairo.import.partialSuccessToast', {\n failed: String(failed),\n imported: String(this.totalCount - failed),\n }),\n action: {\n text: this.translate('cairo.import.downloadFailedRows'),\n onClick: () => this._downloadFailedRows(),\n removeToastOnClick: true,\n },\n });\n }\n\n private _downloadFailedRows() {\n const failedRows = this._failedRowIndices.map(\n (index) => this.csvRows[index],\n );\n const content = unparseCsv(this.csvHeaders, failedRows);\n this.downloadCsv?.(content, `failed-${this.fileName || 'import.csv'}`);\n }\n\n setMapping(header: string, fieldId: string | null) {\n this.mappingByHeader = {\n ...this.mappingByHeader,\n [header]: fieldId,\n };\n }\n\n private async _uploadBatches(batches: Record<string, unknown>[][]) {\n let processedRows = 0;\n let receivedOkResponse = false;\n const failedRowIndices: number[] = [];\n\n for (const batch of batches) {\n if (this._cancelled) {\n break;\n }\n\n const batchStart = processedRows;\n\n try {\n const batchResult = await this.bulkUploadItems(batch);\n receivedOkResponse = true;\n\n this.result = {\n succeeded: this.result.succeeded + batchResult.succeeded,\n failed: this.result.failed + batchResult.failed,\n errors: [...this.result.errors, ...batchResult.errors],\n };\n\n // Rows the server rejected within an otherwise-OK response. `rowIndex`\n // is relative to the batch, so offset it to a global `csvRows` index.\n for (const { rowIndex } of batchResult.errors) {\n failedRowIndices.push(batchStart + rowIndex);\n }\n } catch (error) {\n // Full batch failure: a batch threw before any OK response came back.\n // Surface it as an error state with a \"Try again\" action by rejecting\n // up to `startImport`, instead of reporting a partial success.\n if (!receivedOkResponse) {\n throw error;\n }\n\n // A batch threw after some rows were already imported. Every row from\n // the throwing batch onward (including the batches we won't attempt)\n // counts as failed, on top of any rows already rejected via returned\n // errors in earlier batches.\n for (let index = batchStart; index < this.totalCount; index++) {\n failedRowIndices.push(index);\n }\n\n break;\n }\n\n processedRows += batch.length;\n\n runInAction(() => {\n this.processedCount = Math.min(processedRows, this.totalCount);\n });\n }\n\n this._failedRowIndices = failedRowIndices;\n\n return this.result;\n }\n\n private async _runBackup(): Promise<boolean> {\n const backup = this.backup;\n if (!backup) {\n return false;\n }\n\n try {\n const result = await backup(this._abortController!.signal);\n if (this._cancelled) {\n return true;\n }\n if (result?.restore) {\n this.restoreFn = result.restore;\n }\n } catch (error) {\n if (this._cancelled) {\n return true;\n }\n runInAction(() => {\n this.isBackingUp = false;\n this.importStatus = {\n ...queryStatus.error,\n error,\n };\n });\n return true;\n }\n\n runInAction(() => {\n this.isBackingUp = false;\n });\n return false;\n }\n\n private _lingerOnCompletion() {\n return new Promise<void>((resolve) =>\n setTimeout(resolve, COMPLETION_LINGER_MS),\n );\n }\n\n private _createRowsBatches(rows: Record<string, unknown>[]) {\n return rows.reduce<Record<string, unknown>[][]>((acc, row, index) => {\n if (index % this.batchSize === 0) {\n acc.push([]);\n }\n acc[acc.length - 1].push(row);\n return acc;\n }, []);\n }\n\n async startImport() {\n if (!this.hasMappings) {\n return;\n }\n\n this._cancelled = false;\n this._abortController = new AbortController();\n\n const rows = this.mappedRows;\n const totalCount = rows.length;\n const batches = this._createRowsBatches(rows);\n\n runInAction(() => {\n this.currentStep = 'progress';\n this.totalCount = totalCount;\n this.processedCount = 0;\n this.isBackingUp = !!this.backup;\n // Clear any error/result from a previous attempt so \"Try again\" starts\n // from a clean slate (e.g. after a backup failure).\n this.importStatus = { ...queryStatus.idle };\n this.result = {\n succeeded: 0,\n failed: 0,\n errors: [],\n };\n this._failedRowIndices = [];\n });\n\n const backupFailed = await this._runBackup();\n if (backupFailed) {\n return;\n }\n\n const promise = this._uploadBatches(batches);\n\n this.importStatus = {\n ...queryStatus.loading,\n promise,\n };\n\n try {\n await promise;\n if (this._cancelled) {\n return;\n }\n\n runInAction(() => {\n this.importStatus = {\n ...queryStatus.success,\n data: this.result,\n };\n });\n\n // On a clean import, hold the completed (100%) progress bar on screen\n // briefly so the completion is perceptible even for very few rows. Skip\n // the wait when there are failed rows — that path closes and surfaces a\n // toast instead.\n if (this._failedRowIndices.length === 0) {\n await this._lingerOnCompletion();\n if (this._cancelled) {\n return;\n }\n }\n\n runInAction(() => {\n // Any rows that didn't make it in — whether rejected via a batch's\n // returned `errors` or left unimported when a batch threw — are\n // reported via a toast that offers them as a downloadable CSV.\n if (this._failedRowIndices.length > 0) {\n this._showPartialSuccessToast();\n }\n\n this.importModalState.close();\n this.collection.clearResultAndMoveToStart({ force: true });\n });\n } catch (error) {\n runInAction(() => {\n this.importStatus = {\n ...queryStatus.error,\n error,\n };\n });\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_mobx","require","_model","_ConditionalModalState","_parseCsv","_detectFieldType","_set","_interopRequireDefault","DEFAULT_BATCH_SIZE","COMPLETION_LINGER_MS","normalize","value","trim","toLowerCase","toFieldKey","header","words","split","filter","Boolean","length","map","word","index","charAt","slice","toUpperCase","join","uniqueFieldNameAndKey","usedNames","usedKeys","displayName","suffix","key","has","toMappedRows","rows","headers","mappingByHeader","row","mapped","forEach","mappedField","set","ImportState","constructor","props","_defineProperty2","default","ConditionalModalState","queryStatus","idle","succeeded","failed","errors","fields","bulkUploadItems","backup","updateSchema","collection","importModalState","translate","errorHandler","showToast","downloadCsv","batchSize","_detectColumnType","detectColumnType","makeObservable","currentStep","observable","ref","importStatus","fileName","csvHeaders","csvRows","processedCount","totalCount","result","isBackingUp","isRestoring","hasParsedRows","computed","hasMappings","hasNoMappedData","selectedFieldIds","onUploadContinue","action","bound","goToUpload","setMapping","setNewFieldMapping","close","onFileSelected","startImport","reset","init","undefined","Object","values","some","mappedIndices","reduce","indices","push","Set","m","kind","fieldId","canCreateNewField","_this$_abortControlle","_abortController","abort","restoreFn","_cancelled","_failedRowIndices","_this$_abortControlle2","_restoreBackup","clearResultAndMoveToStart","force","restoreController","AbortController","signal","error","console","runInAction","discardAndGoBack","discardChangesModal","open","modal","promise","discardAndClose","getDefaultMapping","mapping","field","id","normalizedHeader","matched","find","fieldType","_columnValues","columnIndex","TYPE_SAMPLE_SIZE","applyParsedCsv","parsedCsv","file","bytes","_readFileBytes","_showFileReadErrorToast","content","_decodeUtf8","_rejectFile","parseCsv","name","arrayBuffer","e","TextDecoder","fatal","decode","messageKey","_this$showToast","call","type","message","_this$showToast2","text","onClick","removeToastOnClick","_showPartialSuccessToast","_this$showToast3","String","imported","_downloadFailedRows","_this$downloadCsv","failedRows","unparseCsv","indexOf","_uploadBatches","batches","processedRows","receivedOkResponse","failedRowIndices","batch","batchStart","batchResult","rowIndex","Math","min","_runBackup","restore","_lingerOnCompletion","Promise","resolve","setTimeout","_resolveFieldMapping","resolved","newFields","add","_createRowsBatches","acc","backupFailed","resolvedMapping","loading","success","data","exports"],"sources":["../../../../src/state/ImportState/ImportState.ts"],"sourcesContent":["import {\n action,\n computed,\n makeObservable,\n observable,\n runInAction,\n} from 'mobx';\nimport {\n queryStatus,\n ShowToast,\n TaskStatus,\n PatternsErrorHandler,\n} from '../../model';\nimport { Translate, TranslationsKeys } from '../../services';\nimport { ModalState } from '../ModalState';\nimport { ConditionalModalState } from '../ConditionalModalState';\nimport { CreateExportAsyncJobRequest } from '@wix/bex-utils/@wix/ambassador-fedinfra-exportservice-v1-export-async-job/types';\nimport { ParseCsvResult, parseCsv, unparseCsv } from './parseCsv';\nimport {\n detectColumnType,\n TYPE_SAMPLE_SIZE,\n type DetectColumnType,\n type NewFieldType,\n} from './detectFieldType';\nimport set from 'lodash/set';\n\nexport interface ImportCollection {\n clearResultAndMoveToStart(params?: { force?: boolean }): void;\n}\n\nexport interface BulkUploadError {\n rowIndex: number;\n message?: string;\n code?: string;\n}\n\nexport interface BulkUploadResults {\n succeeded: number;\n failed: number;\n errors: BulkUploadError[];\n insertedIds?: string[];\n}\n\nexport type BulkUploadItemsFn = (\n items: Record<string, unknown>[],\n) => Promise<BulkUploadResults>;\n\nexport interface BackupResult {\n restore(signal: AbortSignal): Promise<void>;\n}\n\nexport type BackupFn = (signal: AbortSignal) => Promise<BackupResult | void>;\n\nexport type DownloadCsvFn = (content: string, fileName: string) => void;\n\nexport type ImportField = NonNullable<\n CreateExportAsyncJobRequest['fields']\n>[number];\n\n// `NewFieldType`, `detectColumnType`, etc. are re-exported from the package via\n// the `ImportState` barrel (`./index`), which also exports `./detectFieldType`.\n\n// A new field to add to the collection schema during import. `key` is decided by\n// Cairo (derived from the column header, deduped) and is also the key the\n// column's values are written under, so the consumer must add the field under\n// exactly this key.\nexport interface NewFieldDefinition {\n key: string;\n type: NewFieldType;\n displayName: string;\n}\n\n/**\n * Consumer-supplied callback that adds the given new fields to the collection\n * schema in a single call, before the rows are uploaded. Mirrors the cm-import\n * `beforeImport`/`updateSchema` flow: Cairo decides the fields (and their keys),\n * the consumer performs one schema mutation (e.g. `updateSchema(collectionId,\n * ...addField(key, config))`). Its presence is also the opt-in for the \"create\n * new field\" default — see `getDefaultMapping`.\n */\nexport type UpdateSchemaFn = (fields: NewFieldDefinition[]) => Promise<void>;\n\n/**\n * How a CSV column is mapped:\n * - `existing` — into an existing collection field by id\n * - `new` — into a new field created during import (always text for now)\n * - `null` — don't import (skip)\n */\nexport type ColumnMapping =\n | { kind: 'existing'; fieldId: string }\n | { kind: 'new'; fieldType: NewFieldType }\n | null;\n\nexport interface ImportStateProps {\n fields: CreateExportAsyncJobRequest['fields'];\n bulkUploadItems: BulkUploadItemsFn;\n backup?: BackupFn;\n updateSchema?: UpdateSchemaFn;\n /**\n * Infers a new field's type from its column data. Defaults to the primitive\n * detector (number / date / boolean / url / text). `@wix/patterns` injects a\n * media-aware detector from `@wix/patterns-fields` (image / video / document /\n * audio) — that detection needs the media URI parser, which core can't depend\n * on.\n */\n detectColumnType?: DetectColumnType;\n collection: ImportCollection;\n importModalState: ModalState;\n translate: Translate;\n errorHandler: PatternsErrorHandler;\n showToast?: ShowToast;\n downloadCsv?: DownloadCsvFn;\n batchSize?: number;\n}\n\nexport type ImportStep = 'upload' | 'configuration' | 'progress';\n\nconst DEFAULT_BATCH_SIZE = 100;\n\n// How long to keep the completed progress bar (100%) on screen before closing\n// the modal on a clean import. Without it, an import of very few rows finishes\n// near-instantly and the modal appears to vanish without ever showing the bar\n// reaching completion.\nconst COMPLETION_LINGER_MS = 600;\n\nfunction normalize(value: string) {\n return value.trim().toLowerCase();\n}\n\n// camelCase key for a field created from a column header\n// (e.g. \"Product Name\" -> \"productName\").\nfunction toFieldKey(header: string): string {\n const words = header.trim().split(/[^a-zA-Z0-9]+/).filter(Boolean);\n if (words.length === 0) {\n return 'field';\n }\n return words\n .map((word, index) =>\n index === 0\n ? word.charAt(0).toLowerCase() + word.slice(1)\n : word.charAt(0).toUpperCase() + word.slice(1),\n )\n .join('');\n}\n\n// A display name + key for a field created from a column header, unique against\n// both `usedNames` (existing field display names + names already assigned to\n// earlier new columns) and `usedKeys` (existing field ids + keys already\n// assigned). Mirrors cm-import `generateFieldNameAndKey`: when the name or its\n// derived key collides, suffix the *display name* as `\"<header>-<n>\"` and\n// re-derive the key from it — so the created field's name and key are both\n// unique (otherwise two columns with the same header would create fields showing\n// the same name).\nfunction uniqueFieldNameAndKey(\n header: string,\n usedNames: Set<string>,\n usedKeys: Set<string>,\n): { displayName: string; key: string } {\n let displayName = header;\n for (let suffix = 1; ; suffix++) {\n const key = toFieldKey(displayName);\n if (!usedNames.has(displayName) && !usedKeys.has(key)) {\n return { displayName, key };\n }\n displayName = `${header}-${suffix}`;\n }\n}\n\nfunction toMappedRows(\n rows: string[][],\n headers: string[],\n mappingByHeader: Record<string, string | null | undefined>,\n) {\n return rows.map((row) => {\n const mapped: Record<string, unknown> = {};\n\n headers.forEach((header, index) => {\n const mappedField = mappingByHeader[header];\n if (mappedField == null) {\n return;\n }\n\n set(mapped, mappedField, row[index] ?? '');\n });\n\n return mapped;\n });\n}\n\nexport class ImportState {\n readonly fields: ImportField[];\n readonly bulkUploadItems: BulkUploadItemsFn;\n readonly backup?: BackupFn;\n readonly updateSchema?: UpdateSchemaFn;\n readonly collection: ImportCollection;\n readonly importModalState: ModalState;\n readonly translate: Translate;\n readonly errorHandler: PatternsErrorHandler;\n readonly showToast?: ShowToast;\n readonly downloadCsv?: DownloadCsvFn;\n readonly batchSize: number;\n private readonly _detectColumnType: DetectColumnType;\n readonly discardChangesModal = new ConditionalModalState<\n 'goBack' | 'close'\n >();\n\n currentStep: ImportStep = 'upload';\n importStatus: TaskStatus<BulkUploadResults, unknown> = {\n ...queryStatus.idle,\n };\n fileName = '';\n csvHeaders: string[] = [];\n csvRows: string[][] = [];\n mappingByHeader: Record<string, ColumnMapping> = {};\n processedCount = 0;\n totalCount = 0;\n result: BulkUploadResults = {\n succeeded: 0,\n failed: 0,\n errors: [],\n };\n isBackingUp = false;\n isRestoring = false;\n private restoreFn: ((signal: AbortSignal) => Promise<void>) | null = null;\n private _cancelled = false;\n private _abortController: AbortController | null = null;\n // Global indices (into `csvRows`) of every row that was not imported: rows\n // the server rejected via a batch's returned `errors`, plus — when a batch\n // throws after some rows succeeded — the throwing batch and all un-attempted\n // rows. Offered to the user as a downloadable CSV via the partial toast.\n private _failedRowIndices: number[] = [];\n\n constructor(props: ImportStateProps) {\n this.fields = (props.fields ?? []) as ImportField[];\n this.bulkUploadItems = props.bulkUploadItems;\n this.backup = props.backup;\n this.updateSchema = props.updateSchema;\n this.collection = props.collection;\n this.importModalState = props.importModalState;\n this.translate = props.translate;\n this.errorHandler = props.errorHandler;\n this.showToast = props.showToast;\n this.downloadCsv = props.downloadCsv;\n this.batchSize = props.batchSize ?? DEFAULT_BATCH_SIZE;\n this._detectColumnType = props.detectColumnType ?? detectColumnType;\n\n makeObservable(this, {\n currentStep: observable.ref,\n importStatus: observable.ref,\n fileName: observable.ref,\n csvHeaders: observable.ref,\n csvRows: observable.ref,\n mappingByHeader: observable.ref,\n processedCount: observable.ref,\n totalCount: observable.ref,\n result: observable.ref,\n isBackingUp: observable.ref,\n isRestoring: observable.ref,\n hasParsedRows: computed,\n hasMappings: computed,\n hasNoMappedData: computed,\n selectedFieldIds: computed,\n onUploadContinue: action.bound,\n goToUpload: action.bound,\n setMapping: action.bound,\n setNewFieldMapping: action.bound,\n close: action.bound,\n onFileSelected: action.bound,\n startImport: action.bound,\n reset: action.bound,\n });\n }\n\n init() {\n return () => undefined;\n }\n\n get hasParsedRows() {\n return this.csvHeaders.length > 0 && this.csvRows.length > 0;\n }\n\n get hasMappings() {\n return Object.values(this.mappingByHeader).some((value) => value != null);\n }\n\n /**\n * True when there are mappings but none of the mapped columns contain any\n * data in any row (including the case of zero data rows). Drives the\n * non-blocking \"no rows found\" warning in the configuration step. Returns\n * false when nothing is mapped yet — that case is handled by the disabled\n * import button instead.\n */\n get hasNoMappedData(): boolean {\n if (!this.hasMappings) {\n return false;\n }\n\n const mappedIndices = this.csvHeaders.reduce<number[]>(\n (indices, header, index) => {\n if (this.mappingByHeader[header] != null) {\n indices.push(index);\n }\n return indices;\n },\n [],\n );\n\n return !this.csvRows.some((row) =>\n mappedIndices.some((index) => (row[index] ?? '').trim() !== ''),\n );\n }\n\n get selectedFieldIds(): Set<string> {\n return new Set(\n Object.values(this.mappingByHeader)\n .filter(\n (m): m is { kind: 'existing'; fieldId: string } =>\n m?.kind === 'existing',\n )\n .map((m) => m.fieldId),\n );\n }\n\n /**\n * Whether columns may be mapped to a brand-new field created during import.\n * Driven purely by the presence of the `updateSchema` callback — providing the\n * capability is the opt-in (see `getDefaultMapping`). Never changes after\n * construction, so it isn't an observable.\n */\n get canCreateNewField(): boolean {\n return this.updateSchema != null;\n }\n\n reset() {\n this._abortController?.abort();\n this._abortController = null;\n this.currentStep = 'upload';\n this.importStatus = {\n ...queryStatus.idle,\n };\n this.fileName = '';\n this.csvHeaders = [];\n this.csvRows = [];\n this.mappingByHeader = {};\n this.processedCount = 0;\n this.totalCount = 0;\n this.result = {\n succeeded: 0,\n failed: 0,\n errors: [],\n };\n this.isBackingUp = false;\n this.isRestoring = false;\n this.restoreFn = null;\n this._cancelled = false;\n this._failedRowIndices = [];\n }\n\n async close() {\n if (this.currentStep === 'progress') {\n this._cancelled = true;\n this._abortController?.abort();\n\n if (!this.isBackingUp) {\n await this._restoreBackup();\n }\n\n this.collection.clearResultAndMoveToStart({\n force: true,\n });\n }\n\n this.importModalState.close();\n }\n\n private async _restoreBackup() {\n const restoreFn = this.restoreFn;\n if (!restoreFn) {\n return;\n }\n\n const restoreController = new AbortController();\n this._abortController = restoreController;\n\n this.isRestoring = true;\n try {\n await restoreFn(restoreController.signal);\n } catch (error) {\n console.error('Restore failed', error);\n }\n runInAction(() => {\n this.isRestoring = false;\n this.restoreFn = null;\n });\n }\n\n goToUpload() {\n this.currentStep = 'upload';\n }\n\n async discardAndGoBack() {\n this.discardChangesModal.open('goBack');\n const { result } = await this.discardChangesModal.modal.promise();\n if (result === 'confirmed') {\n this.goToUpload();\n }\n }\n\n async discardAndClose() {\n this.discardChangesModal.open('close');\n const { result } = await this.discardChangesModal.modal.promise();\n if (result === 'confirmed') {\n this.close();\n }\n }\n\n onUploadContinue() {\n if (this.hasParsedRows) {\n this.currentStep = 'configuration';\n }\n }\n\n private getDefaultMapping(headers: string[]) {\n const mapping: Record<string, ColumnMapping> = {};\n const fields = this.fields.map((field) => ({\n id: field.id ?? '',\n header: field.header ?? '',\n }));\n\n headers.forEach((header, index) => {\n const normalizedHeader = normalize(header);\n const matched = fields.find(\n (field) =>\n normalize(field.id) === normalizedHeader ||\n normalize(field.header) === normalizedHeader,\n );\n\n if (matched?.id) {\n mapping[header] = { kind: 'existing', fieldId: matched.id };\n } else {\n // Unmatched columns default to creating a new field (type inferred from\n // the column's data) when the consumer supplied `updateSchema`;\n // otherwise they default to skip.\n mapping[header] = this.canCreateNewField\n ? {\n kind: 'new',\n fieldType: this._detectColumnType(this._columnValues(index)),\n }\n : null;\n }\n });\n\n return mapping;\n }\n\n // The column's values, capped at the detection sample size — detection only\n // looks at the first `TYPE_SAMPLE_SIZE` values, so avoid copying the whole\n // column (a wide CSV would otherwise allocate rows × columns strings).\n private _columnValues(columnIndex: number): string[] {\n return this.csvRows\n .slice(0, TYPE_SAMPLE_SIZE)\n .map((row) => row[columnIndex] ?? '');\n }\n\n private applyParsedCsv(fileName: string, parsedCsv: ParseCsvResult) {\n this.fileName = fileName;\n this.csvHeaders = parsedCsv.headers;\n this.csvRows = parsedCsv.rows;\n this.mappingByHeader = this.getDefaultMapping(parsedCsv.headers);\n this.currentStep = 'configuration';\n }\n\n async onFileSelected(file: File | null) {\n if (file == null) {\n return;\n }\n\n const bytes = await this._readFileBytes(file);\n if (bytes == null) {\n this._showFileReadErrorToast(file);\n return;\n }\n\n const content = this._decodeUtf8(bytes);\n if (content == null) {\n this._rejectFile(file, 'cairo.import.encodingFailed');\n return;\n }\n\n const parsedCsv = parseCsv(content);\n if ('code' in parsedCsv) {\n this._rejectFile(file, 'cairo.import.processFailed');\n return;\n }\n\n runInAction(() => {\n this.applyParsedCsv(file.name, parsedCsv);\n });\n }\n\n private async _readFileBytes(file: File): Promise<ArrayBuffer | null> {\n try {\n return await file.arrayBuffer();\n } catch (e) {\n console.error(e);\n return null;\n }\n }\n\n private _decodeUtf8(bytes: ArrayBuffer): string | null {\n try {\n // `fatal: true` throws on any byte sequence that isn't valid UTF-8,\n // so encoding is validated against the raw bytes before decoding —\n // unlike `File.text()`, which silently substitutes U+FFFD.\n return new TextDecoder('utf-8', { fatal: true }).decode(bytes);\n } catch (e) {\n console.error(e);\n return null;\n }\n }\n\n private _rejectFile(file: File, messageKey: TranslationsKeys) {\n runInAction(() => {\n this.fileName = file.name;\n this.csvHeaders = [];\n this.csvRows = [];\n this.mappingByHeader = {};\n this.currentStep = 'upload';\n });\n this.showToast?.({\n type: 'ERROR',\n message: this.translate(messageKey),\n });\n }\n\n private _showFileReadErrorToast(file: File) {\n this.showToast?.({\n type: 'ERROR',\n message: this.translate('cairo.import.fileReadFailed'),\n action: {\n text: this.translate('cairo.import.tryAgain'),\n onClick: () => this.onFileSelected(file),\n removeToastOnClick: true,\n },\n });\n }\n\n private _showPartialSuccessToast() {\n const failed = this._failedRowIndices.length;\n this.showToast?.({\n type: 'WARNING',\n message: this.translate('cairo.import.partialSuccessToast', {\n failed: String(failed),\n imported: String(this.totalCount - failed),\n }),\n action: {\n text: this.translate('cairo.import.downloadFailedRows'),\n onClick: () => this._downloadFailedRows(),\n removeToastOnClick: true,\n },\n });\n }\n\n private _downloadFailedRows() {\n const failedRows = this._failedRowIndices.map(\n (index) => this.csvRows[index],\n );\n const content = unparseCsv(this.csvHeaders, failedRows);\n this.downloadCsv?.(content, `failed-${this.fileName || 'import.csv'}`);\n }\n\n setMapping(header: string, fieldId: string | null) {\n this.mappingByHeader = {\n ...this.mappingByHeader,\n [header]: fieldId == null ? null : { kind: 'existing', fieldId },\n };\n }\n\n setNewFieldMapping(header: string) {\n const index = this.csvHeaders.indexOf(header);\n const fieldType =\n index >= 0 ? this._detectColumnType(this._columnValues(index)) : 'text';\n this.mappingByHeader = {\n ...this.mappingByHeader,\n [header]: { kind: 'new', fieldType },\n };\n }\n\n private async _uploadBatches(batches: Record<string, unknown>[][]) {\n let processedRows = 0;\n let receivedOkResponse = false;\n const failedRowIndices: number[] = [];\n\n for (const batch of batches) {\n if (this._cancelled) {\n break;\n }\n\n const batchStart = processedRows;\n\n try {\n const batchResult = await this.bulkUploadItems(batch);\n receivedOkResponse = true;\n\n this.result = {\n succeeded: this.result.succeeded + batchResult.succeeded,\n failed: this.result.failed + batchResult.failed,\n errors: [...this.result.errors, ...batchResult.errors],\n };\n\n // Rows the server rejected within an otherwise-OK response. `rowIndex`\n // is relative to the batch, so offset it to a global `csvRows` index.\n for (const { rowIndex } of batchResult.errors) {\n failedRowIndices.push(batchStart + rowIndex);\n }\n } catch (error) {\n // Full batch failure: a batch threw before any OK response came back.\n // Surface it as an error state with a \"Try again\" action by rejecting\n // up to `startImport`, instead of reporting a partial success.\n if (!receivedOkResponse) {\n throw error;\n }\n\n // A batch threw after some rows were already imported. Every row from\n // the throwing batch onward (including the batches we won't attempt)\n // counts as failed, on top of any rows already rejected via returned\n // errors in earlier batches.\n for (let index = batchStart; index < this.totalCount; index++) {\n failedRowIndices.push(index);\n }\n\n break;\n }\n\n processedRows += batch.length;\n\n runInAction(() => {\n this.processedCount = Math.min(processedRows, this.totalCount);\n });\n }\n\n this._failedRowIndices = failedRowIndices;\n\n return this.result;\n }\n\n private async _runBackup(): Promise<boolean> {\n const backup = this.backup;\n if (!backup) {\n return false;\n }\n\n try {\n const result = await backup(this._abortController!.signal);\n if (this._cancelled) {\n return true;\n }\n if (result?.restore) {\n this.restoreFn = result.restore;\n }\n } catch (error) {\n if (this._cancelled) {\n return true;\n }\n runInAction(() => {\n this.isBackingUp = false;\n this.importStatus = {\n ...queryStatus.error,\n error,\n };\n });\n return true;\n }\n\n runInAction(() => {\n this.isBackingUp = false;\n });\n return false;\n }\n\n private _lingerOnCompletion() {\n return new Promise<void>((resolve) =>\n setTimeout(resolve, COMPLETION_LINGER_MS),\n );\n }\n\n /**\n * Resolves every column to the final destination key used in the upload\n * payload: an existing field id, a new field's (Cairo-decided) key, or `null`\n * to skip. All new fields are added to the schema in a single `updateSchema`\n * call before the rows upload — mirroring the cm-import `beforeImport` flow.\n * `updateSchema` may throw — `startImport` surfaces that as the error state.\n */\n private async _resolveFieldMapping(): Promise<Record<string, string | null>> {\n const resolved: Record<string, string | null> = {};\n const newFields: NewFieldDefinition[] = [];\n // Seed with existing field ids/display names so derived keys and names never\n // collide with them or with each other.\n const usedKeys = new Set(\n this.fields.map((field) => field.id).filter((id): id is string => !!id),\n );\n const usedNames = new Set(\n this.fields\n .map((field) => field.header)\n .filter((header): header is string => !!header),\n );\n\n for (const header of this.csvHeaders) {\n const mapping = this.mappingByHeader[header];\n\n if (mapping == null) {\n resolved[header] = null;\n } else if (mapping.kind === 'existing') {\n resolved[header] = mapping.fieldId;\n } else if (this.updateSchema) {\n const { displayName, key } = uniqueFieldNameAndKey(\n header,\n usedNames,\n usedKeys,\n );\n usedKeys.add(key);\n usedNames.add(displayName);\n newFields.push({ key, type: mapping.fieldType, displayName });\n resolved[header] = key;\n } else {\n // \"new\" mapping without an `updateSchema` callback — nothing to map into.\n resolved[header] = null;\n }\n }\n\n if (newFields.length > 0 && this.updateSchema) {\n await this.updateSchema(newFields);\n }\n\n return resolved;\n }\n\n private _createRowsBatches(rows: Record<string, unknown>[]) {\n return rows.reduce<Record<string, unknown>[][]>((acc, row, index) => {\n if (index % this.batchSize === 0) {\n acc.push([]);\n }\n acc[acc.length - 1].push(row);\n return acc;\n }, []);\n }\n\n async startImport() {\n if (!this.hasMappings) {\n return;\n }\n\n this._cancelled = false;\n this._abortController = new AbortController();\n\n // One mapped row is produced per CSV row, so the total is known up front and\n // doesn't depend on field creation below.\n const totalCount = this.csvRows.length;\n\n runInAction(() => {\n this.currentStep = 'progress';\n this.totalCount = totalCount;\n this.processedCount = 0;\n this.isBackingUp = !!this.backup;\n // Clear any error/result from a previous attempt so \"Try again\" starts\n // from a clean slate (e.g. after a backup failure).\n this.importStatus = { ...queryStatus.idle };\n this.result = {\n succeeded: 0,\n failed: 0,\n errors: [],\n };\n this._failedRowIndices = [];\n });\n\n const backupFailed = await this._runBackup();\n if (backupFailed) {\n return;\n }\n if (this._cancelled) {\n return;\n }\n\n // Create any new fields and resolve every column to its destination key\n // before building the payload. A creation failure surfaces as the error\n // state with a \"Try again\" CTA, like a first-batch upload failure.\n let resolvedMapping: Record<string, string | null>;\n try {\n resolvedMapping = await this._resolveFieldMapping();\n } catch (error) {\n runInAction(() => {\n this.importStatus = {\n ...queryStatus.error,\n error,\n };\n });\n return;\n }\n if (this._cancelled) {\n return;\n }\n\n const rows = toMappedRows(this.csvRows, this.csvHeaders, resolvedMapping);\n const batches = this._createRowsBatches(rows);\n\n const promise = this._uploadBatches(batches);\n\n this.importStatus = {\n ...queryStatus.loading,\n promise,\n };\n\n try {\n await promise;\n if (this._cancelled) {\n return;\n }\n\n runInAction(() => {\n this.importStatus = {\n ...queryStatus.success,\n data: this.result,\n };\n });\n\n // On a clean import, hold the completed (100%) progress bar on screen\n // briefly so the completion is perceptible even for very few rows. Skip\n // the wait when there are failed rows — that path closes and surfaces a\n // toast instead.\n if (this._failedRowIndices.length === 0) {\n await this._lingerOnCompletion();\n if (this._cancelled) {\n return;\n }\n }\n\n runInAction(() => {\n // Any rows that didn't make it in — whether rejected via a batch's\n // returned `errors` or left unimported when a batch threw — are\n // reported via a toast that offers them as a downloadable CSV.\n if (this._failedRowIndices.length > 0) {\n this._showPartialSuccessToast();\n }\n\n this.importModalState.close();\n this.collection.clearResultAndMoveToStart({ force: true });\n });\n } catch (error) {\n runInAction(() => {\n this.importStatus = {\n ...queryStatus.error,\n error,\n };\n });\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}