@haus-tech/product-import-export-plugin 3.0.29-0 → 3.0.29
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 +10 -0
- package/package.json +1 -1
- package/src/api/product-export.controller.d.ts +19 -1
- package/src/api/product-export.controller.js +145 -10
- package/src/api/product-export.controller.js.map +1 -1
- package/src/dashboard/bulk-export.tsx +41 -0
- package/src/dashboard/export-dialog.tsx +287 -0
- package/src/dashboard/export.tsx +14 -326
- package/src/dashboard/exported-list.tsx +234 -0
- package/src/dashboard/import.tsx +92 -136
- package/src/dashboard/index.tsx +56 -3
- package/src/events/product-exported.event.d.ts +16 -0
- package/src/events/product-exported.event.js +19 -0
- package/src/events/product-exported.event.js.map +1 -0
- package/src/handlers/product-exported.handler.d.ts +2 -0
- package/src/handlers/product-exported.handler.js +15 -0
- package/src/handlers/product-exported.handler.js.map +1 -0
- package/src/product-import-export.plugin.js +2 -0
- package/src/product-import-export.plugin.js.map +1 -1
- package/src/services/product-export-queue.service.d.ts +31 -0
- package/src/services/product-export-queue.service.js +135 -0
- package/src/services/product-export-queue.service.js.map +1 -0
- package/src/services/product-export.service.d.ts +1 -0
- package/src/services/product-export.service.js +41 -2
- package/src/services/product-export.service.js.map +1 -1
package/src/dashboard/import.tsx
CHANGED
|
@@ -1,15 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Button,
|
|
3
|
-
DashboardRouteDefinition,
|
|
4
|
-
Page,
|
|
5
|
-
PageTitle,
|
|
6
|
-
PageLayout,
|
|
7
|
-
PageBlock,
|
|
8
|
-
Switch,
|
|
9
|
-
Label,
|
|
10
|
-
RadioGroup,
|
|
11
|
-
RadioGroupItem,
|
|
12
|
-
} from '@vendure/dashboard'
|
|
1
|
+
import { Button, Switch, Label, RadioGroup, RadioGroupItem } from '@vendure/dashboard'
|
|
13
2
|
import { UploadIcon } from 'lucide-react'
|
|
14
3
|
import { useState, useRef, useEffect } from 'react'
|
|
15
4
|
import { toast } from 'sonner'
|
|
@@ -24,7 +13,7 @@ import {
|
|
|
24
13
|
} from './utils'
|
|
25
14
|
|
|
26
15
|
// Import page component
|
|
27
|
-
function
|
|
16
|
+
export function ProductImportBlock() {
|
|
28
17
|
const fileInputRef = useRef<HTMLInputElement>(null)
|
|
29
18
|
const [selectedFile, setSelectedFile] = useState<File | null>(null)
|
|
30
19
|
const [validateFile, setValidateFile] = useState<File | null>(null)
|
|
@@ -502,133 +491,100 @@ function ProductImportPage() {
|
|
|
502
491
|
}
|
|
503
492
|
|
|
504
493
|
return (
|
|
505
|
-
<
|
|
506
|
-
<
|
|
507
|
-
|
|
508
|
-
<
|
|
509
|
-
<
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
/>
|
|
521
|
-
{selectedFile
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
</
|
|
494
|
+
<div className="space-y-6">
|
|
495
|
+
<div>
|
|
496
|
+
<Label htmlFor="file-upload">Upload CSV file</Label>
|
|
497
|
+
<div className="flex items-center gap-2 mt-2">
|
|
498
|
+
<input
|
|
499
|
+
ref={fileInputRef}
|
|
500
|
+
type="file"
|
|
501
|
+
id="file-upload"
|
|
502
|
+
accept=".csv"
|
|
503
|
+
onChange={onFileSelected}
|
|
504
|
+
className="hidden"
|
|
505
|
+
/>
|
|
506
|
+
{selectedFile ? (
|
|
507
|
+
<>
|
|
508
|
+
<Button type="button" variant="outline" onClick={() => fileInputRef.current?.click()}>
|
|
509
|
+
<UploadIcon className="mr-2 h-4 w-4" />
|
|
510
|
+
{selectedFile.name}
|
|
511
|
+
</Button>
|
|
512
|
+
<Button type="button" onClick={uploadFile} disabled={!selectedMainLanguage}>
|
|
513
|
+
Upload file
|
|
514
|
+
</Button>
|
|
515
|
+
</>
|
|
516
|
+
) : (
|
|
517
|
+
<Button type="button" variant="default" onClick={() => fileInputRef.current?.click()}>
|
|
518
|
+
<UploadIcon className="mr-2 h-4 w-4" />
|
|
519
|
+
Select file
|
|
520
|
+
</Button>
|
|
521
|
+
)}
|
|
522
|
+
</div>
|
|
523
|
+
</div>
|
|
524
|
+
|
|
525
|
+
{selectedFile && (
|
|
526
|
+
<div className="space-y-4 pt-4 border-t">
|
|
527
|
+
{config?.visibleOptions?.includes('updateProductSlug') && (
|
|
528
|
+
<div className="flex items-center space-x-2">
|
|
529
|
+
<Switch
|
|
530
|
+
id="update-slug"
|
|
531
|
+
checked={updateProductSlug}
|
|
532
|
+
onCheckedChange={setUpdateProductSlug}
|
|
533
|
+
/>
|
|
534
|
+
<Label htmlFor="update-slug">Update product slugs based on name</Label>
|
|
546
535
|
</div>
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
536
|
+
)}
|
|
537
|
+
|
|
538
|
+
<div>
|
|
539
|
+
<Label>Select main language:</Label>
|
|
540
|
+
<RadioGroup
|
|
541
|
+
value={selectedMainLanguage || ''}
|
|
542
|
+
onValueChange={(val) => onMainLanguageChange(val as LanguageCode)}
|
|
543
|
+
>
|
|
544
|
+
<div className="flex flex-col gap-2 mt-2">
|
|
545
|
+
{availableLanguages.map((lang) => (
|
|
546
|
+
<div key={lang} className="flex items-center space-x-2">
|
|
547
|
+
<RadioGroupItem value={lang} id={`lang-${lang}`} />
|
|
548
|
+
<Label htmlFor={`lang-${lang}`} className="font-normal">
|
|
549
|
+
{lang}
|
|
550
|
+
</Label>
|
|
558
551
|
</div>
|
|
559
|
-
)}
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
</
|
|
585
|
-
|
|
586
|
-
<div>
|
|
587
|
-
<Label>Updating strategy for facets and assets:</Label>
|
|
588
|
-
<RadioGroup
|
|
589
|
-
value={updatingStrategy}
|
|
590
|
-
onValueChange={(val) => setUpdatingStrategy(val as UpdatingStrategy)}
|
|
591
|
-
>
|
|
592
|
-
<div className="flex items-center space-x-2">
|
|
593
|
-
<RadioGroupItem value="merge" id="merge" />
|
|
594
|
-
<Label htmlFor="merge" className="font-normal">
|
|
595
|
-
Merge
|
|
596
|
-
</Label>
|
|
597
|
-
</div>
|
|
598
|
-
<div className="flex items-center space-x-2">
|
|
599
|
-
<RadioGroupItem value="replace" id="replace" />
|
|
600
|
-
<Label htmlFor="replace" className="font-normal">
|
|
601
|
-
Overwrite
|
|
602
|
-
</Label>
|
|
603
|
-
</div>
|
|
604
|
-
</RadioGroup>
|
|
605
|
-
{updatingStrategy === 'replace' && (
|
|
606
|
-
<p className="text-sm text-red-600 mt-2">
|
|
607
|
-
Warning: This will remove existing facets and assets from products and
|
|
608
|
-
variants.
|
|
609
|
-
</p>
|
|
610
|
-
)}
|
|
611
|
-
</div>
|
|
552
|
+
))}
|
|
553
|
+
</div>
|
|
554
|
+
</RadioGroup>
|
|
555
|
+
<p className="text-sm text-muted-foreground mt-2 italic">
|
|
556
|
+
The main language is used as a fallback when translations are missing. It is
|
|
557
|
+
recommended to select the language that is used the most in your system.
|
|
558
|
+
</p>
|
|
559
|
+
</div>
|
|
560
|
+
|
|
561
|
+
<div>
|
|
562
|
+
<Label>Strategy for facets and assets:</Label>
|
|
563
|
+
<RadioGroup
|
|
564
|
+
value={updatingStrategy}
|
|
565
|
+
onValueChange={(val) => setUpdatingStrategy(val as UpdatingStrategy)}
|
|
566
|
+
>
|
|
567
|
+
<div className="flex items-center space-x-2 mt-2">
|
|
568
|
+
<RadioGroupItem value="merge" id="merge" />
|
|
569
|
+
<Label htmlFor="merge" className="font-normal">
|
|
570
|
+
Merge
|
|
571
|
+
</Label>
|
|
572
|
+
</div>
|
|
573
|
+
<div className="flex items-center space-x-2">
|
|
574
|
+
<RadioGroupItem value="replace" id="replace" />
|
|
575
|
+
<Label htmlFor="replace" className="font-normal">
|
|
576
|
+
Overwrite
|
|
577
|
+
</Label>
|
|
612
578
|
</div>
|
|
579
|
+
</RadioGroup>
|
|
580
|
+
{updatingStrategy === 'replace' && (
|
|
581
|
+
<p className="text-sm text-red-600 mt-2">
|
|
582
|
+
Warning: This will remove existing facets and assets from products and variants.
|
|
583
|
+
</p>
|
|
613
584
|
)}
|
|
614
585
|
</div>
|
|
615
|
-
</
|
|
616
|
-
|
|
617
|
-
</
|
|
586
|
+
</div>
|
|
587
|
+
)}
|
|
588
|
+
</div>
|
|
618
589
|
)
|
|
619
590
|
}
|
|
620
|
-
|
|
621
|
-
// Import route definition
|
|
622
|
-
export const productImportRoute: DashboardRouteDefinition = {
|
|
623
|
-
navMenuItem: {
|
|
624
|
-
sectionId: 'catalog',
|
|
625
|
-
id: 'product-importer',
|
|
626
|
-
url: '/product-importer',
|
|
627
|
-
title: 'Import Products',
|
|
628
|
-
},
|
|
629
|
-
path: '/product-importer',
|
|
630
|
-
loader: () => ({
|
|
631
|
-
breadcrumb: 'Import Products',
|
|
632
|
-
}),
|
|
633
|
-
component: () => <ProductImportPage />,
|
|
634
|
-
}
|
package/src/dashboard/index.tsx
CHANGED
|
@@ -1,6 +1,59 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
defineDashboardExtension,
|
|
3
|
+
DashboardRouteDefinition,
|
|
4
|
+
PageTitle,
|
|
5
|
+
Page,
|
|
6
|
+
PageLayout,
|
|
7
|
+
PageBlock,
|
|
8
|
+
} from '@vendure/dashboard'
|
|
9
|
+
import { ExportProductsBulkAction } from './bulk-export'
|
|
10
|
+
import { ProductImportBlock } from './import'
|
|
11
|
+
import { ProductExportBlock } from './export'
|
|
12
|
+
import { ExportedList } from './exported-list'
|
|
13
|
+
|
|
14
|
+
export const productImportRoute: DashboardRouteDefinition = {
|
|
15
|
+
navMenuItem: {
|
|
16
|
+
sectionId: 'catalog',
|
|
17
|
+
id: 'product-importer',
|
|
18
|
+
url: '/product-importer',
|
|
19
|
+
title: 'Import/export products',
|
|
20
|
+
},
|
|
21
|
+
path: '/product-importer',
|
|
22
|
+
loader: () => ({
|
|
23
|
+
breadcrumb: 'Import/export products',
|
|
24
|
+
}),
|
|
25
|
+
component: () => (
|
|
26
|
+
<Page pageId="product-import">
|
|
27
|
+
<PageTitle>Import/export products</PageTitle>
|
|
28
|
+
<PageLayout>
|
|
29
|
+
<PageBlock
|
|
30
|
+
column="main"
|
|
31
|
+
blockId="main-form-import"
|
|
32
|
+
title="Import products"
|
|
33
|
+
description="Import products from a CSV file"
|
|
34
|
+
>
|
|
35
|
+
<ProductImportBlock />
|
|
36
|
+
</PageBlock>
|
|
37
|
+
<PageBlock
|
|
38
|
+
column="main"
|
|
39
|
+
blockId="main-form-export"
|
|
40
|
+
title="Export products"
|
|
41
|
+
description="Exports all products to a CSV file. The export is added to the job queue and will be processed in the background. When the file is ready, you will receive an email and the exported file will be available to download from the list below."
|
|
42
|
+
>
|
|
43
|
+
<ProductExportBlock />
|
|
44
|
+
</PageBlock>
|
|
45
|
+
<PageBlock
|
|
46
|
+
column="main"
|
|
47
|
+
blockId="main-form-exported-list"
|
|
48
|
+
title="Exported files"
|
|
49
|
+
description="Files available for download"
|
|
50
|
+
>
|
|
51
|
+
<ExportedList />
|
|
52
|
+
</PageBlock>
|
|
53
|
+
</PageLayout>
|
|
54
|
+
</Page>
|
|
55
|
+
),
|
|
56
|
+
}
|
|
4
57
|
|
|
5
58
|
defineDashboardExtension({
|
|
6
59
|
routes: [productImportRoute],
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { RequestContext, VendureEvent } from '@vendure/core';
|
|
2
|
+
export interface ProductExportResult {
|
|
3
|
+
filePath: string;
|
|
4
|
+
fileName: string;
|
|
5
|
+
productCount: number;
|
|
6
|
+
toEmail: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* @description
|
|
10
|
+
* This event is fired whenever a Product export job completes successfully.
|
|
11
|
+
*/
|
|
12
|
+
export declare class ProductExportedEvent extends VendureEvent {
|
|
13
|
+
ctx: RequestContext;
|
|
14
|
+
input: ProductExportResult;
|
|
15
|
+
constructor(ctx: RequestContext, input: ProductExportResult);
|
|
16
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ProductExportedEvent = void 0;
|
|
4
|
+
const core_1 = require("@vendure/core");
|
|
5
|
+
/**
|
|
6
|
+
* @description
|
|
7
|
+
* This event is fired whenever a Product export job completes successfully.
|
|
8
|
+
*/
|
|
9
|
+
class ProductExportedEvent extends core_1.VendureEvent {
|
|
10
|
+
ctx;
|
|
11
|
+
input;
|
|
12
|
+
constructor(ctx, input) {
|
|
13
|
+
super();
|
|
14
|
+
this.ctx = ctx;
|
|
15
|
+
this.input = input;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.ProductExportedEvent = ProductExportedEvent;
|
|
19
|
+
//# sourceMappingURL=product-exported.event.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product-exported.event.js","sourceRoot":"","sources":["../../../../../packages/product-import-export-plugin/src/events/product-exported.event.ts"],"names":[],"mappings":";;;AAAA,wCAA4D;AAS5D;;;GAGG;AACH,MAAa,oBAAqB,SAAQ,mBAAY;IAE3C;IACA;IAFT,YACS,GAAmB,EACnB,KAA0B;QAEjC,KAAK,EAAE,CAAA;QAHA,QAAG,GAAH,GAAG,CAAgB;QACnB,UAAK,GAAL,KAAK,CAAqB;IAGnC,CAAC;CACF;AAPD,oDAOC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.productExportedHandler = void 0;
|
|
4
|
+
const email_plugin_1 = require("@vendure/email-plugin");
|
|
5
|
+
const product_exported_event_1 = require("../events/product-exported.event");
|
|
6
|
+
exports.productExportedHandler = new email_plugin_1.EmailEventListener('product-export-complete')
|
|
7
|
+
.on(product_exported_event_1.ProductExportedEvent)
|
|
8
|
+
.setRecipient((event) => event.input.toEmail)
|
|
9
|
+
.setFrom('{{ fromAddress }}')
|
|
10
|
+
.setSubject((event) => `Product export complete - ${event.input.fileName}`)
|
|
11
|
+
.setTemplateVars((event) => ({
|
|
12
|
+
fileName: event.input.fileName,
|
|
13
|
+
productCount: event.input.productCount,
|
|
14
|
+
}));
|
|
15
|
+
//# sourceMappingURL=product-exported.handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product-exported.handler.js","sourceRoot":"","sources":["../../../../../packages/product-import-export-plugin/src/handlers/product-exported.handler.ts"],"names":[],"mappings":";;;AAAA,wDAA0D;AAC1D,6EAAuE;AAE1D,QAAA,sBAAsB,GAAG,IAAI,iCAAkB,CAAC,yBAAyB,CAAC;KACpF,EAAE,CAAC,6CAAoB,CAAC;KACxB,YAAY,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC;KAC5C,OAAO,CAAC,mBAAmB,CAAC;KAC5B,UAAU,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,6BAA6B,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;KAC1E,eAAe,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC3B,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,QAAQ;IAC9B,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,YAAY;CACvC,CAAC,CAAC,CAAA"}
|
|
@@ -57,6 +57,7 @@ const asset_importer_1 = require("./providers/import-providers/asset-importer");
|
|
|
57
57
|
const product_import_service_1 = require("./services/product-import.service");
|
|
58
58
|
const extended_fast_importer_service_1 = require("./services/extended-fast-importer.service");
|
|
59
59
|
const product_export_service_1 = require("./services/product-export.service");
|
|
60
|
+
const product_export_queue_service_1 = require("./services/product-export-queue.service");
|
|
60
61
|
let ProductImportExportPlugin = class ProductImportExportPlugin {
|
|
61
62
|
static { ProductImportExportPlugin_1 = this; }
|
|
62
63
|
static options;
|
|
@@ -142,6 +143,7 @@ exports.ProductImportExportPlugin = ProductImportExportPlugin = ProductImportExp
|
|
|
142
143
|
import_parser_1.ImportParser,
|
|
143
144
|
asset_importer_1.ExtendedAssetImporter,
|
|
144
145
|
product_export_service_1.ProductExportService,
|
|
146
|
+
product_export_queue_service_1.ProductExportQueueService,
|
|
145
147
|
],
|
|
146
148
|
controllers: [
|
|
147
149
|
product_import_controller_1.ProductImportController,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-import-export.plugin.js","sourceRoot":"","sources":["../../../../packages/product-import-export-plugin/src/product-import-export.plugin.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wCAAuE;AAEvE,2CAA4B;AAC5B,mCAA6B;AAE7B,2CAAkE;AAGlE,iBAAiB;AACjB,+EAAyE;AACzE,+EAAyE;AACzE,+DAA6E;AAC7E,eAAe;AACf,oFAA+E;AAC/E,8EAAyE;AACzE,gFAAmF;AACnF,cAAc;AACd,8EAAwE;AACxE,8FAAuF;AACvF,8EAAwE;
|
|
1
|
+
{"version":3,"file":"product-import-export.plugin.js","sourceRoot":"","sources":["../../../../packages/product-import-export-plugin/src/product-import-export.plugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { RequestContext, JobQueueService, SerializedRequestContext, ID, EventBus } from '@vendure/core';
|
|
3
|
+
import { PluginInitOptions } from '../types';
|
|
4
|
+
import { ProductExportService } from './product-export.service';
|
|
5
|
+
export declare class ProductExportQueueService implements OnModuleInit {
|
|
6
|
+
private options;
|
|
7
|
+
private jobQueueService;
|
|
8
|
+
private productExportService;
|
|
9
|
+
private eventBus;
|
|
10
|
+
private productExportQueue;
|
|
11
|
+
constructor(options: PluginInitOptions, jobQueueService: JobQueueService, productExportService: ProductExportService, eventBus: EventBus);
|
|
12
|
+
onModuleInit(): Promise<void>;
|
|
13
|
+
triggerExport(ctx: RequestContext, fileName: string, customFields: string, exportAssetsAs: 'url' | 'json', selectedExportFields: string, allProducts?: boolean): Promise<import("@vendure/core/dist/job-queue/subscribable-job").SubscribableJob<{
|
|
14
|
+
ctx: SerializedRequestContext;
|
|
15
|
+
fileName: string;
|
|
16
|
+
customFields: string;
|
|
17
|
+
exportAssetsAs: "url" | "json";
|
|
18
|
+
selectedExportFields: string;
|
|
19
|
+
allProducts: boolean;
|
|
20
|
+
selectedProductIds?: ID[];
|
|
21
|
+
}>>;
|
|
22
|
+
triggerExportWithSelection(ctx: RequestContext, fileName: string, customFields: string, exportAssetsAs: 'url' | 'json', selectedExportFields: string, selectedProductIds: ID[]): Promise<import("@vendure/core/dist/job-queue/subscribable-job").SubscribableJob<{
|
|
23
|
+
ctx: SerializedRequestContext;
|
|
24
|
+
fileName: string;
|
|
25
|
+
customFields: string;
|
|
26
|
+
exportAssetsAs: "url" | "json";
|
|
27
|
+
selectedExportFields: string;
|
|
28
|
+
allProducts: boolean;
|
|
29
|
+
selectedProductIds?: ID[];
|
|
30
|
+
}>>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
22
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
+
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
42
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
43
|
+
};
|
|
44
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
45
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
46
|
+
};
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.ProductExportQueueService = void 0;
|
|
49
|
+
const common_1 = require("@nestjs/common");
|
|
50
|
+
const core_1 = require("@vendure/core");
|
|
51
|
+
const constants_1 = require("../constants");
|
|
52
|
+
const product_export_service_1 = require("./product-export.service");
|
|
53
|
+
const product_exported_event_1 = require("../events/product-exported.event");
|
|
54
|
+
const path = __importStar(require("path"));
|
|
55
|
+
let ProductExportQueueService = class ProductExportQueueService {
|
|
56
|
+
options;
|
|
57
|
+
jobQueueService;
|
|
58
|
+
productExportService;
|
|
59
|
+
eventBus;
|
|
60
|
+
productExportQueue;
|
|
61
|
+
constructor(options, jobQueueService, productExportService, eventBus) {
|
|
62
|
+
this.options = options;
|
|
63
|
+
this.jobQueueService = jobQueueService;
|
|
64
|
+
this.productExportService = productExportService;
|
|
65
|
+
this.eventBus = eventBus;
|
|
66
|
+
}
|
|
67
|
+
async onModuleInit() {
|
|
68
|
+
this.productExportQueue = await this.jobQueueService.createQueue({
|
|
69
|
+
name: 'product-export',
|
|
70
|
+
process: async (job) => {
|
|
71
|
+
try {
|
|
72
|
+
const ctx = core_1.RequestContext.deserialize(job.data.ctx);
|
|
73
|
+
let productIds = [];
|
|
74
|
+
if (job.data.allProducts) {
|
|
75
|
+
productIds = await this.productExportService.getAllProductIds(ctx);
|
|
76
|
+
}
|
|
77
|
+
else if (job.data.selectedProductIds) {
|
|
78
|
+
productIds = job.data.selectedProductIds;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
throw new Error('No products to export');
|
|
82
|
+
}
|
|
83
|
+
const filePath = await this.productExportService.createExportFile(ctx, productIds, job.data.fileName, job.data.customFields, job.data.exportAssetsAs, job.data.selectedExportFields);
|
|
84
|
+
const result = {
|
|
85
|
+
filePath,
|
|
86
|
+
fileName: path.basename(filePath),
|
|
87
|
+
productCount: productIds.length,
|
|
88
|
+
};
|
|
89
|
+
const userEmail = ctx.session?.user?.identifier || '';
|
|
90
|
+
const eventResult = {
|
|
91
|
+
...result,
|
|
92
|
+
toEmail: userEmail,
|
|
93
|
+
};
|
|
94
|
+
// Publish event for email notification
|
|
95
|
+
this.eventBus.publish(new product_exported_event_1.ProductExportedEvent(ctx, eventResult));
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
console.error('Product export job failed:', err);
|
|
100
|
+
throw err;
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
async triggerExport(ctx, fileName, customFields, exportAssetsAs, selectedExportFields, allProducts = true) {
|
|
106
|
+
return this.productExportQueue.add({
|
|
107
|
+
ctx: ctx.serialize(),
|
|
108
|
+
fileName,
|
|
109
|
+
customFields,
|
|
110
|
+
exportAssetsAs,
|
|
111
|
+
selectedExportFields,
|
|
112
|
+
allProducts,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
async triggerExportWithSelection(ctx, fileName, customFields, exportAssetsAs, selectedExportFields, selectedProductIds) {
|
|
116
|
+
return this.productExportQueue.add({
|
|
117
|
+
ctx: ctx.serialize(),
|
|
118
|
+
fileName,
|
|
119
|
+
customFields,
|
|
120
|
+
exportAssetsAs,
|
|
121
|
+
selectedExportFields,
|
|
122
|
+
allProducts: false,
|
|
123
|
+
selectedProductIds,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
exports.ProductExportQueueService = ProductExportQueueService;
|
|
128
|
+
exports.ProductExportQueueService = ProductExportQueueService = __decorate([
|
|
129
|
+
(0, common_1.Injectable)(),
|
|
130
|
+
__param(0, (0, common_1.Inject)(constants_1.PRODUCT_IMPORT_EXPORT_PLUGIN_OPTIONS)),
|
|
131
|
+
__metadata("design:paramtypes", [Object, core_1.JobQueueService,
|
|
132
|
+
product_export_service_1.ProductExportService,
|
|
133
|
+
core_1.EventBus])
|
|
134
|
+
], ProductExportQueueService);
|
|
135
|
+
//# sourceMappingURL=product-export-queue.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product-export-queue.service.js","sourceRoot":"","sources":["../../../../../packages/product-import-export-plugin/src/services/product-export-queue.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAAiE;AACjE,wCAOsB;AACtB,4CAAmE;AAEnE,qEAA+D;AAC/D,6EAAuE;AACvE,2CAA4B;AAGrB,IAAM,yBAAyB,GAA/B,MAAM,yBAAyB;IAYoB;IAC9C;IACA;IACA;IAdF,kBAAkB,CAQxB;IAEF,YACwD,OAA0B,EACxE,eAAgC,EAChC,oBAA0C,EAC1C,QAAkB;QAH4B,YAAO,GAAP,OAAO,CAAmB;QACxE,oBAAe,GAAf,eAAe,CAAiB;QAChC,yBAAoB,GAApB,oBAAoB,CAAsB;QAC1C,aAAQ,GAAR,QAAQ,CAAU;IACzB,CAAC;IAEG,KAAK,CAAC,YAAY;QACvB,IAAI,CAAC,kBAAkB,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC;YAC/D,IAAI,EAAE,gBAAgB;YACtB,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;gBACrB,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,qBAAc,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;oBACpD,IAAI,UAAU,GAAS,EAAE,CAAA;oBAEzB,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;wBACzB,UAAU,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAA;oBACpE,CAAC;yBAAM,IAAI,GAAG,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;wBACvC,UAAU,GAAG,GAAG,CAAC,IAAI,CAAC,kBAAkB,CAAA;oBAC1C,CAAC;yBAAM,CAAC;wBACN,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAA;oBAC1C,CAAC;oBAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,gBAAgB,CAC/D,GAAG,EACH,UAAU,EACV,GAAG,CAAC,IAAI,CAAC,QAAQ,EACjB,GAAG,CAAC,IAAI,CAAC,YAAY,EACrB,GAAG,CAAC,IAAI,CAAC,cAAc,EACvB,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAC9B,CAAA;oBAED,MAAM,MAAM,GAAG;wBACb,QAAQ;wBACR,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;wBACjC,YAAY,EAAE,UAAU,CAAC,MAAM;qBAChC,CAAA;oBAED,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,UAAU,IAAI,EAAE,CAAA;oBAErD,MAAM,WAAW,GAAG;wBAClB,GAAG,MAAM;wBACT,OAAO,EAAE,SAAS;qBACnB,CAAA;oBACD,uCAAuC;oBACvC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,6CAAoB,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAA;oBAEjE,OAAO,MAAM,CAAA;gBACf,CAAC;gBAAC,OAAO,GAAQ,EAAE,CAAC;oBAClB,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,GAAG,CAAC,CAAA;oBAChD,MAAM,GAAG,CAAA;gBACX,CAAC;YACH,CAAC;SACF,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,aAAa,CACjB,GAAmB,EACnB,QAAgB,EAChB,YAAoB,EACpB,cAA8B,EAC9B,oBAA4B,EAC5B,WAAW,GAAG,IAAI;QAElB,OAAO,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC;YACjC,GAAG,EAAE,GAAG,CAAC,SAAS,EAAE;YACpB,QAAQ;YACR,YAAY;YACZ,cAAc;YACd,oBAAoB;YACpB,WAAW;SACZ,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,0BAA0B,CAC9B,GAAmB,EACnB,QAAgB,EAChB,YAAoB,EACpB,cAA8B,EAC9B,oBAA4B,EAC5B,kBAAwB;QAExB,OAAO,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC;YACjC,GAAG,EAAE,GAAG,CAAC,SAAS,EAAE;YACpB,QAAQ;YACR,YAAY;YACZ,cAAc;YACd,oBAAoB;YACpB,WAAW,EAAE,KAAK;YAClB,kBAAkB;SACnB,CAAC,CAAA;IACJ,CAAC;CACF,CAAA;AAvGY,8DAAyB;oCAAzB,yBAAyB;IADrC,IAAA,mBAAU,GAAE;IAaR,WAAA,IAAA,eAAM,EAAC,gDAAoC,CAAC,CAAA;6CACpB,sBAAe;QACV,6CAAoB;QAChC,eAAQ;GAfjB,yBAAyB,CAuGrC"}
|
|
@@ -16,6 +16,7 @@ export declare class ProductExportService {
|
|
|
16
16
|
private getStockOnHand;
|
|
17
17
|
private mapTranslations;
|
|
18
18
|
private mapFacetTranslations;
|
|
19
|
+
getAllProductIds(ctx: RequestContext): Promise<ID[]>;
|
|
19
20
|
getCustomFields(ctx: RequestContext, productIds: string[]): Promise<{
|
|
20
21
|
name: string;
|
|
21
22
|
type: string;
|