@commercetools-frontend-extensions/operations 0.0.0-canary-20251215104232 → 0.0.0-canary-20251216095330

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/CHANGELOG.md CHANGED
@@ -1,6 +1,12 @@
1
1
  # @commercetools-frontend-extensions/operations
2
2
 
3
- ## 0.0.0-canary-20251215104232
3
+ ## 0.0.0-canary-20251216095330
4
+
5
+ ### Minor Changes
6
+
7
+ - [#1684](https://github.com/commercetools/merchant-center-operations/pull/1684) [`6dbe7fc`](https://github.com/commercetools/merchant-center-operations/commit/6dbe7fcff7440e42df01aaaf89dad93cb3bb3126) Thanks [@yassinejebli](https://github.com/yassinejebli)! - fix(import-details): fix progress calculation for new file import flow
8
+
9
+ ## 3.1.2
4
10
 
5
11
  ### Patch Changes
6
12
 
@@ -22,8 +22,8 @@ var _inherits = require('@babel/runtime-corejs3/helpers/inherits');
22
22
  var _wrapNativeSuper = require('@babel/runtime-corejs3/helpers/wrapNativeSuper');
23
23
  var constants = require('@commercetools-frontend/constants');
24
24
  var _everyInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/every');
25
- var _Array$isArray = require('@babel/runtime-corejs3/core-js-stable/array/is-array');
26
25
  var pluralize = require('pluralize');
26
+ var _Array$isArray = require('@babel/runtime-corejs3/core-js-stable/array/is-array');
27
27
  var _reduceInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/reduce');
28
28
  var _flatMapInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/flat-map');
29
29
  var _mapInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/map');
@@ -371,14 +371,9 @@ function assertProcessFileImportJobResponse(maybeResponse) {
371
371
  throw new Error('Invalid Process File Import Job response');
372
372
  }
373
373
  function assertListFileImportJobsResponse(maybeResponse) {
374
- if (!_Array$isArray__default["default"](maybeResponse)) {
375
- throw new Error('Invalid List File Import Jobs response: expected an array');
376
- }
377
- if (maybeResponse.length > 0) {
378
- const requiredFields = ['id', 'fileName', 'importContainerKey', 'state'];
379
- if (!hasRequiredFields(maybeResponse[0], requiredFields)) {
380
- throw new Error('Invalid List File Import Jobs response: missing required fields');
381
- }
374
+ const requiredFields = ['results', 'total', 'limit', 'offset', 'count'];
375
+ if (!hasRequiredFields(maybeResponse, requiredFields)) {
376
+ throw new Error('Invalid List File Import Jobs response: missing required fields');
382
377
  }
383
378
  }
384
379
 
@@ -1160,10 +1155,46 @@ async function listFileImportJobs(_ref6) {
1160
1155
  assertListFileImportJobsResponse(response);
1161
1156
  return response;
1162
1157
  }
1158
+ /**
1159
+ * Gets the file import job info for an import container
1160
+ *
1161
+ * For the new file import job flow, import operations are created incrementally
1162
+ * during the 'initialising' state. The import summary total
1163
+ * reflects only the operations created so far, which can be misleading
1164
+ *
1165
+ * This helper fetches the file import job (if it exists) to get:
1166
+ * - The true total from the job summary (known from initial CSV validation)
1167
+ * - Whether the job is still initializing (creating import operations)
1168
+ *
1169
+ * @returns Job info if found, null otherwise
1170
+ */
1171
+ async function getFileImportJobInfoForContainer(_ref7) {
1172
+ let projectKey = _ref7.projectKey,
1173
+ importContainerKey = _ref7.importContainerKey;
1174
+ try {
1175
+ const response = await listFileImportJobs({
1176
+ projectKey,
1177
+ importContainerKey,
1178
+ limit: 1
1179
+ });
1180
+ if (response.results.length > 0 && response.results[0].summary?.total != null) {
1181
+ const job = response.results[0];
1182
+ return {
1183
+ total: job.summary.total,
1184
+ isInitializing: job.state === 'initialising'
1185
+ };
1186
+ }
1187
+ return null;
1188
+ } catch {
1189
+ // Job might not exist (old flow)
1190
+ return null;
1191
+ }
1192
+ }
1163
1193
 
1164
1194
  function ownKeys$6(e, r) { var t = _Object$keys__default["default"](e); if (_Object$getOwnPropertySymbols__default["default"]) { var o = _Object$getOwnPropertySymbols__default["default"](e); r && (o = _filterInstanceProperty__default["default"](o).call(o, function (r) { return _Object$getOwnPropertyDescriptor__default["default"](e, r).enumerable; })), t.push.apply(t, o); } return t; }
1165
1195
  function _objectSpread$6(e) { for (var r = 1; r < arguments.length; r++) { var _context2, _context3; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context2 = ownKeys$6(Object(t), !0)).call(_context2, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context3 = ownKeys$6(Object(t))).call(_context3, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; }
1166
1196
  function getImportState(importSummary) {
1197
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1167
1198
  const processing = importSummary.states.processing > 0;
1168
1199
  if (processing) return ImportStates.Processing;
1169
1200
  const waitForUnresolvedReferences = importSummary.states.waitForMasterVariant > 0 || importSummary.states.unresolved > 0;
@@ -1172,6 +1203,11 @@ function getImportState(importSummary) {
1172
1203
  if (partiallyCompleted) return ImportStates.PartiallyCompleted;
1173
1204
  const noRunning = importSummary.total === 0;
1174
1205
  if (noRunning) return ImportStates.NoRunningImports;
1206
+
1207
+ // For the new flow: job is actively creating import operations (to show as Processing even if no operations exist yet)
1208
+ if (options.isJobInitializing) {
1209
+ return ImportStates.Processing;
1210
+ }
1175
1211
  const successfullyCompleted = importSummary.states.imported === importSummary.total || importSummary.states.deleted === importSummary.total;
1176
1212
  if (successfullyCompleted) return ImportStates.SuccessfullyCompleted;
1177
1213
  const failed = importSummary.states.rejected + importSummary.states.validationFailed === importSummary.total;
@@ -1320,12 +1356,33 @@ async function cancelImportContainerByKey(_ref8) {
1320
1356
  return response;
1321
1357
  }
1322
1358
  async function importContainerToContainerDetails(projectKey, importContainer) {
1323
- const importSummary = await fetchImportSummary({
1359
+ let importSummary = await fetchImportSummary({
1324
1360
  projectKey,
1325
1361
  importContainerKey: importContainer.key
1326
1362
  });
1327
- const importState = getImportState(importSummary);
1328
1363
  const isFileUploadImport = checkIfFileUploadImport(importContainer.tags);
1364
+
1365
+ // For the new file import job flow the import operations are created incrementally
1366
+ // The import summary total reflects only operations created so far
1367
+ // Only override total when job is actively initializing (creating operations)
1368
+ let isJobInitializing = false;
1369
+ if (isFileUploadImport) {
1370
+ const jobInfo = await getFileImportJobInfoForContainer({
1371
+ projectKey,
1372
+ importContainerKey: importContainer.key
1373
+ });
1374
+ if (jobInfo !== null) {
1375
+ isJobInitializing = jobInfo.isInitializing;
1376
+ if (isJobInitializing || importSummary.total > 0) {
1377
+ importSummary = _objectSpread$6(_objectSpread$6({}, importSummary), {}, {
1378
+ total: jobInfo.total
1379
+ });
1380
+ }
1381
+ }
1382
+ }
1383
+ const importState = getImportState(importSummary, {
1384
+ isJobInitializing
1385
+ });
1329
1386
  return {
1330
1387
  importContainer: importContainer,
1331
1388
  importState,
@@ -3324,6 +3381,7 @@ exports.getFileImportJob = getFileImportJob;
3324
3381
  exports.getFileImportJobByIdURL = getFileImportJobByIdURL;
3325
3382
  exports.getFileImportJobDeleteURL = getFileImportJobDeleteURL;
3326
3383
  exports.getFileImportJobFileType = getFileImportJobFileType;
3384
+ exports.getFileImportJobInfoForContainer = getFileImportJobInfoForContainer;
3327
3385
  exports.getFileImportJobProcessURL = getFileImportJobProcessURL;
3328
3386
  exports.getFileImportJobRecords = getFileImportJobRecords;
3329
3387
  exports.getFileImportJobRecordsURL = getFileImportJobRecordsURL;
@@ -22,8 +22,8 @@ var _inherits = require('@babel/runtime-corejs3/helpers/inherits');
22
22
  var _wrapNativeSuper = require('@babel/runtime-corejs3/helpers/wrapNativeSuper');
23
23
  var constants = require('@commercetools-frontend/constants');
24
24
  var _everyInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/every');
25
- var _Array$isArray = require('@babel/runtime-corejs3/core-js-stable/array/is-array');
26
25
  var pluralize = require('pluralize');
26
+ var _Array$isArray = require('@babel/runtime-corejs3/core-js-stable/array/is-array');
27
27
  var _reduceInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/reduce');
28
28
  var _flatMapInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/flat-map');
29
29
  var _mapInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/map');
@@ -371,14 +371,9 @@ function assertProcessFileImportJobResponse(maybeResponse) {
371
371
  throw new Error('Invalid Process File Import Job response');
372
372
  }
373
373
  function assertListFileImportJobsResponse(maybeResponse) {
374
- if (!_Array$isArray__default["default"](maybeResponse)) {
375
- throw new Error('Invalid List File Import Jobs response: expected an array');
376
- }
377
- if (maybeResponse.length > 0) {
378
- const requiredFields = ['id', 'fileName', 'importContainerKey', 'state'];
379
- if (!hasRequiredFields(maybeResponse[0], requiredFields)) {
380
- throw new Error('Invalid List File Import Jobs response: missing required fields');
381
- }
374
+ const requiredFields = ['results', 'total', 'limit', 'offset', 'count'];
375
+ if (!hasRequiredFields(maybeResponse, requiredFields)) {
376
+ throw new Error('Invalid List File Import Jobs response: missing required fields');
382
377
  }
383
378
  }
384
379
 
@@ -1160,10 +1155,46 @@ async function listFileImportJobs(_ref6) {
1160
1155
  assertListFileImportJobsResponse(response);
1161
1156
  return response;
1162
1157
  }
1158
+ /**
1159
+ * Gets the file import job info for an import container
1160
+ *
1161
+ * For the new file import job flow, import operations are created incrementally
1162
+ * during the 'initialising' state. The import summary total
1163
+ * reflects only the operations created so far, which can be misleading
1164
+ *
1165
+ * This helper fetches the file import job (if it exists) to get:
1166
+ * - The true total from the job summary (known from initial CSV validation)
1167
+ * - Whether the job is still initializing (creating import operations)
1168
+ *
1169
+ * @returns Job info if found, null otherwise
1170
+ */
1171
+ async function getFileImportJobInfoForContainer(_ref7) {
1172
+ let projectKey = _ref7.projectKey,
1173
+ importContainerKey = _ref7.importContainerKey;
1174
+ try {
1175
+ const response = await listFileImportJobs({
1176
+ projectKey,
1177
+ importContainerKey,
1178
+ limit: 1
1179
+ });
1180
+ if (response.results.length > 0 && response.results[0].summary?.total != null) {
1181
+ const job = response.results[0];
1182
+ return {
1183
+ total: job.summary.total,
1184
+ isInitializing: job.state === 'initialising'
1185
+ };
1186
+ }
1187
+ return null;
1188
+ } catch {
1189
+ // Job might not exist (old flow)
1190
+ return null;
1191
+ }
1192
+ }
1163
1193
 
1164
1194
  function ownKeys$6(e, r) { var t = _Object$keys__default["default"](e); if (_Object$getOwnPropertySymbols__default["default"]) { var o = _Object$getOwnPropertySymbols__default["default"](e); r && (o = _filterInstanceProperty__default["default"](o).call(o, function (r) { return _Object$getOwnPropertyDescriptor__default["default"](e, r).enumerable; })), t.push.apply(t, o); } return t; }
1165
1195
  function _objectSpread$6(e) { for (var r = 1; r < arguments.length; r++) { var _context2, _context3; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context2 = ownKeys$6(Object(t), !0)).call(_context2, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context3 = ownKeys$6(Object(t))).call(_context3, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; }
1166
1196
  function getImportState(importSummary) {
1197
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1167
1198
  const processing = importSummary.states.processing > 0;
1168
1199
  if (processing) return ImportStates.Processing;
1169
1200
  const waitForUnresolvedReferences = importSummary.states.waitForMasterVariant > 0 || importSummary.states.unresolved > 0;
@@ -1172,6 +1203,11 @@ function getImportState(importSummary) {
1172
1203
  if (partiallyCompleted) return ImportStates.PartiallyCompleted;
1173
1204
  const noRunning = importSummary.total === 0;
1174
1205
  if (noRunning) return ImportStates.NoRunningImports;
1206
+
1207
+ // For the new flow: job is actively creating import operations (to show as Processing even if no operations exist yet)
1208
+ if (options.isJobInitializing) {
1209
+ return ImportStates.Processing;
1210
+ }
1175
1211
  const successfullyCompleted = importSummary.states.imported === importSummary.total || importSummary.states.deleted === importSummary.total;
1176
1212
  if (successfullyCompleted) return ImportStates.SuccessfullyCompleted;
1177
1213
  const failed = importSummary.states.rejected + importSummary.states.validationFailed === importSummary.total;
@@ -1320,12 +1356,33 @@ async function cancelImportContainerByKey(_ref8) {
1320
1356
  return response;
1321
1357
  }
1322
1358
  async function importContainerToContainerDetails(projectKey, importContainer) {
1323
- const importSummary = await fetchImportSummary({
1359
+ let importSummary = await fetchImportSummary({
1324
1360
  projectKey,
1325
1361
  importContainerKey: importContainer.key
1326
1362
  });
1327
- const importState = getImportState(importSummary);
1328
1363
  const isFileUploadImport = checkIfFileUploadImport(importContainer.tags);
1364
+
1365
+ // For the new file import job flow the import operations are created incrementally
1366
+ // The import summary total reflects only operations created so far
1367
+ // Only override total when job is actively initializing (creating operations)
1368
+ let isJobInitializing = false;
1369
+ if (isFileUploadImport) {
1370
+ const jobInfo = await getFileImportJobInfoForContainer({
1371
+ projectKey,
1372
+ importContainerKey: importContainer.key
1373
+ });
1374
+ if (jobInfo !== null) {
1375
+ isJobInitializing = jobInfo.isInitializing;
1376
+ if (isJobInitializing || importSummary.total > 0) {
1377
+ importSummary = _objectSpread$6(_objectSpread$6({}, importSummary), {}, {
1378
+ total: jobInfo.total
1379
+ });
1380
+ }
1381
+ }
1382
+ }
1383
+ const importState = getImportState(importSummary, {
1384
+ isJobInitializing
1385
+ });
1329
1386
  return {
1330
1387
  importContainer: importContainer,
1331
1388
  importState,
@@ -3316,6 +3373,7 @@ exports.getFileImportJob = getFileImportJob;
3316
3373
  exports.getFileImportJobByIdURL = getFileImportJobByIdURL;
3317
3374
  exports.getFileImportJobDeleteURL = getFileImportJobDeleteURL;
3318
3375
  exports.getFileImportJobFileType = getFileImportJobFileType;
3376
+ exports.getFileImportJobInfoForContainer = getFileImportJobInfoForContainer;
3319
3377
  exports.getFileImportJobProcessURL = getFileImportJobProcessURL;
3320
3378
  exports.getFileImportJobRecords = getFileImportJobRecords;
3321
3379
  exports.getFileImportJobRecordsURL = getFileImportJobRecordsURL;
@@ -18,8 +18,8 @@ import _inherits from '@babel/runtime-corejs3/helpers/esm/inherits';
18
18
  import _wrapNativeSuper from '@babel/runtime-corejs3/helpers/esm/wrapNativeSuper';
19
19
  import { MC_API_PROXY_TARGETS } from '@commercetools-frontend/constants';
20
20
  import _everyInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/every';
21
- import _Array$isArray from '@babel/runtime-corejs3/core-js-stable/array/is-array';
22
21
  import { plural } from 'pluralize';
22
+ import _Array$isArray from '@babel/runtime-corejs3/core-js-stable/array/is-array';
23
23
  import _reduceInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/reduce';
24
24
  import _flatMapInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/flat-map';
25
25
  import _mapInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/map';
@@ -331,14 +331,9 @@ function assertProcessFileImportJobResponse(maybeResponse) {
331
331
  throw new Error('Invalid Process File Import Job response');
332
332
  }
333
333
  function assertListFileImportJobsResponse(maybeResponse) {
334
- if (!_Array$isArray(maybeResponse)) {
335
- throw new Error('Invalid List File Import Jobs response: expected an array');
336
- }
337
- if (maybeResponse.length > 0) {
338
- const requiredFields = ['id', 'fileName', 'importContainerKey', 'state'];
339
- if (!hasRequiredFields(maybeResponse[0], requiredFields)) {
340
- throw new Error('Invalid List File Import Jobs response: missing required fields');
341
- }
334
+ const requiredFields = ['results', 'total', 'limit', 'offset', 'count'];
335
+ if (!hasRequiredFields(maybeResponse, requiredFields)) {
336
+ throw new Error('Invalid List File Import Jobs response: missing required fields');
342
337
  }
343
338
  }
344
339
 
@@ -1120,10 +1115,46 @@ async function listFileImportJobs(_ref6) {
1120
1115
  assertListFileImportJobsResponse(response);
1121
1116
  return response;
1122
1117
  }
1118
+ /**
1119
+ * Gets the file import job info for an import container
1120
+ *
1121
+ * For the new file import job flow, import operations are created incrementally
1122
+ * during the 'initialising' state. The import summary total
1123
+ * reflects only the operations created so far, which can be misleading
1124
+ *
1125
+ * This helper fetches the file import job (if it exists) to get:
1126
+ * - The true total from the job summary (known from initial CSV validation)
1127
+ * - Whether the job is still initializing (creating import operations)
1128
+ *
1129
+ * @returns Job info if found, null otherwise
1130
+ */
1131
+ async function getFileImportJobInfoForContainer(_ref7) {
1132
+ let projectKey = _ref7.projectKey,
1133
+ importContainerKey = _ref7.importContainerKey;
1134
+ try {
1135
+ const response = await listFileImportJobs({
1136
+ projectKey,
1137
+ importContainerKey,
1138
+ limit: 1
1139
+ });
1140
+ if (response.results.length > 0 && response.results[0].summary?.total != null) {
1141
+ const job = response.results[0];
1142
+ return {
1143
+ total: job.summary.total,
1144
+ isInitializing: job.state === 'initialising'
1145
+ };
1146
+ }
1147
+ return null;
1148
+ } catch {
1149
+ // Job might not exist (old flow)
1150
+ return null;
1151
+ }
1152
+ }
1123
1153
 
1124
1154
  function ownKeys$6(e, r) { var t = _Object$keys(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = _filterInstanceProperty(o).call(o, function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
1125
1155
  function _objectSpread$6(e) { for (var r = 1; r < arguments.length; r++) { var _context2, _context3; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty(_context2 = ownKeys$6(Object(t), !0)).call(_context2, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : _forEachInstanceProperty(_context3 = ownKeys$6(Object(t))).call(_context3, function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
1126
1156
  function getImportState(importSummary) {
1157
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1127
1158
  const processing = importSummary.states.processing > 0;
1128
1159
  if (processing) return ImportStates.Processing;
1129
1160
  const waitForUnresolvedReferences = importSummary.states.waitForMasterVariant > 0 || importSummary.states.unresolved > 0;
@@ -1132,6 +1163,11 @@ function getImportState(importSummary) {
1132
1163
  if (partiallyCompleted) return ImportStates.PartiallyCompleted;
1133
1164
  const noRunning = importSummary.total === 0;
1134
1165
  if (noRunning) return ImportStates.NoRunningImports;
1166
+
1167
+ // For the new flow: job is actively creating import operations (to show as Processing even if no operations exist yet)
1168
+ if (options.isJobInitializing) {
1169
+ return ImportStates.Processing;
1170
+ }
1135
1171
  const successfullyCompleted = importSummary.states.imported === importSummary.total || importSummary.states.deleted === importSummary.total;
1136
1172
  if (successfullyCompleted) return ImportStates.SuccessfullyCompleted;
1137
1173
  const failed = importSummary.states.rejected + importSummary.states.validationFailed === importSummary.total;
@@ -1280,12 +1316,33 @@ async function cancelImportContainerByKey(_ref8) {
1280
1316
  return response;
1281
1317
  }
1282
1318
  async function importContainerToContainerDetails(projectKey, importContainer) {
1283
- const importSummary = await fetchImportSummary({
1319
+ let importSummary = await fetchImportSummary({
1284
1320
  projectKey,
1285
1321
  importContainerKey: importContainer.key
1286
1322
  });
1287
- const importState = getImportState(importSummary);
1288
1323
  const isFileUploadImport = checkIfFileUploadImport(importContainer.tags);
1324
+
1325
+ // For the new file import job flow the import operations are created incrementally
1326
+ // The import summary total reflects only operations created so far
1327
+ // Only override total when job is actively initializing (creating operations)
1328
+ let isJobInitializing = false;
1329
+ if (isFileUploadImport) {
1330
+ const jobInfo = await getFileImportJobInfoForContainer({
1331
+ projectKey,
1332
+ importContainerKey: importContainer.key
1333
+ });
1334
+ if (jobInfo !== null) {
1335
+ isJobInitializing = jobInfo.isInitializing;
1336
+ if (isJobInitializing || importSummary.total > 0) {
1337
+ importSummary = _objectSpread$6(_objectSpread$6({}, importSummary), {}, {
1338
+ total: jobInfo.total
1339
+ });
1340
+ }
1341
+ }
1342
+ }
1343
+ const importState = getImportState(importSummary, {
1344
+ isJobInitializing
1345
+ });
1289
1346
  return {
1290
1347
  importContainer: importContainer,
1291
1348
  importState,
@@ -3192,4 +3249,4 @@ const useFileUpload = _ref2 => {
3192
3249
  };
3193
3250
  };
3194
3251
 
3195
- export { ActiveDragDropArea, COLUMN_DELIMITERS, CT_API_DOCS_URL, DELIMITERS, DisabledDropArea, DropAreaWrapper, EnabledDropArea, FILE_IMPORT_JOB_POLLING_INTERVAL, FileDropArea, FileDroppedArea, FileIcon, HttpError, IMPORT_LEGACY_MAX_FILE_SIZE_MB, IMPORT_LEGACY_MAX_ROW_COUNT, IMPORT_MAX_FILE_SIZE_MB, IMPORT_MAX_ITEM_COUNT, IMPORT_TAG_KEYS, IMPORT_TAG_VALUES, ImportStates, InfoBox, InvalidResponseError, LockIcon, NoResourcesToExportError, PollingAbortedError, ProjectKeyNotAvailableError, QueryPredicateError, RESOURCE_TYPE_DOCUMENTATION_LINKS, RESOURCE_TYPE_TEMPLATE_DOWNLOAD_LINKS, TAG_KEY_SOURCE_FILE_UPLOAD, UnexpectedColumnError, UnexpectedOperationStateError, UnexpectedResourceTypeError, UploadSeparator, UploadSettings, UploadingModal, allAutomatedImportOperations, allAutomatedImportOperationsResponse, allFileUploadImportOperations, allFileUploadImportOperationsResponse, appendCsvOrJsonExtensionIfAbsent, assertCancelContainerResponse, assertExportOperationsDownloadFileResponse, assertFileImportJob, assertFileImportJobRecordsResponse, assertFileUploadResponse, assertImportContainer, assertImportContainerPagedResponse, assertImportOperationPagedResponse, assertImportSummary, assertListFileImportJobsResponse, assertPaginatedExportOperationResponse, assertProcessFileImportJobResponse, assertProcessFileResponse, assertResourceType, automatedImportContainerKey, automatedImports, cancelImportContainerByKey, checkIfFileUploadImport, convertFileSizeToKB, countJsonFileItems, countUniqueResourcesInCsv, createFileImportJob, createImportContainerForFileUpload, decodeFileNameFromImportContainerKey, deleteFileImportJob, deleteImportContainer, dropAreaStyles, encodeFileNameWithTimestampToContainerKey, exportOperationsCompleted, exportOperationsProcessing, extractErrorDescriptionFromValidationMessage, fetchExportOperations, fetchImportContainerByKey, fetchImportContainerDetails, fetchImportContainers, fetchImportOperations, fetchImportSummaries, fetchImportSummary, fetchUsingXhr, fetcher, fileUploadImportContainerKey, fileUploadMissingKeysResponse, formatErrorCode, formatKeys, formatQueryString, getCreateImportContainerURL, getDeleteImportContainerURL, getExportOperationsURL, getFileImportJob, getFileImportJobByIdURL, getFileImportJobDeleteURL, getFileImportJobFileType, getFileImportJobProcessURL, getFileImportJobRecords, getFileImportJobRecordsURL, getFileImportJobsListURL, getFileImportJobsURL, getFileUploadErrorsCount, getFileUploadURL, getImportContainerByKeyURL, getImportContainerTasksURL, getImportContainersURL, getImportOperationsURL, getImportState, getImportSummaryURL, getMissingRequiredFields, getProccessFileURL, getRowCount, getValidatedColumns, hasImportJobStartedProcessing, hasOwnProperty, hasRequiredFields, hasSingleKeyColumn, importContainers, importStatesMap, importsSummaries, invalidFileImportJobRecordsResponse, invalidFileImportJobValidated, invalidFileUploadResponse, isAbortError, isError, isImportJobInitializing, isImportJobProcessing, isImportJobQueued, isImportJobReady, isImportJobRejected, isImportJobTerminal, isImportJobValidated, isResourceType, listFileImportJobs, manualImports, mapFileUploadErrorsToUploadFileErrorRows, mapFormikErrors, mapUploadFileErrorsResponseToUploadFileErrorRows, pollJobUntilProcessing, pollJobUntilValidated, processFileImportJob, processFileImportJobResponse, processUploadedFile, shouldContinuePollingForImportValidation, successfulAutomatedImportOperations, successfulAutomatedImportOperationsResponse, successfulFileUploadImportOperations, successfulFileUploadImportOperationsResponse, toBytes, toImportApiResourceType, uploadFileForImport, useFetchExportOperations, useFetchFileImportJob, useFetchFileImportJobRecords, useFetchImportContainerDetails, useFetchImportOperations, useFetchImportSummaries, useFileImportJobUpload, useFileUpload, useImportContainerUpload, validFileImportJobProcessing, validFileImportJobQueued, validFileImportJobRecordsResponse, validFileImportJobValidated, validFileUploadResponse, validProcessFileResponse, validateDelimiter };
3252
+ export { ActiveDragDropArea, COLUMN_DELIMITERS, CT_API_DOCS_URL, DELIMITERS, DisabledDropArea, DropAreaWrapper, EnabledDropArea, FILE_IMPORT_JOB_POLLING_INTERVAL, FileDropArea, FileDroppedArea, FileIcon, HttpError, IMPORT_LEGACY_MAX_FILE_SIZE_MB, IMPORT_LEGACY_MAX_ROW_COUNT, IMPORT_MAX_FILE_SIZE_MB, IMPORT_MAX_ITEM_COUNT, IMPORT_TAG_KEYS, IMPORT_TAG_VALUES, ImportStates, InfoBox, InvalidResponseError, LockIcon, NoResourcesToExportError, PollingAbortedError, ProjectKeyNotAvailableError, QueryPredicateError, RESOURCE_TYPE_DOCUMENTATION_LINKS, RESOURCE_TYPE_TEMPLATE_DOWNLOAD_LINKS, TAG_KEY_SOURCE_FILE_UPLOAD, UnexpectedColumnError, UnexpectedOperationStateError, UnexpectedResourceTypeError, UploadSeparator, UploadSettings, UploadingModal, allAutomatedImportOperations, allAutomatedImportOperationsResponse, allFileUploadImportOperations, allFileUploadImportOperationsResponse, appendCsvOrJsonExtensionIfAbsent, assertCancelContainerResponse, assertExportOperationsDownloadFileResponse, assertFileImportJob, assertFileImportJobRecordsResponse, assertFileUploadResponse, assertImportContainer, assertImportContainerPagedResponse, assertImportOperationPagedResponse, assertImportSummary, assertListFileImportJobsResponse, assertPaginatedExportOperationResponse, assertProcessFileImportJobResponse, assertProcessFileResponse, assertResourceType, automatedImportContainerKey, automatedImports, cancelImportContainerByKey, checkIfFileUploadImport, convertFileSizeToKB, countJsonFileItems, countUniqueResourcesInCsv, createFileImportJob, createImportContainerForFileUpload, decodeFileNameFromImportContainerKey, deleteFileImportJob, deleteImportContainer, dropAreaStyles, encodeFileNameWithTimestampToContainerKey, exportOperationsCompleted, exportOperationsProcessing, extractErrorDescriptionFromValidationMessage, fetchExportOperations, fetchImportContainerByKey, fetchImportContainerDetails, fetchImportContainers, fetchImportOperations, fetchImportSummaries, fetchImportSummary, fetchUsingXhr, fetcher, fileUploadImportContainerKey, fileUploadMissingKeysResponse, formatErrorCode, formatKeys, formatQueryString, getCreateImportContainerURL, getDeleteImportContainerURL, getExportOperationsURL, getFileImportJob, getFileImportJobByIdURL, getFileImportJobDeleteURL, getFileImportJobFileType, getFileImportJobInfoForContainer, getFileImportJobProcessURL, getFileImportJobRecords, getFileImportJobRecordsURL, getFileImportJobsListURL, getFileImportJobsURL, getFileUploadErrorsCount, getFileUploadURL, getImportContainerByKeyURL, getImportContainerTasksURL, getImportContainersURL, getImportOperationsURL, getImportState, getImportSummaryURL, getMissingRequiredFields, getProccessFileURL, getRowCount, getValidatedColumns, hasImportJobStartedProcessing, hasOwnProperty, hasRequiredFields, hasSingleKeyColumn, importContainers, importStatesMap, importsSummaries, invalidFileImportJobRecordsResponse, invalidFileImportJobValidated, invalidFileUploadResponse, isAbortError, isError, isImportJobInitializing, isImportJobProcessing, isImportJobQueued, isImportJobReady, isImportJobRejected, isImportJobTerminal, isImportJobValidated, isResourceType, listFileImportJobs, manualImports, mapFileUploadErrorsToUploadFileErrorRows, mapFormikErrors, mapUploadFileErrorsResponseToUploadFileErrorRows, pollJobUntilProcessing, pollJobUntilValidated, processFileImportJob, processFileImportJobResponse, processUploadedFile, shouldContinuePollingForImportValidation, successfulAutomatedImportOperations, successfulAutomatedImportOperationsResponse, successfulFileUploadImportOperations, successfulFileUploadImportOperationsResponse, toBytes, toImportApiResourceType, uploadFileForImport, useFetchExportOperations, useFetchFileImportJob, useFetchFileImportJobRecords, useFetchImportContainerDetails, useFetchImportOperations, useFetchImportSummaries, useFileImportJobUpload, useFileUpload, useImportContainerUpload, validFileImportJobProcessing, validFileImportJobQueued, validFileImportJobRecordsResponse, validFileImportJobValidated, validFileUploadResponse, validProcessFileResponse, validateDelimiter };
@@ -5,3 +5,24 @@ export declare function getFileImportJobRecords({ projectKey, importContainerKey
5
5
  export declare function processFileImportJob({ projectKey, resourceType, importContainerKey, jobId, action, }: ProcessFileImportJobParameters): Promise<ProcessFileImportJobResponse>;
6
6
  export declare function deleteFileImportJob({ projectKey, importContainerKey, jobId, }: DeleteFileImportJobParameters): Promise<void>;
7
7
  export declare function listFileImportJobs({ projectKey, importContainerKey, limit, offset, }: ListFileImportJobsParameters): Promise<ListFileImportJobsResponse>;
8
+ export type FileImportJobInfo = {
9
+ total: number;
10
+ isInitializing: boolean;
11
+ };
12
+ /**
13
+ * Gets the file import job info for an import container
14
+ *
15
+ * For the new file import job flow, import operations are created incrementally
16
+ * during the 'initialising' state. The import summary total
17
+ * reflects only the operations created so far, which can be misleading
18
+ *
19
+ * This helper fetches the file import job (if it exists) to get:
20
+ * - The true total from the job summary (known from initial CSV validation)
21
+ * - Whether the job is still initializing (creating import operations)
22
+ *
23
+ * @returns Job info if found, null otherwise
24
+ */
25
+ export declare function getFileImportJobInfoForContainer({ projectKey, importContainerKey, }: {
26
+ projectKey: string;
27
+ importContainerKey: string;
28
+ }): Promise<FileImportJobInfo | null>;
@@ -1,6 +1,9 @@
1
1
  import type { ImportContainer, ImportContainerPagedResponse } from '@commercetools/importapi-sdk';
2
2
  import { ImportStates, type ImportContainerQueryParams, type CancelContainerResponse, type ImportSummary, type ExtendedImportContainerDraft, type ImportContainerDetails, type ImportSummaries } from "../@types/index.js";
3
- export declare function getImportState(importSummary: ImportSummary): ImportStates;
3
+ type GetImportStateOptions = {
4
+ isJobInitializing?: boolean;
5
+ };
6
+ export declare function getImportState(importSummary: ImportSummary, options?: GetImportStateOptions): ImportStates;
4
7
  export declare function createImportContainerForFileUpload({ importContainerDraft, projectKey, }: {
5
8
  importContainerDraft: ExtendedImportContainerDraft;
6
9
  projectKey: string;
@@ -33,3 +36,4 @@ export declare function cancelImportContainerByKey({ projectKey, importContainer
33
36
  projectKey: string;
34
37
  importContainerKey: string;
35
38
  }): Promise<CancelContainerResponse>;
39
+ export {};
@@ -93,7 +93,13 @@ export interface ListFileImportJobsParameters {
93
93
  limit?: number;
94
94
  offset?: number;
95
95
  }
96
- export type ListFileImportJobsResponse = FileImportJob[];
96
+ export interface ListFileImportJobsResponse {
97
+ results: FileImportJob[];
98
+ total: number;
99
+ limit: number;
100
+ offset: number;
101
+ count: number;
102
+ }
97
103
  export declare function assertFileImportJob(maybeJob: unknown): asserts maybeJob is FileImportJob;
98
104
  export declare function assertFileImportJobRecordsResponse(maybeRecords: unknown): asserts maybeRecords is FileImportJobRecordsResponse;
99
105
  export declare function assertProcessFileImportJobResponse(maybeResponse: unknown): asserts maybeResponse is ProcessFileImportJobResponse;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commercetools-frontend-extensions/operations",
3
- "version": "0.0.0-canary-20251215104232",
3
+ "version": "0.0.0-canary-20251216095330",
4
4
  "license": "Proprietary",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -18,14 +18,14 @@
18
18
  "react-dropzone": "14.3.8"
19
19
  },
20
20
  "devDependencies": {
21
- "@commercetools-frontend/actions-global": "24.12.0",
22
- "@commercetools-frontend/application-components": "24.12.0",
23
- "@commercetools-frontend/application-shell": "24.12.0",
24
- "@commercetools-frontend/application-shell-connectors": "24.12.0",
25
- "@commercetools-frontend/constants": "24.12.0",
26
- "@commercetools-frontend/jest-preset-mc-app": "24.12.0",
27
- "@commercetools-frontend/permissions": "24.12.0",
28
- "@commercetools-frontend/sentry": "24.12.0",
21
+ "@commercetools-frontend/actions-global": "24.13.0",
22
+ "@commercetools-frontend/application-components": "24.13.0",
23
+ "@commercetools-frontend/application-shell": "24.13.0",
24
+ "@commercetools-frontend/application-shell-connectors": "24.13.0",
25
+ "@commercetools-frontend/constants": "24.13.0",
26
+ "@commercetools-frontend/jest-preset-mc-app": "24.13.0",
27
+ "@commercetools-frontend/permissions": "24.13.0",
28
+ "@commercetools-frontend/sentry": "24.13.0",
29
29
  "@commercetools-frontend/ui-kit": "20.3.0",
30
30
  "@emotion/react": "11.14.0",
31
31
  "@emotion/styled": "11.14.1",
@@ -217,3 +217,53 @@ export async function listFileImportJobs({
217
217
  assertListFileImportJobsResponse(response)
218
218
  return response
219
219
  }
220
+
221
+ export type FileImportJobInfo = {
222
+ total: number
223
+ isInitializing: boolean
224
+ }
225
+
226
+ /**
227
+ * Gets the file import job info for an import container
228
+ *
229
+ * For the new file import job flow, import operations are created incrementally
230
+ * during the 'initialising' state. The import summary total
231
+ * reflects only the operations created so far, which can be misleading
232
+ *
233
+ * This helper fetches the file import job (if it exists) to get:
234
+ * - The true total from the job summary (known from initial CSV validation)
235
+ * - Whether the job is still initializing (creating import operations)
236
+ *
237
+ * @returns Job info if found, null otherwise
238
+ */
239
+ export async function getFileImportJobInfoForContainer({
240
+ projectKey,
241
+ importContainerKey,
242
+ }: {
243
+ projectKey: string
244
+ importContainerKey: string
245
+ }): Promise<FileImportJobInfo | null> {
246
+ try {
247
+ const response = await listFileImportJobs({
248
+ projectKey,
249
+ importContainerKey,
250
+ limit: 1,
251
+ })
252
+
253
+ if (
254
+ response.results.length > 0 &&
255
+ response.results[0].summary?.total != null
256
+ ) {
257
+ const job = response.results[0]
258
+ return {
259
+ total: job.summary.total,
260
+ isInitializing: job.state === 'initialising',
261
+ }
262
+ }
263
+
264
+ return null
265
+ } catch {
266
+ // Job might not exist (old flow)
267
+ return null
268
+ }
269
+ }
@@ -27,8 +27,16 @@ import {
27
27
  } from './urls'
28
28
  import { checkIfFileUploadImport } from '../@utils'
29
29
  import { fetcher } from './fetcher'
30
+ import { getFileImportJobInfoForContainer } from './file-import-jobs'
30
31
 
31
- export function getImportState(importSummary: ImportSummary): ImportStates {
32
+ type GetImportStateOptions = {
33
+ isJobInitializing?: boolean
34
+ }
35
+
36
+ export function getImportState(
37
+ importSummary: ImportSummary,
38
+ options: GetImportStateOptions = {}
39
+ ): ImportStates {
32
40
  const processing = importSummary.states.processing > 0
33
41
  if (processing) return ImportStates.Processing
34
42
 
@@ -48,6 +56,11 @@ export function getImportState(importSummary: ImportSummary): ImportStates {
48
56
  const noRunning = importSummary.total === 0
49
57
  if (noRunning) return ImportStates.NoRunningImports
50
58
 
59
+ // For the new flow: job is actively creating import operations (to show as Processing even if no operations exist yet)
60
+ if (options.isJobInitializing) {
61
+ return ImportStates.Processing
62
+ }
63
+
51
64
  const successfullyCompleted =
52
65
  importSummary.states.imported === importSummary.total ||
53
66
  importSummary.states.deleted === importSummary.total
@@ -240,13 +253,31 @@ async function importContainerToContainerDetails(
240
253
  projectKey: string,
241
254
  importContainer: ExtendedImportContainer
242
255
  ): Promise<ImportContainerDetails> {
243
- const importSummary = await fetchImportSummary({
256
+ let importSummary = await fetchImportSummary({
244
257
  projectKey,
245
258
  importContainerKey: importContainer.key,
246
259
  })
247
- const importState = getImportState(importSummary)
248
260
  const isFileUploadImport = checkIfFileUploadImport(importContainer.tags)
249
261
 
262
+ // For the new file import job flow the import operations are created incrementally
263
+ // The import summary total reflects only operations created so far
264
+ // Only override total when job is actively initializing (creating operations)
265
+ let isJobInitializing = false
266
+ if (isFileUploadImport) {
267
+ const jobInfo = await getFileImportJobInfoForContainer({
268
+ projectKey,
269
+ importContainerKey: importContainer.key,
270
+ })
271
+ if (jobInfo !== null) {
272
+ isJobInitializing = jobInfo.isInitializing
273
+ if (isJobInitializing || importSummary.total > 0) {
274
+ importSummary = { ...importSummary, total: jobInfo.total }
275
+ }
276
+ }
277
+ }
278
+
279
+ const importState = getImportState(importSummary, { isJobInitializing })
280
+
250
281
  return {
251
282
  importContainer: importContainer,
252
283
  importState,
@@ -120,7 +120,13 @@ export interface ListFileImportJobsParameters {
120
120
  offset?: number
121
121
  }
122
122
 
123
- export type ListFileImportJobsResponse = FileImportJob[]
123
+ export interface ListFileImportJobsResponse {
124
+ results: FileImportJob[]
125
+ total: number
126
+ limit: number
127
+ offset: number
128
+ count: number
129
+ }
124
130
 
125
131
  export function assertFileImportJob(
126
132
  maybeJob: unknown
@@ -152,15 +158,10 @@ export function assertProcessFileImportJobResponse(
152
158
  export function assertListFileImportJobsResponse(
153
159
  maybeResponse: unknown
154
160
  ): asserts maybeResponse is ListFileImportJobsResponse {
155
- if (!Array.isArray(maybeResponse)) {
156
- throw new Error('Invalid List File Import Jobs response: expected an array')
157
- }
158
- if (maybeResponse.length > 0) {
159
- const requiredFields = ['id', 'fileName', 'importContainerKey', 'state']
160
- if (!hasRequiredFields(maybeResponse[0], requiredFields)) {
161
- throw new Error(
162
- 'Invalid List File Import Jobs response: missing required fields'
163
- )
164
- }
161
+ const requiredFields = ['results', 'total', 'limit', 'offset', 'count']
162
+ if (!hasRequiredFields(maybeResponse, requiredFields)) {
163
+ throw new Error(
164
+ 'Invalid List File Import Jobs response: missing required fields'
165
+ )
165
166
  }
166
167
  }