Sfoglia il codice sorgente

Merge branch 'minor' into react-dashboard

Michael Bromley 10 mesi fa
parent
commit
b1e467b1ba
45 ha cambiato i file con 324 aggiunte e 150 eliminazioni
  1. 24 0
      CHANGELOG.md
  2. 1 0
      e2e-common/e2e-initial-data.ts
  3. 1 1
      lerna.json
  4. 4 4
      packages/admin-ui-plugin/package.json
  5. 2 2
      packages/admin-ui/package.json
  6. 1 1
      packages/admin-ui/src/lib/catalog/src/components/collection-data-table/collection-data-table.component.html
  7. 2 0
      packages/admin-ui/src/lib/catalog/src/components/product-options-editor/product-options-editor.component.html
  8. 1 1
      packages/admin-ui/src/lib/core/src/common/version.ts
  9. 1 1
      packages/admin-ui/src/lib/core/src/shared/components/data-table-2/data-table2.component.html
  10. 6 5
      packages/admin-ui/src/lib/core/src/shared/components/data-table-2/data-table2.component.ts
  11. 1 1
      packages/admin-ui/src/lib/order/src/components/order-data-table/order-data-table.component.html
  12. 3 3
      packages/asset-server-plugin/package.json
  13. 3 3
      packages/cli/package.json
  14. 1 1
      packages/common/package.json
  15. 5 0
      packages/core/e2e/active-order-strategy.e2e-spec.ts
  16. 9 0
      packages/core/e2e/draft-order.e2e-spec.ts
  17. 20 2
      packages/core/e2e/fixtures/test-plugins/with-job-queue.ts
  18. 15 0
      packages/core/e2e/job-queue.e2e-spec.ts
  19. 1 0
      packages/core/e2e/order-multi-vendor.e2e-spec.ts
  20. 2 2
      packages/core/e2e/order-multiple-shipping.e2e-spec.ts
  21. 12 13
      packages/core/e2e/order.e2e-spec.ts
  22. 26 21
      packages/core/e2e/shipping-method.e2e-spec.ts
  23. 7 0
      packages/core/e2e/shop-order.e2e-spec.ts
  24. 5 2
      packages/core/e2e/utils/test-order-utils.ts
  25. 2 2
      packages/core/package.json
  26. 4 4
      packages/core/src/data-import/providers/importer/fast-importer.service.ts
  27. 2 2
      packages/core/src/data-import/providers/populator/populator.ts
  28. 1 1
      packages/core/src/data-import/types.ts
  29. 24 11
      packages/core/src/job-queue/subscribable-job.ts
  30. 1 1
      packages/core/src/service/helpers/order-modifier/order-modifier.ts
  31. 3 3
      packages/create/package.json
  32. 9 9
      packages/dev-server/package.json
  33. 3 3
      packages/elasticsearch-plugin/package.json
  34. 3 3
      packages/email-plugin/package.json
  35. 3 3
      packages/harden-plugin/package.json
  36. 3 3
      packages/job-queue-plugin/package.json
  37. 23 24
      packages/job-queue-plugin/src/bullmq/bullmq-job-queue-strategy.ts
  38. 1 0
      packages/job-queue-plugin/src/bullmq/constants.ts
  39. 40 0
      packages/job-queue-plugin/src/bullmq/plugin.ts
  40. 32 1
      packages/job-queue-plugin/src/bullmq/types.ts
  41. 4 4
      packages/payments-plugin/package.json
  42. 3 3
      packages/sentry-plugin/package.json
  43. 3 3
      packages/stellate-plugin/package.json
  44. 3 3
      packages/testing/package.json
  45. 4 4
      packages/ui-devkit/package.json

+ 24 - 0
CHANGELOG.md

@@ -1,3 +1,27 @@
+## <small>3.1.7 (2025-03-06)</small>
+
+
+#### Fixes
+
+* **admin-ui** Fix broken Collection list & Order detail views ([6a5bb90](https://github.com/vendure-ecommerce/vendure/commit/6a5bb90)), fixes regression from [#3368](https://github.com/vendure-ecommerce/vendure/issues/3368)
+
+## <small>3.1.6 (2025-03-06)</small>
+
+
+#### Fixes
+
+* **core** Fix FastImporterService when using stockOnHand ([f97484c](https://github.com/vendure-ecommerce/vendure/commit/f97484c)), fixes regression from [#3288](https://github.com/vendure-ecommerce/vendure/issues/3288)
+
+## <small>3.1.5 (2025-03-06)</small>
+
+
+#### Fixes
+
+* **admin-ui** Fix incorrect tracking id on ProductOption's / ProductOption list per page switch (#3368) ([33cfea6](https://github.com/vendure-ecommerce/vendure/commit/33cfea6)), closes [#3368](https://github.com/vendure-ecommerce/vendure/issues/3368)
+* **core** Fix fast-importer-service stock location (#3288) ([59d6447](https://github.com/vendure-ecommerce/vendure/commit/59d6447)), closes [#3288](https://github.com/vendure-ecommerce/vendure/issues/3288)
+* **core** Fix order cancellation when shipping has tax (#3393) ([e753df9](https://github.com/vendure-ecommerce/vendure/commit/e753df9)), closes [#3393](https://github.com/vendure-ecommerce/vendure/issues/3393)
+* **core** Fix server crash when subscribable job times out ([7f851c3](https://github.com/vendure-ecommerce/vendure/commit/7f851c3)), closes [#3397](https://github.com/vendure-ecommerce/vendure/issues/3397)
+
 ## <small>3.1.4 (2025-02-28)</small>
 
 

+ 1 - 0
e2e-common/e2e-initial-data.ts

@@ -12,6 +12,7 @@ export const initialData: InitialData = {
     shippingMethods: [
         { name: 'Standard Shipping', price: 500 },
         { name: 'Express Shipping', price: 1000 },
+        { name: 'Express Shipping (Taxed)', price: 1000, taxRate: 20 },
     ],
     paymentMethods: [],
     countries: [

+ 1 - 1
lerna.json

@@ -1,6 +1,6 @@
 {
     "packages": ["packages/*"],
-    "version": "3.1.4",
+    "version": "3.1.7",
     "npmClient": "npm",
     "command": {
         "version": {

+ 4 - 4
packages/admin-ui-plugin/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@vendure/admin-ui-plugin",
-    "version": "3.1.4",
+    "version": "3.1.7",
     "main": "lib/index.js",
     "types": "lib/index.d.ts",
     "files": [
@@ -21,9 +21,9 @@
     "devDependencies": {
         "@types/express": "^4.17.21",
         "@types/fs-extra": "^11.0.4",
-        "@vendure/admin-ui": "^3.1.4",
-        "@vendure/common": "^3.1.4",
-        "@vendure/core": "^3.1.4",
+        "@vendure/admin-ui": "^3.1.7",
+        "@vendure/common": "^3.1.7",
+        "@vendure/core": "^3.1.7",
         "express": "^4.18.3",
         "rimraf": "^5.0.5",
         "typescript": "5.4.2"

+ 2 - 2
packages/admin-ui/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@vendure/admin-ui",
-    "version": "3.1.4",
+    "version": "3.1.7",
     "license": "GPL-3.0-or-later",
     "scripts": {
         "ng": "ng",
@@ -49,7 +49,7 @@
         "@ng-select/ng-select": "^12.0.7",
         "@ngx-translate/core": "^15.0.0",
         "@ngx-translate/http-loader": "^8.0.0",
-        "@vendure/common": "^3.1.4",
+        "@vendure/common": "^3.1.7",
         "@webcomponents/custom-elements": "^1.6.0",
         "apollo-angular": "^6.0.0",
         "apollo-upload-client": "^18.0.1",

+ 1 - 1
packages/admin-ui/src/lib/catalog/src/components/collection-data-table/collection-data-table.component.html

@@ -114,7 +114,7 @@
                               id: id,
                           };
                 index as i;
-                trackBy: trackByFn
+                trackBy: trackByFn.bind(this)
             "
             >
                 <ng-container

+ 2 - 0
packages/admin-ui/src/lib/catalog/src/components/product-options-editor/product-options-editor.component.html

@@ -78,9 +78,11 @@
                         id="edit-options-list"
                         *ngIf="getOptions(optionGroup) as options"
                         [items]="options"
+                        [trackByPath]="'value.id'"
                         [itemsPerPage]="paginationSettings[optionGroup.value.id]?.itemsPerPage"
                         [currentPage]="paginationSettings[optionGroup.value.id]?.currentPage"
                         (pageChange)="paginationSettings[optionGroup.value.id].currentPage = $event"
+                        (itemsPerPageChange)="paginationSettings[optionGroup.value.id].itemsPerPage = $event"
                         [totalItems]="options.length"
                     >
                         <vdr-dt2-column [heading]="'common.id' | translate" id="id" [hiddenByDefault]="true">

+ 1 - 1
packages/admin-ui/src/lib/core/src/common/version.ts

@@ -1,2 +1,2 @@
 // Auto-generated by the set-version.js script.
-export const ADMIN_UI_VERSION = '3.1.4';
+export const ADMIN_UI_VERSION = '3.1.7';

+ 1 - 1
packages/admin-ui/src/lib/core/src/shared/components/data-table-2/data-table2.component.html

@@ -106,7 +106,7 @@
                                   totalItems: totalItems
                               };
                     index as i;
-                    trackBy: trackByFn
+                    trackBy: trackByFn.bind(this)
                 "
             >
                 <td *ngIf="selectionManager" class="selection-col" [class.active]="activeIndex === i">

+ 6 - 5
packages/admin-ui/src/lib/core/src/shared/components/data-table-2/data-table2.component.ts

@@ -114,6 +114,7 @@ export class DataTable2Component<T> implements AfterContentInit, OnChanges, OnDe
     @Input() emptyStateLabel: string;
     @Input() filters: DataTableFilterCollection;
     @Input() activeIndex = -1;
+    @Input() trackByPath = 'id';
     @Output() pageChange = new EventEmitter<number>();
     @Output() itemsPerPageChange = new EventEmitter<number>();
     @Output() visibleColumnsChange = new EventEmitter<Array<DataTable2ColumnComponent<T>>>();
@@ -296,11 +297,11 @@ export class DataTable2Component<T> implements AfterContentInit, OnChanges, OnDe
     }
 
     trackByFn(index: number, item: any) {
-        if ((item as any).id != null) {
-            return (item as any).id;
-        } else {
-            return index;
-        }
+        return (
+            (this.trackByPath ?? 'id').split('.').reduce((accu, val) => {
+                return accu && accu[val];
+            }, item) ?? index
+        );
     }
 
     onToggleAllClick() {

+ 1 - 1
packages/admin-ui/src/lib/order/src/components/order-data-table/order-data-table.component.html

@@ -100,7 +100,7 @@
                                   totalItems: totalItems
                               };
                     index as i;
-                    trackBy: trackByFn
+                    trackBy: trackByFn.bind(this)
                 "
             >
                 <td *ngIf="selectionManager" class="selection-col" [class.active]="activeIndex === i">

+ 3 - 3
packages/asset-server-plugin/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@vendure/asset-server-plugin",
-    "version": "3.1.4",
+    "version": "3.1.7",
     "main": "lib/index.js",
     "types": "lib/index.d.ts",
     "files": [
@@ -26,8 +26,8 @@
         "@types/express": "^4.17.21",
         "@types/fs-extra": "^11.0.4",
         "@types/node-fetch": "^2.6.11",
-        "@vendure/common": "^3.1.4",
-        "@vendure/core": "^3.1.4",
+        "@vendure/common": "^3.1.7",
+        "@vendure/core": "^3.1.7",
         "express": "^4.18.3",
         "node-fetch": "^2.7.0",
         "rimraf": "^5.0.5",

+ 3 - 3
packages/cli/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@vendure/cli",
-    "version": "3.1.4",
+    "version": "3.1.7",
     "description": "A modern, headless ecommerce framework",
     "repository": {
         "type": "git",
@@ -35,7 +35,7 @@
     ],
     "dependencies": {
         "@clack/prompts": "^0.7.0",
-        "@vendure/common": "^3.1.4",
+        "@vendure/common": "^3.1.7",
         "change-case": "^4.1.2",
         "commander": "^11.0.0",
         "dotenv": "^16.4.5",
@@ -46,7 +46,7 @@
         "tsconfig-paths": "^4.2.0"
     },
     "devDependencies": {
-        "@vendure/core": "^3.1.4",
+        "@vendure/core": "^3.1.7",
         "typescript": "5.3.3"
     }
 }

+ 1 - 1
packages/common/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@vendure/common",
-    "version": "3.1.4",
+    "version": "3.1.7",
     "main": "index.js",
     "license": "GPL-3.0-or-later",
     "scripts": {

+ 5 - 0
packages/core/e2e/active-order-strategy.e2e-spec.ts

@@ -446,6 +446,11 @@ describe('custom ActiveOrderStrategy', () => {
                     name: 'Express Shipping',
                     priceWithTax: 1000,
                 },
+                {
+                    id: 'T_3',
+                    name: 'Express Shipping (Taxed)',
+                    priceWithTax: 1200,
+                },
             ]);
         });
 

+ 9 - 0
packages/core/e2e/draft-order.e2e-spec.ts

@@ -382,6 +382,15 @@ describe('Draft Orders resolver', () => {
                 price: 1000,
                 priceWithTax: 1000,
             },
+            {
+                code: 'express-shipping-taxed',
+                description: '',
+                id: 'T_3',
+                metadata: null,
+                name: 'Express Shipping (Taxed)',
+                price: 1000,
+                priceWithTax: 1200,
+            },
         ]);
     });
 

+ 20 - 2
packages/core/e2e/fixtures/test-plugins/with-job-queue.ts

@@ -1,5 +1,5 @@
 import { Controller, Get, OnModuleInit } from '@nestjs/common';
-import { JobQueue, JobQueueService, PluginCommonModule, VendurePlugin } from '@vendure/core';
+import { JobQueue, JobQueueService, Logger, PluginCommonModule, VendurePlugin } from '@vendure/core';
 import { Subject } from 'rxjs';
 import { take } from 'rxjs/operators';
 
@@ -17,12 +17,20 @@ class TestController implements OnModuleInit {
                     await new Promise(resolve => setTimeout(resolve, 50));
                     return job.data.returnValue;
                 } else {
+                    const interval = setInterval(() => {
+                        Logger.info(`Job is running...`);
+                        if (job.state === 'CANCELLED') {
+                            clearInterval(interval);
+                            PluginWithJobQueue.jobSubject.next();
+                        }
+                    }, 500);
                     return PluginWithJobQueue.jobSubject
                         .pipe(take(1))
                         .toPromise()
                         .then(() => {
                             PluginWithJobQueue.jobHasDoneWork = true;
-                            return job.data.returnValue;
+                            clearInterval(interval);
+                            return 'job result';
                         });
                 }
             },
@@ -43,6 +51,16 @@ class TestController implements OnModuleInit {
             .toPromise()
             .then(update => update?.result);
     }
+
+    @Get('subscribe-timeout')
+    async runJobAndSubscribeTimeout() {
+        const job = await this.queue.add({});
+        const result = await job
+            .updates({ timeoutMs: 50 })
+            .toPromise()
+            .then(update => update?.result);
+        return result;
+    }
 }
 
 @VendurePlugin({

+ 15 - 0
packages/core/e2e/job-queue.e2e-spec.ts

@@ -159,6 +159,21 @@ describe('JobQueue', () => {
         const jobs = await getJobsInTestQueue(JobState.RUNNING);
         expect(jobs.items.length).toBe(0);
     });
+
+    it('subscribable that times out', async () => {
+        const restControllerUrl = `http://localhost:${activeConfig.apiOptions.port}/run-job/subscribe-timeout`;
+        const result = await adminClient.fetch(restControllerUrl);
+
+        expect(result.status).toBe(200);
+        expect(await result.text()).toBe('Job subscription timed out. The job may still be running');
+        const jobs = await getJobsInTestQueue(JobState.RUNNING);
+        expect(jobs.items.length).toBe(1);
+    });
+
+    it('server still running after timeout', async () => {
+        const jobs = await getJobsInTestQueue(JobState.RUNNING);
+        expect(jobs.items.length).toBe(1);
+    });
 });
 
 function sleep(ms: number): Promise<void> {

+ 1 - 0
packages/core/e2e/order-multi-vendor.e2e-spec.ts

@@ -169,6 +169,7 @@ describe('Multi-vendor orders', () => {
             'alices-wares-shipping',
             'bobs-parts-shipping',
             'express-shipping',
+            'express-shipping-taxed',
             'standard-shipping',
         ]);
 

+ 2 - 2
packages/core/e2e/order-multiple-shipping.e2e-spec.ts

@@ -140,8 +140,8 @@ describe('Multiple shipping orders', () => {
             },
         });
 
-        expect(result1.createShippingMethod.id).toBe('T_3');
-        expect(result2.createShippingMethod.id).toBe('T_4');
+        expect(result1.createShippingMethod.id).toBe('T_4');
+        expect(result2.createShippingMethod.id).toBe('T_5');
         lessThan100MethodId = result1.createShippingMethod.id;
         greaterThan100MethodId = result2.createShippingMethod.id;
     });

+ 12 - 13
packages/core/e2e/order.e2e-spec.ts

@@ -1079,9 +1079,8 @@ describe('Orders resolver', () => {
         });
 
         it('order.fulfillments resolver for order list', async () => {
-            const { orders } = await adminClient.query<Codegen.GetOrderListFulfillmentsQuery>(
-                GET_ORDER_LIST_FULFILLMENTS,
-            );
+            const { orders } =
+                await adminClient.query<Codegen.GetOrderListFulfillmentsQuery>(GET_ORDER_LIST_FULFILLMENTS);
 
             expect(orders.items[0].fulfillments).toEqual([]);
             expect(orders.items[1].fulfillments?.sort(sortById)).toEqual([
@@ -1170,7 +1169,7 @@ describe('Orders resolver', () => {
                 customers[0].emailAddress,
                 password,
             );
-            await proceedToArrangingPayment(shopClient);
+            await proceedToArrangingPayment(shopClient, 2);
             const order = await addPaymentToOrder(shopClient, failsToSettlePaymentMethod);
             orderGuard.assertSuccess(order);
 
@@ -1290,7 +1289,7 @@ describe('Orders resolver', () => {
         });
 
         it('cannot cancel from ArrangingPayment state', async () => {
-            await proceedToArrangingPayment(shopClient);
+            await proceedToArrangingPayment(shopClient, 2);
             const { order } = await adminClient.query<Codegen.GetOrderQuery, Codegen.GetOrderQueryVariables>(
                 GET_ORDER,
                 {
@@ -1708,7 +1707,7 @@ describe('Orders resolver', () => {
             >(REFUND_ORDER, {
                 input: {
                     lines: order!.lines.map(l => ({ orderLineId: l.id, quantity: l.quantity })),
-                    shipping: order!.shipping,
+                    shipping: order!.shippingWithTax,
                     adjustment: 0,
                     reason: 'foo',
                     paymentId,
@@ -1716,7 +1715,7 @@ describe('Orders resolver', () => {
             });
             refundGuard.assertSuccess(refundOrder);
 
-            expect(refundOrder.shipping).toBe(order!.shipping);
+            expect(refundOrder.shipping).toBe(order!.shippingWithTax);
             expect(refundOrder.items).toBe(order!.subTotalWithTax);
             expect(refundOrder.total).toBe(order!.totalWithTax);
             expect(refundOrder.transactionId).toBe(null);
@@ -1815,7 +1814,7 @@ describe('Orders resolver', () => {
                 customers[0].emailAddress,
                 password,
             );
-            await proceedToArrangingPayment(shopClient);
+            await proceedToArrangingPayment(shopClient, 2);
             const order = await addPaymentToOrder(shopClient, singleStageRefundFailingPaymentMethod);
             orderGuard.assertSuccess(order);
 
@@ -1827,7 +1826,7 @@ describe('Orders resolver', () => {
             >(REFUND_ORDER, {
                 input: {
                     lines: order.lines.map(l => ({ orderLineId: l.id, quantity: l.quantity })),
-                    shipping: order.shipping,
+                    shipping: order.shippingWithTax,
                     adjustment: 0,
                     reason: 'foo',
                     paymentId: order.payments![0].id,
@@ -1843,7 +1842,7 @@ describe('Orders resolver', () => {
             >(REFUND_ORDER, {
                 input: {
                     lines: order.lines.map(l => ({ orderLineId: l.id, quantity: l.quantity })),
-                    shipping: order.shipping,
+                    shipping: order.shippingWithTax,
                     adjustment: 0,
                     reason: 'foo',
                     paymentId: order.payments![0].id,
@@ -1862,7 +1861,7 @@ describe('Orders resolver', () => {
                 customers[0].emailAddress,
                 password,
             );
-            await proceedToArrangingPayment(shopClient);
+            await proceedToArrangingPayment(shopClient, 2);
             const order = await addPaymentToOrder(shopClient, singleStageRefundablePaymentMethod);
             orderGuard.assertSuccess(order);
 
@@ -1886,7 +1885,7 @@ describe('Orders resolver', () => {
             >(REFUND_ORDER, {
                 input: {
                     lines: order.lines.map(l => ({ orderLineId: l.id, quantity: l.quantity })),
-                    shipping: order.shipping,
+                    shipping: order.shippingWithTax,
                     adjustment: 0,
                     reason: 'foo',
                     paymentId: order.payments![0].id,
@@ -2181,7 +2180,7 @@ describe('Orders resolver', () => {
         });
 
         it('adds a partial payment', async () => {
-            await proceedToArrangingPayment(shopClient);
+            await proceedToArrangingPayment(shopClient, 2);
             const { addPaymentToOrder: order } = await shopClient.query<
                 CodegenShop.AddPaymentToOrderMutation,
                 CodegenShop.AddPaymentToOrderMutationVariables

+ 26 - 21
packages/core/e2e/shipping-method.e2e-spec.ts

@@ -65,9 +65,8 @@ describe('ShippingMethod resolver', () => {
     });
 
     it('shippingEligibilityCheckers', async () => {
-        const { shippingEligibilityCheckers } = await adminClient.query<Codegen.GetEligibilityCheckersQuery>(
-            GET_ELIGIBILITY_CHECKERS,
-        );
+        const { shippingEligibilityCheckers } =
+            await adminClient.query<Codegen.GetEligibilityCheckersQuery>(GET_ELIGIBILITY_CHECKERS);
 
         expect(shippingEligibilityCheckers).toEqual([
             {
@@ -151,12 +150,12 @@ describe('ShippingMethod resolver', () => {
     });
 
     it('shippingMethods', async () => {
-        const { shippingMethods } = await adminClient.query<Codegen.GetShippingMethodListQuery>(
-            GET_SHIPPING_METHOD_LIST,
-        );
-        expect(shippingMethods.totalItems).toEqual(2);
+        const { shippingMethods } =
+            await adminClient.query<Codegen.GetShippingMethodListQuery>(GET_SHIPPING_METHOD_LIST);
+        expect(shippingMethods.totalItems).toEqual(3);
         expect(shippingMethods.items[0].code).toBe('standard-shipping');
         expect(shippingMethods.items[1].code).toBe('express-shipping');
+        expect(shippingMethods.items[2].code).toBe('express-shipping-taxed');
     });
 
     it('shippingMethod', async () => {
@@ -195,7 +194,7 @@ describe('ShippingMethod resolver', () => {
         });
 
         expect(createShippingMethod).toEqual({
-            id: 'T_3',
+            id: 'T_4',
             code: 'new-method',
             name: 'new method',
             description: '',
@@ -268,7 +267,7 @@ describe('ShippingMethod resolver', () => {
 
         expect(testEligibleShippingMethods).toEqual([
             {
-                id: 'T_3',
+                id: 'T_4',
                 name: 'new method',
                 description: '',
                 price: 100,
@@ -292,6 +291,14 @@ describe('ShippingMethod resolver', () => {
                 priceWithTax: 1000,
                 metadata: null,
             },
+            {
+                id: 'T_3',
+                name: 'Express Shipping (Taxed)',
+                description: '',
+                price: 1000,
+                priceWithTax: 1200,
+                metadata: null,
+            },
         ]);
     });
 
@@ -301,7 +308,7 @@ describe('ShippingMethod resolver', () => {
             Codegen.UpdateShippingMethodMutationVariables
         >(UPDATE_SHIPPING_METHOD, {
             input: {
-                id: 'T_3',
+                id: 'T_4',
                 translations: [{ languageCode: LanguageCode.en, name: 'changed method', description: '' }],
             },
         });
@@ -310,16 +317,15 @@ describe('ShippingMethod resolver', () => {
     });
 
     it('deleteShippingMethod', async () => {
-        const listResult1 = await adminClient.query<Codegen.GetShippingMethodListQuery>(
-            GET_SHIPPING_METHOD_LIST,
-        );
-        expect(listResult1.shippingMethods.items.map(i => i.id)).toEqual(['T_1', 'T_2', 'T_3']);
+        const listResult1 =
+            await adminClient.query<Codegen.GetShippingMethodListQuery>(GET_SHIPPING_METHOD_LIST);
+        expect(listResult1.shippingMethods.items.map(i => i.id)).toEqual(['T_1', 'T_2', 'T_3', 'T_4']);
 
         const { deleteShippingMethod } = await adminClient.query<
             Codegen.DeleteShippingMethodMutation,
             Codegen.DeleteShippingMethodMutationVariables
         >(DELETE_SHIPPING_METHOD, {
-            id: 'T_3',
+            id: 'T_4',
         });
 
         expect(deleteShippingMethod).toEqual({
@@ -327,10 +333,9 @@ describe('ShippingMethod resolver', () => {
             message: null,
         });
 
-        const listResult2 = await adminClient.query<Codegen.GetShippingMethodListQuery>(
-            GET_SHIPPING_METHOD_LIST,
-        );
-        expect(listResult2.shippingMethods.items.map(i => i.id)).toEqual(['T_1', 'T_2']);
+        const listResult2 =
+            await adminClient.query<Codegen.GetShippingMethodListQuery>(GET_SHIPPING_METHOD_LIST);
+        expect(listResult2.shippingMethods.items.map(i => i.id)).toEqual(['T_1', 'T_2', 'T_3']);
     });
 
     describe('argument ordering', () => {
@@ -379,7 +384,7 @@ describe('ShippingMethod resolver', () => {
                 Codegen.UpdateShippingMethodMutationVariables
             >(UPDATE_SHIPPING_METHOD, {
                 input: {
-                    id: 'T_4',
+                    id: 'T_5',
                     translations: [],
                     calculator: {
                         code: defaultShippingCalculator.code,
@@ -407,7 +412,7 @@ describe('ShippingMethod resolver', () => {
                 Codegen.GetShippingMethodQuery,
                 Codegen.GetShippingMethodQueryVariables
             >(GET_SHIPPING_METHOD, {
-                id: 'T_4',
+                id: 'T_5',
             });
 
             expect(shippingMethod?.calculator.args).toEqual([

+ 7 - 0
packages/core/e2e/shop-order.e2e-spec.ts

@@ -1623,6 +1623,13 @@ describe('Shop orders', () => {
                         name: 'Express Shipping',
                         description: '',
                     },
+                    {
+                        id: 'T_3',
+                        price: 1000,
+                        code: 'express-shipping-taxed',
+                        name: 'Express Shipping (Taxed)',
+                        description: '',
+                    },
                 ]);
             });
 

+ 5 - 2
packages/core/e2e/utils/test-order-utils.ts

@@ -14,7 +14,10 @@ import {
     TRANSITION_TO_STATE,
 } from '../graphql/shop-definitions';
 
-export async function proceedToArrangingPayment(shopClient: SimpleGraphQLClient): Promise<ID> {
+export async function proceedToArrangingPayment(
+    shopClient: SimpleGraphQLClient,
+    shippingMethodIdx = 1,
+): Promise<ID> {
     await shopClient.query<
         CodegenShop.SetShippingAddressMutation,
         CodegenShop.SetShippingAddressMutationVariables
@@ -36,7 +39,7 @@ export async function proceedToArrangingPayment(shopClient: SimpleGraphQLClient)
         CodegenShop.SetShippingMethodMutation,
         CodegenShop.SetShippingMethodMutationVariables
     >(SET_SHIPPING_METHOD, {
-        id: eligibleShippingMethods[1].id,
+        id: eligibleShippingMethods[shippingMethodIdx].id,
     });
 
     const { transitionOrderToState } = await shopClient.query<

+ 2 - 2
packages/core/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@vendure/core",
-    "version": "3.1.4",
+    "version": "3.1.7",
     "description": "A modern, headless ecommerce framework",
     "repository": {
         "type": "git",
@@ -49,7 +49,7 @@
         "@nestjs/platform-express": "~10.4.12",
         "@nestjs/terminus": "~10.2.3",
         "@nestjs/typeorm": "~10.0.2",
-        "@vendure/common": "^3.1.4",
+        "@vendure/common": "^3.1.7",
         "bcrypt": "^5.1.1",
         "body-parser": "^1.20.2",
         "cookie-session": "^2.1.0",

+ 4 - 4
packages/core/src/data-import/providers/importer/fast-importer.service.ts

@@ -85,7 +85,7 @@ export class FastImporterService {
             beforeSave: async p => {
                 p.channels = unique([this.defaultChannel, this.importCtx.channel], 'id');
                 if (input.facetValueIds) {
-                    p.facetValues = input.facetValueIds.map(id => ({ id } as any));
+                    p.facetValues = input.facetValueIds.map(id => ({ id }) as any);
                 }
                 if (input.featuredAssetId) {
                     p.featuredAsset = { id: input.featuredAssetId } as any;
@@ -164,10 +164,10 @@ export class FastImporterService {
                 variant.channels = unique([this.defaultChannel, this.importCtx.channel], 'id');
                 const { optionIds } = input;
                 if (optionIds && optionIds.length) {
-                    variant.options = optionIds.map(id => ({ id } as any));
+                    variant.options = optionIds.map(id => ({ id }) as any);
                 }
                 if (input.facetValueIds) {
-                    variant.facetValues = input.facetValueIds.map(id => ({ id } as any));
+                    variant.facetValues = input.facetValueIds.map(id => ({ id }) as any);
                 }
                 variant.product = { id: input.productId } as any;
                 variant.taxCategory = { id: input.taxCategoryId } as any;
@@ -192,7 +192,7 @@ export class FastImporterService {
         await this.stockMovementService.adjustProductVariantStock(
             this.importCtx,
             createdVariant.id,
-            input.stockOnHand ?? 0,
+            input.stockLevels ?? input.stockOnHand ?? 0,
         );
         const assignedChannelIds = unique([this.defaultChannel, this.importCtx.channel], 'id').map(c => c.id);
         for (const channelId of assignedChannelIds) {

+ 2 - 2
packages/core/src/data-import/providers/populator/populator.ts

@@ -288,7 +288,7 @@ export class Populator {
 
     private async populateShippingMethods(
         ctx: RequestContext,
-        shippingMethods: Array<{ name: string; price: number }>,
+        shippingMethods: Array<{ name: string; price: number; taxRate?: number }>,
     ) {
         for (const method of shippingMethods) {
             await this.shippingMethodService.create(ctx, {
@@ -301,7 +301,7 @@ export class Populator {
                     code: defaultShippingCalculator.code,
                     arguments: [
                         { name: 'rate', value: method.price.toString() },
-                        { name: 'taxRate', value: '0' },
+                        { name: 'taxRate', value: method.taxRate ? method.taxRate.toString() : '0' },
                         { name: 'includesTax', value: 'auto' },
                     ],
                 },

+ 1 - 1
packages/core/src/data-import/types.ts

@@ -50,7 +50,7 @@ export interface InitialData {
     roles?: RoleDefinition[];
     countries: CountryDefinition[];
     taxRates: Array<{ name: string; percentage: number }>;
-    shippingMethods: Array<{ name: string; price: number }>;
+    shippingMethods: Array<{ name: string; price: number; taxRate?: number }>;
     paymentMethods: Array<{ name: string; handler: ConfigurableOperationInput }>;
     collections: CollectionDefinition[];
 }

+ 24 - 11
packages/core/src/job-queue/subscribable-job.ts

@@ -2,10 +2,11 @@ import { JobState } from '@vendure/common/lib/generated-types';
 import { pick } from '@vendure/common/lib/pick';
 import { notNullOrUndefined } from '@vendure/common/lib/shared-utils';
 import ms from 'ms';
-import { interval, Observable } from 'rxjs';
+import { interval, Observable, race, timer } from 'rxjs';
 import { distinctUntilChanged, filter, map, switchMap, takeWhile, tap } from 'rxjs/operators';
 
 import { InternalServerError } from '../common/error/errors';
+import { Logger } from '../config/index';
 import { isInspectableJobQueueStrategy } from '../config/job-queue/inspectable-job-queue-strategy';
 import { JobQueueStrategy } from '../config/job-queue/job-queue-strategy';
 
@@ -87,16 +88,7 @@ export class SubscribableJob<T extends JobData<T> = any> extends Job<T> {
             );
         } else {
             // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-            return interval(pollInterval).pipe(
-                tap(i => {
-                    if (timeoutMs < i * pollInterval) {
-                        throw new Error(
-                            `Job ${
-                                this.id ?? ''
-                            } SubscribableJob update polling timed out after ${timeoutMs}ms. The job may still be running.`,
-                        );
-                    }
-                }),
+            const updates$ = interval(pollInterval).pipe(
                 switchMap(() => {
                     const id = this.id;
                     if (!id) {
@@ -120,6 +112,27 @@ export class SubscribableJob<T extends JobData<T> = any> extends Job<T> {
                 }),
                 map(job => pick(job, ['id', 'state', 'progress', 'result', 'error', 'data'])),
             );
+            const timeout$ = timer(timeoutMs).pipe(
+                tap(i => {
+                    Logger.error(
+                        `Job ${
+                            this.id ?? ''
+                        } SubscribableJob update polling timed out after ${timeoutMs}ms. The job may still be running.`,
+                    );
+                }),
+                map(
+                    () =>
+                        ({
+                            id: this.id,
+                            state: JobState.RUNNING,
+                            data: this.data,
+                            error: this.error,
+                            progress: this.progress,
+                            result: 'Job subscription timed out. The job may still be running',
+                        }) satisfies JobUpdate<any>,
+                ),
+            );
+            return race(updates$, timeout$);
         }
     }
 }

+ 1 - 1
packages/core/src/service/helpers/order-modifier/order-modifier.ts

@@ -346,7 +346,7 @@ export class OrderModifier {
                     adjustmentSource: 'CANCEL_ORDER',
                     type: AdjustmentType.OTHER,
                     description: 'shipping cancellation',
-                    amount: -shippingLine.discountedPriceWithTax,
+                    amount: -shippingLine.discountedPrice,
                     data: {},
                 });
                 await this.connection.getRepository(ctx, ShippingLine).save(shippingLine, { reload: false });

+ 3 - 3
packages/create/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@vendure/create",
-    "version": "3.1.4",
+    "version": "3.1.7",
     "license": "GPL-3.0-or-later",
     "bin": {
         "create": "./index.js"
@@ -27,14 +27,14 @@
         "@types/fs-extra": "^11.0.4",
         "@types/handlebars": "^4.1.0",
         "@types/semver": "^7.5.8",
-        "@vendure/core": "^3.1.4",
+        "@vendure/core": "^3.1.7",
         "rimraf": "^5.0.5",
         "ts-node": "^10.9.2",
         "typescript": "5.3.3"
     },
     "dependencies": {
         "@clack/prompts": "^0.7.0",
-        "@vendure/common": "^3.1.4",
+        "@vendure/common": "^3.1.7",
         "commander": "^11.0.0",
         "cross-spawn": "^7.0.3",
         "fs-extra": "^11.2.0",

+ 9 - 9
packages/dev-server/package.json

@@ -1,6 +1,6 @@
 {
     "name": "dev-server",
-    "version": "3.1.4",
+    "version": "3.1.7",
     "main": "index.js",
     "license": "GPL-3.0-or-later",
     "private": true,
@@ -16,17 +16,17 @@
     },
     "dependencies": {
         "@nestjs/axios": "^3.0.2",
-        "@vendure/admin-ui-plugin": "^3.1.4",
-        "@vendure/asset-server-plugin": "^3.1.4",
-        "@vendure/common": "^3.1.4",
-        "@vendure/core": "^3.1.4",
-        "@vendure/elasticsearch-plugin": "^3.1.4",
-        "@vendure/email-plugin": "^3.1.4",
+        "@vendure/admin-ui-plugin": "^3.1.7",
+        "@vendure/asset-server-plugin": "^3.1.7",
+        "@vendure/common": "^3.1.7",
+        "@vendure/core": "^3.1.7",
+        "@vendure/elasticsearch-plugin": "^3.1.7",
+        "@vendure/email-plugin": "^3.1.7",
         "typescript": "5.3.3"
     },
     "devDependencies": {
-        "@vendure/testing": "^3.1.4",
-        "@vendure/ui-devkit": "^3.1.4",
+        "@vendure/testing": "^3.1.7",
+        "@vendure/ui-devkit": "^3.1.7",
         "commander": "^12.0.0",
         "concurrently": "^8.2.2",
         "csv-stringify": "^6.4.6",

+ 3 - 3
packages/elasticsearch-plugin/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@vendure/elasticsearch-plugin",
-    "version": "3.1.4",
+    "version": "3.1.7",
     "license": "GPL-3.0-or-later",
     "main": "lib/index.js",
     "types": "lib/index.d.ts",
@@ -26,8 +26,8 @@
         "fast-deep-equal": "^3.1.3"
     },
     "devDependencies": {
-        "@vendure/common": "^3.1.4",
-        "@vendure/core": "^3.1.4",
+        "@vendure/common": "^3.1.7",
+        "@vendure/core": "^3.1.7",
         "rimraf": "^5.0.5",
         "typescript": "5.3.3"
     }

+ 3 - 3
packages/email-plugin/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@vendure/email-plugin",
-    "version": "3.1.4",
+    "version": "3.1.7",
     "license": "GPL-3.0-or-later",
     "main": "lib/index.js",
     "types": "lib/index.d.ts",
@@ -34,8 +34,8 @@
         "@types/express": "^4.17.21",
         "@types/fs-extra": "^11.0.4",
         "@types/mjml": "^4.7.4",
-        "@vendure/common": "^3.1.4",
-        "@vendure/core": "^3.1.4",
+        "@vendure/common": "^3.1.7",
+        "@vendure/core": "^3.1.7",
         "rimraf": "^5.0.5",
         "typescript": "5.3.3"
     }

+ 3 - 3
packages/harden-plugin/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@vendure/harden-plugin",
-    "version": "3.1.4",
+    "version": "3.1.7",
     "license": "GPL-3.0-or-later",
     "main": "lib/index.js",
     "types": "lib/index.d.ts",
@@ -21,7 +21,7 @@
         "graphql-query-complexity": "^0.12.0"
     },
     "devDependencies": {
-        "@vendure/common": "^3.1.4",
-        "@vendure/core": "^3.1.4"
+        "@vendure/common": "^3.1.7",
+        "@vendure/core": "^3.1.7"
     }
 }

+ 3 - 3
packages/job-queue-plugin/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@vendure/job-queue-plugin",
-    "version": "3.1.4",
+    "version": "3.1.7",
     "license": "GPL-3.0-or-later",
     "main": "package/index.js",
     "types": "package/index.d.ts",
@@ -23,8 +23,8 @@
     },
     "devDependencies": {
         "@google-cloud/pubsub": "^2.8.0",
-        "@vendure/common": "^3.1.4",
-        "@vendure/core": "^3.1.4",
+        "@vendure/common": "^3.1.7",
+        "@vendure/core": "^3.1.7",
         "bullmq": "^5.4.2",
         "ioredis": "^5.3.2",
         "rimraf": "^5.0.5",

+ 23 - 24
packages/job-queue-plugin/src/bullmq/bullmq-job-queue-strategy.ts

@@ -159,9 +159,11 @@ export class BullMQJobQueueStrategy implements InspectableJobQueueStrategy {
             delay: 1000,
             type: 'exponential',
         };
+        const customJobOptions = this.options.setJobOptions?.(job.queueName, job) ?? {};
         const bullJob = await this.queue.add(job.queueName, job.data, {
             attempts: retries + 1,
             backoff,
+            ...customJobOptions,
         });
         return this.createVendureJob(bullJob);
     }
@@ -194,7 +196,7 @@ export class BullMQJobQueueStrategy implements InspectableJobQueueStrategy {
         if (stateFilter?.eq) {
             switch (stateFilter.eq) {
                 case 'PENDING':
-                    jobTypes = ['wait'];
+                    jobTypes = ['wait', 'waiting-children', 'prioritized'];
                     break;
                 case 'RUNNING':
                     jobTypes = ['active'];
@@ -218,7 +220,7 @@ export class BullMQJobQueueStrategy implements InspectableJobQueueStrategy {
             jobTypes =
                 settledFilter.eq === true
                     ? ['completed', 'failed']
-                    : ['wait', 'waiting-children', 'active', 'repeat', 'delayed', 'paused'];
+                    : ['wait', 'waiting-children', 'active', 'repeat', 'delayed', 'paused', 'prioritized'];
         }
 
         let items: Bull.Job[] = [];
@@ -382,30 +384,27 @@ export class BullMQJobQueueStrategy implements InspectableJobQueueStrategy {
 
     private async getState(bullJob: Bull.Job): Promise<JobState> {
         const jobId = bullJob.id?.toString();
-
-        if ((await bullJob.isWaiting()) || (await bullJob.isWaitingChildren())) {
-            return JobState.PENDING;
-        }
-        if (await bullJob.isActive()) {
-            const isCancelled =
-                jobId && (await this.redisConnection.sismember(this.CANCELLED_JOB_LIST_NAME, jobId));
-            if (isCancelled) {
-                return JobState.CANCELLED;
-            } else {
-                return JobState.RUNNING;
+        const state = await bullJob.getState();
+        switch (state) {
+            case 'completed':
+                return JobState.COMPLETED;
+            case 'failed':
+                return JobState.FAILED;
+            case 'waiting':
+            case 'waiting-children':
+            case 'prioritized':
+                return JobState.PENDING;
+            case 'delayed':
+                return JobState.RETRYING;
+            case 'active': {
+                const isCancelled =
+                    jobId && (await this.redisConnection.sismember(this.CANCELLED_JOB_LIST_NAME, jobId));
+                return isCancelled ? JobState.CANCELLED : JobState.RUNNING;
             }
+            case 'unknown':
+            default:
+                throw new InternalServerError(`Could not determine job state: ${state}`);
         }
-        if (await bullJob.isDelayed()) {
-            return JobState.RETRYING;
-        }
-        if (await bullJob.isFailed()) {
-            return JobState.FAILED;
-        }
-        if (await bullJob.isCompleted()) {
-            return JobState.COMPLETED;
-        }
-        throw new InternalServerError('Could not determine job state');
-        // TODO: how to handle "cancelled" state? Currently when we cancel a job, we simply remove all record of it.
     }
 
     private callCustomScript<T, Args extends any[]>(

+ 1 - 0
packages/job-queue-plugin/src/bullmq/constants.ts

@@ -12,4 +12,5 @@ export const ALL_JOB_TYPES: JobType[] = [
     'active',
     'wait',
     'paused',
+    'prioritized',
 ];

+ 40 - 0
packages/job-queue-plugin/src/bullmq/plugin.ts

@@ -129,6 +129,46 @@ import { BullMQPluginOptions } from './types';
  * maximum age of a job in seconds. If both options are specified, then the jobs kept will be the ones that satisfy
  * both properties.
  *
+ * ## Job Priority
+ * Some jobs are more important than others. For example, sending out a timely email after a customer places an order
+ * is probably more important than a routine data import task. Sometimes you can get the situation where lower-priority
+ * jobs are blocking higher-priority jobs.
+ *
+ * Let's say you have a data import job that runs periodically and takes a long time to complete. If you have a high-priority
+ * job that needs to be processed quickly, it could be stuck behind the data import job in the queue. A customer might
+ * not get their confirmation email for 30 minutes while that data import job is processed!
+ *
+ * To solve this problem, you can set the `priority` option on a job. Jobs with a higher priority will be processed before
+ * jobs with a lower priority. By default, all jobs have a priority of 0 (which is the highest).
+ *
+ * Learn more about how priority works in BullMQ in their [documentation](https://docs.bullmq.io/guide/jobs/prioritized).
+ *
+ * You can set the priority by using the `setJobOptions` option (introduced in Vendure v3.2.0):
+ *
+ * @example
+ * ```ts
+ * const config: VendureConfig = {
+ *   plugins: [
+ *     BullMQJobQueuePlugin.init({
+ *       setJobOptions: (queueName, job) => {
+ *         let priority = 10;
+ *         switch (queueName) {
+ *           case 'super-critical-task':
+ *             priority = 0;
+ *             break;
+ *           case 'send-email':
+ *             priority = 5;
+ *             break;
+ *           default:
+ *             priority = 10;
+ *         }
+ *         return { priority };
+ *       }
+ *     }),
+ *   ],
+ * };
+ * ```
+ *
  * @docsCategory core plugins/JobQueuePlugin
  */
 @VendurePlugin({

+ 32 - 1
packages/job-queue-plugin/src/bullmq/types.ts

@@ -1,7 +1,14 @@
 import { Job } from '@vendure/core';
-import { ConnectionOptions, WorkerOptions } from 'bullmq';
+import { ConnectionOptions, WorkerOptions, Queue } from 'bullmq';
 import { QueueOptions } from 'bullmq';
 
+/**
+ * @description
+ * This type is the third parameter to the `Queue.add()` method,
+ * which allows additional options to be specified for the job.
+ */
+export type BullJobsOptions = Parameters<Queue['add']>[2];
+
 /**
  * @description
  * Configuration options for the {@link BullMQJobQueuePlugin}.
@@ -54,6 +61,7 @@ export interface BullMQPluginOptions {
      * }
      *  ```
      *
+     * @deprecated Use `setJobOptions` instead.
      * @since 1.3.0
      */
     setRetries?: (queueName: string, job: Job) => number;
@@ -73,10 +81,33 @@ export interface BullMQPluginOptions {
      *   };
      * }
      * ```
+     *
+     * @deprecated Use `setJobOptions` instead.
      * @since 1.3.0
      * @default 'exponential', 1000
      */
     setBackoff?: (queueName: string, job: Job) => BackoffOptions | undefined;
+    /**
+     * @description
+     * This allows you to specify additional options for a job when it is added to the queue.
+     * The object returned is the BullMQ [JobsOptions](https://api.docs.bullmq.io/types/v5.JobsOptions.html)
+     * type, which includes control over settings such as `delay`, `attempts`, `priority` and much more.
+     *
+     * This function is called every time a job is added to the queue, so you can return different options
+     * based on the job being added.
+     *
+     * @example
+     * ```ts
+     * // Here we want to assign a higher priority to jobs in the 'critical' queue
+     * setJobOptions: (queueName, job) => {
+     *   const priority = queueName === 'critical' ? 1 : 5;
+     *   return { priority };
+     * }
+     * ```
+     *
+     * @since 3.2.0
+     */
+    setJobOptions?: (queueName: string, job: Job) => BullJobsOptions;
 }
 
 /**

+ 4 - 4
packages/payments-plugin/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@vendure/payments-plugin",
-    "version": "3.1.4",
+    "version": "3.1.7",
     "license": "GPL-3.0-or-later",
     "main": "package/index.js",
     "types": "package/index.d.ts",
@@ -46,9 +46,9 @@
         "@mollie/api-client": "^3.7.0",
         "@types/braintree": "^3.3.11",
         "@types/localtunnel": "2.0.4",
-        "@vendure/common": "^3.1.4",
-        "@vendure/core": "^3.1.4",
-        "@vendure/testing": "^3.1.4",
+        "@vendure/common": "^3.1.7",
+        "@vendure/core": "^3.1.7",
+        "@vendure/testing": "^3.1.7",
         "braintree": "^3.22.0",
         "localtunnel": "2.0.2",
         "nock": "^13.1.4",

+ 3 - 3
packages/sentry-plugin/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@vendure/sentry-plugin",
-    "version": "3.1.4",
+    "version": "3.1.7",
     "license": "GPL-3.0-or-later",
     "main": "lib/index.js",
     "types": "lib/index.d.ts",
@@ -22,7 +22,7 @@
     },
     "devDependencies": {
         "@sentry/node": "^7.106.1",
-        "@vendure/common": "^3.1.4",
-        "@vendure/core": "^3.1.4"
+        "@vendure/common": "^3.1.7",
+        "@vendure/core": "^3.1.7"
     }
 }

+ 3 - 3
packages/stellate-plugin/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@vendure/stellate-plugin",
-    "version": "3.1.4",
+    "version": "3.1.7",
     "license": "GPL-3.0-or-later",
     "main": "lib/index.js",
     "types": "lib/index.d.ts",
@@ -21,7 +21,7 @@
         "node-fetch": "^2.7.0"
     },
     "devDependencies": {
-        "@vendure/common": "^3.1.4",
-        "@vendure/core": "^3.1.4"
+        "@vendure/common": "^3.1.7",
+        "@vendure/core": "^3.1.7"
     }
 }

+ 3 - 3
packages/testing/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@vendure/testing",
-    "version": "3.1.4",
+    "version": "3.1.7",
     "description": "End-to-end testing tools for Vendure projects",
     "keywords": [
         "vendure",
@@ -38,7 +38,7 @@
     },
     "dependencies": {
         "@graphql-typed-document-node/core": "^3.2.0",
-        "@vendure/common": "^3.1.4",
+        "@vendure/common": "^3.1.7",
         "faker": "^4.1.0",
         "form-data": "^4.0.0",
         "graphql": "~16.10.0",
@@ -51,7 +51,7 @@
         "@types/mysql": "^2.15.26",
         "@types/node-fetch": "^2.6.4",
         "@types/pg": "^8.11.2",
-        "@vendure/core": "^3.1.4",
+        "@vendure/core": "^3.1.7",
         "mysql": "^2.18.1",
         "pg": "^8.11.3",
         "rimraf": "^5.0.5",

+ 4 - 4
packages/ui-devkit/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@vendure/ui-devkit",
-    "version": "3.1.4",
+    "version": "3.1.7",
     "description": "A library for authoring Vendure Admin UI extensions",
     "keywords": [
         "vendure",
@@ -40,8 +40,8 @@
         "@angular/cli": "^17.2.3",
         "@angular/compiler": "^17.2.4",
         "@angular/compiler-cli": "^17.2.4",
-        "@vendure/admin-ui": "^3.1.4",
-        "@vendure/common": "^3.1.4",
+        "@vendure/admin-ui": "^3.1.7",
+        "@vendure/common": "^3.1.7",
         "chalk": "^4.1.0",
         "chokidar": "^3.6.0",
         "fs-extra": "^11.2.0",
@@ -52,7 +52,7 @@
         "@rollup/plugin-node-resolve": "^15.2.3",
         "@rollup/plugin-terser": "^0.4.4",
         "@types/fs-extra": "^11.0.4",
-        "@vendure/core": "^3.1.4",
+        "@vendure/core": "^3.1.7",
         "react": "^19.0.0",
         "react-dom": "^19.0.0",
         "rimraf": "^5.0.5",