From 6872f585f8581027e92d612019c045bc1258ced9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 08:52:02 +0000 Subject: [PATCH 01/25] @sphade has signed the CLA in vendure-ecommerce/vendure#3027 --- license/signatures/version1/cla.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/license/signatures/version1/cla.json b/license/signatures/version1/cla.json index 3c5537fa2f..b7e6f1c302 100644 --- a/license/signatures/version1/cla.json +++ b/license/signatures/version1/cla.json @@ -111,6 +111,14 @@ "created_at": "2024-08-13T15:47:42Z", "repoId": 136938012, "pullRequestNo": 3009 + }, + { + "name": "sphade", + "id": 85949974, + "comment_id": 2304127063, + "created_at": "2024-08-22T08:51:51Z", + "repoId": 136938012, + "pullRequestNo": 3027 } ] } \ No newline at end of file From 2fe500955621d0115ca38a7a8c2eb3ce298bdd3b Mon Sep 17 00:00:00 2001 From: Lawal Adebola Date: Thu, 22 Aug 2024 10:15:38 +0100 Subject: [PATCH 02/25] docs: Fix grammatical error (#3027) changed "The desired shipping method's id is the" to "The desired shipping method's id is then" --- docs/docs/guides/storefront/checkout-flow/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/guides/storefront/checkout-flow/index.mdx b/docs/docs/guides/storefront/checkout-flow/index.mdx index 26c8a5c554..4897500bd9 100644 --- a/docs/docs/guides/storefront/checkout-flow/index.mdx +++ b/docs/docs/guides/storefront/checkout-flow/index.mdx @@ -234,7 +234,7 @@ query GetShippingMethods { The results can then be displayed to the customer so they can choose the desired shipping method. If there is only a single result, then it can be automatically selected. -The desired shipping method's id is the passed to the [`setOrderShippingMethod`](/reference/graphql-api/shop/mutations/#setordershippingmethod) mutation. +The desired shipping method's id is then passed to the [`setOrderShippingMethod`](/reference/graphql-api/shop/mutations/#setordershippingmethod) mutation. ```graphql mutation SetShippingMethod($id: [ID!]!) { From 9aa003dc30f3f5749018d2ef8e1e9a866be02885 Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Mon, 26 Aug 2024 16:26:39 +0200 Subject: [PATCH 03/25] docs: Fix incorrect docs for OrderSellerStrategy --- .../reference/typescript-api/orders/order-seller-strategy.md | 2 +- packages/core/src/config/order/order-seller-strategy.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/reference/typescript-api/orders/order-seller-strategy.md b/docs/docs/reference/typescript-api/orders/order-seller-strategy.md index d3fdfe3975..e2d6fd55bd 100644 --- a/docs/docs/reference/typescript-api/orders/order-seller-strategy.md +++ b/docs/docs/reference/typescript-api/orders/order-seller-strategy.md @@ -50,7 +50,7 @@ interface OrderSellerStrategy extends InjectableStrategy { This method is called whenever a new OrderLine is added to the Order via the `addItemToOrder` mutation or the underlying `addItemToOrder()` method of the OrderService. -It should return the ID of the Channel to which this OrderLine will be assigned, which will be used to set the +It should return the Channel to which this OrderLine will be assigned, which will be used to set the OrderLine `sellerChannel` property. ### splitOrder diff --git a/packages/core/src/config/order/order-seller-strategy.ts b/packages/core/src/config/order/order-seller-strategy.ts index 371e79926a..59080493c4 100644 --- a/packages/core/src/config/order/order-seller-strategy.ts +++ b/packages/core/src/config/order/order-seller-strategy.ts @@ -46,7 +46,7 @@ export interface OrderSellerStrategy extends InjectableStrategy { * This method is called whenever a new OrderLine is added to the Order via the `addItemToOrder` mutation or the * underlying `addItemToOrder()` method of the {@link OrderService}. * - * It should return the ID of the Channel to which this OrderLine will be assigned, which will be used to set the + * It should return the Channel to which this OrderLine will be assigned, which will be used to set the * {@link OrderLine} `sellerChannel` property. */ setOrderLineSellerChannel?( From d267e73c646fd3a8799540555241885cb67183de Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Mon, 26 Aug 2024 20:36:17 +0200 Subject: [PATCH 04/25] docs: Improve Admin UI deployment doc --- docs/docs/guides/deployment/deploying-admin-ui.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/docs/guides/deployment/deploying-admin-ui.md b/docs/docs/guides/deployment/deploying-admin-ui.md index b63c1f8a0c..e394363ee3 100644 --- a/docs/docs/guides/deployment/deploying-admin-ui.md +++ b/docs/docs/guides/deployment/deploying-admin-ui.md @@ -3,8 +3,18 @@ title: "Deploying the Admin UI" showtoc: true --- +## Compiling the Admin UI -If you have customized the Admin UI with extensions, you should [compile your extensions ahead of time as part of the deployment process](/guides/extending-the-admin-ui/getting-started/#compiling-as-a-deployment-step). +If you have customized the Admin UI with extensions, you should compile your custom Admin UI app ahead of time +before deploying it. This will bundle the app into a set of static files which are then served by the AdminUiPlugin. + +- [Guide: Compiling the Admin UI as a deployment step](/guides/extending-the-admin-ui/getting-started/#compiling-as-a-deployment-step). + +:::warning + +It is not recommended to compile the Admin UI on the server at runtime, as this can be slow and resource-intensive. +Instead, compile the Admin UI ahead of time and deploy the compiled assets, as covered in the guide linked above. +::: ## Setting the API host & port From 1baa8e7ef7d62dcdfb855c31f5e5188f061cab83 Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Wed, 28 Aug 2024 18:07:38 +0200 Subject: [PATCH 05/25] perf(core): Fix slow `order` query for postgres v16 Fixes #3037 --- packages/core/src/api/resolvers/admin/order.resolver.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/core/src/api/resolvers/admin/order.resolver.ts b/packages/core/src/api/resolvers/admin/order.resolver.ts index d677652336..0d337708f1 100644 --- a/packages/core/src/api/resolvers/admin/order.resolver.ts +++ b/packages/core/src/api/resolvers/admin/order.resolver.ts @@ -46,7 +46,10 @@ import { Transaction } from '../../decorators/transaction.decorator'; @Resolver() export class OrderResolver { - constructor(private orderService: OrderService, private connection: TransactionalConnection) {} + constructor( + private orderService: OrderService, + private connection: TransactionalConnection, + ) {} @Query() @Allow(Permission.ReadOrder) @@ -63,7 +66,8 @@ export class OrderResolver { async order( @Ctx() ctx: RequestContext, @Args() args: QueryOrderArgs, - @Relations(Order) relations: RelationPaths, + @Relations({ entity: Order, omit: ['aggregateOrder', 'sellerOrders'] }) + relations: RelationPaths, ): Promise { return this.orderService.findOne(ctx, args.id, relations); } From a48c818c7ed18d89504b96435028cd6e8c9849d4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 11:14:26 +0000 Subject: [PATCH 06/25] @hsensh has signed the CLA in vendure-ecommerce/vendure#3041 --- license/signatures/version1/cla.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/license/signatures/version1/cla.json b/license/signatures/version1/cla.json index b7e6f1c302..d84e4b32b4 100644 --- a/license/signatures/version1/cla.json +++ b/license/signatures/version1/cla.json @@ -119,6 +119,14 @@ "created_at": "2024-08-22T08:51:51Z", "repoId": 136938012, "pullRequestNo": 3027 + }, + { + "name": "hsensh", + "id": 23084617, + "comment_id": 2324473830, + "created_at": "2024-09-02T11:14:15Z", + "repoId": 136938012, + "pullRequestNo": 3041 } ] } \ No newline at end of file From 75ed6e12d32ba00b14e62d49f81704ccd9de3a2c Mon Sep 17 00:00:00 2001 From: Hsen Sh Date: Mon, 2 Sep 2024 15:35:31 +0300 Subject: [PATCH 07/25] fix(core): Fix search indexing issue when working with multiple channels (#3041) Relates to #3012. --- .../plugin/default-search-plugin/indexer/indexer.controller.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/core/src/plugin/default-search-plugin/indexer/indexer.controller.ts b/packages/core/src/plugin/default-search-plugin/indexer/indexer.controller.ts index a31635c3bf..b9ee716bb0 100644 --- a/packages/core/src/plugin/default-search-plugin/indexer/indexer.controller.ts +++ b/packages/core/src/plugin/default-search-plugin/indexer/indexer.controller.ts @@ -405,7 +405,9 @@ export class IndexerController { await this.removeSyntheticVariants(ctx, variants); const productMap = new Map(); + const originalChannel = ctx.channel; for (const variant of variants) { + ctx.setChannel(originalChannel); let product = productMap.get(variant.productId); if (!product) { product = await this.getProductInChannelQueryBuilder(ctx, variant.productId, ctx.channel); @@ -496,6 +498,7 @@ export class IndexerController { } } } + ctx.setChannel(originalChannel); await this.queue.push(() => this.connection.getRepository(ctx, SearchIndexItem).save(items, { chunk: 2500 }), From 9d6f9cfc0917c215ef9e8065cf9d84515c1168c1 Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Mon, 2 Sep 2024 14:47:21 +0200 Subject: [PATCH 08/25] fix(elasticsearch-plugin): Fix search multichannel indexing issue Relates to #3012 --- .../src/indexing/indexer.controller.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/elasticsearch-plugin/src/indexing/indexer.controller.ts b/packages/elasticsearch-plugin/src/indexing/indexer.controller.ts index 328a3bdcdc..7eb65c62c4 100644 --- a/packages/elasticsearch-plugin/src/indexing/indexer.controller.ts +++ b/packages/elasticsearch-plugin/src/indexing/indexer.controller.ts @@ -511,7 +511,6 @@ export class ElasticsearchIndexerController implements OnModuleInit, OnModuleDes if (!product) { return; } - let updatedProductVariants: ProductVariant[] = []; try { updatedProductVariants = await this.connection.rawConnection.getRepository(ProductVariant).find({ @@ -541,6 +540,7 @@ export class ElasticsearchIndexerController implements OnModuleInit, OnModuleDes languageVariants.push(...variant.translations.map(t => t.languageCode)); const uniqueLanguageVariants = unique(languageVariants); + const originalChannel = ctx.channel; for (const channel of product.channels) { ctx.setChannel(channel); const variantsInChannel = updatedProductVariants.filter(v => @@ -623,6 +623,7 @@ export class ElasticsearchIndexerController implements OnModuleInit, OnModuleDes } } } + ctx.setChannel(originalChannel); // Because we can have a huge amount of variant for 1 product, we also chunk update operations await this.executeBulkOperationsByChunks( @@ -944,7 +945,13 @@ export class ElasticsearchIndexerController implements OnModuleInit, OnModuleDes const productCustomMappings = Object.entries(this.options.customProductMappings); for (const [name, def] of productCustomMappings) { - item[`product-${name}`] = await def.valueFn(v.product, variants, languageCode, this.injector, ctx); + item[`product-${name}`] = await def.valueFn( + v.product, + variants, + languageCode, + this.injector, + ctx, + ); } return item; } catch (err: any) { From 04340f1c9bb5a93a98e16471150ee3e9a92d79db Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Mon, 2 Sep 2024 15:09:06 +0200 Subject: [PATCH 09/25] fix(admin-ui): Fix removing coupon code from draft order Fixes #2969 --- .../coupon-code-selector/coupon-code-selector.component.html | 2 +- .../coupon-code-selector/coupon-code-selector.component.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/admin-ui/src/lib/order/src/components/coupon-code-selector/coupon-code-selector.component.html b/packages/admin-ui/src/lib/order/src/components/coupon-code-selector/coupon-code-selector.component.html index d02eefae04..c1156a2ba8 100644 --- a/packages/admin-ui/src/lib/order/src/components/coupon-code-selector/coupon-code-selector.component.html +++ b/packages/admin-ui/src/lib/order/src/components/coupon-code-selector/coupon-code-selector.component.html @@ -11,7 +11,7 @@ [typeahead]="couponCodeInput$" [formControl]="control" (add)="addCouponCode.emit($event.code)" - (remove)="removeCouponCode.emit($event.value?.code)" + (remove)="remove($event.code)" >
diff --git a/packages/admin-ui/src/lib/order/src/components/coupon-code-selector/coupon-code-selector.component.ts b/packages/admin-ui/src/lib/order/src/components/coupon-code-selector/coupon-code-selector.component.ts index 3631a48ca6..5aa9a913c6 100644 --- a/packages/admin-ui/src/lib/order/src/components/coupon-code-selector/coupon-code-selector.component.ts +++ b/packages/admin-ui/src/lib/order/src/components/coupon-code-selector/coupon-code-selector.component.ts @@ -65,4 +65,8 @@ export class CouponCodeSelectorComponent implements OnInit { this.control = new UntypedFormControl(this.couponCodes ?? []); } } + + remove(code: string) { + this.removeCouponCode.emit(code); + } } From 4d6578face068ab59ab80c866f3e06cebe92f952 Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Tue, 3 Sep 2024 18:00:15 +0200 Subject: [PATCH 10/25] docs: Update plugin publishing guide with new template info --- .../guides/how-to/publish-plugin/index.mdx | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/docs/docs/guides/how-to/publish-plugin/index.mdx b/docs/docs/guides/how-to/publish-plugin/index.mdx index fe3776430b..8e59a61b21 100644 --- a/docs/docs/guides/how-to/publish-plugin/index.mdx +++ b/docs/docs/guides/how-to/publish-plugin/index.mdx @@ -18,24 +18,21 @@ There are a couple of ways you can structure your plugin project: ### Repo structure -#### Stand-alone repo +We recommend that you use a "monorepo" structure to develop your plugins. This means that you have a single repository +which contains all your plugins, each in its own subdirectory. This makes it easy to manage dependencies between plugins, +and to share common code such as utility functions & dev tooling. -You can have a single repository for your plugin. For this scenario you can use -the [Vendure Plugin Template](https://github.com/vendure-ecommerce/plugin-template) as a starting point. +Even if you only have a single plugin at the moment, it's a good idea to set up your project in this way from the start. -**Pros**: simple to set up. +To that end, we provide a [monorepo plugin starter template](https://github.com/vendure-ecommerce/plugin-template) +which you can use as a starting point for your plugin development. -**Cons**: if you have multiple plugins, you'll have multiple repositories to manage with duplicated setup and configuration. +This starter template includes support for: -#### Monorepo - -If you have multiple plugins, you can use a monorepo setup. Tools such as [Lerna](https://lerna.js.org/) or -[Nx](https://nx.dev/) can help you manage multiple packages in a single repository. A good example of this approach -can be found in the [Pinelab plugins repo](https://github.com/Pinelab-studio/pinelab-vendure-plugins). - -**Pros**: single repository to manage; can scale to any number of plugins; can share configuration and tooling. - -**Cons**: Initial setup is more complex. +- Development & build scripts already set up +- Admin UI extensions already configured +- End-to-end testing infrastructure fully configured +- Code generation for your schema extensions ### Plugin naming From c5914325838855997b28187a134122d61d33067a Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Thu, 5 Sep 2024 08:54:13 +0200 Subject: [PATCH 11/25] perf(core): Optimize setting active order on session We were previously _always_ setting the active order which involves a relatively expensive lookup & save on the session table. --- .../service/helpers/active-order/active-order.service.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/core/src/service/helpers/active-order/active-order.service.ts b/packages/core/src/service/helpers/active-order/active-order.service.ts index 2945f6d23a..8b5bf6fc9d 100644 --- a/packages/core/src/service/helpers/active-order/active-order.service.ts +++ b/packages/core/src/service/helpers/active-order/active-order.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common'; import { RequestContext } from '../../../api/common/request-context'; import { InternalServerError, UserInputError } from '../../../common/error/errors'; +import { idsAreEqual } from '../../../common/utils'; import { ConfigService } from '../../../config/config.service'; import { TransactionalConnection } from '../../../connection/transactional-connection'; import { Order } from '../../../entity/order/order.entity'; @@ -90,7 +91,7 @@ export class ActiveOrderService { input: { [strategyName: string]: Record | undefined } | undefined, createIfNotExists = false, ): Promise { - let order: any; + let order: Order | undefined; if (!order) { const { activeOrderStrategy } = this.configService.orderOptions; const strategyArray = Array.isArray(activeOrderStrategy) @@ -119,7 +120,11 @@ export class ActiveOrderService { } if (order && ctx.session) { - await this.sessionService.setActiveOrder(ctx, ctx.session, order); + const orderAlreadyAssignedToSession = + ctx.session.activeOrderId && idsAreEqual(ctx.session.activeOrderId, order.id); + if (!orderAlreadyAssignedToSession) { + await this.sessionService.setActiveOrder(ctx, ctx.session, order); + } } } return order || undefined; From 70ad853163ce565df33e36ce01053320eadca4ce Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Thu, 5 Sep 2024 11:35:51 +0200 Subject: [PATCH 12/25] perf(core): Optimizations to the addItemToOrder path There are a number of DB operations that are quite expensive. This commit makes optimizations so that the DB does less work when adding an item to an Order. --- .../product-variant/product-variant.entity.ts | 6 ++ .../core/src/entity/product/product.entity.ts | 6 +- .../helpers/order-modifier/order-modifier.ts | 54 ++++++++------- .../src/service/services/order.service.ts | 66 +++++++++++++++++-- 4 files changed, 101 insertions(+), 31 deletions(-) diff --git a/packages/core/src/entity/product-variant/product-variant.entity.ts b/packages/core/src/entity/product-variant/product-variant.entity.ts index 91226f07ff..2cc90ca184 100644 --- a/packages/core/src/entity/product-variant/product-variant.entity.ts +++ b/packages/core/src/entity/product-variant/product-variant.entity.ts @@ -107,6 +107,9 @@ export class ProductVariant @ManyToOne(type => Asset, asset => asset.featuredInVariants, { onDelete: 'SET NULL' }) featuredAsset: Asset; + @EntityId({ nullable: true }) + featuredAssetId: ID; + @OneToMany(type => ProductVariantAsset, productVariantAsset => productVariantAsset.productVariant, { onDelete: 'SET NULL', }) @@ -116,6 +119,9 @@ export class ProductVariant @ManyToOne(type => TaxCategory, taxCategory => taxCategory.productVariants) taxCategory: TaxCategory; + @EntityId({ nullable: true }) + taxCategoryId: ID; + @OneToMany(type => ProductVariantPrice, price => price.variant, { eager: true }) productVariantPrices: ProductVariantPrice[]; diff --git a/packages/core/src/entity/product/product.entity.ts b/packages/core/src/entity/product/product.entity.ts index 82968bcdf9..88a6e7c21a 100644 --- a/packages/core/src/entity/product/product.entity.ts +++ b/packages/core/src/entity/product/product.entity.ts @@ -1,4 +1,4 @@ -import { DeepPartial } from '@vendure/common/lib/shared-types'; +import { DeepPartial, ID } from '@vendure/common/lib/shared-types'; import { Column, Entity, Index, JoinTable, ManyToMany, ManyToOne, OneToMany } from 'typeorm'; import { ChannelAware, SoftDeletable } from '../../common/types/common-types'; @@ -8,6 +8,7 @@ import { Asset } from '../asset/asset.entity'; import { VendureEntity } from '../base/base.entity'; import { Channel } from '../channel/channel.entity'; import { CustomProductFields } from '../custom-entity-fields'; +import { EntityId } from '../entity-id.decorator'; import { FacetValue } from '../facet-value/facet-value.entity'; import { ProductOptionGroup } from '../product-option-group/product-option-group.entity'; import { ProductVariant } from '../product-variant/product-variant.entity'; @@ -47,6 +48,9 @@ export class Product @ManyToOne(type => Asset, asset => asset.featuredInProducts, { onDelete: 'SET NULL' }) featuredAsset: Asset; + @EntityId({ nullable: true }) + featuredAssetId: ID; + @OneToMany(type => ProductAsset, productAsset => productAsset.product) assets: ProductAsset[]; diff --git a/packages/core/src/service/helpers/order-modifier/order-modifier.ts b/packages/core/src/service/helpers/order-modifier/order-modifier.ts index 934d2388c1..839738202f 100644 --- a/packages/core/src/service/helpers/order-modifier/order-modifier.ts +++ b/packages/core/src/service/helpers/order-modifier/order-modifier.ts @@ -10,6 +10,7 @@ import { } from '@vendure/common/lib/generated-types'; import { ID } from '@vendure/common/lib/shared-types'; import { getGraphQlInputName, summate } from '@vendure/common/lib/shared-utils'; +import { IsNull } from 'typeorm'; import { RequestContext } from '../../../api/common/request-context'; import { isGraphQlErrorResult, JustErrorResults } from '../../../common/error/error-result'; @@ -164,12 +165,13 @@ export class OrderModifier { return existingOrderLine; } - const productVariant = await this.getProductVariantOrThrow(ctx, productVariantId); + const productVariant = await this.getProductVariantOrThrow(ctx, productVariantId, order); + const featuredAssetId = productVariant.featuredAssetId ?? productVariant.featuredAssetId; const orderLine = await this.connection.getRepository(ctx, OrderLine).save( new OrderLine({ productVariant, taxCategory: productVariant.taxCategory, - featuredAsset: productVariant.featuredAsset ?? productVariant.product.featuredAsset, + featuredAsset: featuredAssetId ? { id: featuredAssetId } : undefined, listPrice: productVariant.listPrice, listPriceIncludesTax: productVariant.listPriceIncludesTax, adjustments: [], @@ -189,26 +191,15 @@ export class OrderModifier { .set(orderLine.sellerChannel); } await this.customFieldRelationService.updateRelations(ctx, OrderLine, { customFields }, orderLine); - const lineWithRelations = await this.connection.getEntityOrThrow(ctx, OrderLine, orderLine.id, { - relations: [ - 'taxCategory', - 'productVariant', - 'productVariant.productVariantPrices', - 'productVariant.taxCategory', - ], - }); - lineWithRelations.productVariant = this.translator.translate( - await this.productVariantService.applyChannelPriceAndTax( - lineWithRelations.productVariant, - ctx, - order, - ), - ctx, - ); - order.lines.push(lineWithRelations); - await this.connection.getRepository(ctx, Order).save(order, { reload: false }); - await this.eventBus.publish(new OrderLineEvent(ctx, order, lineWithRelations, 'created')); - return lineWithRelations; + order.lines.push(orderLine); + await this.connection + .getRepository(ctx, Order) + .createQueryBuilder() + .relation('lines') + .of(order) + .add(orderLine); + await this.eventBus.publish(new OrderLineEvent(ctx, order, orderLine, 'created')); + return orderLine; } /** @@ -896,11 +887,24 @@ export class OrderModifier { private async getProductVariantOrThrow( ctx: RequestContext, productVariantId: ID, + order: Order, ): Promise { - const productVariant = await this.productVariantService.findOne(ctx, productVariantId); - if (!productVariant) { + const variant = await this.connection.findOneInChannel( + ctx, + ProductVariant, + productVariantId, + ctx.channelId, + { + relations: ['product', 'productVariantPrices', 'taxCategory'], + loadEagerRelations: false, + where: { deletedAt: IsNull() }, + }, + ); + + if (variant) { + return await this.productVariantService.applyChannelPriceAndTax(variant, ctx, order); + } else { throw new EntityNotFoundError('ProductVariant', productVariantId); } - return productVariant; } } diff --git a/packages/core/src/service/services/order.service.ts b/packages/core/src/service/services/order.service.ts index d3afe58ad8..851f38eaf0 100644 --- a/packages/core/src/service/services/order.service.ts +++ b/packages/core/src/service/services/order.service.ts @@ -53,7 +53,6 @@ import { CancelPaymentError, EmptyOrderLineSelectionError, FulfillmentStateTransitionError, - RefundStateTransitionError, InsufficientStockOnHandError, ItemsAlreadyFulfilledError, ManualPaymentStateError, @@ -61,6 +60,7 @@ import { NothingToRefundError, PaymentOrderMismatchError, RefundOrderStateError, + RefundStateTransitionError, SettlePaymentError, } from '../../common/error/generated-graphql-admin-errors'; import { @@ -561,6 +561,7 @@ export class OrderService { enabled: true, deletedAt: IsNull(), }, + loadEagerRelations: false, }); if (variant.product.enabled === false) { throw new EntityNotFoundError('ProductVariant', productVariantId); @@ -1776,22 +1777,77 @@ export class OrderService { } } + // Get the shipping line IDs before doing the order calculation + // step, which can in some cases change the applied shipping lines. + const shippingLineIdsPre = order.shippingLines.map(l => l.id); + const updatedOrder = await this.orderCalculator.applyPriceAdjustments( ctx, order, promotions, updatedOrderLines ?? [], ); + + const shippingLineIdsPost = updatedOrder.shippingLines.map(l => l.id); + await this.applyChangesToShippingLines(ctx, updatedOrder, shippingLineIdsPre, shippingLineIdsPost); + + // Explicitly omit the shippingAddress and billingAddress properties to avoid + // a race condition where changing one or the other in parallel can + // overwrite the other's changes. The other omissions prevent the save + // function from doing more work than necessary. await this.connection .getRepository(ctx, Order) - // Explicitly omit the shippingAddress and billingAddress properties to avoid - // a race condition where changing one or the other in parallel can - // overwrite the other's changes. - .save(omit(updatedOrder, ['shippingAddress', 'billingAddress']), { reload: false }); + .save( + omit(updatedOrder, [ + 'shippingAddress', + 'billingAddress', + 'lines', + 'shippingLines', + 'aggregateOrder', + 'sellerOrders', + 'customer', + 'modifications', + ]), + { + reload: false, + }, + ); await this.connection.getRepository(ctx, OrderLine).save(updatedOrder.lines, { reload: false }); await this.connection.getRepository(ctx, ShippingLine).save(order.shippingLines, { reload: false }); await this.promotionService.runPromotionSideEffects(ctx, order, activePromotionsPre); return assertFound(this.findOne(ctx, order.id)); } + + /** + * Applies changes to the shipping lines of an order, adding or removing the relations + * in the database. + */ + private async applyChangesToShippingLines( + ctx: RequestContext, + order: Order, + shippingLineIdsPre: ID[], + shippingLineIdsPost: ID[], + ) { + const removedShippingLineIds = shippingLineIdsPre.filter(id => !shippingLineIdsPost.includes(id)); + const newlyAddedShippingLineIds = shippingLineIdsPost.filter(id => !shippingLineIdsPre.includes(id)); + + for (const idToRemove of removedShippingLineIds) { + await this.connection + .getRepository(ctx, Order) + .createQueryBuilder() + .relation('shippingLines') + .of(order) + .remove(idToRemove); + } + + for (const idToAdd of newlyAddedShippingLineIds) { + await this.connection + .getRepository(ctx, Order) + .createQueryBuilder() + .relation('shippingLines') + .of(order) + .add(idToAdd); + } + } } From ad30b5581ef4f2beb9bff14bc68db91b04ec94f3 Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Mon, 9 Sep 2024 13:49:10 +0200 Subject: [PATCH 13/25] perf(core): Omit ID encode/decode step if default EntityIdStrategy used This saves some milliseconds when using the default strategies. --- .../api/config/configure-graphql-module.ts | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/packages/core/src/api/config/configure-graphql-module.ts b/packages/core/src/api/config/configure-graphql-module.ts index bfe261c36d..2959b72637 100644 --- a/packages/core/src/api/config/configure-graphql-module.ts +++ b/packages/core/src/api/config/configure-graphql-module.ts @@ -7,6 +7,7 @@ import path from 'path'; import { ConfigModule } from '../../config/config.module'; import { ConfigService } from '../../config/config.service'; +import { AutoIncrementIdStrategy, EntityIdStrategy, UuidIdStrategy } from '../../config/index'; import { I18nModule } from '../../i18n/i18n.module'; import { I18nService } from '../../i18n/i18n.service'; import { getPluginAPIExtensions } from '../../plugin/plugin-metadata'; @@ -96,6 +97,24 @@ async function createGraphQLOptions( options.apiType, builtSchema, ); + + const apolloServerPlugins = [ + new TranslateErrorsPlugin(i18nService), + new AssetInterceptorPlugin(configService), + ...configService.apiOptions.apolloServerPlugins, + ]; + // We only need to add the IdCodecPlugin if the user has configured + // a non-default EntityIdStrategy. This is a performance optimization + // that prevents unnecessary traversal of each response when no + // actual encoding/decoding is taking place. + if ( + !isUsingDefaultEntityIdStrategy( + configService.entityOptions.entityIdStrategy ?? configService.entityIdStrategy, + ) + ) { + apolloServerPlugins.unshift(new IdCodecPlugin(idCodecService)); + } + return { path: '/' + options.apiPath, typeDefs: printSchema(builtSchema), @@ -112,12 +131,7 @@ async function createGraphQLOptions( context: (req: any) => req, // This is handled by the Express cors plugin cors: false, - plugins: [ - new IdCodecPlugin(idCodecService), - new TranslateErrorsPlugin(i18nService), - new AssetInterceptorPlugin(configService), - ...configService.apiOptions.apolloServerPlugins, - ], + plugins: apolloServerPlugins, validationRules: options.validationRules, introspection: configService.apiOptions.introspection ?? true, } as ApolloDriverConfig; @@ -165,3 +179,10 @@ async function createGraphQLOptions( return schema; } } + +function isUsingDefaultEntityIdStrategy(entityIdStrategy: EntityIdStrategy): boolean { + return ( + entityIdStrategy.constructor === AutoIncrementIdStrategy || + entityIdStrategy.constructor === UuidIdStrategy + ); +} From d7bd446df17b59345bb957c858d3db5651e021b8 Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Mon, 9 Sep 2024 13:53:17 +0200 Subject: [PATCH 14/25] perf(core): Optimize resolution of featuredAsset fields Previously, if one of the entities had no assigned featuredAsset, the value to the resolver would be `null`, which would cause _another_ DB lookup. Additionally, we are now preventing unnecessary loading of eager relations when loading a featuredAsset. --- .../src/api/resolvers/entity/collection-entity.resolver.ts | 2 +- .../src/api/resolvers/entity/order-line-entity.resolver.ts | 2 +- .../core/src/api/resolvers/entity/product-entity.resolver.ts | 2 +- .../api/resolvers/entity/product-variant-entity.resolver.ts | 4 ++-- packages/core/src/service/services/asset.service.ts | 2 ++ 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/core/src/api/resolvers/entity/collection-entity.resolver.ts b/packages/core/src/api/resolvers/entity/collection-entity.resolver.ts index 9d7383d66c..165d694bec 100644 --- a/packages/core/src/api/resolvers/entity/collection-entity.resolver.ts +++ b/packages/core/src/api/resolvers/entity/collection-entity.resolver.ts @@ -116,7 +116,7 @@ export class CollectionEntityResolver { @Ctx() ctx: RequestContext, @Parent() collection: Collection, ): Promise { - if (collection.featuredAsset) { + if (collection.featuredAsset !== undefined) { return collection.featuredAsset; } return this.assetService.getFeaturedAsset(ctx, collection); diff --git a/packages/core/src/api/resolvers/entity/order-line-entity.resolver.ts b/packages/core/src/api/resolvers/entity/order-line-entity.resolver.ts index bd57dd4339..e8cc63a348 100644 --- a/packages/core/src/api/resolvers/entity/order-line-entity.resolver.ts +++ b/packages/core/src/api/resolvers/entity/order-line-entity.resolver.ts @@ -31,7 +31,7 @@ export class OrderLineEntityResolver { @Ctx() ctx: RequestContext, @Parent() orderLine: OrderLine, ): Promise { - if (orderLine.featuredAsset) { + if (orderLine.featuredAsset !== undefined) { return orderLine.featuredAsset; } else { return this.assetService.getFeaturedAsset(ctx, orderLine); diff --git a/packages/core/src/api/resolvers/entity/product-entity.resolver.ts b/packages/core/src/api/resolvers/entity/product-entity.resolver.ts index 9086c3be31..f89b988293 100644 --- a/packages/core/src/api/resolvers/entity/product-entity.resolver.ts +++ b/packages/core/src/api/resolvers/entity/product-entity.resolver.ts @@ -129,7 +129,7 @@ export class ProductEntityResolver { @ResolveField() async featuredAsset(@Ctx() ctx: RequestContext, @Parent() product: Product): Promise { - if (product.featuredAsset) { + if (product.featuredAsset !== undefined) { return product.featuredAsset; } return this.assetService.getFeaturedAsset(ctx, product); diff --git a/packages/core/src/api/resolvers/entity/product-variant-entity.resolver.ts b/packages/core/src/api/resolvers/entity/product-variant-entity.resolver.ts index addcf02b32..ceea767662 100644 --- a/packages/core/src/api/resolvers/entity/product-variant-entity.resolver.ts +++ b/packages/core/src/api/resolvers/entity/product-variant-entity.resolver.ts @@ -14,9 +14,9 @@ import { Asset, Channel, FacetValue, Product, ProductOption, StockLevel, TaxRate import { ProductVariant } from '../../../entity/product-variant/product-variant.entity'; import { StockMovement } from '../../../entity/stock-movement/stock-movement.entity'; import { LocaleStringHydrator } from '../../../service/helpers/locale-string-hydrator/locale-string-hydrator'; -import { StockLevelService } from '../../../service/services/stock-level.service'; import { AssetService } from '../../../service/services/asset.service'; import { ProductVariantService } from '../../../service/services/product-variant.service'; +import { StockLevelService } from '../../../service/services/stock-level.service'; import { StockMovementService } from '../../../service/services/stock-movement.service'; import { ApiType } from '../../common/get-api-type'; import { RequestContext } from '../../common/request-context'; @@ -103,7 +103,7 @@ export class ProductVariantEntityResolver { @Ctx() ctx: RequestContext, @Parent() productVariant: ProductVariant, ): Promise { - if (productVariant.featuredAsset) { + if (productVariant.featuredAsset !== undefined) { return productVariant.featuredAsset; } return this.assetService.getFeaturedAsset(ctx, productVariant); diff --git a/packages/core/src/service/services/asset.service.ts b/packages/core/src/service/services/asset.service.ts index 234e504f21..b50b43f3a9 100644 --- a/packages/core/src/service/services/asset.service.ts +++ b/packages/core/src/service/services/asset.service.ts @@ -168,6 +168,7 @@ export class AssetService { ctx.channelId, { relations: ['featuredAsset'], + loadEagerRelations: false, }, ); } else { @@ -178,6 +179,7 @@ export class AssetService { relations: { featuredAsset: true, }, + loadEagerRelations: false, // TODO: satisfies } as FindOneOptions) .then(result => result ?? undefined); From e3d6c21ea37a5df8513b88eea0ac472054a35247 Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Mon, 9 Sep 2024 14:04:45 +0200 Subject: [PATCH 15/25] perf(core): Optimize order operations This commit introduces a number of small optimizations to order-related code paths: - Relations decorator added to `addItemToOrder` and `adjustOrderLine` - Relations array passed down through key OrderService methods - Ids used for tax calculations, so entire entities do not need to be joined --- .../api/resolvers/shop/shop-order.resolver.ts | 17 ++++++++--- .../entity/order-line/order-line.entity.ts | 3 ++ .../src/entity/tax-rate/tax-rate.entity.ts | 19 ++++++++++-- .../order-calculator/order-calculator.ts | 21 +++++++------ .../helpers/order-modifier/order-modifier.ts | 2 +- .../helpers/order-splitter/order-splitter.ts | 2 ++ .../service/services/order-testing.service.ts | 1 + .../src/service/services/order.service.ts | 30 +++++++++++++++---- .../src/service/services/tax-rate.service.ts | 6 +++- 9 files changed, 75 insertions(+), 26 deletions(-) diff --git a/packages/core/src/api/resolvers/shop/shop-order.resolver.ts b/packages/core/src/api/resolvers/shop/shop-order.resolver.ts index d418034587..98758ce23f 100644 --- a/packages/core/src/api/resolvers/shop/shop-order.resolver.ts +++ b/packages/core/src/api/resolvers/shop/shop-order.resolver.ts @@ -76,7 +76,8 @@ export class ShopOrderResolver { async order( @Ctx() ctx: RequestContext, @Args() args: QueryOrderArgs, - @Relations(Order) relations: RelationPaths, + @Relations({ entity: Order, omit: ['aggregateOrder', 'sellerOrders'] }) + relations: RelationPaths, ): Promise { const requiredRelations: RelationPaths = ['customer', 'customer.user']; const order = await this.orderService.findOne( @@ -98,7 +99,8 @@ export class ShopOrderResolver { @Allow(Permission.Owner) async activeOrder( @Ctx() ctx: RequestContext, - @Relations(Order) relations: RelationPaths, + @Relations({ entity: Order, omit: ['aggregateOrder', 'sellerOrders'] }) + relations: RelationPaths, @Args() args: ActiveOrderArgs, ): Promise { if (ctx.authorizedAsOwnerOnly) { @@ -107,7 +109,7 @@ export class ShopOrderResolver { args[ACTIVE_ORDER_INPUT_FIELD_NAME], ); if (sessionOrder) { - return this.orderService.findOne(ctx, sessionOrder.id); + return this.orderService.findOne(ctx, sessionOrder.id, relations); } else { return; } @@ -119,7 +121,8 @@ export class ShopOrderResolver { async orderByCode( @Ctx() ctx: RequestContext, @Args() args: QueryOrderByCodeArgs, - @Relations(Order) relations: RelationPaths, + @Relations({ entity: Order, omit: ['aggregateOrder', 'sellerOrders'] }) + relations: RelationPaths, ): Promise { if (ctx.authorizedAsOwnerOnly) { const requiredRelations: RelationPaths = ['customer', 'customer.user']; @@ -294,6 +297,8 @@ export class ShopOrderResolver { async addItemToOrder( @Ctx() ctx: RequestContext, @Args() args: MutationAddItemToOrderArgs & ActiveOrderArgs, + @Relations({ entity: Order, omit: ['aggregateOrder', 'sellerOrders'] }) + relations: RelationPaths, ): Promise> { const order = await this.activeOrderService.getActiveOrder( ctx, @@ -306,6 +311,7 @@ export class ShopOrderResolver { args.productVariantId, args.quantity, (args as any).customFields, + relations, ); } @@ -315,6 +321,8 @@ export class ShopOrderResolver { async adjustOrderLine( @Ctx() ctx: RequestContext, @Args() args: MutationAdjustOrderLineArgs & ActiveOrderArgs, + @Relations({ entity: Order, omit: ['aggregateOrder', 'sellerOrders'] }) + relations: RelationPaths, ): Promise> { if (args.quantity === 0) { return this.removeOrderLine(ctx, { orderLineId: args.orderLineId }); @@ -330,6 +338,7 @@ export class ShopOrderResolver { args.orderLineId, args.quantity, (args as any).customFields, + relations, ); } diff --git a/packages/core/src/entity/order-line/order-line.entity.ts b/packages/core/src/entity/order-line/order-line.entity.ts index a9c44fc229..4f747ca67d 100644 --- a/packages/core/src/entity/order-line/order-line.entity.ts +++ b/packages/core/src/entity/order-line/order-line.entity.ts @@ -76,6 +76,9 @@ export class OrderLine extends VendureEntity implements HasCustomFields { @ManyToOne(type => TaxCategory) taxCategory: TaxCategory; + @EntityId({ nullable: true }) + taxCategoryId: ID; + @Index() @ManyToOne(type => Asset, asset => asset.featuredInVariants, { onDelete: 'SET NULL' }) featuredAsset: Asset; diff --git a/packages/core/src/entity/tax-rate/tax-rate.entity.ts b/packages/core/src/entity/tax-rate/tax-rate.entity.ts index eeb2ea433a..630ef74de3 100644 --- a/packages/core/src/entity/tax-rate/tax-rate.entity.ts +++ b/packages/core/src/entity/tax-rate/tax-rate.entity.ts @@ -1,5 +1,5 @@ import { TaxLine } from '@vendure/common/lib/generated-types'; -import { DeepPartial } from '@vendure/common/lib/shared-types'; +import { DeepPartial, ID } from '@vendure/common/lib/shared-types'; import { Column, Entity, Index, ManyToOne } from 'typeorm'; import { grossPriceOf, netPriceOf, taxComponentOf, taxPayableOn } from '../../common/tax-utils'; @@ -8,6 +8,7 @@ import { HasCustomFields } from '../../config/custom-field/custom-field-types'; import { VendureEntity } from '../base/base.entity'; import { CustomTaxRateFields } from '../custom-entity-fields'; import { CustomerGroup } from '../customer-group/customer-group.entity'; +import { EntityId } from '../entity-id.decorator'; import { TaxCategory } from '../tax-category/tax-category.entity'; import { DecimalTransformer } from '../value-transformers'; import { Zone } from '../zone/zone.entity'; @@ -38,10 +39,16 @@ export class TaxRate extends VendureEntity implements HasCustomFields { @ManyToOne(type => TaxCategory, taxCategory => taxCategory.taxRates) category: TaxCategory; + @EntityId({ nullable: true }) + categoryId: ID; + @Index() @ManyToOne(type => Zone, zone => zone.taxRates) zone: Zone; + @EntityId({ nullable: true }) + zoneId: ID; + @Index() @ManyToOne(type => CustomerGroup, customerGroup => customerGroup.taxRates, { nullable: true }) customerGroup?: CustomerGroup; @@ -84,7 +91,13 @@ export class TaxRate extends VendureEntity implements HasCustomFields { }; } - test(zone: Zone, taxCategory: TaxCategory): boolean { - return idsAreEqual(taxCategory.id, this.category.id) && idsAreEqual(zone.id, this.zone.id); + test(zone: Zone | ID, taxCategory: TaxCategory | ID): boolean { + const taxCategoryId = this.isId(taxCategory) ? taxCategory : taxCategory.id; + const zoneId = this.isId(zone) ? zone : zone.id; + return idsAreEqual(taxCategoryId, this.categoryId) && idsAreEqual(zoneId, this.zoneId); + } + + private isId(entityOrId: T | ID): entityOrId is ID { + return typeof entityOrId === 'string' || typeof entityOrId === 'number'; } } diff --git a/packages/core/src/service/helpers/order-calculator/order-calculator.ts b/packages/core/src/service/helpers/order-calculator/order-calculator.ts index c1cb98f705..b0e153cc46 100644 --- a/packages/core/src/service/helpers/order-calculator/order-calculator.ts +++ b/packages/core/src/service/helpers/order-calculator/order-calculator.ts @@ -1,6 +1,7 @@ import { Injectable } from '@nestjs/common'; import { filterAsync } from '@vendure/common/lib/filter-async'; import { AdjustmentType } from '@vendure/common/lib/generated-types'; +import { ID } from '@vendure/common/lib/shared-types'; import { RequestContext } from '../../../api/common/request-context'; import { RequestContextCacheService } from '../../../cache/request-context-cache.service'; @@ -76,7 +77,6 @@ export class OrderCalculator { ctx, order, updatedOrderLine, - activeTaxZone, this.createTaxRateGetter(ctx, activeTaxZone), ); } @@ -113,7 +113,7 @@ export class OrderCalculator { private async applyTaxes(ctx: RequestContext, order: Order, activeZone: Zone) { const getTaxRate = this.createTaxRateGetter(ctx, activeZone); for (const line of order.lines) { - await this.applyTaxesToOrderLine(ctx, order, line, activeZone, getTaxRate); + await this.applyTaxesToOrderLine(ctx, order, line, getTaxRate); } this.calculateOrderTotals(order); } @@ -126,10 +126,9 @@ export class OrderCalculator { ctx: RequestContext, order: Order, line: OrderLine, - activeZone: Zone, - getTaxRate: (taxCategory: TaxCategory) => Promise, + getTaxRate: (taxCategoryId: ID) => Promise, ) { - const applicableTaxRate = await getTaxRate(line.taxCategory); + const applicableTaxRate = await getTaxRate(line.taxCategoryId); const { taxLineCalculationStrategy } = this.configService.taxOptions; line.taxLines = await taxLineCalculationStrategy.calculate({ ctx, @@ -147,16 +146,16 @@ export class OrderCalculator { private createTaxRateGetter( ctx: RequestContext, activeZone: Zone, - ): (taxCategory: TaxCategory) => Promise { - const taxRateCache = new Map(); + ): (taxCategoryId: ID) => Promise { + const taxRateCache = new Map(); - return async (taxCategory: TaxCategory): Promise => { - const cached = taxRateCache.get(taxCategory); + return async (taxCategoryId: ID): Promise => { + const cached = taxRateCache.get(taxCategoryId); if (cached) { return cached; } - const rate = await this.taxRateService.getApplicableTaxRate(ctx, activeZone, taxCategory); - taxRateCache.set(taxCategory, rate); + const rate = await this.taxRateService.getApplicableTaxRate(ctx, activeZone, taxCategoryId); + taxRateCache.set(taxCategoryId, rate); return rate; }; } diff --git a/packages/core/src/service/helpers/order-modifier/order-modifier.ts b/packages/core/src/service/helpers/order-modifier/order-modifier.ts index 839738202f..a5153e1319 100644 --- a/packages/core/src/service/helpers/order-modifier/order-modifier.ts +++ b/packages/core/src/service/helpers/order-modifier/order-modifier.ts @@ -141,7 +141,7 @@ export class OrderModifier { ): Promise { for (const line of order.lines) { const match = - idsAreEqual(line.productVariant.id, productVariantId) && + idsAreEqual(line.productVariantId, productVariantId) && (await this.customFieldsAreEqual(ctx, line, customFields, line.customFields)); if (match) { return line; diff --git a/packages/core/src/service/helpers/order-splitter/order-splitter.ts b/packages/core/src/service/helpers/order-splitter/order-splitter.ts index 9dc510bb46..d550e63723 100644 --- a/packages/core/src/service/helpers/order-splitter/order-splitter.ts +++ b/packages/core/src/service/helpers/order-splitter/order-splitter.ts @@ -90,7 +90,9 @@ export class OrderSplitter { ...pick(line, [ 'quantity', 'productVariant', + 'productVariantId', 'taxCategory', + 'taxCategoryId', 'featuredAsset', 'shippingLine', 'shippingLineId', diff --git a/packages/core/src/service/services/order-testing.service.ts b/packages/core/src/service/services/order-testing.service.ts index 56603b46c2..b40973da94 100644 --- a/packages/core/src/service/services/order-testing.service.ts +++ b/packages/core/src/service/services/order-testing.service.ts @@ -130,6 +130,7 @@ export class OrderTestingService { taxLines: [], quantity: line.quantity, taxCategory: productVariant.taxCategory, + taxCategoryId: productVariant.taxCategoryId, }); mockOrder.lines.push(orderLine); diff --git a/packages/core/src/service/services/order.service.ts b/packages/core/src/service/services/order.service.ts index 851f38eaf0..180411c361 100644 --- a/packages/core/src/service/services/order.service.ts +++ b/packages/core/src/service/services/order.service.ts @@ -489,7 +489,7 @@ export class OrderService { * @since 2.2.0 */ async updateOrderCustomer(ctx: RequestContext, { customerId, orderId, note }: SetOrderCustomerInput) { - const order = await this.getOrderOrThrow(ctx, orderId); + const order = await this.getOrderOrThrow(ctx, orderId, ['channels', 'customer']); const currentCustomer = order.customer; if (currentCustomer?.id === customerId) { // No change in customer, so just return the order as-is @@ -539,6 +539,7 @@ export class OrderService { productVariantId: ID, quantity: number, customFields?: { [key: string]: any }, + relations?: RelationPaths, ): Promise> { const order = await this.getOrderOrThrow(ctx, orderId); const existingOrderLine = await this.orderModifier.getExistingOrderLine( @@ -597,7 +598,7 @@ export class OrderService { await this.orderModifier.updateOrderLineQuantity(ctx, orderLine, correctedQuantity, order); } const quantityWasAdjustedDown = correctedQuantity < quantity; - const updatedOrder = await this.applyPriceAdjustments(ctx, order, [orderLine]); + const updatedOrder = await this.applyPriceAdjustments(ctx, order, [orderLine], relations); if (quantityWasAdjustedDown) { return new InsufficientStockError({ quantityAvailable: correctedQuantity, order: updatedOrder }); } else { @@ -615,6 +616,7 @@ export class OrderService { orderLineId: ID, quantity: number, customFields?: { [key: string]: any }, + relations?: RelationPaths, ): Promise> { const order = await this.getOrderOrThrow(ctx, orderId); const orderLine = this.getOrderLineOrThrow(order, orderLineId); @@ -661,7 +663,7 @@ export class OrderService { await this.orderModifier.updateOrderLineQuantity(ctx, orderLine, correctedQuantity, order); } const quantityWasAdjustedDown = correctedQuantity < quantity; - const updatedOrder = await this.applyPriceAdjustments(ctx, order, updatedOrderLines); + const updatedOrder = await this.applyPriceAdjustments(ctx, order, updatedOrderLines, relations); if (quantityWasAdjustedDown) { return new InsufficientStockError({ quantityAvailable: correctedQuantity, order: updatedOrder }); } else { @@ -1664,8 +1666,23 @@ export class OrderService { return order; } - private async getOrderOrThrow(ctx: RequestContext, orderId: ID): Promise { - const order = await this.findOne(ctx, orderId); + private async getOrderOrThrow( + ctx: RequestContext, + orderId: ID, + relations?: RelationPaths, + ): Promise { + const order = await this.findOne( + ctx, + orderId, + relations ?? [ + 'lines', + 'lines.productVariant', + 'lines.productVariant.productVariantPrices', + 'shippingLines', + 'surcharges', + 'customer', + ], + ); if (!order) { throw new EntityNotFoundError('Order', orderId); } @@ -1731,6 +1748,7 @@ export class OrderService { ctx: RequestContext, order: Order, updatedOrderLines?: OrderLine[], + relations?: RelationPaths, ): Promise { const promotions = await this.promotionService.getActivePromotionsInChannel(ctx); const activePromotionsPre = await this.promotionService.getActivePromotionsOnOrder(ctx, order.id); @@ -1816,7 +1834,7 @@ export class OrderService { await this.connection.getRepository(ctx, ShippingLine).save(order.shippingLines, { reload: false }); await this.promotionService.runPromotionSideEffects(ctx, order, activePromotionsPre); - return assertFound(this.findOne(ctx, order.id)); + return assertFound(this.findOne(ctx, order.id, relations)); } /** diff --git a/packages/core/src/service/services/tax-rate.service.ts b/packages/core/src/service/services/tax-rate.service.ts index c0c2979d1a..cad588b3aa 100644 --- a/packages/core/src/service/services/tax-rate.service.ts +++ b/packages/core/src/service/services/tax-rate.service.ts @@ -164,7 +164,11 @@ export class TaxRateService { * Returns the applicable TaxRate based on the specified Zone and TaxCategory. Used when calculating Order * prices. */ - async getApplicableTaxRate(ctx: RequestContext, zone: Zone, taxCategory: TaxCategory): Promise { + async getApplicableTaxRate( + ctx: RequestContext, + zone: Zone | ID, + taxCategory: TaxCategory | ID, + ): Promise { const rate = (await this.getActiveTaxRates(ctx)).find(r => r.test(zone, taxCategory)); return rate || this.defaultTaxRate; } From 7ae064c704ab613ea429bfe098debe72946a438e Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Mon, 9 Sep 2024 14:05:33 +0200 Subject: [PATCH 16/25] chore(core): Refactor init of EntityIdStrategy --- packages/core/src/config/config.module.ts | 6 +++--- packages/core/src/config/default-config.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/src/config/config.module.ts b/packages/core/src/config/config.module.ts index 8c7cb88feb..26b9662268 100644 --- a/packages/core/src/config/config.module.ts +++ b/packages/core/src/config/config.module.ts @@ -106,10 +106,11 @@ export class ConfigModule implements OnApplicationBootstrap, OnApplicationShutdo } = this.configService.shippingOptions; const { customPaymentProcess, process: paymentProcess } = this.configService.paymentOptions; const { entityIdStrategy: entityIdStrategyDeprecated } = this.configService; - const { entityIdStrategy } = this.configService.entityOptions; + const { entityIdStrategy: entityIdStrategyCurrent } = this.configService.entityOptions; const { healthChecks, errorHandlers } = this.configService.systemOptions; const { assetImportStrategy } = this.configService.importExportOptions; const { refundProcess: refundProcess } = this.configService.paymentOptions; + const entityIdStrategy = entityIdStrategyCurrent ?? entityIdStrategyDeprecated; return [ ...adminAuthenticationStrategy, ...shopAuthenticationStrategy, @@ -127,8 +128,7 @@ export class ConfigModule implements OnApplicationBootstrap, OnApplicationShutdo checkoutMergeStrategy, orderCodeStrategy, orderByCodeAccessStrategy, - entityIdStrategyDeprecated, - ...[entityIdStrategy].filter(notNullOrUndefined), + entityIdStrategy, productVariantPriceCalculationStrategy, productVariantPriceUpdateStrategy, orderItemPriceCalculationStrategy, diff --git a/packages/core/src/config/default-config.ts b/packages/core/src/config/default-config.ts index e7b5f5b6dc..30fcc89b84 100644 --- a/packages/core/src/config/default-config.ts +++ b/packages/core/src/config/default-config.ts @@ -118,7 +118,6 @@ export const defaultConfig: RuntimeVendureConfig = { stockDisplayStrategy: new DefaultStockDisplayStrategy(), stockLocationStrategy: new DefaultStockLocationStrategy(), }, - entityIdStrategy: new AutoIncrementIdStrategy(), assetOptions: { assetNamingStrategy: new DefaultAssetNamingStrategy(), assetStorageStrategy: new NoAssetStorageStrategy(), @@ -131,6 +130,7 @@ export const defaultConfig: RuntimeVendureConfig = { type: 'mysql', }, entityOptions: { + entityIdStrategy: new AutoIncrementIdStrategy(), moneyStrategy: new DefaultMoneyStrategy(), entityDuplicators: defaultEntityDuplicators, channelCacheTtl: 30000, From 042abdb9ece99845a48fed94890c8973bb68722c Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Mon, 9 Sep 2024 17:24:35 +0200 Subject: [PATCH 17/25] fix(core): Prevent exposure of private custom fields via JSON type Fixes #3049 --- packages/core/e2e/custom-fields.e2e-spec.ts | 36 +++++++++++++------ .../core/src/api/config/generate-resolvers.ts | 11 ++++++ 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/packages/core/e2e/custom-fields.e2e-spec.ts b/packages/core/e2e/custom-fields.e2e-spec.ts index a39d7c7394..d436b8d557 100644 --- a/packages/core/e2e/custom-fields.e2e-spec.ts +++ b/packages/core/e2e/custom-fields.e2e-spec.ts @@ -183,6 +183,10 @@ const customConfig = mergeConfig(testConfig(), { readonly: true, }, ], + Collection: [ + { name: 'secretKey1', type: 'string', defaultValue: '', public: false, internal: true }, + { name: 'secretKey2', type: 'string', defaultValue: '', public: false, internal: false }, + ], OrderLine: [{ name: 'validateInt', type: 'int', min: 0, max: 10 }], } as CustomFields, }); @@ -942,6 +946,20 @@ describe('Custom fields', () => { `); }, 'Cannot query field "internalString" on type "ProductCustomFields"'), ); + + // https://github.com/vendure-ecommerce/vendure/issues/3049 + it('does not leak private fields via JSON type', async () => { + const { collection } = await shopClient.query(gql` + query { + collection(id: "T_1") { + id + customFields + } + } + `); + + expect(collection.customFields).toBe(null); + }); }); describe('sort & filter', () => { @@ -1087,18 +1105,16 @@ describe('Custom fields', () => { describe('unique constraint', () => { it('setting unique value works', async () => { - const result = await adminClient.query( - gql` - mutation { - updateProduct(input: { id: "T_1", customFields: { uniqueString: "foo" } }) { - id - customFields { - uniqueString - } + const result = await adminClient.query(gql` + mutation { + updateProduct(input: { id: "T_1", customFields: { uniqueString: "foo" } }) { + id + customFields { + uniqueString } } - `, - ); + } + `); expect(result.updateProduct.customFields.uniqueString).toBe('foo'); }); diff --git a/packages/core/src/api/config/generate-resolvers.ts b/packages/core/src/api/config/generate-resolvers.ts index 2d72f8af57..2552ae254f 100644 --- a/packages/core/src/api/config/generate-resolvers.ts +++ b/packages/core/src/api/config/generate-resolvers.ts @@ -255,6 +255,17 @@ function generateCustomFieldRelationResolvers( } as any; } } + const allCustomFieldsAreNonPublic = customFields.every( + f => f.public === false || f.internal === true, + ); + if (allCustomFieldsAreNonPublic) { + // When an entity has only non-public custom fields, the GraphQL type used for the + // customFields field is `JSON`. This type will simply return the full object, which + // will cause a leak of private data unless we force a `null` return value in the case + // that there are no public fields. + // See https://github.com/vendure-ecommerce/vendure/issues/3049 + shopResolvers[entityName] = { customFields: () => null }; + } } return { adminResolvers, shopResolvers }; } From e1595d2a31fbff3eb3ffc72fc929c908fb226604 Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Mon, 9 Sep 2024 17:25:59 +0200 Subject: [PATCH 18/25] chore(core): Fix type error introduced by entityIdStrategy refactor --- packages/core/src/config/default-config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/src/config/default-config.ts b/packages/core/src/config/default-config.ts index 30fcc89b84..dcc0372c54 100644 --- a/packages/core/src/config/default-config.ts +++ b/packages/core/src/config/default-config.ts @@ -84,6 +84,7 @@ export const defaultConfig: RuntimeVendureConfig = { introspection: true, apolloServerPlugins: [], }, + entityIdStrategy: new AutoIncrementIdStrategy(), authOptions: { disableAuth: false, tokenMethod: 'cookie', From 17290e28c95216b4ae1549c883df35868f6349a3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 06:27:08 +0000 Subject: [PATCH 19/25] @neokim has signed the CLA in vendure-ecommerce/vendure#3052 --- license/signatures/version1/cla.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/license/signatures/version1/cla.json b/license/signatures/version1/cla.json index d84e4b32b4..ca817815a3 100644 --- a/license/signatures/version1/cla.json +++ b/license/signatures/version1/cla.json @@ -127,6 +127,14 @@ "created_at": "2024-09-02T11:14:15Z", "repoId": 136938012, "pullRequestNo": 3041 + }, + { + "name": "neokim", + "id": 3601028, + "comment_id": 2339775064, + "created_at": "2024-09-10T06:26:52Z", + "repoId": 136938012, + "pullRequestNo": 3052 } ] } \ No newline at end of file From 44f973f2dfcb1986ad72c7927732bd04529c1f20 Mon Sep 17 00:00:00 2001 From: Neo Kim Date: Tue, 10 Sep 2024 15:55:46 +0900 Subject: [PATCH 20/25] docs: Fix incorrect docs for resolving port conflict in e2e test. (#3052) --- docs/docs/guides/developer-guide/testing/index.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/docs/guides/developer-guide/testing/index.md b/docs/docs/guides/developer-guide/testing/index.md index c0f0c93301..02cd50a0fa 100644 --- a/docs/docs/guides/developer-guide/testing/index.md +++ b/docs/docs/guides/developer-guide/testing/index.md @@ -195,21 +195,24 @@ All that's left is to run your tests to find out whether your code behaves as ex :::caution **Note:** When using **Vitest** with multiple test suites (multiple `.e2e-spec.ts` files), it will attempt to run them in parallel. If all the test servers are running -on the same port (the default in the `testConfig` is `3050`), then this will cause a port conflict. To avoid this, you can manually set a unique port for each test suite: +on the same port (the default in the `testConfig` is `3050`), then this will cause a port conflict. To avoid this, you can manually set a unique port for each test suite. Be aware that `mergeConfig` is used here: ```ts title="src/plugins/my-plugin/e2e/my-plugin.e2e-spec.ts" import { createTestEnvironment, testConfig } from '@vendure/testing'; +import { mergeConfig } from "@vendure/core"; import { describe } from 'vitest'; import { MyPlugin } from '../my-plugin.ts'; describe('my plugin', () => { - const {server, adminClient, shopClient} = createTestEnvironment({ - ...testConfig, - // highlight-next-line - port: 3051, + const {server, adminClient, shopClient} = createTestEnvironment(mergeConfig(testConfig, { + // highlight-start + apiOptions: { + port: 3051, + }, + // highlight-end plugins: [MyPlugin], - }); + })); }); ``` From 2cac88526920e0d8ffd2cd3381c4dc8a1a803dd9 Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Tue, 10 Sep 2024 09:27:38 +0200 Subject: [PATCH 21/25] chore(core): Fix failing tests --- .../core/src/api/config/generate-resolvers.ts | 5 ++--- .../order-calculator/order-calculator.ts | 2 +- packages/core/src/testing/order-test-utils.ts | 19 +++++++++++++++++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/core/src/api/config/generate-resolvers.ts b/packages/core/src/api/config/generate-resolvers.ts index 2552ae254f..0cb89df116 100644 --- a/packages/core/src/api/config/generate-resolvers.ts +++ b/packages/core/src/api/config/generate-resolvers.ts @@ -255,9 +255,8 @@ function generateCustomFieldRelationResolvers( } as any; } } - const allCustomFieldsAreNonPublic = customFields.every( - f => f.public === false || f.internal === true, - ); + const allCustomFieldsAreNonPublic = + customFields.length && customFields.every(f => f.public === false || f.internal === true); if (allCustomFieldsAreNonPublic) { // When an entity has only non-public custom fields, the GraphQL type used for the // customFields field is `JSON`. This type will simply return the full object, which diff --git a/packages/core/src/service/helpers/order-calculator/order-calculator.ts b/packages/core/src/service/helpers/order-calculator/order-calculator.ts index b0e153cc46..c2190bf35a 100644 --- a/packages/core/src/service/helpers/order-calculator/order-calculator.ts +++ b/packages/core/src/service/helpers/order-calculator/order-calculator.ts @@ -9,7 +9,7 @@ import { CacheKey } from '../../../common/constants'; import { InternalServerError } from '../../../common/error/errors'; import { idsAreEqual } from '../../../common/utils'; import { ConfigService } from '../../../config/config.service'; -import { OrderLine, TaxCategory, TaxRate } from '../../../entity'; +import { OrderLine, TaxRate } from '../../../entity'; import { Order } from '../../../entity/order/order.entity'; import { Promotion } from '../../../entity/promotion/promotion.entity'; import { Zone } from '../../../entity/zone/zone.entity'; diff --git a/packages/core/src/testing/order-test-utils.ts b/packages/core/src/testing/order-test-utils.ts index 3d3c38a5f5..6471c0ead5 100644 --- a/packages/core/src/testing/order-test-utils.ts +++ b/packages/core/src/testing/order-test-utils.ts @@ -76,7 +76,9 @@ export const taxRateDefaultStandard = new TaxRate({ value: 20, enabled: true, zone: zoneDefault, + zoneId: zoneDefault.id, category: taxCategoryStandard, + categoryId: taxCategoryStandard.id, }); export const taxRateDefaultReduced = new TaxRate({ id: 'taxRateDefaultReduced', @@ -84,7 +86,9 @@ export const taxRateDefaultReduced = new TaxRate({ value: 10, enabled: true, zone: zoneDefault, + zoneId: zoneDefault.id, category: taxCategoryReduced, + categoryId: taxCategoryReduced.id, }); export const taxRateDefaultZero = new TaxRate({ id: 'taxRateDefaultZero', @@ -92,7 +96,9 @@ export const taxRateDefaultZero = new TaxRate({ value: 0, enabled: true, zone: zoneDefault, + zoneId: zoneDefault.id, category: taxCategoryZero, + categoryId: taxCategoryZero.id, }); export const taxRateOtherStandard = new TaxRate({ id: 'taxRateOtherStandard', @@ -100,7 +106,9 @@ export const taxRateOtherStandard = new TaxRate({ value: 15, enabled: true, zone: zoneOther, + zoneId: zoneOther.id, category: taxCategoryStandard, + categoryId: taxCategoryStandard.id, }); export const taxRateOtherReduced = new TaxRate({ id: 'taxRateOtherReduced', @@ -108,7 +116,9 @@ export const taxRateOtherReduced = new TaxRate({ value: 5, enabled: true, zone: zoneOther, + zoneId: zoneOther.id, category: taxCategoryReduced, + categoryId: taxCategoryReduced.id, }); export class MockTaxRateService { @@ -124,14 +134,18 @@ export class MockTaxRateService { /* noop */ } - async getApplicableTaxRate(ctx: RequestContext, zone: Zone, taxCategory: TaxCategory): Promise { + async getApplicableTaxRate( + ctx: RequestContext, + zone: Zone | ID, + taxCategory: TaxCategory | ID, + ): Promise { const rate = this.activeTaxRates.find(r => r.test(zone, taxCategory)); return rate || taxRateDefaultStandard; } } export function createOrder( - orderConfig: Partial> & { + orderConfig: Partial> & { ctx: RequestContext; lines: Array<{ listPrice: number; @@ -145,6 +159,7 @@ export function createOrder( ({ listPrice, taxCategory, quantity }) => new OrderLine({ taxCategory, + taxCategoryId: taxCategory.id, quantity, orderPlacedQuantity: 0, listPrice, From 56787ee3f9c72922cac2c06497bb5d7001b59f1b Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Tue, 10 Sep 2024 09:42:17 +0200 Subject: [PATCH 22/25] chore(core): Remove logger from draft order e2e test suite --- packages/core/e2e/draft-order.e2e-spec.ts | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/packages/core/e2e/draft-order.e2e-spec.ts b/packages/core/e2e/draft-order.e2e-spec.ts index e9759d7ed7..cf5ce03989 100644 --- a/packages/core/e2e/draft-order.e2e-spec.ts +++ b/packages/core/e2e/draft-order.e2e-spec.ts @@ -1,7 +1,6 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import { LanguageCode } from '@vendure/common/lib/generated-types'; import { - DefaultLogger, DefaultOrderPlacedStrategy, mergeConfig, Order, @@ -15,7 +14,7 @@ import path from 'path'; import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; import { initialData } from '../../../e2e-common/e2e-initial-data'; -import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config'; +import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config'; import { singleStageRefundablePaymentMethod } from './fixtures/test-payment-methods'; import { ORDER_WITH_LINES_FRAGMENT } from './graphql/fragments'; @@ -24,14 +23,12 @@ import { AddManualPaymentDocument, AdminTransitionDocument, CanceledOrderFragment, - GetOrderDocument, GetOrderPlacedAtDocument, OrderWithLinesFragment, } from './graphql/generated-e2e-admin-types'; import { GetActiveCustomerOrdersQuery, TestOrderFragmentFragment, - TransitionToStateDocument, UpdatedOrderFragment, } from './graphql/generated-e2e-shop-types'; import { CREATE_PROMOTION, GET_CUSTOMER_LIST } from './graphql/shared-definitions'; @@ -53,7 +50,6 @@ class TestOrderPlacedStrategy extends DefaultOrderPlacedStrategy { describe('Draft Orders resolver', () => { const { server, adminClient, shopClient } = createTestEnvironment( mergeConfig(testConfig(), { - logger: new DefaultLogger(), paymentOptions: { paymentMethodHandlers: [singleStageRefundablePaymentMethod], }, @@ -125,9 +121,8 @@ describe('Draft Orders resolver', () => { }); it('create draft order', async () => { - const { createDraftOrder } = await adminClient.query( - CREATE_DRAFT_ORDER, - ); + const { createDraftOrder } = + await adminClient.query(CREATE_DRAFT_ORDER); expect(createDraftOrder.state).toBe('Draft'); expect(createDraftOrder.active).toBe(false); @@ -213,9 +208,8 @@ describe('Draft Orders resolver', () => { it('custom does not see draft orders in history', async () => { await shopClient.asUserWithCredentials(customers[0].emailAddress, 'test'); - const { activeCustomer } = await shopClient.query( - GET_ACTIVE_CUSTOMER_ORDERS, - ); + const { activeCustomer } = + await shopClient.query(GET_ACTIVE_CUSTOMER_ORDERS); expect(activeCustomer?.orders.totalItems).toBe(0); expect(activeCustomer?.orders.items.length).toBe(0); From 9fcf919f5f5782a7feca448c078d2cf6535d7257 Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Tue, 10 Sep 2024 09:56:39 +0200 Subject: [PATCH 23/25] chore(dev-server): Fix imports in load tests --- packages/dev-server/load-testing/init-load-test.ts | 5 ++++- packages/dev-server/load-testing/run-load-test.ts | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/dev-server/load-testing/init-load-test.ts b/packages/dev-server/load-testing/init-load-test.ts index 48f96b3fce..90946daabe 100644 --- a/packages/dev-server/load-testing/init-load-test.ts +++ b/packages/dev-server/load-testing/init-load-test.ts @@ -3,7 +3,7 @@ import { bootstrap, JobQueueService, Logger } from '@vendure/core'; import { populate } from '@vendure/core/cli/populate'; import { clearAllTables, populateCustomers, SimpleGraphQLClient } from '@vendure/testing'; -import stringify from 'csv-stringify'; +import { stringify } from 'csv-stringify'; import fs from 'fs'; import path from 'path'; @@ -100,6 +100,9 @@ async function isDatabasePopulated(databaseName: string): Promise { await client.connect(); try { const res = await client.query('SELECT COUNT(id) as prodCount FROM product'); + if (res.rows[0]?.prodcount < 1) { + return false; + } return true; } catch (e: any) { if (e.message === 'relation "product" does not exist') { diff --git a/packages/dev-server/load-testing/run-load-test.ts b/packages/dev-server/load-testing/run-load-test.ts index 4b062970a6..f928974022 100644 --- a/packages/dev-server/load-testing/run-load-test.ts +++ b/packages/dev-server/load-testing/run-load-test.ts @@ -2,7 +2,7 @@ import { INestApplication } from '@nestjs/common'; import { bootstrap, JobQueueService } from '@vendure/core'; import { spawn } from 'child_process'; -import stringify from 'csv-stringify'; +import { stringify } from 'csv-stringify'; import fs from 'fs'; import path from 'path'; From a28befb35fc06a1bf8d0992d0e5d1066f35bb41c Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Tue, 10 Sep 2024 09:57:30 +0200 Subject: [PATCH 24/25] chore(dev-server): Add return to bootstrap --- packages/dev-server/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dev-server/index.ts b/packages/dev-server/index.ts index 845fa81e90..93a9aae1e7 100644 --- a/packages/dev-server/index.ts +++ b/packages/dev-server/index.ts @@ -8,7 +8,7 @@ import { devConfig } from './dev-config'; bootstrap(devConfig) .then(app => { if (process.env.RUN_JOB_QUEUE === '1') { - app.get(JobQueueService).start(); + return app.get(JobQueueService).start(); } }) .catch(err => { From 589d54de0acc76bba717aff66ee64638e4106dbb Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Tue, 10 Sep 2024 10:02:29 +0200 Subject: [PATCH 25/25] chore: Publish v3.0.2 --- CHANGELOG.md | 19 +++ lerna.json | 2 +- package-lock.json | 112 +++++++++--------- packages/admin-ui-plugin/package.json | 8 +- packages/admin-ui/package.json | 4 +- .../src/lib/core/src/common/version.ts | 2 +- packages/asset-server-plugin/package.json | 6 +- packages/cli/package.json | 6 +- packages/common/package.json | 2 +- packages/core/package.json | 4 +- packages/create/package.json | 6 +- packages/dev-server/package.json | 18 +-- packages/elasticsearch-plugin/package.json | 6 +- packages/email-plugin/package.json | 6 +- packages/harden-plugin/package.json | 6 +- packages/job-queue-plugin/package.json | 6 +- packages/payments-plugin/package.json | 8 +- packages/sentry-plugin/package.json | 6 +- packages/stellate-plugin/package.json | 6 +- packages/testing/package.json | 6 +- packages/ui-devkit/package.json | 8 +- 21 files changed, 133 insertions(+), 114 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc070f3ae0..48e4c9d252 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +## 3.0.2 (2024-09-10) + + +#### Fixes + +* **admin-ui** Fix removing coupon code from draft order ([04340f1](https://github.com/vendure-ecommerce/vendure/commit/04340f1)), closes [#2969](https://github.com/vendure-ecommerce/vendure/issues/2969) +* **core** Fix search indexing issue when working with multiple channels (#3041) ([75ed6e1](https://github.com/vendure-ecommerce/vendure/commit/75ed6e1)), closes [#3041](https://github.com/vendure-ecommerce/vendure/issues/3041) [#3012](https://github.com/vendure-ecommerce/vendure/issues/3012) +* **core** Prevent exposure of private custom fields via JSON type ([042abdb](https://github.com/vendure-ecommerce/vendure/commit/042abdb)), closes [#3049](https://github.com/vendure-ecommerce/vendure/issues/3049) +* **elasticsearch-plugin** Fix search multichannel indexing issue ([9d6f9cf](https://github.com/vendure-ecommerce/vendure/commit/9d6f9cf)), closes [#3012](https://github.com/vendure-ecommerce/vendure/issues/3012) + +#### Perf + +* **core** Fix slow `order` query for postgres v16 ([1baa8e7](https://github.com/vendure-ecommerce/vendure/commit/1baa8e7)), closes [#3037](https://github.com/vendure-ecommerce/vendure/issues/3037) +* **core** Omit ID encode/decode step if default EntityIdStrategy used ([ad30b55](https://github.com/vendure-ecommerce/vendure/commit/ad30b55)) +* **core** Optimizations to the addItemToOrder path ([70ad853](https://github.com/vendure-ecommerce/vendure/commit/70ad853)) +* **core** Optimize order operations ([e3d6c21](https://github.com/vendure-ecommerce/vendure/commit/e3d6c21)) +* **core** Optimize resolution of featuredAsset fields ([d7bd446](https://github.com/vendure-ecommerce/vendure/commit/d7bd446)) +* **core** Optimize setting active order on session ([c591432](https://github.com/vendure-ecommerce/vendure/commit/c591432)) + ## 3.0.1 (2024-08-21) diff --git a/lerna.json b/lerna.json index b756f71a01..7a249402d9 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "packages": ["packages/*"], - "version": "3.0.1", + "version": "3.0.2", "npmClient": "npm", "command": { "version": { diff --git a/package-lock.json b/package-lock.json index eba9a08fd0..1323866c5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31919,7 +31919,7 @@ }, "packages/admin-ui": { "name": "@vendure/admin-ui", - "version": "3.0.1", + "version": "3.0.2", "license": "GPL-3.0-or-later", "dependencies": { "@angular/animations": "^17.2.4", @@ -31942,7 +31942,7 @@ "@ng-select/ng-select": "^12.0.7", "@ngx-translate/core": "^15.0.0", "@ngx-translate/http-loader": "^8.0.0", - "@vendure/common": "^3.0.1", + "@vendure/common": "^3.0.2", "@webcomponents/custom-elements": "^1.6.0", "apollo-angular": "^6.0.0", "apollo-upload-client": "^18.0.1", @@ -32013,7 +32013,7 @@ }, "packages/admin-ui-plugin": { "name": "@vendure/admin-ui-plugin", - "version": "3.0.1", + "version": "3.0.2", "license": "GPL-3.0-or-later", "dependencies": { "date-fns": "^2.30.0", @@ -32022,9 +32022,9 @@ "devDependencies": { "@types/express": "^4.17.21", "@types/fs-extra": "^11.0.4", - "@vendure/admin-ui": "^3.0.1", - "@vendure/common": "^3.0.1", - "@vendure/core": "^3.0.1", + "@vendure/admin-ui": "^3.0.2", + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2", "express": "^4.18.3", "rimraf": "^5.0.5", "typescript": "5.4.2" @@ -32055,7 +32055,7 @@ }, "packages/asset-server-plugin": { "name": "@vendure/asset-server-plugin", - "version": "3.0.1", + "version": "3.0.2", "license": "GPL-3.0-or-later", "dependencies": { "file-type": "^19.0.0", @@ -32068,8 +32068,8 @@ "@types/express": "^4.17.21", "@types/fs-extra": "^11.0.4", "@types/node-fetch": "^2.6.11", - "@vendure/common": "^3.0.1", - "@vendure/core": "^3.0.1", + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2", "express": "^4.18.3", "node-fetch": "^2.7.0", "rimraf": "^5.0.5", @@ -32081,11 +32081,11 @@ }, "packages/cli": { "name": "@vendure/cli", - "version": "3.0.1", + "version": "3.0.2", "license": "GPL-3.0-or-later", "dependencies": { "@clack/prompts": "^0.7.0", - "@vendure/common": "^3.0.1", + "@vendure/common": "^3.0.2", "change-case": "^4.1.2", "commander": "^11.0.0", "dotenv": "^16.4.5", @@ -32099,7 +32099,7 @@ "vendure": "dist/cli.js" }, "devDependencies": { - "@vendure/core": "^3.0.1", + "@vendure/core": "^3.0.2", "typescript": "5.3.3" }, "funding": { @@ -32136,7 +32136,7 @@ }, "packages/common": { "name": "@vendure/common", - "version": "3.0.1", + "version": "3.0.2", "license": "GPL-3.0-or-later", "devDependencies": { "rimraf": "^5.0.5", @@ -32148,7 +32148,7 @@ }, "packages/core": { "name": "@vendure/core", - "version": "3.0.1", + "version": "3.0.2", "license": "GPL-3.0-or-later", "dependencies": { "@apollo/server": "^4.10.4", @@ -32162,7 +32162,7 @@ "@nestjs/testing": "~10.3.10", "@nestjs/typeorm": "~10.0.2", "@types/fs-extra": "^9.0.1", - "@vendure/common": "^3.0.1", + "@vendure/common": "^3.0.2", "bcrypt": "^5.1.1", "body-parser": "^1.20.2", "cookie-session": "^2.1.0", @@ -32298,11 +32298,11 @@ }, "packages/create": { "name": "@vendure/create", - "version": "3.0.1", + "version": "3.0.2", "license": "GPL-3.0-or-later", "dependencies": { "@clack/prompts": "^0.7.0", - "@vendure/common": "^3.0.1", + "@vendure/common": "^3.0.2", "commander": "^11.0.0", "cross-spawn": "^7.0.3", "fs-extra": "^11.2.0", @@ -32319,7 +32319,7 @@ "@types/fs-extra": "^11.0.4", "@types/handlebars": "^4.1.0", "@types/semver": "^7.5.8", - "@vendure/core": "^3.0.1", + "@vendure/core": "^3.0.2", "rimraf": "^5.0.5", "ts-node": "^10.9.2", "typescript": "5.3.3" @@ -32336,21 +32336,21 @@ } }, "packages/dev-server": { - "version": "3.0.1", + "version": "3.0.2", "license": "GPL-3.0-or-later", "dependencies": { "@nestjs/axios": "^3.0.2", - "@vendure/admin-ui-plugin": "^3.0.1", - "@vendure/asset-server-plugin": "^3.0.1", - "@vendure/common": "^3.0.1", - "@vendure/core": "^3.0.1", - "@vendure/elasticsearch-plugin": "^3.0.1", - "@vendure/email-plugin": "^3.0.1", + "@vendure/admin-ui-plugin": "^3.0.2", + "@vendure/asset-server-plugin": "^3.0.2", + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2", + "@vendure/elasticsearch-plugin": "^3.0.2", + "@vendure/email-plugin": "^3.0.2", "typescript": "5.3.3" }, "devDependencies": { - "@vendure/testing": "^3.0.1", - "@vendure/ui-devkit": "^3.0.1", + "@vendure/testing": "^3.0.2", + "@vendure/ui-devkit": "^3.0.2", "commander": "^12.0.0", "concurrently": "^8.2.2", "csv-stringify": "^6.4.6", @@ -32368,7 +32368,7 @@ }, "packages/elasticsearch-plugin": { "name": "@vendure/elasticsearch-plugin", - "version": "3.0.1", + "version": "3.0.2", "license": "GPL-3.0-or-later", "dependencies": { "@elastic/elasticsearch": "~7.9.1", @@ -32376,8 +32376,8 @@ "fast-deep-equal": "^3.1.3" }, "devDependencies": { - "@vendure/common": "^3.0.1", - "@vendure/core": "^3.0.1", + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2", "rimraf": "^5.0.5", "typescript": "5.3.3" }, @@ -32387,7 +32387,7 @@ }, "packages/email-plugin": { "name": "@vendure/email-plugin", - "version": "3.0.1", + "version": "3.0.2", "license": "GPL-3.0-or-later", "dependencies": { "@types/nodemailer": "^6.4.9", @@ -32403,8 +32403,8 @@ "@types/express": "^4.17.21", "@types/fs-extra": "^11.0.4", "@types/mjml": "^4.7.4", - "@vendure/common": "^3.0.1", - "@vendure/core": "^3.0.1", + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2", "rimraf": "^5.0.5", "typescript": "5.3.3" }, @@ -32414,14 +32414,14 @@ }, "packages/harden-plugin": { "name": "@vendure/harden-plugin", - "version": "3.0.1", + "version": "3.0.2", "license": "GPL-3.0-or-later", "dependencies": { "graphql-query-complexity": "^0.12.0" }, "devDependencies": { - "@vendure/common": "^3.0.1", - "@vendure/core": "^3.0.1" + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2" }, "funding": { "url": "https://github.com/sponsors/michaelbromley" @@ -32429,12 +32429,12 @@ }, "packages/job-queue-plugin": { "name": "@vendure/job-queue-plugin", - "version": "3.0.1", + "version": "3.0.2", "license": "GPL-3.0-or-later", "devDependencies": { "@google-cloud/pubsub": "^2.8.0", - "@vendure/common": "^3.0.1", - "@vendure/core": "^3.0.1", + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2", "bullmq": "^5.4.2", "ioredis": "^5.3.2", "rimraf": "^5.0.5", @@ -32446,7 +32446,7 @@ }, "packages/payments-plugin": { "name": "@vendure/payments-plugin", - "version": "3.0.1", + "version": "3.0.2", "license": "GPL-3.0-or-later", "dependencies": { "currency.js": "2.0.4" @@ -32455,9 +32455,9 @@ "@mollie/api-client": "^3.7.0", "@types/braintree": "^3.3.11", "@types/localtunnel": "2.0.4", - "@vendure/common": "^3.0.1", - "@vendure/core": "^3.0.1", - "@vendure/testing": "^3.0.1", + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2", + "@vendure/testing": "^3.0.2", "braintree": "^3.22.0", "localtunnel": "2.0.2", "nock": "^13.1.4", @@ -32513,12 +32513,12 @@ }, "packages/sentry-plugin": { "name": "@vendure/sentry-plugin", - "version": "3.0.1", + "version": "3.0.2", "license": "GPL-3.0-or-later", "devDependencies": { "@sentry/node": "^7.106.1", - "@vendure/common": "^3.0.1", - "@vendure/core": "^3.0.1" + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2" }, "funding": { "url": "https://github.com/sponsors/michaelbromley" @@ -32529,14 +32529,14 @@ }, "packages/stellate-plugin": { "name": "@vendure/stellate-plugin", - "version": "3.0.1", + "version": "3.0.2", "license": "GPL-3.0-or-later", "dependencies": { "node-fetch": "^2.7.0" }, "devDependencies": { - "@vendure/common": "^3.0.1", - "@vendure/core": "^3.0.1" + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2" }, "funding": { "url": "https://github.com/sponsors/michaelbromley" @@ -32544,11 +32544,11 @@ }, "packages/testing": { "name": "@vendure/testing", - "version": "3.0.1", + "version": "3.0.2", "license": "GPL-3.0-or-later", "dependencies": { "@graphql-typed-document-node/core": "^3.2.0", - "@vendure/common": "^3.0.1", + "@vendure/common": "^3.0.2", "faker": "^4.1.0", "form-data": "^4.0.0", "graphql": "~16.9.0", @@ -32561,7 +32561,7 @@ "@types/mysql": "^2.15.26", "@types/node-fetch": "^2.6.4", "@types/pg": "^8.11.2", - "@vendure/core": "^3.0.1", + "@vendure/core": "^3.0.2", "mysql": "^2.18.1", "pg": "^8.11.3", "rimraf": "^5.0.5", @@ -32577,15 +32577,15 @@ }, "packages/ui-devkit": { "name": "@vendure/ui-devkit", - "version": "3.0.1", + "version": "3.0.2", "license": "GPL-3.0-or-later", "dependencies": { "@angular-devkit/build-angular": "^17.2.3", "@angular/cli": "^17.2.3", "@angular/compiler": "^17.2.4", "@angular/compiler-cli": "^17.2.4", - "@vendure/admin-ui": "^3.0.1", - "@vendure/common": "^3.0.1", + "@vendure/admin-ui": "^3.0.2", + "@vendure/common": "^3.0.2", "chalk": "^4.1.0", "chokidar": "^3.6.0", "fs-extra": "^11.2.0", @@ -32596,7 +32596,7 @@ "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", "@types/fs-extra": "^11.0.4", - "@vendure/core": "^3.0.1", + "@vendure/core": "^3.0.2", "react": "^18.2.0", "react-dom": "^18.2.0", "rimraf": "^5.0.5", diff --git a/packages/admin-ui-plugin/package.json b/packages/admin-ui-plugin/package.json index fa5db3cbce..332d273d86 100644 --- a/packages/admin-ui-plugin/package.json +++ b/packages/admin-ui-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@vendure/admin-ui-plugin", - "version": "3.0.1", + "version": "3.0.2", "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.0.1", - "@vendure/common": "^3.0.1", - "@vendure/core": "^3.0.1", + "@vendure/admin-ui": "^3.0.2", + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2", "express": "^4.18.3", "rimraf": "^5.0.5", "typescript": "5.4.2" diff --git a/packages/admin-ui/package.json b/packages/admin-ui/package.json index 9081b6b425..077fb5f439 100644 --- a/packages/admin-ui/package.json +++ b/packages/admin-ui/package.json @@ -1,6 +1,6 @@ { "name": "@vendure/admin-ui", - "version": "3.0.1", + "version": "3.0.2", "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.0.1", + "@vendure/common": "^3.0.2", "@webcomponents/custom-elements": "^1.6.0", "apollo-angular": "^6.0.0", "apollo-upload-client": "^18.0.1", diff --git a/packages/admin-ui/src/lib/core/src/common/version.ts b/packages/admin-ui/src/lib/core/src/common/version.ts index b663b0b764..8fcc51e575 100644 --- a/packages/admin-ui/src/lib/core/src/common/version.ts +++ b/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.0.1'; +export const ADMIN_UI_VERSION = '3.0.2'; diff --git a/packages/asset-server-plugin/package.json b/packages/asset-server-plugin/package.json index 605166bf8b..17717fd47e 100644 --- a/packages/asset-server-plugin/package.json +++ b/packages/asset-server-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@vendure/asset-server-plugin", - "version": "3.0.1", + "version": "3.0.2", "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.0.1", - "@vendure/core": "^3.0.1", + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2", "express": "^4.18.3", "node-fetch": "^2.7.0", "rimraf": "^5.0.5", diff --git a/packages/cli/package.json b/packages/cli/package.json index f447f8d0e3..d95772d4ce 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@vendure/cli", - "version": "3.0.1", + "version": "3.0.2", "description": "A modern, headless ecommerce framework", "repository": { "type": "git", @@ -35,7 +35,7 @@ ], "dependencies": { "@clack/prompts": "^0.7.0", - "@vendure/common": "^3.0.1", + "@vendure/common": "^3.0.2", "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.0.1", + "@vendure/core": "^3.0.2", "typescript": "5.3.3" } } diff --git a/packages/common/package.json b/packages/common/package.json index 33077d2427..436f27f2ae 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -1,6 +1,6 @@ { "name": "@vendure/common", - "version": "3.0.1", + "version": "3.0.2", "main": "index.js", "license": "GPL-3.0-or-later", "scripts": { diff --git a/packages/core/package.json b/packages/core/package.json index f94c7de5f0..0ee66fffa1 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@vendure/core", - "version": "3.0.1", + "version": "3.0.2", "description": "A modern, headless ecommerce framework", "repository": { "type": "git", @@ -51,7 +51,7 @@ "@nestjs/testing": "~10.3.10", "@nestjs/typeorm": "~10.0.2", "@types/fs-extra": "^9.0.1", - "@vendure/common": "^3.0.1", + "@vendure/common": "^3.0.2", "bcrypt": "^5.1.1", "body-parser": "^1.20.2", "cookie-session": "^2.1.0", diff --git a/packages/create/package.json b/packages/create/package.json index 3327b5160b..f4c9d6eb5a 100644 --- a/packages/create/package.json +++ b/packages/create/package.json @@ -1,6 +1,6 @@ { "name": "@vendure/create", - "version": "3.0.1", + "version": "3.0.2", "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.0.1", + "@vendure/core": "^3.0.2", "rimraf": "^5.0.5", "ts-node": "^10.9.2", "typescript": "5.3.3" }, "dependencies": { "@clack/prompts": "^0.7.0", - "@vendure/common": "^3.0.1", + "@vendure/common": "^3.0.2", "commander": "^11.0.0", "cross-spawn": "^7.0.3", "fs-extra": "^11.2.0", diff --git a/packages/dev-server/package.json b/packages/dev-server/package.json index 834625bcc4..79c9f956cf 100644 --- a/packages/dev-server/package.json +++ b/packages/dev-server/package.json @@ -1,6 +1,6 @@ { "name": "dev-server", - "version": "3.0.1", + "version": "3.0.2", "main": "index.js", "license": "GPL-3.0-or-later", "private": true, @@ -15,17 +15,17 @@ }, "dependencies": { "@nestjs/axios": "^3.0.2", - "@vendure/admin-ui-plugin": "^3.0.1", - "@vendure/asset-server-plugin": "^3.0.1", - "@vendure/common": "^3.0.1", - "@vendure/core": "^3.0.1", - "@vendure/elasticsearch-plugin": "^3.0.1", - "@vendure/email-plugin": "^3.0.1", + "@vendure/admin-ui-plugin": "^3.0.2", + "@vendure/asset-server-plugin": "^3.0.2", + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2", + "@vendure/elasticsearch-plugin": "^3.0.2", + "@vendure/email-plugin": "^3.0.2", "typescript": "5.3.3" }, "devDependencies": { - "@vendure/testing": "^3.0.1", - "@vendure/ui-devkit": "^3.0.1", + "@vendure/testing": "^3.0.2", + "@vendure/ui-devkit": "^3.0.2", "commander": "^12.0.0", "concurrently": "^8.2.2", "csv-stringify": "^6.4.6", diff --git a/packages/elasticsearch-plugin/package.json b/packages/elasticsearch-plugin/package.json index 4e58598334..5a0c492fce 100644 --- a/packages/elasticsearch-plugin/package.json +++ b/packages/elasticsearch-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@vendure/elasticsearch-plugin", - "version": "3.0.1", + "version": "3.0.2", "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.0.1", - "@vendure/core": "^3.0.1", + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2", "rimraf": "^5.0.5", "typescript": "5.3.3" } diff --git a/packages/email-plugin/package.json b/packages/email-plugin/package.json index 9a3363b1ca..782dcfdf8f 100644 --- a/packages/email-plugin/package.json +++ b/packages/email-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@vendure/email-plugin", - "version": "3.0.1", + "version": "3.0.2", "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.0.1", - "@vendure/core": "^3.0.1", + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2", "rimraf": "^5.0.5", "typescript": "5.3.3" } diff --git a/packages/harden-plugin/package.json b/packages/harden-plugin/package.json index 306c51ea09..635f0a92c6 100644 --- a/packages/harden-plugin/package.json +++ b/packages/harden-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@vendure/harden-plugin", - "version": "3.0.1", + "version": "3.0.2", "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.0.1", - "@vendure/core": "^3.0.1" + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2" } } diff --git a/packages/job-queue-plugin/package.json b/packages/job-queue-plugin/package.json index e4d95a0809..593580c38d 100644 --- a/packages/job-queue-plugin/package.json +++ b/packages/job-queue-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@vendure/job-queue-plugin", - "version": "3.0.1", + "version": "3.0.2", "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.0.1", - "@vendure/core": "^3.0.1", + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2", "bullmq": "^5.4.2", "ioredis": "^5.3.2", "rimraf": "^5.0.5", diff --git a/packages/payments-plugin/package.json b/packages/payments-plugin/package.json index dee37aa7b2..edaad30e5a 100644 --- a/packages/payments-plugin/package.json +++ b/packages/payments-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@vendure/payments-plugin", - "version": "3.0.1", + "version": "3.0.2", "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.0.1", - "@vendure/core": "^3.0.1", - "@vendure/testing": "^3.0.1", + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2", + "@vendure/testing": "^3.0.2", "braintree": "^3.22.0", "localtunnel": "2.0.2", "nock": "^13.1.4", diff --git a/packages/sentry-plugin/package.json b/packages/sentry-plugin/package.json index 6ccfffebda..2ba0057616 100644 --- a/packages/sentry-plugin/package.json +++ b/packages/sentry-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@vendure/sentry-plugin", - "version": "3.0.1", + "version": "3.0.2", "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.0.1", - "@vendure/core": "^3.0.1" + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2" } } diff --git a/packages/stellate-plugin/package.json b/packages/stellate-plugin/package.json index 0cdc223914..87d0013496 100644 --- a/packages/stellate-plugin/package.json +++ b/packages/stellate-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@vendure/stellate-plugin", - "version": "3.0.1", + "version": "3.0.2", "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.0.1", - "@vendure/core": "^3.0.1" + "@vendure/common": "^3.0.2", + "@vendure/core": "^3.0.2" } } diff --git a/packages/testing/package.json b/packages/testing/package.json index 6b5180d066..178ad9f34f 100644 --- a/packages/testing/package.json +++ b/packages/testing/package.json @@ -1,6 +1,6 @@ { "name": "@vendure/testing", - "version": "3.0.1", + "version": "3.0.2", "description": "End-to-end testing tools for Vendure projects", "keywords": [ "vendure", @@ -37,7 +37,7 @@ }, "dependencies": { "@graphql-typed-document-node/core": "^3.2.0", - "@vendure/common": "^3.0.1", + "@vendure/common": "^3.0.2", "faker": "^4.1.0", "form-data": "^4.0.0", "graphql": "~16.9.0", @@ -50,7 +50,7 @@ "@types/mysql": "^2.15.26", "@types/node-fetch": "^2.6.4", "@types/pg": "^8.11.2", - "@vendure/core": "^3.0.1", + "@vendure/core": "^3.0.2", "mysql": "^2.18.1", "pg": "^8.11.3", "rimraf": "^5.0.5", diff --git a/packages/ui-devkit/package.json b/packages/ui-devkit/package.json index fa8ff42399..a2a13beedd 100644 --- a/packages/ui-devkit/package.json +++ b/packages/ui-devkit/package.json @@ -1,6 +1,6 @@ { "name": "@vendure/ui-devkit", - "version": "3.0.1", + "version": "3.0.2", "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.0.1", - "@vendure/common": "^3.0.1", + "@vendure/admin-ui": "^3.0.2", + "@vendure/common": "^3.0.2", "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.0.1", + "@vendure/core": "^3.0.2", "react": "^18.2.0", "react-dom": "^18.2.0", "rimraf": "^5.0.5",