@commercetools-frontend-extensions/operations 0.0.0-canary-20251209161906

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 (180) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +178 -0
  3. package/babel.config.js +6 -0
  4. package/dist/commercetools-frontend-extensions-operations.cjs.d.ts +2 -0
  5. package/dist/commercetools-frontend-extensions-operations.cjs.dev.js +3273 -0
  6. package/dist/commercetools-frontend-extensions-operations.cjs.js +7 -0
  7. package/dist/commercetools-frontend-extensions-operations.cjs.prod.js +3265 -0
  8. package/dist/commercetools-frontend-extensions-operations.esm.js +3074 -0
  9. package/dist/declarations/src/@api/export-operations.d.ts +5 -0
  10. package/dist/declarations/src/@api/fetcher.d.ts +17 -0
  11. package/dist/declarations/src/@api/file-import-jobs.d.ts +7 -0
  12. package/dist/declarations/src/@api/file-upload.d.ts +3 -0
  13. package/dist/declarations/src/@api/import-containers.d.ts +35 -0
  14. package/dist/declarations/src/@api/import-operations.d.ts +6 -0
  15. package/dist/declarations/src/@api/index.d.ts +9 -0
  16. package/dist/declarations/src/@api/process-file.d.ts +3 -0
  17. package/dist/declarations/src/@api/test-fixtures.d.ts +279 -0
  18. package/dist/declarations/src/@api/urls.d.ts +74 -0
  19. package/dist/declarations/src/@components/file-drop-area/active-drag-drop-area.d.ts +10 -0
  20. package/dist/declarations/src/@components/file-drop-area/disabled-drop-area.d.ts +5 -0
  21. package/dist/declarations/src/@components/file-drop-area/drop-area-wrapper.d.ts +11 -0
  22. package/dist/declarations/src/@components/file-drop-area/enabled-drop-area.d.ts +7 -0
  23. package/dist/declarations/src/@components/file-drop-area/file-drop-area.d.ts +14 -0
  24. package/dist/declarations/src/@components/file-drop-area/file-dropped-area.d.ts +6 -0
  25. package/dist/declarations/src/@components/file-drop-area/index.d.ts +7 -0
  26. package/dist/declarations/src/@components/file-drop-area/styles.d.ts +9 -0
  27. package/dist/declarations/src/@components/icons/file-icon.d.ts +2 -0
  28. package/dist/declarations/src/@components/icons/index.d.ts +2 -0
  29. package/dist/declarations/src/@components/icons/lock-icon.d.ts +2 -0
  30. package/dist/declarations/src/@components/index.d.ts +6 -0
  31. package/dist/declarations/src/@components/info-box/index.d.ts +1 -0
  32. package/dist/declarations/src/@components/info-box/info-box.d.ts +7 -0
  33. package/dist/declarations/src/@components/upload-separator/index.d.ts +1 -0
  34. package/dist/declarations/src/@components/upload-separator/upload-separator.d.ts +12 -0
  35. package/dist/declarations/src/@components/upload-settings/index.d.ts +1 -0
  36. package/dist/declarations/src/@components/upload-settings/upload-settings.d.ts +11 -0
  37. package/dist/declarations/src/@components/uploading-modal/index.d.ts +1 -0
  38. package/dist/declarations/src/@components/uploading-modal/uploading-modal.d.ts +13 -0
  39. package/dist/declarations/src/@constants/delimiters.d.ts +8 -0
  40. package/dist/declarations/src/@constants/file-import-job.d.ts +1 -0
  41. package/dist/declarations/src/@constants/import-limits.d.ts +6 -0
  42. package/dist/declarations/src/@constants/import-tags.d.ts +7 -0
  43. package/dist/declarations/src/@constants/index.d.ts +5 -0
  44. package/dist/declarations/src/@constants/resource-links.d.ts +10 -0
  45. package/dist/declarations/src/@errors/http-error.d.ts +6 -0
  46. package/dist/declarations/src/@errors/index.d.ts +9 -0
  47. package/dist/declarations/src/@errors/invalid-response-error.d.ts +3 -0
  48. package/dist/declarations/src/@errors/no-resources-to-export-error.d.ts +3 -0
  49. package/dist/declarations/src/@errors/polling-aborted-error.d.ts +3 -0
  50. package/dist/declarations/src/@errors/project-key-not-available-error.d.ts +3 -0
  51. package/dist/declarations/src/@errors/query-predicate-error.d.ts +4 -0
  52. package/dist/declarations/src/@errors/unexpected-column-error.d.ts +3 -0
  53. package/dist/declarations/src/@errors/unexpected-operation-state-error.d.ts +4 -0
  54. package/dist/declarations/src/@errors/unexpected-resource-type-error.d.ts +3 -0
  55. package/dist/declarations/src/@hooks/index.d.ts +8 -0
  56. package/dist/declarations/src/@hooks/use-fetch-export-operations.d.ts +15 -0
  57. package/dist/declarations/src/@hooks/use-fetch-file-import-job.d.ts +17 -0
  58. package/dist/declarations/src/@hooks/use-fetch-import-container-details.d.ts +15 -0
  59. package/dist/declarations/src/@hooks/use-fetch-import-operations.d.ts +16 -0
  60. package/dist/declarations/src/@hooks/use-fetch-import-summaries.d.ts +20 -0
  61. package/dist/declarations/src/@hooks/use-file-import-job-upload.d.ts +18 -0
  62. package/dist/declarations/src/@hooks/use-file-upload.d.ts +28 -0
  63. package/dist/declarations/src/@hooks/use-import-container-upload.d.ts +19 -0
  64. package/dist/declarations/src/@types/api.d.ts +13 -0
  65. package/dist/declarations/src/@types/basic-error-data-type.d.ts +5 -0
  66. package/dist/declarations/src/@types/export-operation.d.ts +97 -0
  67. package/dist/declarations/src/@types/file-import-job.d.ts +99 -0
  68. package/dist/declarations/src/@types/file-upload-result.d.ts +21 -0
  69. package/dist/declarations/src/@types/file-upload.d.ts +63 -0
  70. package/dist/declarations/src/@types/import-container.d.ts +53 -0
  71. package/dist/declarations/src/@types/import-operation.d.ts +13 -0
  72. package/dist/declarations/src/@types/import-states.d.ts +9 -0
  73. package/dist/declarations/src/@types/import-summary.d.ts +15 -0
  74. package/dist/declarations/src/@types/index.d.ts +11 -0
  75. package/dist/declarations/src/@types/shared.d.ts +7 -0
  76. package/dist/declarations/src/@utils/error-mapping.d.ts +19 -0
  77. package/dist/declarations/src/@utils/file-import-job-helpers.d.ts +12 -0
  78. package/dist/declarations/src/@utils/file-upload.d.ts +54 -0
  79. package/dist/declarations/src/@utils/form.d.ts +1 -0
  80. package/dist/declarations/src/@utils/format.d.ts +5 -0
  81. package/dist/declarations/src/@utils/import-container.d.ts +8 -0
  82. package/dist/declarations/src/@utils/index.d.ts +8 -0
  83. package/dist/declarations/src/@utils/poll-job-until-validated.d.ts +11 -0
  84. package/dist/declarations/src/@utils/url.d.ts +6 -0
  85. package/dist/declarations/src/index.d.ts +26 -0
  86. package/index.js +1 -0
  87. package/jest.test.config.js +11 -0
  88. package/package.json +62 -0
  89. package/src/@api/export-operations.ts +26 -0
  90. package/src/@api/fetcher.spec.ts +51 -0
  91. package/src/@api/fetcher.ts +137 -0
  92. package/src/@api/file-import-jobs.ts +217 -0
  93. package/src/@api/file-upload.spec.ts +85 -0
  94. package/src/@api/file-upload.ts +46 -0
  95. package/src/@api/import-containers.ts +256 -0
  96. package/src/@api/import-operations.ts +33 -0
  97. package/src/@api/index.ts +9 -0
  98. package/src/@api/process-file.spec.ts +74 -0
  99. package/src/@api/process-file.ts +53 -0
  100. package/src/@api/test-fixtures.ts +894 -0
  101. package/src/@api/urls.ts +194 -0
  102. package/src/@components/file-drop-area/active-drag-drop-area.tsx +33 -0
  103. package/src/@components/file-drop-area/disabled-drop-area.tsx +17 -0
  104. package/src/@components/file-drop-area/drop-area-wrapper.tsx +38 -0
  105. package/src/@components/file-drop-area/enabled-drop-area.tsx +27 -0
  106. package/src/@components/file-drop-area/file-drop-area.tsx +74 -0
  107. package/src/@components/file-drop-area/file-dropped-area.tsx +29 -0
  108. package/src/@components/file-drop-area/index.ts +7 -0
  109. package/src/@components/file-drop-area/styles.ts +67 -0
  110. package/src/@components/icons/file-icon.tsx +30 -0
  111. package/src/@components/icons/index.ts +2 -0
  112. package/src/@components/icons/lock-icon.tsx +34 -0
  113. package/src/@components/index.ts +6 -0
  114. package/src/@components/info-box/index.ts +1 -0
  115. package/src/@components/info-box/info-box.tsx +23 -0
  116. package/src/@components/upload-separator/index.ts +1 -0
  117. package/src/@components/upload-separator/upload-separator.tsx +61 -0
  118. package/src/@components/upload-settings/index.ts +1 -0
  119. package/src/@components/upload-settings/upload-settings.tsx +36 -0
  120. package/src/@components/uploading-modal/index.ts +1 -0
  121. package/src/@components/uploading-modal/uploading-modal.tsx +66 -0
  122. package/src/@constants/delimiters.ts +14 -0
  123. package/src/@constants/file-import-job.ts +1 -0
  124. package/src/@constants/import-limits.ts +13 -0
  125. package/src/@constants/import-tags.ts +9 -0
  126. package/src/@constants/index.ts +5 -0
  127. package/src/@constants/resource-links.ts +61 -0
  128. package/src/@errors/http-error.ts +17 -0
  129. package/src/@errors/index.ts +9 -0
  130. package/src/@errors/invalid-response-error.ts +6 -0
  131. package/src/@errors/no-resources-to-export-error.ts +6 -0
  132. package/src/@errors/polling-aborted-error.ts +6 -0
  133. package/src/@errors/project-key-not-available-error.ts +6 -0
  134. package/src/@errors/query-predicate-error.ts +10 -0
  135. package/src/@errors/unexpected-column-error.ts +6 -0
  136. package/src/@errors/unexpected-operation-state-error.ts +8 -0
  137. package/src/@errors/unexpected-resource-type-error.ts +6 -0
  138. package/src/@hooks/index.ts +8 -0
  139. package/src/@hooks/use-fetch-export-operations.ts +34 -0
  140. package/src/@hooks/use-fetch-file-import-job.spec.ts +131 -0
  141. package/src/@hooks/use-fetch-file-import-job.ts +38 -0
  142. package/src/@hooks/use-fetch-import-container-details.ts +31 -0
  143. package/src/@hooks/use-fetch-import-operations.ts +42 -0
  144. package/src/@hooks/use-fetch-import-summaries.ts +47 -0
  145. package/src/@hooks/use-fetch.spec.ts +68 -0
  146. package/src/@hooks/use-fetch.ts +76 -0
  147. package/src/@hooks/use-file-import-job-upload.spec.ts +273 -0
  148. package/src/@hooks/use-file-import-job-upload.ts +101 -0
  149. package/src/@hooks/use-file-upload.ts +223 -0
  150. package/src/@hooks/use-import-container-upload.spec.ts +297 -0
  151. package/src/@hooks/use-import-container-upload.ts +130 -0
  152. package/src/@types/api.ts +14 -0
  153. package/src/@types/basic-error-data-type.ts +5 -0
  154. package/src/@types/export-operation.ts +147 -0
  155. package/src/@types/file-import-job.ts +165 -0
  156. package/src/@types/file-upload-result.ts +23 -0
  157. package/src/@types/file-upload.ts +81 -0
  158. package/src/@types/import-container.ts +104 -0
  159. package/src/@types/import-operation.ts +31 -0
  160. package/src/@types/import-states.ts +9 -0
  161. package/src/@types/import-summary.ts +22 -0
  162. package/src/@types/index.ts +11 -0
  163. package/src/@types/shared.ts +52 -0
  164. package/src/@utils/error-mapping.spec.ts +126 -0
  165. package/src/@utils/error-mapping.ts +40 -0
  166. package/src/@utils/file-import-job-helpers.spec.ts +147 -0
  167. package/src/@utils/file-import-job-helpers.ts +47 -0
  168. package/src/@utils/file-upload.spec.ts +151 -0
  169. package/src/@utils/file-upload.ts +189 -0
  170. package/src/@utils/form.ts +20 -0
  171. package/src/@utils/format.spec.ts +62 -0
  172. package/src/@utils/format.ts +53 -0
  173. package/src/@utils/import-container.spec.ts +26 -0
  174. package/src/@utils/import-container.ts +34 -0
  175. package/src/@utils/index.ts +8 -0
  176. package/src/@utils/poll-job-until-validated.ts +76 -0
  177. package/src/@utils/url.spec.ts +75 -0
  178. package/src/@utils/url.ts +18 -0
  179. package/src/index.ts +27 -0
  180. package/tsconfig.json +9 -0
@@ -0,0 +1,85 @@
1
+ import { waitFor } from '@testing-library/react'
2
+ import { rest } from 'msw'
3
+ import { setupServer } from 'msw/node'
4
+ import { uploadFileForImport } from './file-upload'
5
+ import type { FileUploadResponse } from '../@types'
6
+
7
+ const validFileUploadResponse: FileUploadResponse = {
8
+ valid: 1,
9
+ results: [],
10
+ invalid: 0,
11
+ fileName: 'file.csv',
12
+ itemsCount: 0,
13
+ // TODO: Remove rowsCount and columnsCount once we remove the old flow
14
+ rowsCount: 0,
15
+ columnsCount: 0,
16
+ //
17
+ fields: ['id', 'name', 'description'],
18
+ ignoredFields: ['id', 'name'],
19
+ }
20
+
21
+ type ResourceTypeEntry = {
22
+ name: string
23
+ apiPath: string
24
+ }
25
+
26
+ const resourceTypes: Array<ResourceTypeEntry> = [
27
+ {
28
+ name: 'category',
29
+ apiPath: 'categories',
30
+ },
31
+ {
32
+ name: 'product',
33
+ apiPath: 'products',
34
+ },
35
+ {
36
+ name: 'inventory',
37
+ apiPath: 'inventories',
38
+ },
39
+ ]
40
+
41
+ const mockServer = setupServer(
42
+ ...resourceTypes.map(({ apiPath }) =>
43
+ rest.post(
44
+ `http://localhost:8080/proxy/import/test-with-big-data-key/${apiPath}/import-containers/container-key/file-upload`,
45
+ (_, res, ctx) => res(ctx.json(validFileUploadResponse))
46
+ )
47
+ )
48
+ )
49
+
50
+ afterEach(() => {
51
+ mockServer.resetHandlers()
52
+ })
53
+
54
+ beforeAll(() => {
55
+ mockServer.listen()
56
+ })
57
+
58
+ afterAll(() => {
59
+ mockServer.close()
60
+ })
61
+
62
+ describe('uploadFileForImport', () => {
63
+ const projectKey = 'test-with-big-data-key'
64
+ const containerKey = 'container-key'
65
+ const file: File = new File([], 'file.csv')
66
+
67
+ it.each([['category'], ['product'], ['inventory']])(
68
+ 'should post the file to the correct endpoint for the resource type %s',
69
+ async (resourceType) => {
70
+ const onSuccess = jest.fn()
71
+ uploadFileForImport({
72
+ projectKey,
73
+ importContainerKey: containerKey,
74
+ resourceType,
75
+ file,
76
+ onSuccess,
77
+ onProgress: jest.fn(),
78
+ onError: jest.fn(),
79
+ })
80
+ await waitFor(() =>
81
+ expect(onSuccess).toHaveBeenCalledWith(validFileUploadResponse)
82
+ )
83
+ }
84
+ )
85
+ })
@@ -0,0 +1,46 @@
1
+ import { MC_API_PROXY_TARGETS } from '@commercetools-frontend/constants'
2
+ import {
3
+ type FileUploadResponse,
4
+ type FileUploadRequestParameters,
5
+ hasRequiredFields,
6
+ } from '../@types'
7
+ import { fetchUsingXhr } from './fetcher'
8
+ import { getFileUploadURL } from './urls'
9
+
10
+ export function uploadFileForImport({
11
+ projectKey,
12
+ importContainerKey,
13
+ resourceType,
14
+ file,
15
+ abortSignal,
16
+ onSuccess,
17
+ onProgress,
18
+ onError,
19
+ }: FileUploadRequestParameters): XMLHttpRequest {
20
+ const uri = getFileUploadURL({ projectKey, resourceType, importContainerKey })
21
+ const formData = new FormData()
22
+ formData.append('file', file, file.name)
23
+ return fetchUsingXhr({
24
+ url: uri,
25
+ payload: formData,
26
+ config: {
27
+ abortSignal,
28
+ proxy: MC_API_PROXY_TARGETS.IMPORT,
29
+ method: 'POST',
30
+ headers: {
31
+ 'Content-Type': null,
32
+ },
33
+ },
34
+ onProgress,
35
+ onSuccess,
36
+ onError,
37
+ })
38
+ }
39
+
40
+ export function assertFileUploadResponse(
41
+ maybeFileUploadResponse: unknown
42
+ ): asserts maybeFileUploadResponse is FileUploadResponse {
43
+ const requiredFields = ['results', 'valid']
44
+ if (hasRequiredFields(maybeFileUploadResponse, requiredFields)) return
45
+ throw new Error('Invalid response')
46
+ }
@@ -0,0 +1,256 @@
1
+ import type {
2
+ ImportContainer,
3
+ ImportContainerPagedResponse,
4
+ } from '@commercetools/importapi-sdk'
5
+ import { MC_API_PROXY_TARGETS } from '@commercetools-frontend/constants'
6
+ import {
7
+ assertImportContainer,
8
+ assertImportContainerPagedResponse,
9
+ assertImportSummary,
10
+ ImportStates,
11
+ type ImportContainerQueryParams,
12
+ type CancelContainerResponse,
13
+ type ImportSummary,
14
+ type ExtendedImportContainer,
15
+ type ExtendedImportContainerDraft,
16
+ type ImportContainerDetails,
17
+ type ImportSummaries,
18
+ assertCancelContainerResponse,
19
+ } from '../@types'
20
+ import {
21
+ getImportContainersURL,
22
+ getImportContainerByKeyURL,
23
+ getImportSummaryURL,
24
+ getCreateImportContainerURL,
25
+ getDeleteImportContainerURL,
26
+ getImportContainerTasksURL,
27
+ } from './urls'
28
+ import { checkIfFileUploadImport } from '../@utils'
29
+ import { fetcher } from './fetcher'
30
+
31
+ export function getImportState(importSummary: ImportSummary): ImportStates {
32
+ const processing = importSummary.states.processing > 0
33
+ if (processing) return ImportStates.Processing
34
+
35
+ const waitForUnresolvedReferences =
36
+ importSummary.states.waitForMasterVariant > 0 ||
37
+ importSummary.states.unresolved > 0
38
+ if (waitForUnresolvedReferences)
39
+ return ImportStates.WaitForUnresolvedReferences
40
+
41
+ const partiallyCompleted =
42
+ (importSummary.states.imported > 0 &&
43
+ importSummary.states.imported < importSummary.total) ||
44
+ (importSummary.states.deleted > 0 &&
45
+ importSummary.states.deleted < importSummary.total)
46
+ if (partiallyCompleted) return ImportStates.PartiallyCompleted
47
+
48
+ const noRunning = importSummary.total === 0
49
+ if (noRunning) return ImportStates.NoRunningImports
50
+
51
+ const successfullyCompleted =
52
+ importSummary.states.imported === importSummary.total ||
53
+ importSummary.states.deleted === importSummary.total
54
+ if (successfullyCompleted) return ImportStates.SuccessfullyCompleted
55
+
56
+ const failed =
57
+ importSummary.states.rejected + importSummary.states.validationFailed ===
58
+ importSummary.total
59
+ if (failed) return ImportStates.Failed
60
+
61
+ const canceled = importSummary.states.canceled > 0
62
+ if (canceled) return ImportStates.Canceled
63
+
64
+ throw new Error(`Unsupported state ${JSON.stringify(importSummary.states)}`)
65
+ }
66
+
67
+ export function createImportContainerForFileUpload({
68
+ importContainerDraft,
69
+ projectKey,
70
+ }: {
71
+ importContainerDraft: ExtendedImportContainerDraft
72
+ projectKey: string
73
+ }): Promise<unknown> {
74
+ return fetcher({
75
+ url: getCreateImportContainerURL({ projectKey }),
76
+ payload: JSON.stringify({
77
+ retentionPolicy: {
78
+ strategy: 'ttl',
79
+ config: {
80
+ timeToLive: '54h', // 2 days and 6 hours
81
+ },
82
+ },
83
+ ...importContainerDraft,
84
+ }),
85
+ config: {
86
+ proxy: MC_API_PROXY_TARGETS.IMPORT,
87
+ method: 'POST',
88
+ headers: {
89
+ accept: 'application/json',
90
+ 'Content-Type': 'application/json',
91
+ },
92
+ },
93
+ })
94
+ }
95
+
96
+ export function deleteImportContainer({
97
+ projectKey,
98
+ importContainerKey,
99
+ }: {
100
+ projectKey: string
101
+ importContainerKey: string
102
+ }): Promise<unknown> {
103
+ return fetcher({
104
+ url: getDeleteImportContainerURL({ projectKey, importContainerKey }),
105
+ config: {
106
+ proxy: MC_API_PROXY_TARGETS.IMPORT,
107
+ method: 'DELETE',
108
+ headers: {
109
+ accept: 'application/json',
110
+ },
111
+ },
112
+ })
113
+ }
114
+
115
+ export async function fetchImportSummary({
116
+ projectKey,
117
+ importContainerKey,
118
+ }: {
119
+ projectKey: string
120
+ importContainerKey: string
121
+ }): Promise<ImportSummary> {
122
+ const importSummary = await fetcher<ImportSummary>({
123
+ url: getImportSummaryURL({ projectKey, importContainerKey }),
124
+ config: {
125
+ proxy: MC_API_PROXY_TARGETS.IMPORT,
126
+ method: 'GET',
127
+ },
128
+ })
129
+
130
+ assertImportSummary(importSummary)
131
+
132
+ return importSummary
133
+ }
134
+
135
+ export async function fetchImportContainers({
136
+ projectKey,
137
+ queryParams,
138
+ }: {
139
+ projectKey: string
140
+ queryParams: ImportContainerQueryParams
141
+ }): Promise<ImportContainerPagedResponse> {
142
+ const importContainers = await fetcher<ImportContainerPagedResponse>({
143
+ url: getImportContainersURL({ projectKey, queryParams }),
144
+ config: {
145
+ proxy: MC_API_PROXY_TARGETS.IMPORT,
146
+ method: 'GET',
147
+ },
148
+ })
149
+ assertImportContainerPagedResponse(importContainers)
150
+
151
+ return importContainers
152
+ }
153
+
154
+ export async function fetchImportSummaries({
155
+ projectKey,
156
+ queryParams,
157
+ }: {
158
+ projectKey: string
159
+ queryParams: ImportContainerQueryParams
160
+ }): Promise<ImportSummaries> {
161
+ const importContainers = await fetchImportContainers({
162
+ projectKey,
163
+ queryParams,
164
+ })
165
+
166
+ const results: Array<Promise<ImportContainerDetails>> =
167
+ importContainers.results.map(async (importContainer) => {
168
+ return await importContainerToContainerDetails(
169
+ projectKey,
170
+ importContainer
171
+ )
172
+ })
173
+
174
+ return {
175
+ results,
176
+ count: importContainers.count,
177
+ total: importContainers.total ?? 0,
178
+ queryParams: {
179
+ limit: importContainers.limit,
180
+ offset: importContainers.offset,
181
+ },
182
+ }
183
+ }
184
+
185
+ export async function fetchImportContainerDetails({
186
+ projectKey,
187
+ importContainerKey,
188
+ }: {
189
+ projectKey: string
190
+ importContainerKey: string
191
+ }): Promise<ImportContainerDetails> {
192
+ const importContainer = await fetchImportContainerByKey({
193
+ projectKey,
194
+ importContainerKey,
195
+ })
196
+ return await importContainerToContainerDetails(projectKey, importContainer)
197
+ }
198
+
199
+ export async function fetchImportContainerByKey({
200
+ projectKey,
201
+ importContainerKey,
202
+ }: {
203
+ projectKey: string
204
+ importContainerKey: string
205
+ }): Promise<ImportContainer> {
206
+ const importContainer = await fetcher<ImportContainer>({
207
+ url: getImportContainerByKeyURL({ projectKey, importContainerKey }),
208
+ config: {
209
+ proxy: MC_API_PROXY_TARGETS.IMPORT,
210
+ method: 'GET',
211
+ },
212
+ })
213
+ assertImportContainer(importContainer)
214
+
215
+ return importContainer
216
+ }
217
+
218
+ export async function cancelImportContainerByKey({
219
+ projectKey,
220
+ importContainerKey,
221
+ }: {
222
+ projectKey: string
223
+ importContainerKey: string
224
+ }): Promise<CancelContainerResponse> {
225
+ const response = await fetcher<CancelContainerResponse>({
226
+ url: getImportContainerTasksURL({ projectKey, importContainerKey }),
227
+ payload: JSON.stringify({
228
+ task: 'cancel',
229
+ }),
230
+ config: {
231
+ proxy: MC_API_PROXY_TARGETS.IMPORT,
232
+ method: 'POST',
233
+ },
234
+ })
235
+ assertCancelContainerResponse(response)
236
+ return response
237
+ }
238
+
239
+ async function importContainerToContainerDetails(
240
+ projectKey: string,
241
+ importContainer: ExtendedImportContainer
242
+ ): Promise<ImportContainerDetails> {
243
+ const importSummary = await fetchImportSummary({
244
+ projectKey,
245
+ importContainerKey: importContainer.key,
246
+ })
247
+ const importState = getImportState(importSummary)
248
+ const isFileUploadImport = checkIfFileUploadImport(importContainer.tags)
249
+
250
+ return {
251
+ importContainer: importContainer,
252
+ importState,
253
+ importSummary,
254
+ isFileUploadImport,
255
+ }
256
+ }
@@ -0,0 +1,33 @@
1
+ import { MC_API_PROXY_TARGETS } from '@commercetools-frontend/constants'
2
+ import {
3
+ assertImportOperationPagedResponse,
4
+ type ExtendedImportOperationPagedResponse,
5
+ type ImportOperationQueryParams,
6
+ } from '../@types'
7
+ import { fetcher } from './fetcher'
8
+ import { getImportOperationsURL } from './urls'
9
+
10
+ export async function fetchImportOperations({
11
+ projectKey,
12
+ importContainerKey,
13
+ queryParams,
14
+ }: {
15
+ projectKey: string
16
+ importContainerKey: string
17
+ queryParams: ImportOperationQueryParams
18
+ }): Promise<ExtendedImportOperationPagedResponse> {
19
+ const importOperations = await fetcher<ExtendedImportOperationPagedResponse>({
20
+ url: getImportOperationsURL({
21
+ projectKey,
22
+ importContainerKey,
23
+ queryParams,
24
+ }),
25
+ config: {
26
+ proxy: MC_API_PROXY_TARGETS.IMPORT,
27
+ method: 'GET',
28
+ },
29
+ })
30
+ assertImportOperationPagedResponse(importOperations)
31
+
32
+ return importOperations
33
+ }
@@ -0,0 +1,9 @@
1
+ export * from './fetcher'
2
+ export * from './file-upload'
3
+ export * from './file-import-jobs'
4
+ export * from './import-containers'
5
+ export * from './import-operations'
6
+ export * from './export-operations'
7
+ export * from './process-file'
8
+ export * from './urls'
9
+ export * from './test-fixtures'
@@ -0,0 +1,74 @@
1
+ import { plural } from 'pluralize'
2
+ import { rest } from 'msw'
3
+ import { setupServer } from 'msw/node'
4
+ import { processUploadedFile } from './process-file'
5
+ import { validProcessFileResponse } from './test-fixtures'
6
+
7
+ const mockServer = setupServer()
8
+
9
+ beforeAll(() => {
10
+ mockServer.listen()
11
+ })
12
+ afterEach(() => {
13
+ mockServer.resetHandlers()
14
+ })
15
+ afterAll(() => {
16
+ mockServer.close()
17
+ })
18
+
19
+ describe('processUploadedFile', () => {
20
+ const projectKey = 'test-with-big-data'
21
+ const containerKey = 'container-key'
22
+ const resourceType = 'category'
23
+
24
+ it('should process the file with the correct endpoint for the current project', async () => {
25
+ mockServer.use(
26
+ rest.post(
27
+ `http://localhost:8080/proxy/import/${projectKey}/${plural(
28
+ resourceType
29
+ )}/import-containers/${containerKey}/process-file`,
30
+ (_, res, ctx) => {
31
+ return res(ctx.json(validProcessFileResponse))
32
+ }
33
+ )
34
+ )
35
+
36
+ const response = await processUploadedFile({
37
+ projectKey,
38
+ importContainerKey: containerKey,
39
+ resourceType,
40
+ })
41
+
42
+ expect(response.message).toEqual(validProcessFileResponse.message)
43
+ })
44
+
45
+ it('should process the file with delete action using the tasks endpoint', async () => {
46
+ let requestBody: any
47
+
48
+ mockServer.use(
49
+ rest.post(
50
+ `http://localhost:8080/proxy/import/${projectKey}/import-containers/${containerKey}/tasks`,
51
+ async (req, res, ctx) => {
52
+ requestBody = await req.json()
53
+ return res(ctx.json(validProcessFileResponse))
54
+ }
55
+ )
56
+ )
57
+
58
+ const response = await processUploadedFile({
59
+ projectKey,
60
+ importContainerKey: containerKey,
61
+ resourceType,
62
+ action: 'delete',
63
+ })
64
+
65
+ expect(response.message).toEqual(validProcessFileResponse.message)
66
+ expect(requestBody).toEqual({
67
+ task: 'process-file',
68
+ parameter: {
69
+ resourceType,
70
+ action: 'delete',
71
+ },
72
+ })
73
+ })
74
+ })
@@ -0,0 +1,53 @@
1
+ import { MC_API_PROXY_TARGETS } from '@commercetools-frontend/constants'
2
+ import type {
3
+ ProcessUploadedFileRequestParameters,
4
+ ProcessFileResponse,
5
+ } from '../@types'
6
+ import { hasRequiredFields } from '../@types'
7
+ import { fetcher } from './fetcher'
8
+ import { getProccessFileURL, getImportContainerTasksURL } from './urls'
9
+
10
+ export async function processUploadedFile({
11
+ projectKey,
12
+ importContainerKey,
13
+ resourceType,
14
+ action,
15
+ }: ProcessUploadedFileRequestParameters): Promise<ProcessFileResponse> {
16
+ // For delete operations with action (like 'delete') -> use different URL and payload structure
17
+ const uri = action
18
+ ? getImportContainerTasksURL({ projectKey, importContainerKey })
19
+ : getProccessFileURL({ projectKey, resourceType, importContainerKey })
20
+
21
+ const payload = action
22
+ ? {
23
+ task: 'process-file',
24
+ parameter: {
25
+ resourceType,
26
+ action,
27
+ },
28
+ }
29
+ : {}
30
+
31
+ const response = await fetcher<ProcessFileResponse>({
32
+ url: uri,
33
+ payload: JSON.stringify(payload),
34
+ config: {
35
+ proxy: MC_API_PROXY_TARGETS.IMPORT,
36
+ method: 'POST',
37
+ headers: {
38
+ accept: 'application/json',
39
+ 'Content-Type': 'application/json',
40
+ },
41
+ },
42
+ })
43
+ assertProcessFileResponse(response)
44
+ return response
45
+ }
46
+
47
+ export function assertProcessFileResponse(
48
+ maybeProcessFileResponse: unknown
49
+ ): asserts maybeProcessFileResponse is ProcessFileResponse {
50
+ const requiredFields = ['message']
51
+ if (hasRequiredFields(maybeProcessFileResponse, requiredFields)) return
52
+ throw new Error('Invalid response')
53
+ }