@haus-tech/product-import-export-plugin 3.3.2-next.0 → 3.3.2-next.1
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 +8 -0
- package/README.mdx +21 -4
- package/package.json +1 -1
- package/src/api/product-export.controller.d.ts +1 -0
- package/src/api/product-export.controller.js +16 -0
- package/src/api/product-export.controller.js.map +1 -1
- package/src/api/product-import.controller.js +2 -2
- package/src/api/product-import.controller.js.map +1 -1
- package/src/constants.d.ts +1 -0
- package/src/constants.js +2 -1
- package/src/constants.js.map +1 -1
- package/src/dashboard/export-dialog.tsx +21 -7
- package/src/dashboard/import.tsx +6 -3
- package/src/dashboard/utils.ts +0 -1
- package/src/index.d.ts +3 -0
- package/src/index.js +3 -0
- package/src/index.js.map +1 -1
- package/src/product-import-export.plugin.js +21 -0
- package/src/product-import-export.plugin.js.map +1 -1
- package/src/providers/import-providers/import-parser.d.ts +7 -5
- package/src/providers/import-providers/import-parser.js +53 -15
- package/src/providers/import-providers/import-parser.js.map +1 -1
- package/src/providers/import-providers/product-importer.d.ts +1 -0
- package/src/providers/import-providers/product-importer.js +120 -74
- package/src/providers/import-providers/product-importer.js.map +1 -1
- package/src/services/extended-fast-importer.service.d.ts +5 -3
- package/src/services/extended-fast-importer.service.js +18 -6
- package/src/services/extended-fast-importer.service.js.map +1 -1
- package/src/services/import-storage/import-job-storage-strategy.d.ts +22 -0
- package/src/services/import-storage/import-job-storage-strategy.js +3 -0
- package/src/services/import-storage/import-job-storage-strategy.js.map +1 -0
- package/src/services/import-storage/local-import-job-storage-strategy.d.ts +18 -0
- package/src/services/import-storage/local-import-job-storage-strategy.js +76 -0
- package/src/services/import-storage/local-import-job-storage-strategy.js.map +1 -0
- package/src/services/import-storage/s3-import-job-storage-strategy.d.ts +13 -0
- package/src/services/import-storage/s3-import-job-storage-strategy.js +109 -0
- package/src/services/import-storage/s3-import-job-storage-strategy.js.map +1 -0
- package/src/services/product-export.service.d.ts +1 -0
- package/src/services/product-export.service.js +24 -3
- package/src/services/product-export.service.js.map +1 -1
- package/src/services/product-import.service.d.ts +10 -6
- package/src/services/product-import.service.js +62 -37
- package/src/services/product-import.service.js.map +1 -1
- package/src/types.d.ts +21 -1
- package/src/ui/components/export-dialog.component.html +1 -1
- package/src/ui/components/export-dialog.component.ts +10 -2
- package/src/ui/components/product-import.component.html +6 -8
- package/src/ui/translations/en.json +1 -1
- package/src/ui/translations/sv.json +1 -1
|
@@ -20,20 +20,19 @@ const constants_1 = require("../constants");
|
|
|
20
20
|
const product_importer_1 = require("../providers/import-providers/product-importer");
|
|
21
21
|
const lodash_1 = require("lodash");
|
|
22
22
|
let ProductImportService = class ProductImportService {
|
|
23
|
-
|
|
23
|
+
importJobStorageStrategy;
|
|
24
24
|
jobQueueService;
|
|
25
25
|
productImporter;
|
|
26
26
|
searchService;
|
|
27
|
-
collectionService;
|
|
28
27
|
productService;
|
|
29
28
|
eventBus;
|
|
29
|
+
loggerCtx = 'ProductImportService';
|
|
30
30
|
productImportQueue;
|
|
31
|
-
constructor(
|
|
32
|
-
this.
|
|
31
|
+
constructor(importJobStorageStrategy, jobQueueService, productImporter, searchService, productService, eventBus) {
|
|
32
|
+
this.importJobStorageStrategy = importJobStorageStrategy;
|
|
33
33
|
this.jobQueueService = jobQueueService;
|
|
34
34
|
this.productImporter = productImporter;
|
|
35
35
|
this.searchService = searchService;
|
|
36
|
-
this.collectionService = collectionService;
|
|
37
36
|
this.productService = productService;
|
|
38
37
|
this.eventBus = eventBus;
|
|
39
38
|
}
|
|
@@ -41,46 +40,73 @@ let ProductImportService = class ProductImportService {
|
|
|
41
40
|
this.productImportQueue = await this.jobQueueService.createQueue({
|
|
42
41
|
name: 'product-import',
|
|
43
42
|
process: async (job) => {
|
|
44
|
-
// Deserialize the RequestContext from the job data
|
|
45
43
|
const ctx = core_2.RequestContext.deserialize(job.data.ctx);
|
|
46
44
|
let jobResult;
|
|
47
|
-
|
|
48
|
-
this.
|
|
49
|
-
|
|
50
|
-
.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
},
|
|
45
|
+
try {
|
|
46
|
+
const fileContent = await this.importJobStorageStrategy.getImportFileContent(ctx, job.data.storageKey);
|
|
47
|
+
return await new Promise((resolve, reject) => {
|
|
48
|
+
this.productImporter
|
|
49
|
+
.parseAndImport(fileContent, ctx, job.data.updateProductSlug, job.data.mainLanguage, job.data.updatingStrategy)
|
|
50
|
+
.subscribe({
|
|
51
|
+
next: (result) => {
|
|
52
|
+
const processedCount = result.processed || 1;
|
|
53
|
+
const importedCount = result.imported || 0;
|
|
54
|
+
const percentage = (importedCount / processedCount) * 100;
|
|
55
|
+
job.setProgress(percentage);
|
|
56
|
+
jobResult = result;
|
|
57
|
+
},
|
|
58
|
+
complete: () => {
|
|
59
|
+
resolve(jobResult ?? { imported: 0, processed: 0, errors: [], currentProduct: '' });
|
|
60
|
+
},
|
|
61
|
+
error: (err) => {
|
|
62
|
+
reject(err);
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
}).then(async (result) => {
|
|
66
|
+
await this.runPostImportTasks(ctx, result);
|
|
67
|
+
return (0, lodash_1.omit)(result, 'currentProduct');
|
|
71
68
|
});
|
|
72
|
-
}
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
await this.cleanupStoredImportFile(ctx, job.data.storageKey);
|
|
72
|
+
}
|
|
73
73
|
},
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
76
|
async processFile(ctx, file, updateProductSlug, mainLanguage, updatingStrategy) {
|
|
77
|
-
const
|
|
78
|
-
|
|
77
|
+
const storageKey = await this.importJobStorageStrategy.storeImportFile(ctx, {
|
|
78
|
+
originalname: file.originalname,
|
|
79
|
+
buffer: file.buffer,
|
|
80
|
+
});
|
|
81
|
+
return this.triggerProductImport(ctx, storageKey, file.originalname, updateProductSlug, mainLanguage, updatingStrategy);
|
|
82
|
+
}
|
|
83
|
+
async cleanupStoredImportFile(ctx, storageKey) {
|
|
84
|
+
try {
|
|
85
|
+
await this.importJobStorageStrategy.deleteImportFile(ctx, storageKey);
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
core_1.Logger.warn(`Failed to cleanup stored import file "${storageKey}": ${error.message}`, this.loggerCtx);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async runPostImportTasks(ctx, result) {
|
|
92
|
+
if (result.imported <= 0) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const firstProduct = await this.productService.findAll(ctx, { take: 1 });
|
|
96
|
+
const firstItem = firstProduct.items[0];
|
|
97
|
+
if (firstItem) {
|
|
98
|
+
this.eventBus.publish(new core_2.ProductEvent(ctx, firstItem, 'updated'));
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
core_1.Logger.warn('Skipping ProductEvent publish because no product was found', this.loggerCtx);
|
|
102
|
+
}
|
|
103
|
+
await this.searchService.reindex(ctx);
|
|
79
104
|
}
|
|
80
|
-
triggerProductImport(ctx,
|
|
105
|
+
triggerProductImport(ctx, storageKey, fileName, updateProductSlug, mainLanguage, updatingStrategy) {
|
|
81
106
|
return this.productImportQueue.add({
|
|
82
107
|
ctx: ctx.serialize(),
|
|
83
|
-
|
|
108
|
+
storageKey,
|
|
109
|
+
fileName,
|
|
84
110
|
updateProductSlug,
|
|
85
111
|
mainLanguage,
|
|
86
112
|
updatingStrategy,
|
|
@@ -90,11 +116,10 @@ let ProductImportService = class ProductImportService {
|
|
|
90
116
|
exports.ProductImportService = ProductImportService;
|
|
91
117
|
exports.ProductImportService = ProductImportService = __decorate([
|
|
92
118
|
(0, common_1.Injectable)(),
|
|
93
|
-
__param(0, (0, common_1.Inject)(constants_1.
|
|
119
|
+
__param(0, (0, common_1.Inject)(constants_1.IMPORT_JOB_STORAGE_STRATEGY)),
|
|
94
120
|
__metadata("design:paramtypes", [Object, core_1.JobQueueService,
|
|
95
121
|
product_importer_1.ProductImporter,
|
|
96
122
|
core_1.SearchService,
|
|
97
|
-
core_1.CollectionService,
|
|
98
123
|
core_1.ProductService,
|
|
99
124
|
core_1.EventBus])
|
|
100
125
|
], ProductImportService);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-import.service.js","sourceRoot":"","sources":["../../../../../packages/product-import-export-plugin/src/services/product-import.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AACA,2CAAmD;AACnD,wCAUsB;AACtB,
|
|
1
|
+
{"version":3,"file":"product-import.service.js","sourceRoot":"","sources":["../../../../../packages/product-import-export-plugin/src/services/product-import.service.ts"],"names":[],"mappings":"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"}
|
package/src/types.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { ID } from '@vendure/core';
|
|
|
2
2
|
import { ParsedProduct, ParsedProductWithVariants } from './providers/import-providers/import-parser';
|
|
3
3
|
import type { Injector } from '@vendure/core';
|
|
4
4
|
import { ExportStorageStrategy } from './services/export-storage/export-storage-strategy';
|
|
5
|
+
import { ImportJobStorageStrategy } from './services/import-storage/import-job-storage-strategy';
|
|
5
6
|
/**
|
|
6
7
|
* @description
|
|
7
8
|
* The plugin can be configured using the following options:
|
|
@@ -18,11 +19,30 @@ type ImportOptions = {
|
|
|
18
19
|
* will be restored during import. If false, deleted entities will remain deleted.
|
|
19
20
|
*/
|
|
20
21
|
restoreSoftDeleted?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* @description
|
|
24
|
+
* Preferred configuration: provide an import job storage strategy instance directly.
|
|
25
|
+
*/
|
|
26
|
+
storageStrategy?: ImportJobStorageStrategy;
|
|
27
|
+
/**
|
|
28
|
+
* @description
|
|
29
|
+
* Preferred configuration: provide a factory which can use Vendure's DI via the Injector.
|
|
30
|
+
*/
|
|
31
|
+
storageStrategyFactory?: (injector: Injector) => ImportJobStorageStrategy | Promise<ImportJobStorageStrategy>;
|
|
32
|
+
/**
|
|
33
|
+
* @description
|
|
34
|
+
* Deprecated. Kept for backward compatibility.
|
|
35
|
+
* Use `storageStrategy` or `storageStrategyFactory` instead.
|
|
36
|
+
*/
|
|
37
|
+
importJobStorage?: 'local' | 's3';
|
|
21
38
|
};
|
|
22
39
|
export interface PluginInitOptions {
|
|
23
40
|
importOptions: {
|
|
24
41
|
visibleOptions?: Array<keyof ImportOptions>;
|
|
25
42
|
defaultOptions?: ImportOptions;
|
|
43
|
+
storageStrategy?: ImportOptions['storageStrategy'];
|
|
44
|
+
storageStrategyFactory?: ImportOptions['storageStrategyFactory'];
|
|
45
|
+
importJobStorage?: ImportOptions['importJobStorage'];
|
|
26
46
|
};
|
|
27
47
|
exportOptions: {
|
|
28
48
|
defaultFileName?: string;
|
|
@@ -54,7 +74,7 @@ export type JsonAsset = {
|
|
|
54
74
|
name?: string;
|
|
55
75
|
};
|
|
56
76
|
type ExportFields = Array<ProductFields | VariantFields>;
|
|
57
|
-
type ProductFields = '
|
|
77
|
+
type ProductFields = 'name' | 'slug' | 'description' | 'assets' | 'facets' | 'optionGroups';
|
|
58
78
|
type VariantFields = 'sku' | 'optionValues' | 'price' | 'taxCategory' | 'stockOnHand' | 'trackInventory' | 'variantAssets' | 'variantFacets' | 'enabled';
|
|
59
79
|
export type UpdatingStrategy = 'replace' | 'merge';
|
|
60
80
|
export {};
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
[value]="field"
|
|
27
27
|
(change)="toggleExportFieldSelection(field)"
|
|
28
28
|
[checked]="selectedExportFields.includes(field)"
|
|
29
|
-
[disabled]="config.requiredExportFields.includes(field)"
|
|
29
|
+
[disabled]="config.requiredExportFields.includes(field) || isMandatoryExportField(field)"
|
|
30
30
|
/>
|
|
31
31
|
{{ field }}
|
|
32
32
|
</div>
|
|
@@ -5,7 +5,6 @@ import { SharedModule } from '@vendure/admin-ui/core'
|
|
|
5
5
|
import { uniq } from 'lodash'
|
|
6
6
|
|
|
7
7
|
type ProductFields =
|
|
8
|
-
| 'productId'
|
|
9
8
|
| 'name'
|
|
10
9
|
| 'slug'
|
|
11
10
|
| 'description'
|
|
@@ -51,6 +50,7 @@ export class ExportDialogComponent
|
|
|
51
50
|
AfterViewInit,
|
|
52
51
|
OnInit
|
|
53
52
|
{
|
|
53
|
+
private mandatoryOptionFields: Array<ProductFields | VariantFields> = ['optionGroups', 'optionValues']
|
|
54
54
|
@ViewChild('fileNameInput', { static: false }) fileNameElement: ElementRef<HTMLInputElement>
|
|
55
55
|
|
|
56
56
|
resolveWith: (result?: {
|
|
@@ -67,7 +67,6 @@ export class ExportDialogComponent
|
|
|
67
67
|
exportAssetsAs: 'url' | 'json' = 'url'
|
|
68
68
|
selectedExportFields: ExportFields = []
|
|
69
69
|
availableExportFields: ExportFields = [
|
|
70
|
-
'productId',
|
|
71
70
|
'name',
|
|
72
71
|
'slug',
|
|
73
72
|
'description',
|
|
@@ -99,6 +98,7 @@ export class ExportDialogComponent
|
|
|
99
98
|
this.selectedExportFields = uniq([
|
|
100
99
|
...(this.config.defaultExportFields || []),
|
|
101
100
|
...(this.config.requiredExportFields || []),
|
|
101
|
+
...this.mandatoryOptionFields,
|
|
102
102
|
])
|
|
103
103
|
}
|
|
104
104
|
|
|
@@ -137,6 +137,9 @@ export class ExportDialogComponent
|
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
toggleExportFieldSelection(fieldName: ProductFields | VariantFields) {
|
|
140
|
+
if (this.mandatoryOptionFields.includes(fieldName)) {
|
|
141
|
+
return
|
|
142
|
+
}
|
|
140
143
|
const index = this.selectedExportFields.indexOf(fieldName)
|
|
141
144
|
if (index > -1) {
|
|
142
145
|
this.selectedExportFields.splice(index, 1)
|
|
@@ -158,8 +161,13 @@ export class ExportDialogComponent
|
|
|
158
161
|
...this.availableExportFields.filter((field) =>
|
|
159
162
|
this.config.requiredExportFields?.includes(field),
|
|
160
163
|
),
|
|
164
|
+
...this.mandatoryOptionFields,
|
|
161
165
|
]
|
|
162
166
|
this.selectedFields = []
|
|
163
167
|
}
|
|
164
168
|
}
|
|
169
|
+
|
|
170
|
+
isMandatoryExportField(field: ProductFields | VariantFields): boolean {
|
|
171
|
+
return this.mandatoryOptionFields.includes(field)
|
|
172
|
+
}
|
|
165
173
|
}
|
|
@@ -14,14 +14,6 @@
|
|
|
14
14
|
<button class="button primary" *ngIf="!selectedFile" (click)="fileUpload.click()">
|
|
15
15
|
{{ 'product-import.card.button-select' | translate }}
|
|
16
16
|
</button>
|
|
17
|
-
<button
|
|
18
|
-
class="button primary"
|
|
19
|
-
*ngIf="selectedFile"
|
|
20
|
-
(click)="uploadFile()"
|
|
21
|
-
[disabled]="!selectedMainLanguage"
|
|
22
|
-
>
|
|
23
|
-
{{ 'product-import.card.button-upload' | translate }}
|
|
24
|
-
</button>
|
|
25
17
|
</div>
|
|
26
18
|
</vdr-form-field>
|
|
27
19
|
</div>
|
|
@@ -106,6 +98,12 @@
|
|
|
106
98
|
</label>
|
|
107
99
|
</div>
|
|
108
100
|
</div>
|
|
101
|
+
|
|
102
|
+
<div class="input-row" style="margin-top: 24px; padding-top: 16px; border-top: 1px solid #cdcdcd">
|
|
103
|
+
<button class="button primary" (click)="uploadFile()" [disabled]="!selectedMainLanguage">
|
|
104
|
+
{{ 'product-import.card.button-upload' | translate }}
|
|
105
|
+
</button>
|
|
106
|
+
</div>
|
|
109
107
|
</div>
|
|
110
108
|
</vdr-card>
|
|
111
109
|
</vdr-page-block>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"title": "Import products from CSV",
|
|
6
6
|
"description": "Choose a CSV file to import products from",
|
|
7
7
|
"button-select": "Select file",
|
|
8
|
-
"button-upload": "
|
|
8
|
+
"button-upload": "Start import now",
|
|
9
9
|
"update-product-slugs": "Update product slugs based on name",
|
|
10
10
|
"select-main-language": "Select main language: ",
|
|
11
11
|
"updating-strategy": "Updating strategy for facets and assets: ",
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"title": "Importera produkter från CSV",
|
|
6
6
|
"description": "Välj en CSV-fil att importera produkter från",
|
|
7
7
|
"button-select": "Välj fil",
|
|
8
|
-
"button-upload": "
|
|
8
|
+
"button-upload": "Starta import nu",
|
|
9
9
|
"update-product-slugs": "Uppdatera produkt-sluggar utifrån namn",
|
|
10
10
|
"select-main-language": "Välj huvudspråk: ",
|
|
11
11
|
"updating-strategy": "Uppdateringsstrategi för etiketter och filer: ",
|