Browse Source

feat(core): Allow unsetting of shipping and billing addresses (#3185)

Oliver Streißelberger 1 year ago
parent
commit
e0f2118d00
56 changed files with 1872 additions and 1114 deletions
  1. 21 0
      .vscode/launch.json
  2. 4 0
      README.md
  3. 41 41
      docs/docs/reference/admin-ui-api/bulk-actions/bulk-action.md
  4. 9 9
      docs/docs/reference/admin-ui-api/list-detail-views/detail-component-with-resolver.md
  5. 7 7
      docs/docs/reference/admin-ui-api/list-detail-views/typed-base-list-component.md
  6. 7 7
      docs/docs/reference/admin-ui-api/react-components/form-field.md
  7. 12 12
      docs/docs/reference/core-plugins/asset-server-plugin/asset-server-options.md
  8. 1 2
      docs/docs/reference/core-plugins/asset-server-plugin/s3asset-storage-strategy.md
  9. 114 114
      docs/docs/reference/core-plugins/elasticsearch-plugin/elasticsearch-options.md
  10. 23 23
      docs/docs/reference/core-plugins/harden-plugin/harden-plugin-options.md
  11. 116 116
      docs/docs/reference/core-plugins/payments-plugin/mollie-plugin.md
  12. 165 165
      docs/docs/reference/core-plugins/payments-plugin/stripe-plugin.md
  13. 9 9
      docs/docs/reference/core-plugins/stellate-plugin/purge-rule.md
  14. 1 1
      docs/docs/reference/graphql-api/admin/object-types.md
  15. 28 4
      docs/docs/reference/graphql-api/shop/mutations.md
  16. 9 9
      docs/docs/reference/typescript-api/configurable-operation-def/default-form-config-hash.md
  17. 13 13
      docs/docs/reference/typescript-api/configuration/entity-duplicator.md
  18. 1 2
      docs/docs/reference/typescript-api/custom-fields/index.md
  19. 1 2
      docs/docs/reference/typescript-api/data-access/calculated.md
  20. 48 48
      docs/docs/reference/typescript-api/data-access/transactional-connection.md
  21. 30 30
      docs/docs/reference/typescript-api/entities/promotion.md
  22. 44 44
      docs/docs/reference/typescript-api/events/event-types.md
  23. 14 14
      docs/docs/reference/typescript-api/fulfillment/fulfillment-process.md
  24. 5 5
      docs/docs/reference/typescript-api/import-export/default-asset-import-strategy.md
  25. 33 33
      docs/docs/reference/typescript-api/import-export/import-parser.md
  26. 1 2
      docs/docs/reference/typescript-api/job-queue/types.md
  27. 25 25
      docs/docs/reference/typescript-api/orders/guest-checkout-strategy.md
  28. 1 2
      docs/docs/reference/typescript-api/orders/order-item-price-calculation-strategy.md
  29. 13 13
      docs/docs/reference/typescript-api/request/request-context-service.md
  30. 11 11
      docs/docs/reference/typescript-api/service-helpers/slug-validator.md
  31. 25 25
      docs/docs/reference/typescript-api/services/customer-service.md
  32. 11 11
      docs/docs/reference/typescript-api/services/fulfillment-service.md
  33. 72 60
      docs/docs/reference/typescript-api/services/order-service.md
  34. 5 5
      docs/docs/reference/typescript-api/services/payment-method-service.md
  35. 21 21
      docs/docs/reference/typescript-api/services/user-service.md
  36. 1 1
      packages/admin-ui/src/lib/core/src/common/generated-types.ts
  37. 1 1
      packages/asset-server-plugin/e2e/graphql/generated-e2e-asset-server-plugin-types.ts
  38. 8 4
      packages/common/src/generated-shop-types.ts
  39. 1 1
      packages/common/src/generated-types.ts
  40. 50 0
      packages/core/e2e/active-order-strategy.e2e-spec.ts
  41. 80 1
      packages/core/e2e/graphql/generated-e2e-admin-types.ts
  42. 477 106
      packages/core/e2e/graphql/generated-e2e-shop-types.ts
  43. 58 25
      packages/core/e2e/graphql/shop-definitions.ts
  44. 108 39
      packages/core/e2e/shop-order.e2e-spec.ts
  45. 2 0
      packages/core/src/api/config/generate-active-order-types.ts
  46. 38 0
      packages/core/src/api/resolvers/shop/shop-order.resolver.ts
  47. 30 13
      packages/core/src/api/schema/shop-api/shop.api.graphql
  48. 48 0
      packages/core/src/service/services/order.service.ts
  49. 1 16
      packages/dev-server/dev-config.ts
  50. 10 12
      packages/dev-server/tsconfig.json
  51. 1 1
      packages/elasticsearch-plugin/e2e/graphql/generated-e2e-elasticsearch-plugin-types.ts
  52. 1 1
      packages/payments-plugin/e2e/graphql/generated-admin-types.ts
  53. 8 4
      packages/payments-plugin/e2e/graphql/generated-shop-types.ts
  54. 8 4
      packages/payments-plugin/src/mollie/graphql/generated-shop-types.ts
  55. 0 0
      schema-admin.json
  56. 0 0
      schema-shop.json

+ 21 - 0
.vscode/launch.json

@@ -0,0 +1,21 @@
+{
+    // Use IntelliSense to learn about possible attributes.
+    // Hover to view descriptions of existing attributes.
+    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "type": "node",
+            "request": "launch",
+            "name": "Debug Dev Server",
+            "program": "${workspaceFolder}/packages/dev-server/index.ts",
+            "outFiles": ["${workspaceFolder}/**/*.js"],
+            "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/ts-node",
+            "runtimeArgs": ["--transpile-only"],
+            "skipFiles": ["<node_internals>/**", "node_modules/**"],
+            "cwd": "${workspaceRoot}",
+            "resolveSourceMapLocations": ["${workspaceFolder}/**", "!**/node_modules/**"],
+            "console": "integratedTerminal"
+        }
+    ]
+}

+ 4 - 0
README.md

@@ -142,6 +142,10 @@ DB=sqlite npm run dev
 
 3. The dev-server will now have your local changes from the changed package.
 
+### Interactive debugging
+
+To debug the dev server with VS Code use the include [launch.json](/.vscode/launch.json) configuration.
+
 ### Code generation
 
 [graphql-code-generator](https://github.com/dotansimha/graphql-code-generator) is used to automatically create TypeScript interfaces for all GraphQL server operations and admin ui queries. These generated interfaces are used in both the admin ui and the server.

+ 41 - 41
docs/docs/reference/admin-ui-api/bulk-actions/bulk-action.md

@@ -13,16 +13,16 @@ import MemberDescription from '@site/src/components/MemberDescription';
 
 <GenerationInfo sourceFile="packages/admin-ui/src/lib/core/src/providers/bulk-action-registry/bulk-action-types.ts" sourceLine="99" packageName="@vendure/admin-ui" since="1.8.0" />
 
-Configures a bulk action which can be performed on all selected items in a list view.
-
+Configures a bulk action which can be performed on all selected items in a list view.
+
 For a full example, see the <a href='/reference/admin-ui-api/bulk-actions/register-bulk-action#registerbulkaction'>registerBulkAction</a> docs.
 
 ```ts title="Signature"
 interface BulkAction<ItemType = any, ComponentType = any> {
     location: BulkActionLocationId;
     label: string;
-    getTranslationVars?: (
-        context: BulkActionFunctionContext<ItemType, ComponentType>,
+    getTranslationVars?: (
+        context: BulkActionFunctionContext<ItemType, ComponentType>,
     ) => Record<string, string | number> | Promise<Record<string, string | number>>;
     icon?: string;
     iconClass?: string;
@@ -46,26 +46,26 @@ interface BulkAction<ItemType = any, ComponentType = any> {
 
 ### getTranslationVars
 
-<MemberInfo kind="property" type={`(
         context: <a href='/reference/admin-ui-api/bulk-actions/bulk-action#bulkactionfunctioncontext'>BulkActionFunctionContext</a>&#60;ItemType, ComponentType&#62;,
     ) =&#62; Record&#60;string, string | number&#62; | Promise&#60;Record&#60;string, string | number&#62;&#62;`}   />
+<MemberInfo kind="property" type={`(         context: <a href='/reference/admin-ui-api/bulk-actions/bulk-action#bulkactionfunctioncontext'>BulkActionFunctionContext</a>&#60;ItemType, ComponentType&#62;,     ) =&#62; Record&#60;string, string | number&#62; | Promise&#60;Record&#60;string, string | number&#62;&#62;`}   />
 
-An optional function that should resolve to a map of translation variables which can be
+An optional function that should resolve to a map of translation variables which can be
 used when translating the `label` string.
 ### icon
 
 <MemberInfo kind="property" type={`string`}   />
 
-A valid [Clarity Icons](https://core.clarity.design/foundation/icons/shapes/) icon shape, e.g.
+A valid [Clarity Icons](https://core.clarity.design/foundation/icons/shapes/) icon shape, e.g.
 "cog", "user", "info-standard".
 ### iconClass
 
 <MemberInfo kind="property" type={`string`}   />
 
-A class to be added to the icon element. Examples:
-
-- is-success
-- is-danger
-- is-warning
-- is-info
+A class to be added to the icon element. Examples:
+
+- is-success
+- is-danger
+- is-warning
+- is-info
 - is-highlight
 ### onClick
 
@@ -76,10 +76,10 @@ Defines the logic that executes when the bulk action button is clicked.
 
 <MemberInfo kind="property" type={`(context: <a href='/reference/admin-ui-api/bulk-actions/bulk-action#bulkactionfunctioncontext'>BulkActionFunctionContext</a>&#60;ItemType, ComponentType&#62;) =&#62; boolean | Promise&#60;boolean&#62;`}   />
 
-A function that determines whether this bulk action item should be displayed in the menu.
-If not defined, the item will always be displayed.
-
-This function will be invoked each time the selection is changed, so try to avoid expensive code
+A function that determines whether this bulk action item should be displayed in the menu.
+If not defined, the item will always be displayed.
+
+This function will be invoked each time the selection is changed, so try to avoid expensive code
 running here.
 
 *Example*
@@ -130,25 +130,25 @@ registerBulkAction({
 A valid location of a list view that supports the bulk actions API.
 
 ```ts title="Signature"
-type BulkActionLocationId = | 'product-list'
-    | 'facet-list'
-    | 'collection-list'
-    | 'customer-list'
-    | 'customer-group-list'
-    | 'customer-group-members-list'
-    | 'customer-group-members-picker-list'
-    | 'promotion-list'
-    | 'seller-list'
-    | 'channel-list'
-    | 'administrator-list'
-    | 'role-list'
-    | 'shipping-method-list'
-    | 'stock-location-list'
-    | 'payment-method-list'
-    | 'tax-category-list'
-    | 'tax-rate-list'
-    | 'zone-list'
-    | 'zone-members-list'
+type BulkActionLocationId = | 'product-list'
+    | 'facet-list'
+    | 'collection-list'
+    | 'customer-list'
+    | 'customer-group-list'
+    | 'customer-group-members-list'
+    | 'customer-group-members-picker-list'
+    | 'promotion-list'
+    | 'seller-list'
+    | 'channel-list'
+    | 'administrator-list'
+    | 'role-list'
+    | 'shipping-method-list'
+    | 'stock-location-list'
+    | 'payment-method-list'
+    | 'tax-category-list'
+    | 'tax-rate-list'
+    | 'zone-list'
+    | 'zone-members-list'
     | string
 ```
 
@@ -157,7 +157,7 @@ type BulkActionLocationId = | 'product-list'
 
 <GenerationInfo sourceFile="packages/admin-ui/src/lib/core/src/providers/bulk-action-registry/bulk-action-types.ts" sourceLine="43" packageName="@vendure/admin-ui" since="1.8.0" />
 
-This is the argument which gets passed to the `getTranslationVars` and `isVisible` functions
+This is the argument which gets passed to the `getTranslationVars` and `isVisible` functions
 of the BulkAction definition.
 
 ```ts title="Signature"
@@ -180,15 +180,15 @@ An array of the selected items from the list.
 
 <MemberInfo kind="property" type={`ComponentType`}   />
 
-The component instance that is hosting the list view. For instance,
-`ProductListComponent`. This can be used to call methods on the instance,
-e.g. calling `hostComponent.refresh()` to force a list refresh after
+The component instance that is hosting the list view. For instance,
+`ProductListComponent`. This can be used to call methods on the instance,
+e.g. calling `hostComponent.refresh()` to force a list refresh after
 deleting the selected items.
 ### injector
 
 <MemberInfo kind="property" type={`<a href='/reference/typescript-api/common/injector#injector'>Injector</a>`}   />
 
-The Angular [Injector](https://angular.io/api/core/Injector) which can be used
+The Angular [Injector](https://angular.io/api/core/Injector) which can be used
 to get service instances which might be needed in the click handler.
 ### route
 

+ 9 - 9
docs/docs/reference/admin-ui-api/list-detail-views/detail-component-with-resolver.md

@@ -13,8 +13,8 @@ import MemberDescription from '@site/src/components/MemberDescription';
 
 <GenerationInfo sourceFile="packages/admin-ui/src/lib/core/src/common/base-detail.component.ts" sourceLine="256" packageName="@vendure/admin-ui" />
 
-A helper function for creating tabs that point to a <a href='/reference/admin-ui-api/list-detail-views/typed-base-detail-component#typedbasedetailcomponent'>TypedBaseDetailComponent</a>. This takes
-care of the route resolver parts so that the detail component automatically has access to the
+A helper function for creating tabs that point to a <a href='/reference/admin-ui-api/list-detail-views/typed-base-detail-component#typedbasedetailcomponent'>TypedBaseDetailComponent</a>. This takes
+care of the route resolver parts so that the detail component automatically has access to the
 correct resolved detail data.
 
 *Example*
@@ -40,17 +40,17 @@ export class ProductSpecsUiExtensionModule {}
 ```
 
 ```ts title="Signature"
-function detailComponentWithResolver<T extends TypedDocumentNode<any, { id: string }>, Field extends keyof ResultOf<T>, R extends Field>(config: {
-    component: Type<TypedBaseDetailComponent<T, Field>>;
-    query: T;
-    entityKey: R;
-    getBreadcrumbs?: (entity: ResultOf<T>[R]) => BreadcrumbValue;
-    variables?: T extends TypedDocumentNode<any, infer V> ? Omit<V, 'id'> : never;
+function detailComponentWithResolver<T extends TypedDocumentNode<any, { id: string }>, Field extends keyof ResultOf<T>, R extends Field>(config: {
+    component: Type<TypedBaseDetailComponent<T, Field>>;
+    query: T;
+    entityKey: R;
+    getBreadcrumbs?: (entity: ResultOf<T>[R]) => BreadcrumbValue;
+    variables?: T extends TypedDocumentNode<any, infer V> ? Omit<V, 'id'> : never;
 }): void
 ```
 Parameters
 
 ### config
 
-<MemberInfo kind="parameter" type={`{
     component: Type&#60;<a href='/reference/admin-ui-api/list-detail-views/typed-base-detail-component#typedbasedetailcomponent'>TypedBaseDetailComponent</a>&#60;T, Field&#62;&#62;;
     query: T;
     entityKey: R;
     getBreadcrumbs?: (entity: ResultOf&#60;T&#62;[R]) =&#62; BreadcrumbValue;
     variables?: T extends TypedDocumentNode&#60;any, infer V&#62; ? Omit&#60;V, 'id'&#62; : never;
 }`} />
+<MemberInfo kind="parameter" type={`{     component: Type&#60;<a href='/reference/admin-ui-api/list-detail-views/typed-base-detail-component#typedbasedetailcomponent'>TypedBaseDetailComponent</a>&#60;T, Field&#62;&#62;;     query: T;     entityKey: R;     getBreadcrumbs?: (entity: ResultOf&#60;T&#62;[R]) =&#62; BreadcrumbValue;     variables?: T extends TypedDocumentNode&#60;any, infer V&#62; ? Omit&#60;V, 'id'&#62; : never; }`} />
 

+ 7 - 7
docs/docs/reference/admin-ui-api/list-detail-views/typed-base-list-component.md

@@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription';
 
 <GenerationInfo sourceFile="packages/admin-ui/src/lib/core/src/common/base-list.component.ts" sourceLine="217" packageName="@vendure/admin-ui" />
 
-A version of the <a href='/reference/admin-ui-api/list-detail-views/base-list-component#baselistcomponent'>BaseListComponent</a> which is designed to be used with a
+A version of the <a href='/reference/admin-ui-api/list-detail-views/base-list-component#baselistcomponent'>BaseListComponent</a> which is designed to be used with a
 [TypedDocumentNode](https://the-guild.dev/graphql/codegen/plugins/typescript/typed-document-node).
 
 ```ts title="Signature"
@@ -27,11 +27,11 @@ class TypedBaseListComponent<T extends TypedDocumentNode<any, Vars>, Field exten
     protected dataTableConfigService = inject(DataTableConfigService);
     protected dataTableListId: string | undefined;
     constructor()
-    configure(config: {
-        document: T;
-        getItems: (data: ResultOf<T>) => { items: Array<ItemOf<ResultOf<T>, Field>>; totalItems: number };
-        setVariables?: (skip: number, take: number) => VariablesOf<T>;
-        refreshListOnChanges?: Array<Observable<any>>;
+    configure(config: {
+        document: T;
+        getItems: (data: ResultOf<T>) => { items: Array<ItemOf<ResultOf<T>, Field>>; totalItems: number };
+        setVariables?: (skip: number, take: number) => VariablesOf<T>;
+        refreshListOnChanges?: Array<Observable<any>>;
     }) => ;
     ngOnInit() => ;
     createFilterCollection() => DataTableFilterCollection<NonNullable<NonNullable<Vars['options']>['filter']>>;
@@ -96,7 +96,7 @@ class TypedBaseListComponent<T extends TypedDocumentNode<any, Vars>, Field exten
 
 ### configure
 
-<MemberInfo kind="method" type={`(config: {
         document: T;
         getItems: (data: ResultOf&#60;T&#62;) =&#62; { items: Array&#60;ItemOf&#60;ResultOf&#60;T&#62;, Field&#62;&#62;; totalItems: number };
         setVariables?: (skip: number, take: number) =&#62; VariablesOf&#60;T&#62;;
         refreshListOnChanges?: Array&#60;Observable&#60;any&#62;&#62;;
     }) => `}   />
+<MemberInfo kind="method" type={`(config: {         document: T;         getItems: (data: ResultOf&#60;T&#62;) =&#62; { items: Array&#60;ItemOf&#60;ResultOf&#60;T&#62;, Field&#62;&#62;; totalItems: number };         setVariables?: (skip: number, take: number) =&#62; VariablesOf&#60;T&#62;;         refreshListOnChanges?: Array&#60;Observable&#60;any&#62;&#62;;     }) => `}   />
 
 
 ### ngOnInit

+ 7 - 7
docs/docs/reference/admin-ui-api/react-components/form-field.md

@@ -30,17 +30,17 @@ export function MyReactComponent() {
 ```
 
 ```ts title="Signature"
-function FormField(props: PropsWithChildren<{
-        for?: string;
-        label?: string;
-        tooltip?: string;
-        invalid?: boolean;
-        errorMessage?: string;
+function FormField(props: PropsWithChildren<{
+        for?: string;
+        label?: string;
+        tooltip?: string;
+        invalid?: boolean;
+        errorMessage?: string;
     }>): void
 ```
 Parameters
 
 ### props
 
-<MemberInfo kind="parameter" type={`PropsWithChildren&#60;{
         for?: string;
         label?: string;
         tooltip?: string;
         invalid?: boolean;
         errorMessage?: string;
     }&#62;`} />
+<MemberInfo kind="parameter" type={`PropsWithChildren&#60;{         for?: string;         label?: string;         tooltip?: string;         invalid?: boolean;         errorMessage?: string;     }&#62;`} />
 

+ 12 - 12
docs/docs/reference/core-plugins/asset-server-plugin/asset-server-options.md

@@ -25,8 +25,8 @@ interface AssetServerOptions {
     presets?: ImageTransformPreset[];
     namingStrategy?: AssetNamingStrategy;
     previewStrategy?: AssetPreviewStrategy;
-    storageStrategyFactory?: (
-        options: AssetServerOptions,
+    storageStrategyFactory?: (
+        options: AssetServerOptions,
     ) => AssetStorageStrategy | Promise<AssetStorageStrategy>;
     cacheHeader?: CacheConfig | string;
 }
@@ -48,12 +48,12 @@ The local directory to which assets will be uploaded when using the <a href='/re
 
 <MemberInfo kind="property" type={`string | ((ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, identifier: string) =&#62; string)`}   />
 
-The complete URL prefix of the asset files. For example, "https://demo.vendure.io/assets/". A
-function can also be provided to handle more complex cases, such as serving multiple domains
-from a single server. In this case, the function should return a string url prefix.
-
-If not provided, the plugin will attempt to guess based off the incoming
-request and the configured route. However, in all but the simplest cases,
+The complete URL prefix of the asset files. For example, "https://demo.vendure.io/assets/". A
+function can also be provided to handle more complex cases, such as serving multiple domains
+from a single server. In this case, the function should return a string url prefix.
+
+If not provided, the plugin will attempt to guess based off the incoming
+request and the configured route. However, in all but the simplest cases,
 this guess may not yield correct results.
 ### previewMaxWidth
 
@@ -79,19 +79,19 @@ Defines how asset files and preview images are named before being saved.
 
 <MemberInfo kind="property" type={`<a href='/reference/typescript-api/assets/asset-preview-strategy#assetpreviewstrategy'>AssetPreviewStrategy</a>`}  since="1.7.0"  />
 
-Defines how previews are generated for a given Asset binary. By default, this uses
+Defines how previews are generated for a given Asset binary. By default, this uses
 the <a href='/reference/core-plugins/asset-server-plugin/sharp-asset-preview-strategy#sharpassetpreviewstrategy'>SharpAssetPreviewStrategy</a>
 ### storageStrategyFactory
 
-<MemberInfo kind="property" type={`(
         options: <a href='/reference/core-plugins/asset-server-plugin/asset-server-options#assetserveroptions'>AssetServerOptions</a>,
     ) =&#62; <a href='/reference/typescript-api/assets/asset-storage-strategy#assetstoragestrategy'>AssetStorageStrategy</a> | Promise&#60;<a href='/reference/typescript-api/assets/asset-storage-strategy#assetstoragestrategy'>AssetStorageStrategy</a>&#62;`} default={`() =&#62; <a href='/reference/core-plugins/asset-server-plugin/local-asset-storage-strategy#localassetstoragestrategy'>LocalAssetStorageStrategy</a>`}   />
+<MemberInfo kind="property" type={`(         options: <a href='/reference/core-plugins/asset-server-plugin/asset-server-options#assetserveroptions'>AssetServerOptions</a>,     ) =&#62; <a href='/reference/typescript-api/assets/asset-storage-strategy#assetstoragestrategy'>AssetStorageStrategy</a> | Promise&#60;<a href='/reference/typescript-api/assets/asset-storage-strategy#assetstoragestrategy'>AssetStorageStrategy</a>&#62;`} default={`() =&#62; <a href='/reference/core-plugins/asset-server-plugin/local-asset-storage-strategy#localassetstoragestrategy'>LocalAssetStorageStrategy</a>`}   />
 
-A function which can be used to configure an <a href='/reference/typescript-api/assets/asset-storage-strategy#assetstoragestrategy'>AssetStorageStrategy</a>. This is useful e.g. if you wish to store your assets
+A function which can be used to configure an <a href='/reference/typescript-api/assets/asset-storage-strategy#assetstoragestrategy'>AssetStorageStrategy</a>. This is useful e.g. if you wish to store your assets
 using a cloud storage provider. By default, the <a href='/reference/core-plugins/asset-server-plugin/local-asset-storage-strategy#localassetstoragestrategy'>LocalAssetStorageStrategy</a> is used.
 ### cacheHeader
 
 <MemberInfo kind="property" type={`<a href='/reference/core-plugins/asset-server-plugin/cache-config#cacheconfig'>CacheConfig</a> | string`} default={`'public, max-age=15552000'`}  since="1.9.3"  />
 
-Configures the `Cache-Control` directive for response to control caching in browsers and shared caches (e.g. Proxies, CDNs).
+Configures the `Cache-Control` directive for response to control caching in browsers and shared caches (e.g. Proxies, CDNs).
 Defaults to publicly cached for 6 months.
 
 

+ 1 - 2
docs/docs/reference/core-plugins/asset-server-plugin/s3asset-storage-strategy.md

@@ -151,8 +151,7 @@ Using type `any` in order to avoid the need to include `aws-sdk` dependency in g
 
 <GenerationInfo sourceFile="packages/asset-server-plugin/src/s3-asset-storage-strategy.ts" sourceLine="119" packageName="@vendure/asset-server-plugin" />
 
-Returns a configured instance of the <a href='/reference/core-plugins/asset-server-plugin/s3asset-storage-strategy#s3assetstoragestrategy'>S3AssetStorageStrategy</a> which can then be passed to the <a href='/reference/core-plugins/asset-server-plugin/asset-server-options#assetserveroptions'>AssetServerOptions</a>
-`storageStrategyFactory` property.
+Returns a configured instance of the <a href='/reference/core-plugins/asset-server-plugin/s3asset-storage-strategy#s3assetstoragestrategy'>S3AssetStorageStrategy</a> which can then be passed to the <a href='/reference/core-plugins/asset-server-plugin/asset-server-options#assetserveroptions'>AssetServerOptions</a>`storageStrategyFactory` property.
 
 Before using this strategy, make sure you have the `@aws-sdk/client-s3` and `@aws-sdk/lib-storage` package installed:
 

+ 114 - 114
docs/docs/reference/core-plugins/elasticsearch-plugin/elasticsearch-options.md

@@ -24,23 +24,23 @@ interface ElasticsearchOptions {
     clientOptions?: ClientOptions;
     indexPrefix?: string;
     indexSettings?: object;
-    indexMappingProperties?: {
-        [indexName: string]: object;
+    indexMappingProperties?: {
+        [indexName: string]: object;
     };
     reindexProductsChunkSize?: number;
     reindexBulkOperationSizeLimit?: number;
     searchConfig?: SearchConfig;
-    customProductMappings?: {
-        [fieldName: string]: CustomMapping<[Product, ProductVariant[], LanguageCode, Injector, RequestContext]>;
+    customProductMappings?: {
+        [fieldName: string]: CustomMapping<[Product, ProductVariant[], LanguageCode, Injector, RequestContext]>;
     };
-    customProductVariantMappings?: {
-        [fieldName: string]: CustomMapping<[ProductVariant, LanguageCode, Injector, RequestContext]>;
+    customProductVariantMappings?: {
+        [fieldName: string]: CustomMapping<[ProductVariant, LanguageCode, Injector, RequestContext]>;
     };
     bufferUpdates?: boolean;
     hydrateProductRelations?: Array<EntityRelationPaths<Product>>;
     hydrateProductVariantRelations?: Array<EntityRelationPaths<ProductVariant>>;
-    extendSearchInputType?: {
-        [name: string]: PrimitiveTypeVariations<GraphQlPrimitive>;
+    extendSearchInputType?: {
+        [name: string]: PrimitiveTypeVariations<GraphQlPrimitive>;
     };
     extendSearchSortType?: string[];
 }
@@ -72,9 +72,9 @@ Interval in milliseconds between attempts to connect to the ElasticSearch server
 
 <MemberInfo kind="property" type={`ClientOptions`}   />
 
-Options to pass directly to the
-[Elasticsearch Node.js client](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/index.html). For example, to
-set authentication or other more advanced options.
+Options to pass directly to the
+[Elasticsearch Node.js client](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/index.html). For example, to
+set authentication or other more advanced options.
 Note that if the `node` or `nodes` option is specified, it will override the values provided in the `host` and `port` options.
 ### indexPrefix
 
@@ -85,7 +85,7 @@ Prefix for the indices created by the plugin.
 
 <MemberInfo kind="property" type={`object`} default={`{}`}  since="1.2.0"  />
 
-[These options](https://www.elastic.co/guide/en/elasticsearch/reference/7.x/index-modules.html#index-modules-settings)
+[These options](https://www.elastic.co/guide/en/elasticsearch/reference/7.x/index-modules.html#index-modules-settings)
 are directly passed to index settings. To apply some settings indices will be recreated.
 
 *Example*
@@ -116,10 +116,10 @@ A more complete example can be found in the discussion thread
 [How to make elastic plugin to search by substring with stemming](https://github.com/vendure-ecommerce/vendure/discussions/1066).
 ### indexMappingProperties
 
-<MemberInfo kind="property" type={`{
         [indexName: string]: object;
     }`} default={`{}`}  since="1.2.0"  />
+<MemberInfo kind="property" type={`{         [indexName: string]: object;     }`} default={`{}`}  since="1.2.0"  />
 
-This option allow to redefine or define new properties in mapping. More about elastic
-[mapping](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html)
+This option allow to redefine or define new properties in mapping. More about elastic
+[mapping](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html)
 After changing this option indices will be recreated.
 
 *Example*
@@ -167,8 +167,8 @@ Products limit chunk size for each loop iteration when indexing products.
 
 <MemberInfo kind="property" type={`number`} default={`3000`}  since="2.1.7"  />
 
-Index operations are performed in bulk, with each bulk operation containing a number of individual
-index operations. This option sets the maximum number of operations in the memory buffer before a
+Index operations are performed in bulk, with each bulk operation containing a number of individual
+index operations. This option sets the maximum number of operations in the memory buffer before a
 bulk operation is executed.
 ### searchConfig
 
@@ -177,21 +177,21 @@ bulk operation is executed.
 Configuration of the internal Elasticsearch query.
 ### customProductMappings
 
-<MemberInfo kind="property" type={`{
         [fieldName: string]: CustomMapping&#60;[<a href='/reference/typescript-api/entities/product#product'>Product</a>, <a href='/reference/typescript-api/entities/product-variant#productvariant'>ProductVariant</a>[], <a href='/reference/typescript-api/common/language-code#languagecode'>LanguageCode</a>, <a href='/reference/typescript-api/common/injector#injector'>Injector</a>, <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>]&#62;;
     }`}   />
-
-Custom mappings may be defined which will add the defined data to the
-Elasticsearch index and expose that data via the SearchResult GraphQL type,
-adding a new `customMappings`, `customProductMappings` & `customProductVariantMappings` fields.
-
-The `graphQlType` property may be one of `String`, `Int`, `Float`, `Boolean`, `ID` or list
-versions thereof (`[String!]` etc) and can be appended with a `!` to indicate non-nullable fields.
-
-The `public` (default = `true`) property is used to reveal or hide the property in the GraphQL API schema.
-If this property is set to `false` it's not accessible in the `customMappings` field but it's still getting
-parsed to the elasticsearch index.
-
-This config option defines custom mappings which are accessible when the "groupByProduct"
-input options is set to `true`. In addition, custom variant mappings can be accessed by using
+<MemberInfo kind="property" type={`{         [fieldName: string]: CustomMapping&#60;[<a href='/reference/typescript-api/entities/product#product'>Product</a>, <a href='/reference/typescript-api/entities/product-variant#productvariant'>ProductVariant</a>[], <a href='/reference/typescript-api/common/language-code#languagecode'>LanguageCode</a>, <a href='/reference/typescript-api/common/injector#injector'>Injector</a>, <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>]&#62;;     }`}   />
+
+Custom mappings may be defined which will add the defined data to the
+Elasticsearch index and expose that data via the SearchResult GraphQL type,
+adding a new `customMappings`, `customProductMappings` & `customProductVariantMappings` fields.
+
+The `graphQlType` property may be one of `String`, `Int`, `Float`, `Boolean`, `ID` or list
+versions thereof (`[String!]` etc) and can be appended with a `!` to indicate non-nullable fields.
+
+The `public` (default = `true`) property is used to reveal or hide the property in the GraphQL API schema.
+If this property is set to `false` it's not accessible in the `customMappings` field but it's still getting
+parsed to the elasticsearch index.
+
+This config option defines custom mappings which are accessible when the "groupByProduct"
+input options is set to `true`. In addition, custom variant mappings can be accessed by using
 the `customProductVariantMappings` field, which is always available.
 
 *Example*
@@ -240,10 +240,10 @@ query SearchProducts($input: SearchInput!) {
 ```
 ### customProductVariantMappings
 
-<MemberInfo kind="property" type={`{
         [fieldName: string]: CustomMapping&#60;[<a href='/reference/typescript-api/entities/product-variant#productvariant'>ProductVariant</a>, <a href='/reference/typescript-api/common/language-code#languagecode'>LanguageCode</a>, <a href='/reference/typescript-api/common/injector#injector'>Injector</a>, <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>]&#62;;
     }`}   />
+<MemberInfo kind="property" type={`{         [fieldName: string]: CustomMapping&#60;[<a href='/reference/typescript-api/entities/product-variant#productvariant'>ProductVariant</a>, <a href='/reference/typescript-api/common/language-code#languagecode'>LanguageCode</a>, <a href='/reference/typescript-api/common/injector#injector'>Injector</a>, <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>]&#62;;     }`}   />
 
-This config option defines custom mappings which are accessible when the "groupByProduct"
-input options is set to `false`. In addition, custom product mappings can be accessed by using
+This config option defines custom mappings which are accessible when the "groupByProduct"
+input options is set to `false`. In addition, custom product mappings can be accessed by using
 the `customProductMappings` field, which is always available.
 
 *Example*
@@ -271,20 +271,20 @@ query SearchProducts($input: SearchInput!) {
 
 <MemberInfo kind="property" type={`boolean`} default={`false`}  since="1.3.0"  />
 
-If set to `true`, updates to Products, ProductVariants and Collections will not immediately
-trigger an update to the search index. Instead, all these changes will be buffered and will
-only be run via a call to the `runPendingSearchIndexUpdates` mutation in the Admin API.
-
-This is very useful for installations with a large number of ProductVariants and/or
-Collections, as the buffering allows better control over when these expensive jobs are run,
-and also performs optimizations to minimize the amount of work that needs to be performed by
+If set to `true`, updates to Products, ProductVariants and Collections will not immediately
+trigger an update to the search index. Instead, all these changes will be buffered and will
+only be run via a call to the `runPendingSearchIndexUpdates` mutation in the Admin API.
+
+This is very useful for installations with a large number of ProductVariants and/or
+Collections, as the buffering allows better control over when these expensive jobs are run,
+and also performs optimizations to minimize the amount of work that needs to be performed by
 the worker.
 ### hydrateProductRelations
 
 <MemberInfo kind="property" type={`Array&#60;<a href='/reference/typescript-api/common/entity-relation-paths#entityrelationpaths'>EntityRelationPaths</a>&#60;<a href='/reference/typescript-api/entities/product#product'>Product</a>&#62;&#62;`} default={`[]`}  since="1.3.0"  />
 
-Additional product relations that will be fetched from DB while reindexing. This can be used
-in combination with `customProductMappings` to ensure that the required relations are joined
+Additional product relations that will be fetched from DB while reindexing. This can be used
+in combination with `customProductMappings` to ensure that the required relations are joined
 before the `product` object is passed to the `valueFn`.
 
 *Example*
@@ -306,14 +306,14 @@ before the `product` object is passed to the `valueFn`.
 
 <MemberInfo kind="property" type={`Array&#60;<a href='/reference/typescript-api/common/entity-relation-paths#entityrelationpaths'>EntityRelationPaths</a>&#60;<a href='/reference/typescript-api/entities/product-variant#productvariant'>ProductVariant</a>&#62;&#62;`} default={`[]`}  since="1.3.0"  />
 
-Additional variant relations that will be fetched from DB while reindexing. See
+Additional variant relations that will be fetched from DB while reindexing. See
 `hydrateProductRelations` for more explanation and a usage example.
 ### extendSearchInputType
 
-<MemberInfo kind="property" type={`{
         [name: string]: PrimitiveTypeVariations&#60;GraphQlPrimitive&#62;;
     }`} default={`{}`}  since="1.3.0"  />
+<MemberInfo kind="property" type={`{         [name: string]: PrimitiveTypeVariations&#60;GraphQlPrimitive&#62;;     }`} default={`{}`}  since="1.3.0"  />
 
-Allows the `SearchInput` type to be extended with new input fields. This allows arbitrary
-data to be passed in, which can then be used e.g. in the `mapQuery()` function or
+Allows the `SearchInput` type to be extended with new input fields. This allows arbitrary
+data to be passed in, which can then be used e.g. in the `mapQuery()` function or
 custom `scriptFields` functions.
 
 *Example*
@@ -347,7 +347,7 @@ query {
 
 <MemberInfo kind="property" type={`string[]`} default={`[]`}  since="1.4.0"  />
 
-Adds a list of sort parameters. This is mostly important to make the
+Adds a list of sort parameters. This is mostly important to make the
 correct sort order values available inside `input` parameter of the `mapSort` option.
 
 *Example*
@@ -384,12 +384,12 @@ interface SearchConfig {
     multiMatchType?: 'best_fields' | 'most_fields' | 'cross_fields' | 'phrase' | 'phrase_prefix' | 'bool_prefix';
     boostFields?: BoostFieldsConfig;
     priceRangeBucketInterval?: number;
-    mapQuery?: (
-        query: any,
-        input: ElasticSearchInput,
-        searchConfig: DeepRequired<SearchConfig>,
-        channelId: ID,
-        enabledOnly: boolean,
+    mapQuery?: (
+        query: any,
+        input: ElasticSearchInput,
+        searchConfig: DeepRequired<SearchConfig>,
+        channelId: ID,
+        enabledOnly: boolean,
     ) => any;
     scriptFields?: { [fieldName: string]: CustomScriptMapping<[ElasticSearchInput]> };
     mapSort?: (sort: ElasticSearchSortInput, input: ElasticSearchInput) => ElasticSearchSortInput;
@@ -402,29 +402,29 @@ interface SearchConfig {
 
 <MemberInfo kind="property" type={`number`} default={`50`}   />
 
-The maximum number of FacetValues to return from the search query. Internally, this
+The maximum number of FacetValues to return from the search query. Internally, this
 value sets the "size" property of an Elasticsearch aggregation.
 ### collectionMaxSize
 
 <MemberInfo kind="property" type={`number`} default={`50`}  since="1.1.0"  />
 
-The maximum number of Collections to return from the search query. Internally, this
+The maximum number of Collections to return from the search query. Internally, this
 value sets the "size" property of an Elasticsearch aggregation.
 ### totalItemsMaxSize
 
 <MemberInfo kind="property" type={`number | boolean`} default={`10000`}  since="1.2.0"  />
 
-The maximum number of totalItems to return from the search query. Internally, this
-value sets the "track_total_hits" property of an Elasticsearch query.
-If this parameter is set to "True", accurate count of totalItems will be returned.
-If this parameter is set to "False", totalItems will be returned as 0.
+The maximum number of totalItems to return from the search query. Internally, this
+value sets the "track_total_hits" property of an Elasticsearch query.
+If this parameter is set to "True", accurate count of totalItems will be returned.
+If this parameter is set to "False", totalItems will be returned as 0.
 If this parameter is set to integer, accurate count of totalItems will be returned not bigger than integer.
 ### multiMatchType
 
 <MemberInfo kind="property" type={`'best_fields' | 'most_fields' | 'cross_fields' | 'phrase' | 'phrase_prefix' | 'bool_prefix'`} default={`'best_fields'`}   />
 
-Defines the
-[multi match type](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html#multi-match-types)
+Defines the
+[multi match type](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html#multi-match-types)
 used when matching against a search term.
 ### boostFields
 
@@ -435,43 +435,43 @@ Set custom boost values for particular fields when matching against a search ter
 
 <MemberInfo kind="property" type={`number`}   />
 
-The interval used to group search results into buckets according to price range. For example, setting this to
-`2000` will group into buckets every $20.00:
-
-```json
-{
-  "data": {
-    "search": {
-      "totalItems": 32,
-      "priceRange": {
-        "buckets": [
-          {
-            "to": 2000,
-            "count": 21
-          },
-          {
-            "to": 4000,
-            "count": 7
-          },
-          {
-            "to": 6000,
-            "count": 3
-          },
-          {
-            "to": 12000,
-            "count": 1
-          }
-        ]
-      }
-    }
-  }
-}
+The interval used to group search results into buckets according to price range. For example, setting this to
+`2000` will group into buckets every $20.00:
+
+```json
+{
+  "data": {
+    "search": {
+      "totalItems": 32,
+      "priceRange": {
+        "buckets": [
+          {
+            "to": 2000,
+            "count": 21
+          },
+          {
+            "to": 4000,
+            "count": 7
+          },
+          {
+            "to": 6000,
+            "count": 3
+          },
+          {
+            "to": 12000,
+            "count": 1
+          }
+        ]
+      }
+    }
+  }
+}
 ```
 ### mapQuery
 
-<MemberInfo kind="property" type={`(
         query: any,
         input: ElasticSearchInput,
         searchConfig: DeepRequired&#60;<a href='/reference/core-plugins/elasticsearch-plugin/elasticsearch-options#searchconfig'>SearchConfig</a>&#62;,
         channelId: <a href='/reference/typescript-api/common/id#id'>ID</a>,
         enabledOnly: boolean,
     ) =&#62; any`}   />
+<MemberInfo kind="property" type={`(         query: any,         input: ElasticSearchInput,         searchConfig: DeepRequired&#60;<a href='/reference/core-plugins/elasticsearch-plugin/elasticsearch-options#searchconfig'>SearchConfig</a>&#62;,         channelId: <a href='/reference/typescript-api/common/id#id'>ID</a>,         enabledOnly: boolean,     ) =&#62; any`}   />
 
-This config option allows the the modification of the whole (already built) search query. This allows
+This config option allows the the modification of the whole (already built) search query. This allows
 for e.g. wildcard / fuzzy searches on the index.
 
 *Example*
@@ -510,17 +510,17 @@ mapQuery: (query, input, searchConfig, channelId, enabledOnly){
 
 <MemberInfo kind="property" type={`{ [fieldName: string]: CustomScriptMapping&#60;[ElasticSearchInput]&#62; }`}  since="1.3.0"  />
 
-Sets `script_fields` inside the elasticsearch body which allows returning a script evaluation for each hit.
-
-The script field definition consists of three properties:
-
-* `graphQlType`: This is the type that will be returned when this script field is queried
-via the GraphQL API. It may be one of `String`, `Int`, `Float`, `Boolean`, `ID` or list
-versions thereof (`[String!]` etc) and can be appended with a `!` to indicate non-nullable fields.
-* `context`: determines whether this script field is available when grouping by product. Can be
-`product`, `variant` or `both`.
-* `scriptFn`: This is the function to run on each hit. Should return an object with a `script` property,
-as covered in the
+Sets `script_fields` inside the elasticsearch body which allows returning a script evaluation for each hit.
+
+The script field definition consists of three properties:
+
+* `graphQlType`: This is the type that will be returned when this script field is queried
+via the GraphQL API. It may be one of `String`, `Int`, `Float`, `Boolean`, `ID` or list
+versions thereof (`[String!]` etc) and can be appended with a `!` to indicate non-nullable fields.
+* `context`: determines whether this script field is available when grouping by product. Can be
+`product`, `variant` or `both`.
+* `scriptFn`: This is the function to run on each hit. Should return an object with a `script` property,
+as covered in the
 [Elasticsearch script fields docs](https://www.elastic.co/guide/en/elasticsearch/reference/7.15/search-fields.html#script-fields)
 
 *Example*
@@ -571,10 +571,10 @@ searchConfig: {
 
 <MemberInfo kind="property" type={`(sort: ElasticSearchSortInput, input: ElasticSearchInput) =&#62; ElasticSearchSortInput`} default={`{}`}  since="1.4.0"  />
 
-Allows extending the `sort` input of the elasticsearch body as covered in
-[Elasticsearch sort docs](https://www.elastic.co/guide/en/elasticsearch/reference/current/sort-search-results.html)
-
-The `sort` input parameter contains the ElasticSearchSortInput generated for the default sort parameters "name" and "price".
+Allows extending the `sort` input of the elasticsearch body as covered in
+[Elasticsearch sort docs](https://www.elastic.co/guide/en/elasticsearch/reference/current/sort-search-results.html)
+
+The `sort` input parameter contains the ElasticSearchSortInput generated for the default sort parameters "name" and "price".
 If neither of those are applied it will be empty.
 
 *Example*
@@ -655,9 +655,9 @@ searchConfig: {
 
 <GenerationInfo sourceFile="packages/elasticsearch-plugin/src/options.ts" sourceLine="680" packageName="@vendure/elasticsearch-plugin" />
 
-Configuration for [boosting](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html#field-boost)
-the scores of given fields when performing a search against a term.
-
+Configuration for [boosting](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html#field-boost)
+the scores of given fields when performing a search against a term.
+
 Boosting a field acts as a score multiplier for matches against that field.
 
 ```ts title="Signature"

+ 23 - 23
docs/docs/reference/core-plugins/harden-plugin/harden-plugin-options.md

@@ -20,8 +20,8 @@ interface HardenPluginOptions {
     maxQueryComplexity?: number;
     queryComplexityEstimators?: ComplexityEstimator[];
     logComplexityScore?: boolean;
-    customComplexityFactors?: {
-        [path: string]: number;
+    customComplexityFactors?: {
+        [path: string]: number;
     };
     hideFieldSuggestions?: boolean;
     apiMode?: 'dev' | 'prod';
@@ -34,33 +34,33 @@ interface HardenPluginOptions {
 
 <MemberInfo kind="property" type={`number`} default={`1000`}   />
 
-Defines the maximum permitted complexity score of a query. The complexity score is based
-on the number of fields being selected as well as other factors like whether there are nested
-lists.
-
+Defines the maximum permitted complexity score of a query. The complexity score is based
+on the number of fields being selected as well as other factors like whether there are nested
+lists.
+
 A query which exceeds the maximum score will result in an error.
 ### queryComplexityEstimators
 
 <MemberInfo kind="property" type={`ComplexityEstimator[]`}   />
 
-An array of custom estimator functions for calculating the complexity of a query. By default,
-the plugin will use the <a href='/reference/core-plugins/harden-plugin/default-vendure-complexity-estimator#defaultvendurecomplexityestimator'>defaultVendureComplexityEstimator</a> which is specifically
+An array of custom estimator functions for calculating the complexity of a query. By default,
+the plugin will use the <a href='/reference/core-plugins/harden-plugin/default-vendure-complexity-estimator#defaultvendurecomplexityestimator'>defaultVendureComplexityEstimator</a> which is specifically
 tuned to accurately estimate Vendure queries.
 ### logComplexityScore
 
 <MemberInfo kind="property" type={`boolean`} default={`false`}   />
 
-When set to `true`, the complexity score of each query will be logged at the Verbose
-log level, and a breakdown of the calculation for each field will be logged at the Debug level.
-
+When set to `true`, the complexity score of each query will be logged at the Verbose
+log level, and a breakdown of the calculation for each field will be logged at the Debug level.
+
 This is very useful for tuning your complexity scores.
 ### customComplexityFactors
 
-<MemberInfo kind="property" type={`{
         [path: string]: number;
     }`}   />
+<MemberInfo kind="property" type={`{         [path: string]: number;     }`}   />
 
-This object allows you to tune the complexity weight of specific fields. For example,
-if you have a custom `stockLocations` field defined on the `ProductVariant` type, and
-you know that it is a particularly expensive operation to execute, you can increase
+This object allows you to tune the complexity weight of specific fields. For example,
+if you have a custom `stockLocations` field defined on the `ProductVariant` type, and
+you know that it is a particularly expensive operation to execute, you can increase
 its complexity like this:
 
 *Example*
@@ -77,19 +77,19 @@ HardenPlugin.init({
 
 <MemberInfo kind="property" type={`boolean`} default={`true`}   />
 
-Graphql-js will make suggestions about the names of fields if an invalid field name is provided.
-This would allow an attacker to find out the available fields by brute force even if introspection
-is disabled.
-
-Setting this option to `true` will prevent these suggestion error messages from being returned,
+Graphql-js will make suggestions about the names of fields if an invalid field name is provided.
+This would allow an attacker to find out the available fields by brute force even if introspection
+is disabled.
+
+Setting this option to `true` will prevent these suggestion error messages from being returned,
 instead replacing the message with a generic "Invalid request" message.
 ### apiMode
 
 <MemberInfo kind="property" type={`'dev' | 'prod'`} default={`'prod'`}   />
 
-When set to `'prod'`, the plugin will disable dev-mode features of the GraphQL APIs:
-
-- introspection
+When set to `'prod'`, the plugin will disable dev-mode features of the GraphQL APIs:
+
+- introspection
 - GraphQL playground
 
 

+ 116 - 116
docs/docs/reference/core-plugins/payments-plugin/mollie-plugin.md

@@ -13,110 +13,110 @@ import MemberDescription from '@site/src/components/MemberDescription';
 
 <GenerationInfo sourceFile="packages/payments-plugin/src/mollie/mollie.plugin.ts" sourceLine="191" packageName="@vendure/payments-plugin" />
 
-Plugin to enable payments through the [Mollie platform](https://docs.mollie.com/).
-This plugin uses the Order API from Mollie, not the Payments API.
-
-## Requirements
-
-1. You will need to create a Mollie account and get your apiKey in the dashboard.
-2. Install the Payments plugin and the Mollie client:
-
-    `yarn add @vendure/payments-plugin @mollie/api-client`
-
-    or
-
-    `npm install @vendure/payments-plugin @mollie/api-client`
-
-## Setup
-
-1. Add the plugin to your VendureConfig `plugins` array:
-    ```ts
-    import { MolliePlugin } from '@vendure/payments-plugin/package/mollie';
-
-    // ...
-
-    plugins: [
-      MolliePlugin.init({ vendureHost: 'https://yourhost.io/' }),
-    ]
-    ```
-2. Run a database migration to add the `mollieOrderId` custom field to the order entity.
-3. Create a new PaymentMethod in the Admin UI, and select "Mollie payments" as the handler.
-4. Set your Mollie apiKey in the `API Key` field.
-5. Set the `Fallback redirectUrl` to the url that the customer should be redirected to after completing the payment.
-You can override this url by passing the `redirectUrl` as an argument to the `createMolliePaymentIntent` mutation.
-
-## Storefront usage
-
-In your storefront you add a payment to an order using the `createMolliePaymentIntent` mutation. In this example, our Mollie
-PaymentMethod was given the code "mollie-payment-method". The `redirectUrl``is the url that is used to redirect the end-user
-back to your storefront after completing the payment.
-
-```GraphQL
-mutation CreateMolliePaymentIntent {
-  createMolliePaymentIntent(input: {
-    redirectUrl: "https://storefront/order/1234XYZ"
-    paymentMethodCode: "mollie-payment-method"
-    molliePaymentMethodCode: "ideal"
-  }) {
-         ... on MolliePaymentIntent {
-              url
-          }
-         ... on MolliePaymentIntentError {
-              errorCode
-              message
-         }
-  }
-}
-```
-
-The response will contain
-a redirectUrl, which can be used to redirect your customer to the Mollie
-platform.
-
-'molliePaymentMethodCode' is an optional parameter that can be passed to skip Mollie's hosted payment method selection screen
-You can get available Mollie payment methods with the following query:
-
-```GraphQL
-{
- molliePaymentMethods(input: { paymentMethodCode: "mollie-payment-method" }) {
-   id
-   code
-   description
-   minimumAmount {
-     value
-     currency
-   }
-   maximumAmount {
-     value
-     currency
-   }
-   image {
-     size1x
-     size2x
-     svg
-   }
- }
-}
-```
-You can pass `creditcard` for example, to the `createMolliePaymentIntent` mutation to skip the method selection.
-
-After completing payment on the Mollie platform,
-the user is redirected to the given redirect url, e.g. `https://storefront/order/CH234X5`
-
-## Pay later methods
-Mollie supports pay-later methods like 'Klarna Pay Later'. For pay-later methods, the status of an order is
-'PaymentAuthorized' after the Mollie hosted checkout. You need to manually settle the payment via the admin ui to capture the payment!
-Make sure you capture a payment within 28 days, because this is the Klarna expiry time
-
-If you don't want this behaviour (Authorized first), you can set 'autoCapture=true' on the payment method. This option will immediately
-capture the payment after a customer authorizes the payment.
-
-## ArrangingAdditionalPayment state
-
-In some rare cases, a customer can add items to the active order, while a Mollie payment is still open,
-for example by opening your storefront in another browser tab.
-This could result in an order being in `ArrangingAdditionalPayment` status after the customer finished payment.
-You should check if there is still an active order with status `ArrangingAdditionalPayment` on your order confirmation page,
+Plugin to enable payments through the [Mollie platform](https://docs.mollie.com/).
+This plugin uses the Order API from Mollie, not the Payments API.
+
+## Requirements
+
+1. You will need to create a Mollie account and get your apiKey in the dashboard.
+2. Install the Payments plugin and the Mollie client:
+
+    `yarn add @vendure/payments-plugin @mollie/api-client`
+
+    or
+
+    `npm install @vendure/payments-plugin @mollie/api-client`
+
+## Setup
+
+1. Add the plugin to your VendureConfig `plugins` array:
+    ```ts
+    import { MolliePlugin } from '@vendure/payments-plugin/package/mollie';
+
+    // ...
+
+    plugins: [
+      MolliePlugin.init({ vendureHost: 'https://yourhost.io/' }),
+    ]
+    ```
+2. Run a database migration to add the `mollieOrderId` custom field to the order entity.
+3. Create a new PaymentMethod in the Admin UI, and select "Mollie payments" as the handler.
+4. Set your Mollie apiKey in the `API Key` field.
+5. Set the `Fallback redirectUrl` to the url that the customer should be redirected to after completing the payment.
+You can override this url by passing the `redirectUrl` as an argument to the `createMolliePaymentIntent` mutation.
+
+## Storefront usage
+
+In your storefront you add a payment to an order using the `createMolliePaymentIntent` mutation. In this example, our Mollie
+PaymentMethod was given the code "mollie-payment-method". The `redirectUrl``is the url that is used to redirect the end-user
+back to your storefront after completing the payment.
+
+```GraphQL
+mutation CreateMolliePaymentIntent {
+  createMolliePaymentIntent(input: {
+    redirectUrl: "https://storefront/order/1234XYZ"
+    paymentMethodCode: "mollie-payment-method"
+    molliePaymentMethodCode: "ideal"
+  }) {
+         ... on MolliePaymentIntent {
+              url
+          }
+         ... on MolliePaymentIntentError {
+              errorCode
+              message
+         }
+  }
+}
+```
+
+The response will contain
+a redirectUrl, which can be used to redirect your customer to the Mollie
+platform.
+
+'molliePaymentMethodCode' is an optional parameter that can be passed to skip Mollie's hosted payment method selection screen
+You can get available Mollie payment methods with the following query:
+
+```GraphQL
+{
+ molliePaymentMethods(input: { paymentMethodCode: "mollie-payment-method" }) {
+   id
+   code
+   description
+   minimumAmount {
+     value
+     currency
+   }
+   maximumAmount {
+     value
+     currency
+   }
+   image {
+     size1x
+     size2x
+     svg
+   }
+ }
+}
+```
+You can pass `creditcard` for example, to the `createMolliePaymentIntent` mutation to skip the method selection.
+
+After completing payment on the Mollie platform,
+the user is redirected to the given redirect url, e.g. `https://storefront/order/CH234X5`
+
+## Pay later methods
+Mollie supports pay-later methods like 'Klarna Pay Later'. For pay-later methods, the status of an order is
+'PaymentAuthorized' after the Mollie hosted checkout. You need to manually settle the payment via the admin ui to capture the payment!
+Make sure you capture a payment within 28 days, because this is the Klarna expiry time
+
+If you don't want this behaviour (Authorized first), you can set 'autoCapture=true' on the payment method. This option will immediately
+capture the payment after a customer authorizes the payment.
+
+## ArrangingAdditionalPayment state
+
+In some rare cases, a customer can add items to the active order, while a Mollie payment is still open,
+for example by opening your storefront in another browser tab.
+This could result in an order being in `ArrangingAdditionalPayment` status after the customer finished payment.
+You should check if there is still an active order with status `ArrangingAdditionalPayment` on your order confirmation page,
 and if so, allow your customer to pay for the additional items by creating another Mollie payment.
 
 ```ts title="Signature"
@@ -152,10 +152,10 @@ Configuration options for the Mollie payments plugin.
 ```ts title="Signature"
 interface MolliePluginOptions {
     vendureHost: string;
-    enabledPaymentMethodsParams?: (
-        injector: Injector,
-        ctx: RequestContext,
-        order: Order | null,
+    enabledPaymentMethodsParams?: (
+        injector: Injector,
+        ctx: RequestContext,
+        order: Order | null,
     ) => AdditionalEnabledPaymentMethodsParams | Promise<AdditionalEnabledPaymentMethodsParams>;
 }
 ```
@@ -166,18 +166,18 @@ interface MolliePluginOptions {
 
 <MemberInfo kind="property" type={`string`}   />
 
-The host of your Vendure server, e.g. `'https://my-vendure.io'`.
+The host of your Vendure server, e.g. `'https://my-vendure.io'`.
 This is used by Mollie to send webhook events to the Vendure server
 ### enabledPaymentMethodsParams
 
-<MemberInfo kind="property" type={`(
         injector: <a href='/reference/typescript-api/common/injector#injector'>Injector</a>,
         ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>,
         order: <a href='/reference/typescript-api/entities/order#order'>Order</a> | null,
     ) =&#62; AdditionalEnabledPaymentMethodsParams | Promise&#60;AdditionalEnabledPaymentMethodsParams&#62;`}  since="2.2.0"  />
+<MemberInfo kind="property" type={`(         injector: <a href='/reference/typescript-api/common/injector#injector'>Injector</a>,         ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>,         order: <a href='/reference/typescript-api/entities/order#order'>Order</a> | null,     ) =&#62; AdditionalEnabledPaymentMethodsParams | Promise&#60;AdditionalEnabledPaymentMethodsParams&#62;`}  since="2.2.0"  />
+
+Provide additional parameters to the Mollie enabled payment methods API call. By default,
+the plugin will already pass the `resource` parameter.
+
+For example, if you want to provide a `locale` and `billingCountry` for the API call, you can do so like this:
 
-Provide additional parameters to the Mollie enabled payment methods API call. By default,
-the plugin will already pass the `resource` parameter.
-
-For example, if you want to provide a `locale` and `billingCountry` for the API call, you can do so like this:
-
-**Note:** The `order` argument is possibly `null`, this could happen when you fetch the available payment methods
+**Note:** The `order` argument is possibly `null`, this could happen when you fetch the available payment methods
 before the order is created.
 
 *Example*

+ 165 - 165
docs/docs/reference/core-plugins/payments-plugin/stripe-plugin.md

@@ -13,147 +13,147 @@ import MemberDescription from '@site/src/components/MemberDescription';
 
 <GenerationInfo sourceFile="packages/payments-plugin/src/stripe/stripe.plugin.ts" sourceLine="161" packageName="@vendure/payments-plugin" />
 
-Plugin to enable payments through [Stripe](https://stripe.com/docs) via the Payment Intents API.
-
-## Requirements
-
-1. You will need to create a Stripe account and get your secret key in the dashboard.
-2. Create a webhook endpoint in the Stripe dashboard (Developers -> Webhooks, "Add an endpoint") which listens to the `payment_intent.succeeded`
-and `payment_intent.payment_failed` events. The URL should be `https://my-server.com/payments/stripe`, where
-`my-server.com` is the host of your Vendure server. *Note:* for local development, you'll need to use
-the Stripe CLI to test your webhook locally. See the _local development_ section below.
-3. Get the signing secret for the newly created webhook.
-4. Install the Payments plugin and the Stripe Node library:
-
-    `yarn add @vendure/payments-plugin stripe`
-
-    or
-
-    `npm install @vendure/payments-plugin stripe`
-
-## Setup
-
-1. Add the plugin to your VendureConfig `plugins` array:
-    ```ts
-    import { StripePlugin } from '@vendure/payments-plugin/package/stripe';
-
-    // ...
-
-    plugins: [
-      StripePlugin.init({
-        // This prevents different customers from using the same PaymentIntent
-        storeCustomersInStripe: true,
-      }),
-    ]
-    ````
-    For all the plugin options, see the <a href='/reference/core-plugins/payments-plugin/stripe-plugin#stripepluginoptions'>StripePluginOptions</a> type.
-2. Create a new PaymentMethod in the Admin UI, and select "Stripe payments" as the handler.
-3. Set the webhook secret and API key in the PaymentMethod form.
-
-## Storefront usage
-
-The plugin is designed to work with the [Custom payment flow](https://stripe.com/docs/payments/accept-a-payment?platform=web&ui=elements).
-In this flow, Stripe provides libraries which handle the payment UI and confirmation for you. You can install it in your storefront project
-with:
-
-```shell
-yarn add @stripe/stripe-js
-# or
-npm install @stripe/stripe-js
-```
-
-If you are using React, you should also consider installing `@stripe/react-stripe-js`, which is a wrapper around Stripe Elements.
-
-The high-level workflow is:
-1. Create a "payment intent" on the server by executing the `createStripePaymentIntent` mutation which is exposed by this plugin.
-2. Use the returned client secret to instantiate the Stripe Payment Element:
-   ```ts
-   import { Elements } from '@stripe/react-stripe-js';
-   import { loadStripe, Stripe } from '@stripe/stripe-js';
-   import { CheckoutForm } from './CheckoutForm';
-
-   const stripePromise = getStripe('pk_test_....wr83u');
-
-   type StripePaymentsProps = {
-     clientSecret: string;
-     orderCode: string;
-   }
-
-   export function StripePayments({ clientSecret, orderCode }: StripePaymentsProps) {
-     const options = {
-       // passing the client secret obtained from the server
-       clientSecret,
-     }
-     return (
-       <Elements stripe={stripePromise} options={options}>
-         <CheckoutForm orderCode={orderCode} />
-       </Elements>
-     );
-   }
-   ```
-   ```ts
-   // CheckoutForm.tsx
-   import { useStripe, useElements, PaymentElement } from '@stripe/react-stripe-js';
-   import { FormEvent } from 'react';
-
-   export const CheckoutForm = ({ orderCode }: { orderCode: string }) => {
-     const stripe = useStripe();
-     const elements = useElements();
-
-     const handleSubmit = async (event: FormEvent) => {
-       // We don't want to let default form submission happen here,
-       // which would refresh the page.
-       event.preventDefault();
-
-       if (!stripe || !elements) {
-         // Stripe.js has not yet loaded.
-         // Make sure to disable form submission until Stripe.js has loaded.
-         return;
-       }
-
-       const result = await stripe.confirmPayment({
-         //`Elements` instance that was used to create the Payment Element
-         elements,
-         confirmParams: {
-           return_url: location.origin + `/checkout/confirmation/${orderCode}`,
-         },
-       });
-
-       if (result.error) {
-         // Show error to your customer (for example, payment details incomplete)
-         console.log(result.error.message);
-       } else {
-         // Your customer will be redirected to your `return_url`. For some payment
-         // methods like iDEAL, your customer will be redirected to an intermediate
-         // site first to authorize the payment, then redirected to the `return_url`.
-       }
-     };
-
-     return (
-       <form onSubmit={handleSubmit}>
-         <PaymentElement />
-         <button disabled={!stripe}>Submit</button>
-       </form>
-     );
-   };
-   ```
-3. Once the form is submitted and Stripe processes the payment, the webhook takes care of updating the order without additional action
-in the storefront. As in the code above, the customer will be redirected to `/checkout/confirmation/${orderCode}`.
-
-:::info
-A full working storefront example of the Stripe integration can be found in the
-[Remix Starter repo](https://github.com/vendure-ecommerce/storefront-remix-starter/tree/master/app/components/checkout/stripe)
-:::
-
-## Local development
-
-1. Download & install the Stripe CLI: https://stripe.com/docs/stripe-cli
-2. From your Stripe dashboard, go to Developers -> Webhooks and click "Add an endpoint" and follow the instructions
-under "Test in a local environment".
-3. The Stripe CLI command will look like
-   ```shell
-   stripe listen --forward-to localhost:3000/payments/stripe
-   ```
+Plugin to enable payments through [Stripe](https://stripe.com/docs) via the Payment Intents API.
+
+## Requirements
+
+1. You will need to create a Stripe account and get your secret key in the dashboard.
+2. Create a webhook endpoint in the Stripe dashboard (Developers -> Webhooks, "Add an endpoint") which listens to the `payment_intent.succeeded`
+and `payment_intent.payment_failed` events. The URL should be `https://my-server.com/payments/stripe`, where
+`my-server.com` is the host of your Vendure server. *Note:* for local development, you'll need to use
+the Stripe CLI to test your webhook locally. See the _local development_ section below.
+3. Get the signing secret for the newly created webhook.
+4. Install the Payments plugin and the Stripe Node library:
+
+    `yarn add @vendure/payments-plugin stripe`
+
+    or
+
+    `npm install @vendure/payments-plugin stripe`
+
+## Setup
+
+1. Add the plugin to your VendureConfig `plugins` array:
+    ```ts
+    import { StripePlugin } from '@vendure/payments-plugin/package/stripe';
+
+    // ...
+
+    plugins: [
+      StripePlugin.init({
+        // This prevents different customers from using the same PaymentIntent
+        storeCustomersInStripe: true,
+      }),
+    ]
+    ````
+    For all the plugin options, see the <a href='/reference/core-plugins/payments-plugin/stripe-plugin#stripepluginoptions'>StripePluginOptions</a> type.
+2. Create a new PaymentMethod in the Admin UI, and select "Stripe payments" as the handler.
+3. Set the webhook secret and API key in the PaymentMethod form.
+
+## Storefront usage
+
+The plugin is designed to work with the [Custom payment flow](https://stripe.com/docs/payments/accept-a-payment?platform=web&ui=elements).
+In this flow, Stripe provides libraries which handle the payment UI and confirmation for you. You can install it in your storefront project
+with:
+
+```shell
+yarn add @stripe/stripe-js
+# or
+npm install @stripe/stripe-js
+```
+
+If you are using React, you should also consider installing `@stripe/react-stripe-js`, which is a wrapper around Stripe Elements.
+
+The high-level workflow is:
+1. Create a "payment intent" on the server by executing the `createStripePaymentIntent` mutation which is exposed by this plugin.
+2. Use the returned client secret to instantiate the Stripe Payment Element:
+   ```ts
+   import { Elements } from '@stripe/react-stripe-js';
+   import { loadStripe, Stripe } from '@stripe/stripe-js';
+   import { CheckoutForm } from './CheckoutForm';
+
+   const stripePromise = getStripe('pk_test_....wr83u');
+
+   type StripePaymentsProps = {
+     clientSecret: string;
+     orderCode: string;
+   }
+
+   export function StripePayments({ clientSecret, orderCode }: StripePaymentsProps) {
+     const options = {
+       // passing the client secret obtained from the server
+       clientSecret,
+     }
+     return (
+       <Elements stripe={stripePromise} options={options}>
+         <CheckoutForm orderCode={orderCode} />
+       </Elements>
+     );
+   }
+   ```
+   ```ts
+   // CheckoutForm.tsx
+   import { useStripe, useElements, PaymentElement } from '@stripe/react-stripe-js';
+   import { FormEvent } from 'react';
+
+   export const CheckoutForm = ({ orderCode }: { orderCode: string }) => {
+     const stripe = useStripe();
+     const elements = useElements();
+
+     const handleSubmit = async (event: FormEvent) => {
+       // We don't want to let default form submission happen here,
+       // which would refresh the page.
+       event.preventDefault();
+
+       if (!stripe || !elements) {
+         // Stripe.js has not yet loaded.
+         // Make sure to disable form submission until Stripe.js has loaded.
+         return;
+       }
+
+       const result = await stripe.confirmPayment({
+         //`Elements` instance that was used to create the Payment Element
+         elements,
+         confirmParams: {
+           return_url: location.origin + `/checkout/confirmation/${orderCode}`,
+         },
+       });
+
+       if (result.error) {
+         // Show error to your customer (for example, payment details incomplete)
+         console.log(result.error.message);
+       } else {
+         // Your customer will be redirected to your `return_url`. For some payment
+         // methods like iDEAL, your customer will be redirected to an intermediate
+         // site first to authorize the payment, then redirected to the `return_url`.
+       }
+     };
+
+     return (
+       <form onSubmit={handleSubmit}>
+         <PaymentElement />
+         <button disabled={!stripe}>Submit</button>
+       </form>
+     );
+   };
+   ```
+3. Once the form is submitted and Stripe processes the payment, the webhook takes care of updating the order without additional action
+in the storefront. As in the code above, the customer will be redirected to `/checkout/confirmation/${orderCode}`.
+
+:::info
+A full working storefront example of the Stripe integration can be found in the
+[Remix Starter repo](https://github.com/vendure-ecommerce/storefront-remix-starter/tree/master/app/components/checkout/stripe)
+:::
+
+## Local development
+
+1. Download & install the Stripe CLI: https://stripe.com/docs/stripe-cli
+2. From your Stripe dashboard, go to Developers -> Webhooks and click "Add an endpoint" and follow the instructions
+under "Test in a local environment".
+3. The Stripe CLI command will look like
+   ```shell
+   stripe listen --forward-to localhost:3000/payments/stripe
+   ```
 4. The Stripe CLI will create a webhook signing secret you can then use in your config of the StripePlugin.
 
 ```ts title="Signature"
@@ -189,20 +189,20 @@ Configuration options for the Stripe payments plugin.
 ```ts title="Signature"
 interface StripePluginOptions {
     storeCustomersInStripe?: boolean;
-    metadata?: (
-        injector: Injector,
-        ctx: RequestContext,
-        order: Order,
+    metadata?: (
+        injector: Injector,
+        ctx: RequestContext,
+        order: Order,
     ) => Stripe.MetadataParam | Promise<Stripe.MetadataParam>;
-    paymentIntentCreateParams?: (
-        injector: Injector,
-        ctx: RequestContext,
-        order: Order,
+    paymentIntentCreateParams?: (
+        injector: Injector,
+        ctx: RequestContext,
+        order: Order,
     ) => AdditionalPaymentIntentCreateParams | Promise<AdditionalPaymentIntentCreateParams>;
-    customerCreateParams?: (
-        injector: Injector,
-        ctx: RequestContext,
-        order: Order,
+    customerCreateParams?: (
+        injector: Injector,
+        ctx: RequestContext,
+        order: Order,
     ) => AdditionalCustomerCreateParams | Promise<AdditionalCustomerCreateParams>;
 }
 ```
@@ -213,13 +213,13 @@ interface StripePluginOptions {
 
 <MemberInfo kind="property" type={`boolean`} default={`false`}   />
 
-If set to `true`, a [Customer](https://stripe.com/docs/api/customers) object will be created in Stripe - if
-it doesn't already exist - for authenticated users, which prevents payment methods attached to other Customers
-to be used with the same PaymentIntent. This is done by adding a custom field to the Customer entity to store
+If set to `true`, a [Customer](https://stripe.com/docs/api/customers) object will be created in Stripe - if
+it doesn't already exist - for authenticated users, which prevents payment methods attached to other Customers
+to be used with the same PaymentIntent. This is done by adding a custom field to the Customer entity to store
 the Stripe customer ID, so switching this on will require a database migration / synchronization.
 ### metadata
 
-<MemberInfo kind="property" type={`(
         injector: <a href='/reference/typescript-api/common/injector#injector'>Injector</a>,
         ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>,
         order: <a href='/reference/typescript-api/entities/order#order'>Order</a>,
     ) =&#62; Stripe.MetadataParam | Promise&#60;Stripe.MetadataParam&#62;`}  since="1.9.7"  />
+<MemberInfo kind="property" type={`(         injector: <a href='/reference/typescript-api/common/injector#injector'>Injector</a>,         ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>,         order: <a href='/reference/typescript-api/entities/order#order'>Order</a>,     ) =&#62; Stripe.MetadataParam | Promise&#60;Stripe.MetadataParam&#62;`}  since="1.9.7"  />
 
 Attach extra metadata to Stripe payment intent creation call.
 
@@ -249,11 +249,11 @@ Note: If the `paymentIntentCreateParams` is also used and returns a `metadata` k
 returned by both functions will be merged.
 ### paymentIntentCreateParams
 
-<MemberInfo kind="property" type={`(
         injector: <a href='/reference/typescript-api/common/injector#injector'>Injector</a>,
         ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>,
         order: <a href='/reference/typescript-api/entities/order#order'>Order</a>,
     ) =&#62; AdditionalPaymentIntentCreateParams | Promise&#60;AdditionalPaymentIntentCreateParams&#62;`}  since="2.1.0"  />
+<MemberInfo kind="property" type={`(         injector: <a href='/reference/typescript-api/common/injector#injector'>Injector</a>,         ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>,         order: <a href='/reference/typescript-api/entities/order#order'>Order</a>,     ) =&#62; AdditionalPaymentIntentCreateParams | Promise&#60;AdditionalPaymentIntentCreateParams&#62;`}  since="2.1.0"  />
+
+Provide additional parameters to the Stripe payment intent creation. By default,
+the plugin will already pass the `amount`, `currency`, `customer` and `automatic_payment_methods: { enabled: true }` parameters.
 
-Provide additional parameters to the Stripe payment intent creation. By default,
-the plugin will already pass the `amount`, `currency`, `customer` and `automatic_payment_methods: { enabled: true }` parameters.
-
 For example, if you want to provide a `description` for the payment intent, you can do so like this:
 
 *Example*
@@ -277,11 +277,11 @@ export const config: VendureConfig = {
 ```
 ### customerCreateParams
 
-<MemberInfo kind="property" type={`(
         injector: <a href='/reference/typescript-api/common/injector#injector'>Injector</a>,
         ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>,
         order: <a href='/reference/typescript-api/entities/order#order'>Order</a>,
     ) =&#62; AdditionalCustomerCreateParams | Promise&#60;AdditionalCustomerCreateParams&#62;`}  since="2.1.0"  />
+<MemberInfo kind="property" type={`(         injector: <a href='/reference/typescript-api/common/injector#injector'>Injector</a>,         ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>,         order: <a href='/reference/typescript-api/entities/order#order'>Order</a>,     ) =&#62; AdditionalCustomerCreateParams | Promise&#60;AdditionalCustomerCreateParams&#62;`}  since="2.1.0"  />
+
+Provide additional parameters to the Stripe customer creation. By default,
+the plugin will already pass the `email` and `name` parameters.
 
-Provide additional parameters to the Stripe customer creation. By default,
-the plugin will already pass the `email` and `name` parameters.
-
 For example, if you want to provide an address for the customer:
 
 *Example*

+ 9 - 9
docs/docs/reference/core-plugins/stellate-plugin/purge-rule.md

@@ -13,8 +13,8 @@ import MemberDescription from '@site/src/components/MemberDescription';
 
 <GenerationInfo sourceFile="packages/stellate-plugin/src/purge-rule.ts" sourceLine="49" packageName="@vendure/stellate-plugin" />
 
-Defines a rule that listens for a particular VendureEvent and uses that to
-make calls to the [Stellate Purging API](https://docs.stellate.co/docs/purging-api) via
+Defines a rule that listens for a particular VendureEvent and uses that to
+make calls to the [Stellate Purging API](https://docs.stellate.co/docs/purging-api) via
 the provided <a href='/reference/core-plugins/stellate-plugin/stellate-service#stellateservice'>StellateService</a> instance.
 
 ```ts title="Signature"
@@ -63,10 +63,10 @@ Configures a <a href='/reference/core-plugins/stellate-plugin/purge-rule#purgeru
 interface PurgeRuleConfig<Event extends VendureEvent> {
     eventType: Type<Event>;
     bufferTime?: number;
-    handler: (handlerArgs: {
-        events: Event[];
-        stellateService: StellateService;
-        injector: Injector;
+    handler: (handlerArgs: {
+        events: Event[];
+        stellateService: StellateService;
+        injector: Injector;
     }) => void | Promise<void>;
 }
 ```
@@ -82,13 +82,13 @@ Specifies which VendureEvent will trigger this purge rule.
 
 <MemberInfo kind="property" type={`number`} default={`5000`}   />
 
-How long to buffer events for in milliseconds before executing the handler. This allows
+How long to buffer events for in milliseconds before executing the handler. This allows
 us to efficiently batch calls to the Stellate Purge API.
 ### handler
 
-<MemberInfo kind="property" type={`(handlerArgs: {
         events: Event[];
         stellateService: <a href='/reference/core-plugins/stellate-plugin/stellate-service#stellateservice'>StellateService</a>;
         injector: <a href='/reference/typescript-api/common/injector#injector'>Injector</a>;
     }) =&#62; void | Promise&#60;void&#62;`}   />
+<MemberInfo kind="property" type={`(handlerArgs: {         events: Event[];         stellateService: <a href='/reference/core-plugins/stellate-plugin/stellate-service#stellateservice'>StellateService</a>;         injector: <a href='/reference/typescript-api/common/injector#injector'>Injector</a>;     }) =&#62; void | Promise&#60;void&#62;`}   />
 
-The function to invoke when the specified event is published. This function should use the
+The function to invoke when the specified event is published. This function should use the
 <a href='/reference/core-plugins/stellate-plugin/stellate-service#stellateservice'>StellateService</a> instance to call the Stellate Purge API.
 
 

+ 1 - 1
docs/docs/reference/graphql-api/admin/object-types.md

@@ -802,7 +802,7 @@ import MemberDescription from '@site/src/components/MemberDescription';
 <div class="graphql-code-line top-level comment">"""</div>
 <div class="graphql-code-line top-level comment">This type is deprecated in v2.2 in favor of the EntityCustomFields type,</div>
 
-<div class="graphql-code-line top-level comment">which allows custom fields to be defined on user-supplies entities.</div>
+<div class="graphql-code-line top-level comment">which allows custom fields to be defined on user-supplied entities.</div>
 <div class="graphql-code-line top-level comment">"""</div>
 <div class="graphql-code-line top-level">type <span class="graphql-code-identifier">CustomFields</span> &#123;</div>
 <div class="graphql-code-line ">Address: [<a href="/reference/graphql-api/admin/object-types#customfieldconfig">CustomFieldConfig</a>!]!</div>

+ 28 - 4
docs/docs/reference/graphql-api/shop/mutations.md

@@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription';
 ## addItemToOrder
 <div class="graphql-code-block">
 <div class="graphql-code-line top-level comment">"""</div>
-<div class="graphql-code-line top-level comment">Adds an item to the order. If custom fields are defined on the OrderLine entity, a third argument 'customFields' will be available.</div>
+<div class="graphql-code-line top-level comment">Adds an item to the Order. If custom fields are defined on the OrderLine entity, a third argument 'customFields' will be available.</div>
 <div class="graphql-code-line top-level comment">"""</div>
 <div class="graphql-code-line top-level">type <span class="graphql-code-identifier">Mutation</span> &#123;</div>
 <div class="graphql-code-line ">addItemToOrder(productVariantId: <a href="/reference/graphql-api/shop/object-types#id">ID</a>!, quantity: <a href="/reference/graphql-api/shop/object-types#int">Int</a>!): <a href="/reference/graphql-api/shop/object-types#updateorderitemsresult">UpdateOrderItemsResult</a>!</div>
@@ -267,7 +267,7 @@ import MemberDescription from '@site/src/components/MemberDescription';
 ## setOrderBillingAddress
 <div class="graphql-code-block">
 <div class="graphql-code-line top-level comment">"""</div>
-<div class="graphql-code-line top-level comment">Sets the billing address for this order</div>
+<div class="graphql-code-line top-level comment">Sets the billing address for the active Order</div>
 <div class="graphql-code-line top-level comment">"""</div>
 <div class="graphql-code-line top-level">type <span class="graphql-code-identifier">Mutation</span> &#123;</div>
 <div class="graphql-code-line ">setOrderBillingAddress(input: <a href="/reference/graphql-api/shop/input-types#createaddressinput">CreateAddressInput</a>!): <a href="/reference/graphql-api/shop/object-types#activeorderresult">ActiveOrderResult</a>!</div>
@@ -279,7 +279,7 @@ import MemberDescription from '@site/src/components/MemberDescription';
 ## setOrderCustomFields
 <div class="graphql-code-block">
 <div class="graphql-code-line top-level comment">"""</div>
-<div class="graphql-code-line top-level comment">Allows any custom fields to be set for the active order</div>
+<div class="graphql-code-line top-level comment">Allows any custom fields to be set for the active Order</div>
 <div class="graphql-code-line top-level comment">"""</div>
 <div class="graphql-code-line top-level">type <span class="graphql-code-identifier">Mutation</span> &#123;</div>
 <div class="graphql-code-line ">setOrderCustomFields(input: <a href="/reference/graphql-api/shop/input-types#updateorderinput">UpdateOrderInput</a>!): <a href="/reference/graphql-api/shop/object-types#activeorderresult">ActiveOrderResult</a>!</div>
@@ -291,7 +291,7 @@ import MemberDescription from '@site/src/components/MemberDescription';
 ## setOrderShippingAddress
 <div class="graphql-code-block">
 <div class="graphql-code-line top-level comment">"""</div>
-<div class="graphql-code-line top-level comment">Sets the shipping address for this order</div>
+<div class="graphql-code-line top-level comment">Sets the shipping address for the active Order</div>
 <div class="graphql-code-line top-level comment">"""</div>
 <div class="graphql-code-line top-level">type <span class="graphql-code-identifier">Mutation</span> &#123;</div>
 <div class="graphql-code-line ">setOrderShippingAddress(input: <a href="/reference/graphql-api/shop/input-types#createaddressinput">CreateAddressInput</a>!): <a href="/reference/graphql-api/shop/object-types#activeorderresult">ActiveOrderResult</a>!</div>
@@ -327,6 +327,30 @@ import MemberDescription from '@site/src/components/MemberDescription';
 <div class="graphql-code-line ">transitionOrderToState(state: <a href="/reference/graphql-api/shop/object-types#string">String</a>!): <a href="/reference/graphql-api/shop/object-types#transitionordertostateresult">TransitionOrderToStateResult</a></div>
 
 
+<div class="graphql-code-line top-level">&#125;</div>
+</div>
+
+## unsetOrderBillingAddress
+<div class="graphql-code-block">
+<div class="graphql-code-line top-level comment">"""</div>
+<div class="graphql-code-line top-level comment">Unsets the billing address for the active Order. Available since version 3.1.0</div>
+<div class="graphql-code-line top-level comment">"""</div>
+<div class="graphql-code-line top-level">type <span class="graphql-code-identifier">Mutation</span> &#123;</div>
+<div class="graphql-code-line ">unsetOrderBillingAddress: <a href="/reference/graphql-api/shop/object-types#activeorderresult">ActiveOrderResult</a>!</div>
+
+
+<div class="graphql-code-line top-level">&#125;</div>
+</div>
+
+## unsetOrderShippingAddress
+<div class="graphql-code-block">
+<div class="graphql-code-line top-level comment">"""</div>
+<div class="graphql-code-line top-level comment">Unsets the shipping address for the active Order. Available since version 3.1.0</div>
+<div class="graphql-code-line top-level comment">"""</div>
+<div class="graphql-code-line top-level">type <span class="graphql-code-identifier">Mutation</span> &#123;</div>
+<div class="graphql-code-line ">unsetOrderShippingAddress: <a href="/reference/graphql-api/shop/object-types#activeorderresult">ActiveOrderResult</a>!</div>
+
+
 <div class="graphql-code-line top-level">&#125;</div>
 </div>
 

+ 9 - 9
docs/docs/reference/typescript-api/configurable-operation-def/default-form-config-hash.md

@@ -29,15 +29,15 @@ type DefaultFormConfigHash = {
     'product-selector-form-input': Record<string, never>;
     'relation-form-input': Record<string, never>;
     'rich-text-form-input': Record<string, never>;
-    'select-form-input': {
-        options?: Array<{ value: string; label?: Array<Omit<LocalizedString, '__typename'>> }>;
+    'select-form-input': {
+        options?: Array<{ value: string; label?: Array<Omit<LocalizedString, '__typename'>> }>;
     };
     'text-form-input': { prefix?: string; suffix?: string };
-    'textarea-form-input': {
-        spellcheck?: boolean;
+    'textarea-form-input': {
+        spellcheck?: boolean;
     };
-    'product-multi-form-input': {
-        selectionMode?: 'product' | 'variant';
+    'product-multi-form-input': {
+        selectionMode?: 'product' | 'variant';
     };
     'combination-mode-form-input': Record<string, never>;
 }
@@ -107,7 +107,7 @@ type DefaultFormConfigHash = {
 
 ### 'select-form-input'
 
-<MemberInfo kind="property" type={`{
         options?: Array&#60;{ value: string; label?: Array&#60;Omit&#60;LocalizedString, '__typename'&#62;&#62; }&#62;;
     }`}   />
+<MemberInfo kind="property" type={`{         options?: Array&#60;{ value: string; label?: Array&#60;Omit&#60;LocalizedString, '__typename'&#62;&#62; }&#62;;     }`}   />
 
 
 ### 'text-form-input'
@@ -117,12 +117,12 @@ type DefaultFormConfigHash = {
 
 ### 'textarea-form-input'
 
-<MemberInfo kind="property" type={`{
         spellcheck?: boolean;
     }`}   />
+<MemberInfo kind="property" type={`{         spellcheck?: boolean;     }`}   />
 
 
 ### 'product-multi-form-input'
 
-<MemberInfo kind="property" type={`{
         selectionMode?: 'product' | 'variant';
     }`}   />
+<MemberInfo kind="property" type={`{         selectionMode?: 'product' | 'variant';     }`}   />
 
 
 ### 'combination-mode-form-input'

+ 13 - 13
docs/docs/reference/typescript-api/configuration/entity-duplicator.md

@@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription';
 
 <GenerationInfo sourceFile="packages/core/src/config/entity/entity-duplicator.ts" sourceLine="158" packageName="@vendure/core" since="2.2.0" />
 
-An EntityDuplicator is used to define the logic for duplicating entities when the `duplicateEntity` mutation is called.
+An EntityDuplicator is used to define the logic for duplicating entities when the `duplicateEntity` mutation is called.
 This allows you to add support for duplication of both core and custom entities.
 
 *Example*
@@ -102,11 +102,11 @@ export const config: VendureConfig = {
 ```ts title="Signature"
 class EntityDuplicator<T extends ConfigArgs = ConfigArgs> extends ConfigurableOperationDef<T> {
     constructor(config: EntityDuplicatorConfig<T>)
-    duplicate(input: {
-        ctx: RequestContext;
-        entityName: string;
-        id: ID;
-        args: ConfigArg[];
+    duplicate(input: {
+        ctx: RequestContext;
+        entityName: string;
+        id: ID;
+        args: ConfigArg[];
     }) => Promise<VendureEntity>;
 }
 ```
@@ -123,7 +123,7 @@ class EntityDuplicator<T extends ConfigArgs = ConfigArgs> extends ConfigurableOp
 
 ### duplicate
 
-<MemberInfo kind="method" type={`(input: {
         ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>;
         entityName: string;
         id: <a href='/reference/typescript-api/common/id#id'>ID</a>;
         args: ConfigArg[];
     }) => Promise&#60;<a href='/reference/typescript-api/entities/vendure-entity#vendureentity'>VendureEntity</a>&#62;`}   />
+<MemberInfo kind="method" type={`(input: {         ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>;         entityName: string;         id: <a href='/reference/typescript-api/common/id#id'>ID</a>;         args: ConfigArg[];     }) => Promise&#60;<a href='/reference/typescript-api/entities/vendure-entity#vendureentity'>VendureEntity</a>&#62;`}   />
 
 
 
@@ -138,11 +138,11 @@ class EntityDuplicator<T extends ConfigArgs = ConfigArgs> extends ConfigurableOp
 A function which performs the duplication of an entity.
 
 ```ts title="Signature"
-type DuplicateEntityFn<T extends ConfigArgs> = (input: {
-    ctx: RequestContext;
-    entityName: string;
-    id: ID;
-    args: ConfigArgValues<T>;
+type DuplicateEntityFn<T extends ConfigArgs> = (input: {
+    ctx: RequestContext;
+    entityName: string;
+    id: ID;
+    args: ConfigArgValues<T>;
 }) => Promise<VendureEntity>
 ```
 
@@ -170,7 +170,7 @@ interface EntityDuplicatorConfig<T extends ConfigArgs> extends ConfigurableOpera
 
 <MemberInfo kind="property" type={`Array&#60;<a href='/reference/typescript-api/common/permission#permission'>Permission</a> | string&#62; | <a href='/reference/typescript-api/common/permission#permission'>Permission</a> | string`}   />
 
-The permissions required in order to execute this duplicator. If an array is passed,
+The permissions required in order to execute this duplicator. If an array is passed,
 then the administrator must have at least one of the permissions in the array.
 ### forEntities
 

+ 1 - 2
docs/docs/reference/typescript-api/custom-fields/index.md

@@ -13,8 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription';
 
 <GenerationInfo sourceFile="packages/core/src/config/custom-field/custom-field-types.ts" sourceLine="159" packageName="@vendure/core" />
 
-Most entities can have additional fields added to them by defining an array of <a href='/reference/typescript-api/custom-fields/custom-field-config#customfieldconfig'>CustomFieldConfig</a>
-objects on against the corresponding key.
+Most entities can have additional fields added to them by defining an array of <a href='/reference/typescript-api/custom-fields/custom-field-config#customfieldconfig'>CustomFieldConfig</a>objects on against the corresponding key.
 
 *Example*
 

+ 1 - 2
docs/docs/reference/typescript-api/data-access/calculated.md

@@ -14,8 +14,7 @@ import MemberDescription from '@site/src/components/MemberDescription';
 <GenerationInfo sourceFile="packages/core/src/common/calculated-decorator.ts" sourceLine="43" packageName="@vendure/core" />
 
 Used to define calculated entity getters. The decorator simply attaches an array of "calculated"
-property names to the entity's prototype. This array is then used by the <a href='/reference/typescript-api/data-access/calculated-property-subscriber#calculatedpropertysubscriber'>CalculatedPropertySubscriber</a>
-to transfer the getter function from the prototype to the entity instance.
+property names to the entity's prototype. This array is then used by the <a href='/reference/typescript-api/data-access/calculated-property-subscriber#calculatedpropertysubscriber'>CalculatedPropertySubscriber</a>to transfer the getter function from the prototype to the entity instance.
 
 ```ts title="Signature"
 function Calculated(queryInstruction?: CalculatedColumnQueryInstruction): MethodDecorator

+ 48 - 48
docs/docs/reference/typescript-api/data-access/transactional-connection.md

@@ -13,12 +13,12 @@ import MemberDescription from '@site/src/components/MemberDescription';
 
 <GenerationInfo sourceFile="packages/core/src/connection/transactional-connection.ts" sourceLine="41" packageName="@vendure/core" />
 
-The TransactionalConnection is a wrapper around the TypeORM `Connection` object which works in conjunction
-with the <a href='/reference/typescript-api/request/transaction-decorator#transaction'>Transaction</a> decorator to implement per-request transactions. All services which access the
-database should use this class rather than the raw TypeORM connection, to ensure that db changes can be
-easily wrapped in transactions when required.
-
-The service layer does not need to know about the scope of a transaction, as this is covered at the
+The TransactionalConnection is a wrapper around the TypeORM `Connection` object which works in conjunction
+with the <a href='/reference/typescript-api/request/transaction-decorator#transaction'>Transaction</a> decorator to implement per-request transactions. All services which access the
+database should use this class rather than the raw TypeORM connection, to ensure that db changes can be
+easily wrapped in transactions when required.
+
+The service layer does not need to know about the scope of a transaction, as this is covered at the
 API by the use of the `Transaction` decorator.
 
 ```ts title="Signature"
@@ -26,11 +26,11 @@ class TransactionalConnection {
     constructor(dataSource: DataSource, transactionWrapper: TransactionWrapper)
     rawConnection: DataSource
     getRepository(target: ObjectType<Entity> | EntitySchema<Entity> | string) => Repository<Entity>;
-    getRepository(ctx: RequestContext | undefined, target: ObjectType<Entity> | EntitySchema<Entity> | string, options?: {
-            replicationMode?: ReplicationMode;
+    getRepository(ctx: RequestContext | undefined, target: ObjectType<Entity> | EntitySchema<Entity> | string, options?: {
+            replicationMode?: ReplicationMode;
         }) => Repository<Entity>;
-    getRepository(ctxOrTarget: RequestContext | ObjectType<Entity> | EntitySchema<Entity> | string | undefined, maybeTarget?: ObjectType<Entity> | EntitySchema<Entity> | string, options?: {
-            replicationMode?: ReplicationMode;
+    getRepository(ctxOrTarget: RequestContext | ObjectType<Entity> | EntitySchema<Entity> | string | undefined, maybeTarget?: ObjectType<Entity> | EntitySchema<Entity> | string, options?: {
+            replicationMode?: ReplicationMode;
         }) => Repository<Entity>;
     withTransaction(work: (ctx: RequestContext) => Promise<T>) => Promise<T>;
     withTransaction(ctx: RequestContext, work: (ctx: RequestContext) => Promise<T>) => Promise<T>;
@@ -55,53 +55,53 @@ class TransactionalConnection {
 
 <MemberInfo kind="property" type={`DataSource`}   />
 
-The plain TypeORM Connection object. Should be used carefully as any operations
-performed with this connection will not be performed within any outer
+The plain TypeORM Connection object. Should be used carefully as any operations
+performed with this connection will not be performed within any outer
 transactions.
 ### getRepository
 
 <MemberInfo kind="method" type={`(target: ObjectType&#60;Entity&#62; | EntitySchema&#60;Entity&#62; | string) => Repository&#60;Entity&#62;`}   />
 
-Returns a TypeORM repository. Note that when no RequestContext is supplied, the repository will not
-be aware of any existing transaction. Therefore, calling this method without supplying a RequestContext
+Returns a TypeORM repository. Note that when no RequestContext is supplied, the repository will not
+be aware of any existing transaction. Therefore, calling this method without supplying a RequestContext
 is discouraged without a deliberate reason.
 ### getRepository
 
-<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a> | undefined, target: ObjectType&#60;Entity&#62; | EntitySchema&#60;Entity&#62; | string, options?: {
             replicationMode?: ReplicationMode;
         }) => Repository&#60;Entity&#62;`}   />
+<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a> | undefined, target: ObjectType&#60;Entity&#62; | EntitySchema&#60;Entity&#62; | string, options?: {             replicationMode?: ReplicationMode;         }) => Repository&#60;Entity&#62;`}   />
+
+Returns a TypeORM repository which is bound to any existing transactions. It is recommended to _always_ pass
+the RequestContext argument when possible, otherwise the queries will be executed outside of any
+ongoing transactions which have been started by the <a href='/reference/typescript-api/request/transaction-decorator#transaction'>Transaction</a> decorator.
 
-Returns a TypeORM repository which is bound to any existing transactions. It is recommended to _always_ pass
-the RequestContext argument when possible, otherwise the queries will be executed outside of any
-ongoing transactions which have been started by the <a href='/reference/typescript-api/request/transaction-decorator#transaction'>Transaction</a> decorator.
-
-The `options` parameter allows specifying additional configurations, such as the `replicationMode`,
+The `options` parameter allows specifying additional configurations, such as the `replicationMode`,
 which determines whether the repository should interact with the master or replica database.
 ### getRepository
 
-<MemberInfo kind="method" type={`(ctxOrTarget: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a> | ObjectType&#60;Entity&#62; | EntitySchema&#60;Entity&#62; | string | undefined, maybeTarget?: ObjectType&#60;Entity&#62; | EntitySchema&#60;Entity&#62; | string, options?: {
             replicationMode?: ReplicationMode;
         }) => Repository&#60;Entity&#62;`}   />
+<MemberInfo kind="method" type={`(ctxOrTarget: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a> | ObjectType&#60;Entity&#62; | EntitySchema&#60;Entity&#62; | string | undefined, maybeTarget?: ObjectType&#60;Entity&#62; | EntitySchema&#60;Entity&#62; | string, options?: {             replicationMode?: ReplicationMode;         }) => Repository&#60;Entity&#62;`}   />
 
-Returns a TypeORM repository. Depending on the parameters passed, it will either be transaction-aware
-or not. If `RequestContext` is provided, the repository is bound to any ongoing transactions. The
+Returns a TypeORM repository. Depending on the parameters passed, it will either be transaction-aware
+or not. If `RequestContext` is provided, the repository is bound to any ongoing transactions. The
 `options` parameter allows further customization, such as selecting the replication mode (e.g., 'master').
 ### withTransaction
 
 <MemberInfo kind="method" type={`(work: (ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>) =&#62; Promise&#60;T&#62;) => Promise&#60;T&#62;`}  since="1.3.0"  />
 
-Allows database operations to be wrapped in a transaction, ensuring that in the event of an error being
-thrown at any point, the entire transaction will be rolled back and no changes will be saved.
-
-In the context of API requests, you should instead use the <a href='/reference/typescript-api/request/transaction-decorator#transaction'>Transaction</a> decorator on your resolver or
-controller method.
-
-On the other hand, for code that does not run in the context of a GraphQL/REST request, this method
-should be used to protect against non-atomic changes to the data which could leave your data in an
-inconsistent state.
-
-Such situations include function processed by the JobQueue or stand-alone scripts which make use
-of Vendure internal services.
-
-If there is already a <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a> object available, you should pass it in as the first
-argument in order to create transactional context as the copy. If not, omit the first argument and an empty
-RequestContext object will be created, which is then used to propagate the transaction to
+Allows database operations to be wrapped in a transaction, ensuring that in the event of an error being
+thrown at any point, the entire transaction will be rolled back and no changes will be saved.
+
+In the context of API requests, you should instead use the <a href='/reference/typescript-api/request/transaction-decorator#transaction'>Transaction</a> decorator on your resolver or
+controller method.
+
+On the other hand, for code that does not run in the context of a GraphQL/REST request, this method
+should be used to protect against non-atomic changes to the data which could leave your data in an
+inconsistent state.
+
+Such situations include function processed by the JobQueue or stand-alone scripts which make use
+of Vendure internal services.
+
+If there is already a <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a> object available, you should pass it in as the first
+argument in order to create transactional context as the copy. If not, omit the first argument and an empty
+RequestContext object will be created, which is then used to propagate the transaction to
 all inner method calls.
 
 *Example*
@@ -137,40 +137,40 @@ private async transferCredit(outerCtx: RequestContext, fromId: ID, toId: ID, amo
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, isolationLevel?: <a href='/reference/typescript-api/request/transaction-decorator#transactionisolationlevel'>TransactionIsolationLevel</a>) => `}   />
 
-Manually start a transaction if one is not already in progress. This method should be used in
+Manually start a transaction if one is not already in progress. This method should be used in
 conjunction with the `'manual'` mode of the <a href='/reference/typescript-api/request/transaction-decorator#transaction'>Transaction</a> decorator.
 ### commitOpenTransaction
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>) => `}   />
 
-Manually commits any open transaction. Should be very rarely needed, since the <a href='/reference/typescript-api/request/transaction-decorator#transaction'>Transaction</a> decorator
-and the internal TransactionInterceptor take care of this automatically. Use-cases include situations
-in which the worker thread needs to access changes made in the current transaction, or when using the
+Manually commits any open transaction. Should be very rarely needed, since the <a href='/reference/typescript-api/request/transaction-decorator#transaction'>Transaction</a> decorator
+and the internal TransactionInterceptor take care of this automatically. Use-cases include situations
+in which the worker thread needs to access changes made in the current transaction, or when using the
 Transaction decorator in manual mode.
 ### rollBackTransaction
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>) => `}   />
 
-Manually rolls back any open transaction. Should be very rarely needed, since the <a href='/reference/typescript-api/request/transaction-decorator#transaction'>Transaction</a> decorator
-and the internal TransactionInterceptor take care of this automatically. Use-cases include when using the
+Manually rolls back any open transaction. Should be very rarely needed, since the <a href='/reference/typescript-api/request/transaction-decorator#transaction'>Transaction</a> decorator
+and the internal TransactionInterceptor take care of this automatically. Use-cases include when using the
 Transaction decorator in manual mode.
 ### getEntityOrThrow
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, entityType: Type&#60;T&#62;, id: <a href='/reference/typescript-api/common/id#id'>ID</a>, options: <a href='/reference/typescript-api/data-access/get-entity-or-throw-options#getentityorthrowoptions'>GetEntityOrThrowOptions</a>&#60;T&#62; = {}) => Promise&#60;T&#62;`}   />
 
-Finds an entity of the given type by ID, or throws an `EntityNotFoundError` if none
+Finds an entity of the given type by ID, or throws an `EntityNotFoundError` if none
 is found.
 ### findOneInChannel
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, entity: Type&#60;T&#62;, id: <a href='/reference/typescript-api/common/id#id'>ID</a>, channelId: <a href='/reference/typescript-api/common/id#id'>ID</a>, options: FindOneOptions&#60;T&#62; = {}) => `}   />
 
-Like the TypeOrm `Repository.findOne()` method, but limits the results to
+Like the TypeOrm `Repository.findOne()` method, but limits the results to
 the given Channel.
 ### findByIdsInChannel
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, entity: Type&#60;T&#62;, ids: <a href='/reference/typescript-api/common/id#id'>ID</a>[], channelId: <a href='/reference/typescript-api/common/id#id'>ID</a>, options: FindManyOptions&#60;T&#62;) => `}   />
 
-Like the TypeOrm `Repository.findByIds()` method, but limits the results to
+Like the TypeOrm `Repository.findByIds()` method, but limits the results to
 the given Channel.
 
 

+ 30 - 30
docs/docs/reference/typescript-api/entities/promotion.md

@@ -13,42 +13,42 @@ import MemberDescription from '@site/src/components/MemberDescription';
 
 <GenerationInfo sourceFile="packages/core/src/entity/promotion/promotion.entity.ts" sourceLine="61" packageName="@vendure/core" />
 
-A Promotion is used to define a set of conditions under which promotions actions (typically discounts)
-will be applied to an Order.
-
-Each assigned <a href='/reference/typescript-api/promotions/promotion-condition#promotioncondition'>PromotionCondition</a> is checked against the Order, and if they all return `true`,
+A Promotion is used to define a set of conditions under which promotions actions (typically discounts)
+will be applied to an Order.
+
+Each assigned <a href='/reference/typescript-api/promotions/promotion-condition#promotioncondition'>PromotionCondition</a> is checked against the Order, and if they all return `true`,
 then each assign <a href='/reference/typescript-api/promotions/promotion-action#promotionitemaction'>PromotionItemAction</a> / <a href='/reference/typescript-api/promotions/promotion-action#promotionlineaction'>PromotionLineAction</a> / <a href='/reference/typescript-api/promotions/promotion-action#promotionorderaction'>PromotionOrderAction</a> / <a href='/reference/typescript-api/promotions/promotion-action#promotionshippingaction'>PromotionShippingAction</a> is applied to the Order.
 
 ```ts title="Signature"
 class Promotion extends AdjustmentSource implements ChannelAware, SoftDeletable, HasCustomFields, Translatable {
     type = AdjustmentType.PROMOTION;
-    constructor(input?: DeepPartial<Promotion> & {
-            promotionConditions?: Array<PromotionCondition<any>>;
-            promotionActions?: Array<PromotionAction<any>>;
+    constructor(input?: DeepPartial<Promotion> & {
+            promotionConditions?: Array<PromotionCondition<any>>;
+            promotionActions?: Array<PromotionAction<any>>;
         })
-    @Column({ type: Date, nullable: true })
+    @Column({ type: Date, nullable: true })
     deletedAt: Date | null;
-    @Column({ type: Date, nullable: true })
+    @Column({ type: Date, nullable: true })
     startsAt: Date | null;
-    @Column({ type: Date, nullable: true })
+    @Column({ type: Date, nullable: true })
     endsAt: Date | null;
-    @Column({ nullable: true })
+    @Column({ nullable: true })
     couponCode: string;
-    @Column({ nullable: true })
+    @Column({ nullable: true })
     perCustomerUsageLimit: number;
-    @Column({ nullable: true })
+    @Column({ nullable: true })
     usageLimit: number;
     name: LocaleString;
     description: LocaleString;
-    @OneToMany(type => PromotionTranslation, translation => translation.base, { eager: true })
+    @OneToMany(type => PromotionTranslation, translation => translation.base, { eager: true })
     translations: Array<Translation<Promotion>>;
     @Column() enabled: boolean;
-    @ManyToMany(type => Channel, channel => channel.promotions)
-    @JoinTable()
+    @ManyToMany(type => Channel, channel => channel.promotions)
+    @JoinTable()
     channels: Channel[];
-    @ManyToMany(type => Order, order => order.promotions)
+    @ManyToMany(type => Order, order => order.promotions)
     orders: Order[];
-    @Column(type => CustomPromotionFields)
+    @Column(type => CustomPromotionFields)
     customFields: CustomPromotionFields;
     @Column('simple-json') conditions: ConfigurableOperation[];
     @Column('simple-json') actions: ConfigurableOperation[];
@@ -75,7 +75,7 @@ class Promotion extends AdjustmentSource implements ChannelAware, SoftDeletable,
 
 ### constructor
 
-<MemberInfo kind="method" type={`(input?: DeepPartial&#60;<a href='/reference/typescript-api/entities/promotion#promotion'>Promotion</a>&#62; &#38; {
             promotionConditions?: Array&#60;<a href='/reference/typescript-api/promotions/promotion-condition#promotioncondition'>PromotionCondition</a>&#60;any&#62;&#62;;
             promotionActions?: Array&#60;<a href='/reference/typescript-api/promotions/promotion-action#promotionaction'>PromotionAction</a>&#60;any&#62;&#62;;
         }) => Promotion`}   />
+<MemberInfo kind="method" type={`(input?: DeepPartial&#60;<a href='/reference/typescript-api/entities/promotion#promotion'>Promotion</a>&#62; &#38; {             promotionConditions?: Array&#60;<a href='/reference/typescript-api/promotions/promotion-condition#promotioncondition'>PromotionCondition</a>&#60;any&#62;&#62;;             promotionActions?: Array&#60;<a href='/reference/typescript-api/promotions/promotion-action#promotionaction'>PromotionAction</a>&#60;any&#62;&#62;;         }) => Promotion`}   />
 
 
 ### deletedAt
@@ -157,17 +157,17 @@ class Promotion extends AdjustmentSource implements ChannelAware, SoftDeletable,
 
 <MemberInfo kind="property" type={`number`}   />
 
-The PriorityScore is used to determine the sequence in which multiple promotions are tested
-on a given order. A higher number moves the Promotion towards the end of the sequence.
-
-The score is derived from the sum of the priorityValues of the PromotionConditions and
-PromotionActions comprising this Promotion.
-
-An example illustrating the need for a priority is this:
-
-
-Consider 2 Promotions, 1) buy 1 get one free and 2) 10% off when order total is over $50.
-If Promotion 2 is evaluated prior to Promotion 1, then it can trigger the 10% discount even
+The PriorityScore is used to determine the sequence in which multiple promotions are tested
+on a given order. A higher number moves the Promotion towards the end of the sequence.
+
+The score is derived from the sum of the priorityValues of the PromotionConditions and
+PromotionActions comprising this Promotion.
+
+An example illustrating the need for a priority is this:
+
+
+Consider 2 Promotions, 1) buy 1 get one free and 2) 10% off when order total is over $50.
+If Promotion 2 is evaluated prior to Promotion 1, then it can trigger the 10% discount even
 if the subsequent application of Promotion 1 brings the order total down to way below $50.
 ### apply
 

+ 44 - 44
docs/docs/reference/typescript-api/events/event-types.md

@@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription';
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/account-registration-event.ts" sourceLine="13" packageName="@vendure/core" />
 
-This event is fired when a new user registers an account, either as a stand-alone signup or after
+This event is fired when a new user registers an account, either as a stand-alone signup or after
 placing an order.
 
 ```ts title="Signature"
@@ -41,7 +41,7 @@ class AccountRegistrationEvent extends VendureEvent {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/account-verified-event.ts" sourceLine="13" packageName="@vendure/core" />
 
-This event is fired when a users email address successfully gets verified after
+This event is fired when a users email address successfully gets verified after
 the `verifyCustomerAccount` mutation was executed.
 
 ```ts title="Signature"
@@ -96,7 +96,7 @@ class AdministratorEvent extends VendureEntityEvent<Administrator, Administrator
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/asset-channel-event.ts" sourceLine="15" packageName="@vendure/core" />
 
-This event is fired whenever an <a href='/reference/typescript-api/entities/asset#asset'>Asset</a> is assigned or removed
+This event is fired whenever an <a href='/reference/typescript-api/entities/asset#asset'>Asset</a> is assigned or removed
 From a channel.
 
 ```ts title="Signature"
@@ -157,8 +157,8 @@ class AssetEvent extends VendureEntityEvent<Asset, AssetInputTypes> {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/attempted-login-event.ts" sourceLine="14" packageName="@vendure/core" />
 
-This event is fired when an attempt is made to log in via the shop or admin API `login` mutation.
-The `strategy` represents the name of the AuthenticationStrategy used in the login attempt.
+This event is fired when an attempt is made to log in via the shop or admin API `login` mutation.
+The `strategy` represents the name of the AuthenticationStrategy used in the login attempt.
 If the "native" strategy is used, the additional `identifier` property will be available.
 
 ```ts title="Signature"
@@ -186,7 +186,7 @@ class AttemptedLoginEvent extends VendureEvent {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/change-channel-event.ts" sourceLine="17" packageName="@vendure/core" since="1.4" />
 
-This event is fired whenever an <a href='/reference/typescript-api/entities/interfaces#channelaware'>ChannelAware</a> entity is assigned or removed
+This event is fired whenever an <a href='/reference/typescript-api/entities/interfaces#channelaware'>ChannelAware</a> entity is assigned or removed
 from a channel. The entity property contains the value before updating the channels.
 
 ```ts title="Signature"
@@ -268,10 +268,10 @@ class CollectionEvent extends VendureEntityEvent<Collection, CollectionInputType
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/collection-modification-event.ts" sourceLine="18" packageName="@vendure/core" />
 
-This event is fired whenever a Collection is modified in some way. The `productVariantIds`
-argument is an array of ids of all ProductVariants which:
-
-1. were part of this collection prior to modification and are no longer
+This event is fired whenever a Collection is modified in some way. The `productVariantIds`
+argument is an array of ids of all ProductVariants which:
+
+1. were part of this collection prior to modification and are no longer
 2. are now part of this collection after modification but were not before
 
 ```ts title="Signature"
@@ -326,7 +326,7 @@ class CountryEvent extends VendureEntityEvent<Country, CountryInputTypes> {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/coupon-code-event.ts" sourceLine="15" packageName="@vendure/core" since="1.4" />
 
-This event is fired whenever an coupon code of an active <a href='/reference/typescript-api/entities/promotion#promotion'>Promotion</a>
+This event is fired whenever an coupon code of an active <a href='/reference/typescript-api/entities/promotion#promotion'>Promotion</a>
 is assigned or removed to an <a href='/reference/typescript-api/entities/order#order'>Order</a>.
 
 ```ts title="Signature"
@@ -354,7 +354,7 @@ class CouponCodeEvent extends VendureEvent {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/customer-address-event.ts" sourceLine="22" packageName="@vendure/core" since="1.4" />
 
-This event is fired whenever a <a href='/reference/typescript-api/entities/address#address'>Address</a> is added, updated
+This event is fired whenever a <a href='/reference/typescript-api/entities/address#address'>Address</a> is added, updated
 or deleted.
 
 ```ts title="Signature"
@@ -388,7 +388,7 @@ class CustomerAddressEvent extends VendureEntityEvent<Address, CustomerAddressIn
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/customer-event.ts" sourceLine="22" packageName="@vendure/core" />
 
-This event is fired whenever a <a href='/reference/typescript-api/entities/customer#customer'>Customer</a> is added, updated
+This event is fired whenever a <a href='/reference/typescript-api/entities/customer#customer'>Customer</a> is added, updated
 or deleted.
 
 ```ts title="Signature"
@@ -422,7 +422,7 @@ class CustomerEvent extends VendureEntityEvent<Customer, CustomerInputTypes> {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/customer-group-change-event.ts" sourceLine="15" packageName="@vendure/core" since="1.4" />
 
-This event is fired whenever one or more <a href='/reference/typescript-api/entities/customer#customer'>Customer</a> is assigned to or removed from a
+This event is fired whenever one or more <a href='/reference/typescript-api/entities/customer#customer'>Customer</a> is assigned to or removed from a
 <a href='/reference/typescript-api/entities/customer-group#customergroup'>CustomerGroup</a>.
 
 ```ts title="Signature"
@@ -585,7 +585,7 @@ class FulfillmentStateTransitionEvent extends VendureEvent {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/global-settings-event.ts" sourceLine="16" packageName="@vendure/core" since="1.4" />
 
-This event is fired whenever a <a href='/reference/typescript-api/entities/global-settings#globalsettings'>GlobalSettings</a> is added. The type is always `updated`, because it's
+This event is fired whenever a <a href='/reference/typescript-api/entities/global-settings#globalsettings'>GlobalSettings</a> is added. The type is always `updated`, because it's
 only created once and never deleted.
 
 ```ts title="Signature"
@@ -646,7 +646,7 @@ class HistoryEntryEvent extends VendureEntityEvent<HistoryEntry, HistoryInput> {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/identifier-change-event.ts" sourceLine="13" packageName="@vendure/core" />
 
-This event is fired when a registered user successfully changes the identifier (ie email address)
+This event is fired when a registered user successfully changes the identifier (ie email address)
 associated with their account.
 
 ```ts title="Signature"
@@ -674,7 +674,7 @@ class IdentifierChangeEvent extends VendureEvent {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/identifier-change-request-event.ts" sourceLine="13" packageName="@vendure/core" />
 
-This event is fired when a registered user requests to update the identifier (ie email address)
+This event is fired when a registered user requests to update the identifier (ie email address)
 associated with the account.
 
 ```ts title="Signature"
@@ -783,7 +783,7 @@ class LogoutEvent extends VendureEvent {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/order-event.ts" sourceLine="13" packageName="@vendure/core" />
 
-This event is fired whenever an <a href='/reference/typescript-api/entities/order#order'>Order</a> is added, updated
+This event is fired whenever an <a href='/reference/typescript-api/entities/order#order'>Order</a> is added, updated
 or deleted.
 
 ```ts title="Signature"
@@ -811,7 +811,7 @@ class OrderEvent extends VendureEvent {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/order-line-event.ts" sourceLine="13" packageName="@vendure/core" />
 
-This event is fired whenever an <a href='/reference/typescript-api/entities/order-line#orderline'>OrderLine</a> is added, updated
+This event is fired whenever an <a href='/reference/typescript-api/entities/order-line#orderline'>OrderLine</a> is added, updated
 or deleted.
 
 ```ts title="Signature"
@@ -839,10 +839,10 @@ class OrderLineEvent extends VendureEvent {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/order-placed-event.ts" sourceLine="17" packageName="@vendure/core" />
 
-This event is fired whenever an <a href='/reference/typescript-api/entities/order#order'>Order</a> is set as "placed", which by default is
-when it transitions from 'ArrangingPayment' to either 'PaymentAuthorized' or 'PaymentSettled'.
-
-Note that the exact point that it is set as "placed" can be configured according to the
+This event is fired whenever an <a href='/reference/typescript-api/entities/order#order'>Order</a> is set as "placed", which by default is
+when it transitions from 'ArrangingPayment' to either 'PaymentAuthorized' or 'PaymentSettled'.
+
+Note that the exact point that it is set as "placed" can be configured according to the
 <a href='/reference/typescript-api/orders/order-placed-strategy#orderplacedstrategy'>OrderPlacedStrategy</a>.
 
 ```ts title="Signature"
@@ -951,7 +951,7 @@ class PasswordResetVerifiedEvent extends VendureEvent {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/payment-method-event.ts" sourceLine="18" packageName="@vendure/core" />
 
-This event is fired whenever a <a href='/reference/typescript-api/entities/payment-method#paymentmethod'>PaymentMethod</a> is added, updated
+This event is fired whenever a <a href='/reference/typescript-api/entities/payment-method#paymentmethod'>PaymentMethod</a> is added, updated
 or deleted.
 
 ```ts title="Signature"
@@ -979,7 +979,7 @@ class PaymentMethodEvent extends VendureEntityEvent<PaymentMethod, PaymentMethod
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/payment-state-transition-event.ts" sourceLine="15" packageName="@vendure/core" />
 
-This event is fired whenever a <a href='/reference/typescript-api/entities/payment#payment'>Payment</a> transitions from one <a href='/reference/typescript-api/payment/payment-state#paymentstate'>PaymentState</a> to another, e.g.
+This event is fired whenever a <a href='/reference/typescript-api/entities/payment#payment'>Payment</a> transitions from one <a href='/reference/typescript-api/payment/payment-state#paymentstate'>PaymentState</a> to another, e.g.
 a Payment is authorized by the payment provider.
 
 ```ts title="Signature"
@@ -1007,7 +1007,7 @@ class PaymentStateTransitionEvent extends VendureEvent {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/product-channel-event.ts" sourceLine="15" packageName="@vendure/core" />
 
-This event is fired whenever a <a href='/reference/typescript-api/entities/product#product'>Product</a> is added, updated
+This event is fired whenever a <a href='/reference/typescript-api/entities/product#product'>Product</a> is added, updated
 or deleted.
 
 ```ts title="Signature"
@@ -1035,7 +1035,7 @@ class ProductChannelEvent extends VendureEvent {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/product-event.ts" sourceLine="18" packageName="@vendure/core" />
 
-This event is fired whenever a <a href='/reference/typescript-api/entities/product#product'>Product</a> is added, updated
+This event is fired whenever a <a href='/reference/typescript-api/entities/product#product'>Product</a> is added, updated
 or deleted.
 
 ```ts title="Signature"
@@ -1126,14 +1126,14 @@ class ProductOptionGroupChangeEvent extends VendureEvent {
 This event is fired whenever a <a href='/reference/typescript-api/entities/product-option-group#productoptiongroup'>ProductOptionGroup</a> is added or updated.
 
 ```ts title="Signature"
-class ProductOptionGroupEvent extends VendureEntityEvent<
-    ProductOptionGroup,
-    ProductOptionGroupInputTypes
+class ProductOptionGroupEvent extends VendureEntityEvent<
+    ProductOptionGroup,
+    ProductOptionGroupInputTypes
 > {
     constructor(ctx: RequestContext, entity: ProductOptionGroup, type: 'created' | 'updated' | 'deleted', input?: ProductOptionGroupInputTypes)
 }
 ```
-* Extends: <code><a href='/reference/typescript-api/events/vendure-entity-event#vendureentityevent'>VendureEntityEvent</a>&#60;
     <a href='/reference/typescript-api/entities/product-option-group#productoptiongroup'>ProductOptionGroup</a>,
     ProductOptionGroupInputTypes
 &#62;</code>
+* Extends: <code><a href='/reference/typescript-api/events/vendure-entity-event#vendureentityevent'>VendureEntityEvent</a>&#60;     <a href='/reference/typescript-api/entities/product-option-group#productoptiongroup'>ProductOptionGroup</a>,     ProductOptionGroupInputTypes &#62;</code>
 
 
 
@@ -1180,7 +1180,7 @@ class ProductVariantChannelEvent extends VendureEvent {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/product-variant-event.ts" sourceLine="18" packageName="@vendure/core" />
 
-This event is fired whenever a <a href='/reference/typescript-api/entities/product-variant#productvariant'>ProductVariant</a> is added, updated
+This event is fired whenever a <a href='/reference/typescript-api/entities/product-variant#productvariant'>ProductVariant</a> is added, updated
 or deleted.
 
 ```ts title="Signature"
@@ -1217,14 +1217,14 @@ class ProductVariantEvent extends VendureEntityEvent<ProductVariant[], ProductVa
 This event is fired whenever a <a href='/reference/typescript-api/entities/product-variant-price#productvariantprice'>ProductVariantPrice</a> is added, updated or deleted.
 
 ```ts title="Signature"
-class ProductVariantPriceEvent extends VendureEntityEvent<
-    ProductVariantPrice[],
-    ProductVariantInputTypes
+class ProductVariantPriceEvent extends VendureEntityEvent<
+    ProductVariantPrice[],
+    ProductVariantInputTypes
 > {
     constructor(ctx: RequestContext, entity: ProductVariantPrice[], type: 'created' | 'updated' | 'deleted', input?: ProductVariantInputTypes)
 }
 ```
-* Extends: <code><a href='/reference/typescript-api/events/vendure-entity-event#vendureentityevent'>VendureEntityEvent</a>&#60;
     <a href='/reference/typescript-api/entities/product-variant-price#productvariantprice'>ProductVariantPrice</a>[],
     ProductVariantInputTypes
 &#62;</code>
+* Extends: <code><a href='/reference/typescript-api/events/vendure-entity-event#vendureentityevent'>VendureEntityEvent</a>&#60;     <a href='/reference/typescript-api/entities/product-variant-price#productvariantprice'>ProductVariantPrice</a>[],     ProductVariantInputTypes &#62;</code>
 
 
 
@@ -1244,7 +1244,7 @@ class ProductVariantPriceEvent extends VendureEntityEvent<
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/promotion-event.ts" sourceLine="18" packageName="@vendure/core" />
 
-This event is fired whenever a <a href='/reference/typescript-api/entities/promotion#promotion'>Promotion</a> is added, updated
+This event is fired whenever a <a href='/reference/typescript-api/entities/promotion#promotion'>Promotion</a> is added, updated
 or deleted.
 
 ```ts title="Signature"
@@ -1353,7 +1353,7 @@ class RefundStateTransitionEvent extends VendureEvent {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/role-change-event.ts" sourceLine="16" packageName="@vendure/core" since="1.4" />
 
-This event is fired whenever one <a href='/reference/typescript-api/entities/role#role'>Role</a> is assigned or removed from a user.
+This event is fired whenever one <a href='/reference/typescript-api/entities/role#role'>Role</a> is assigned or removed from a user.
 The property `roleIds` only contains the removed or assigned role ids.
 
 ```ts title="Signature"
@@ -1462,7 +1462,7 @@ class SellerEvent extends VendureEntityEvent<Seller, SellerInputTypes> {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/shipping-method-event.ts" sourceLine="18" packageName="@vendure/core" />
 
-This event is fired whenever a <a href='/reference/typescript-api/entities/shipping-method#shippingmethod'>ShippingMethod</a> is added, updated
+This event is fired whenever a <a href='/reference/typescript-api/entities/shipping-method#shippingmethod'>ShippingMethod</a> is added, updated
 or deleted.
 
 ```ts title="Signature"
@@ -1490,7 +1490,7 @@ class ShippingMethodEvent extends VendureEntityEvent<ShippingMethod, ShippingMet
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/stock-movement-event.ts" sourceLine="16" packageName="@vendure/core" since="1.1.0" />
 
-This event is fired whenever a <a href='/reference/typescript-api/entities/stock-movement#stockmovement'>StockMovement</a> entity is created, which occurs when the saleable
+This event is fired whenever a <a href='/reference/typescript-api/entities/stock-movement#stockmovement'>StockMovement</a> entity is created, which occurs when the saleable
 stock level of a ProductVariant is altered due to things like sales, manual adjustments, and cancellations.
 
 ```ts title="Signature"
@@ -1524,7 +1524,7 @@ class StockMovementEvent extends VendureEvent {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/tax-category-event.ts" sourceLine="18" packageName="@vendure/core" />
 
-This event is fired whenever a <a href='/reference/typescript-api/entities/tax-category#taxcategory'>TaxCategory</a> is added, updated
+This event is fired whenever a <a href='/reference/typescript-api/entities/tax-category#taxcategory'>TaxCategory</a> is added, updated
 or deleted.
 
 ```ts title="Signature"
@@ -1552,7 +1552,7 @@ class TaxCategoryEvent extends VendureEntityEvent<TaxCategory, TaxCategoryInputT
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/tax-rate-event.ts" sourceLine="18" packageName="@vendure/core" />
 
-This event is fired whenever a <a href='/reference/typescript-api/entities/tax-rate#taxrate'>TaxRate</a> is added, updated
+This event is fired whenever a <a href='/reference/typescript-api/entities/tax-rate#taxrate'>TaxRate</a> is added, updated
 or deleted.
 
 ```ts title="Signature"
@@ -1607,7 +1607,7 @@ class TaxRateModificationEvent extends VendureEvent {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/zone-event.ts" sourceLine="18" packageName="@vendure/core" />
 
-This event is fired whenever a <a href='/reference/typescript-api/entities/zone#zone'>Zone</a> is added, updated
+This event is fired whenever a <a href='/reference/typescript-api/entities/zone#zone'>Zone</a> is added, updated
 or deleted.
 
 ```ts title="Signature"
@@ -1635,7 +1635,7 @@ class ZoneEvent extends VendureEntityEvent<Zone, ZoneInputTypes> {
 
 <GenerationInfo sourceFile="packages/core/src/event-bus/events/zone-members-event.ts" sourceLine="15" packageName="@vendure/core" />
 
-This event is fired whenever a <a href='/reference/typescript-api/entities/zone#zone'>Zone</a> gets <a href='/reference/typescript-api/entities/country#country'>Country</a> members assigned or removed
+This event is fired whenever a <a href='/reference/typescript-api/entities/zone#zone'>Zone</a> gets <a href='/reference/typescript-api/entities/country#country'>Country</a> members assigned or removed
 The `entity` property contains the zone with the already updated member field.
 
 ```ts title="Signature"

+ 14 - 14
docs/docs/reference/typescript-api/fulfillment/fulfillment-process.md

@@ -13,13 +13,13 @@ import MemberDescription from '@site/src/components/MemberDescription';
 
 <GenerationInfo sourceFile="packages/core/src/config/fulfillment/default-fulfillment-process.ts" sourceLine="45" packageName="@vendure/core" since="2.0.0" />
 
-The default <a href='/reference/typescript-api/fulfillment/fulfillment-process#fulfillmentprocess'>FulfillmentProcess</a>. This process includes the following actions:
-
-- Executes the configured `FulfillmentHandler.onFulfillmentTransition()` before any state
-  transition.
-- On cancellation of a Fulfillment, creates the necessary <a href='/reference/typescript-api/entities/stock-movement#cancellation'>Cancellation</a> & <a href='/reference/typescript-api/entities/stock-movement#allocation'>Allocation</a>
-  stock movement records.
-- When a Fulfillment transitions from the `Created` to `Pending` state, the necessary
+The default <a href='/reference/typescript-api/fulfillment/fulfillment-process#fulfillmentprocess'>FulfillmentProcess</a>. This process includes the following actions:
+
+- Executes the configured `FulfillmentHandler.onFulfillmentTransition()` before any state
+  transition.
+- On cancellation of a Fulfillment, creates the necessary <a href='/reference/typescript-api/entities/stock-movement#cancellation'>Cancellation</a> & <a href='/reference/typescript-api/entities/stock-movement#allocation'>Allocation</a>
+  stock movement records.
+- When a Fulfillment transitions from the `Created` to `Pending` state, the necessary
   <a href='/reference/typescript-api/entities/stock-movement#sale'>Sale</a> stock movements are created.
 
 
@@ -28,16 +28,16 @@ The default <a href='/reference/typescript-api/fulfillment/fulfillment-process#f
 
 <GenerationInfo sourceFile="packages/core/src/config/fulfillment/fulfillment-process.ts" sourceLine="26" packageName="@vendure/core" since="2.0.0" />
 
-A FulfillmentProcess is used to define the way the fulfillment process works as in: what states a Fulfillment can be
-in, and how it may transition from one state to another. Using the `onTransitionStart()` hook, a
-FulfillmentProcess can perform checks before allowing a state transition to occur, and the `onTransitionEnd()`
-hook allows logic to be executed after a state change.
-
+A FulfillmentProcess is used to define the way the fulfillment process works as in: what states a Fulfillment can be
+in, and how it may transition from one state to another. Using the `onTransitionStart()` hook, a
+FulfillmentProcess can perform checks before allowing a state transition to occur, and the `onTransitionEnd()`
+hook allows logic to be executed after a state change.
+
 For detailed description of the interface members, see the <a href='/reference/typescript-api/state-machine/state-machine-config#statemachineconfig'>StateMachineConfig</a> docs.
 
 ```ts title="Signature"
 interface FulfillmentProcess<State extends keyof CustomFulfillmentStates | string> extends InjectableStrategy {
-    transitions?: Transitions<State, State | FulfillmentState> &
+    transitions?: Transitions<State, State | FulfillmentState> &
         Partial<Transitions<FulfillmentState | State>>;
     onTransitionStart?: OnTransitionStartFn<State | FulfillmentState, FulfillmentTransitionData>;
     onTransitionEnd?: OnTransitionEndFn<State | FulfillmentState, FulfillmentTransitionData>;
@@ -52,7 +52,7 @@ interface FulfillmentProcess<State extends keyof CustomFulfillmentStates | strin
 
 ### transitions
 
-<MemberInfo kind="property" type={`<a href='/reference/typescript-api/state-machine/transitions#transitions'>Transitions</a>&#60;State, State | <a href='/reference/typescript-api/fulfillment/fulfillment-state#fulfillmentstate'>FulfillmentState</a>&#62; &#38;
         Partial&#60;<a href='/reference/typescript-api/state-machine/transitions#transitions'>Transitions</a>&#60;<a href='/reference/typescript-api/fulfillment/fulfillment-state#fulfillmentstate'>FulfillmentState</a> | State&#62;&#62;`}   />
+<MemberInfo kind="property" type={`<a href='/reference/typescript-api/state-machine/transitions#transitions'>Transitions</a>&#60;State, State | <a href='/reference/typescript-api/fulfillment/fulfillment-state#fulfillmentstate'>FulfillmentState</a>&#62; &#38;         Partial&#60;<a href='/reference/typescript-api/state-machine/transitions#transitions'>Transitions</a>&#60;<a href='/reference/typescript-api/fulfillment/fulfillment-state#fulfillmentstate'>FulfillmentState</a> | State&#62;&#62;`}   />
 
 
 ### onTransitionStart

+ 5 - 5
docs/docs/reference/typescript-api/import-export/default-asset-import-strategy.md

@@ -13,14 +13,14 @@ import MemberDescription from '@site/src/components/MemberDescription';
 
 <GenerationInfo sourceFile="packages/core/src/config/asset-import-strategy/default-asset-import-strategy.ts" sourceLine="50" packageName="@vendure/core" since="1.7.0" />
 
-The DefaultAssetImportStrategy is able to import paths from the local filesystem (taking into account the
+The DefaultAssetImportStrategy is able to import paths from the local filesystem (taking into account the
 `importExportOptions.importAssetsDir` setting) as well as remote http/https urls.
 
 ```ts title="Signature"
 class DefaultAssetImportStrategy implements AssetImportStrategy {
-    constructor(options?: {
-            retryDelayMs: number;
-            retryCount: number;
+    constructor(options?: {
+            retryDelayMs: number;
+            retryCount: number;
         })
     init(injector: Injector) => ;
     getStreamFromPath(assetPath: string) => ;
@@ -34,7 +34,7 @@ class DefaultAssetImportStrategy implements AssetImportStrategy {
 
 ### constructor
 
-<MemberInfo kind="method" type={`(options?: {
             retryDelayMs: number;
             retryCount: number;
         }) => DefaultAssetImportStrategy`}   />
+<MemberInfo kind="method" type={`(options?: {             retryDelayMs: number;             retryCount: number;         }) => DefaultAssetImportStrategy`}   />
 
 
 ### init

+ 33 - 33
docs/docs/reference/typescript-api/import-export/import-parser.md

@@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription';
 
 <GenerationInfo sourceFile="packages/core/src/data-import/providers/import-parser/import-parser.ts" sourceLine="152" packageName="@vendure/core" />
 
-Validates and parses CSV files into a data structure which can then be used to created new entities.
+Validates and parses CSV files into a data structure which can then be used to created new entities.
 This is used internally by the <a href='/reference/typescript-api/import-export/importer#importer'>Importer</a>.
 
 ```ts title="Signature"
@@ -28,7 +28,7 @@ class ImportParser {
 
 <MemberInfo kind="method" type={`(input: string | Stream, mainLanguage: <a href='/reference/typescript-api/common/language-code#languagecode'>LanguageCode</a> = this.configService.defaultLanguageCode) => Promise&#60;<a href='/reference/typescript-api/import-export/import-parser#parseresult'>ParseResult</a>&#60;<a href='/reference/typescript-api/import-export/import-parser#parsedproductwithvariants'>ParsedProductWithVariants</a>&#62;&#62;`}   />
 
-Parses the contents of the [product import CSV file](/guides/developer-guide/importing-data/#product-import-format) and
+Parses the contents of the [product import CSV file](/guides/developer-guide/importing-data/#product-import-format) and
 returns a data structure which can then be used to populate Vendure using the <a href='/reference/typescript-api/import-export/fast-importer-service#fastimporterservice'>FastImporterService</a>.
 
 
@@ -39,15 +39,15 @@ returns a data structure which can then be used to populate Vendure using the <a
 
 <GenerationInfo sourceFile="packages/core/src/data-import/providers/import-parser/import-parser.ts" sourceLine="45" packageName="@vendure/core" />
 
-The intermediate representation of an OptionGroup after it has been parsed
+The intermediate representation of an OptionGroup after it has been parsed
 by the <a href='/reference/typescript-api/import-export/import-parser#importparser'>ImportParser</a>.
 
 ```ts title="Signature"
 interface ParsedOptionGroup {
-    translations: Array<{
-        languageCode: LanguageCode;
-        name: string;
-        values: string[];
+    translations: Array<{
+        languageCode: LanguageCode;
+        name: string;
+        values: string[];
     }>;
 }
 ```
@@ -56,7 +56,7 @@ interface ParsedOptionGroup {
 
 ### translations
 
-<MemberInfo kind="property" type={`Array&#60;{
         languageCode: <a href='/reference/typescript-api/common/language-code#languagecode'>LanguageCode</a>;
         name: string;
         values: string[];
     }&#62;`}   />
+<MemberInfo kind="property" type={`Array&#60;{         languageCode: <a href='/reference/typescript-api/common/language-code#languagecode'>LanguageCode</a>;         name: string;         values: string[];     }&#62;`}   />
 
 
 
@@ -68,15 +68,15 @@ interface ParsedOptionGroup {
 
 <GenerationInfo sourceFile="packages/core/src/data-import/providers/import-parser/import-parser.ts" sourceLine="61" packageName="@vendure/core" />
 
-The intermediate representation of a Facet after it has been parsed
+The intermediate representation of a Facet after it has been parsed
 by the <a href='/reference/typescript-api/import-export/import-parser#importparser'>ImportParser</a>.
 
 ```ts title="Signature"
 interface ParsedFacet {
-    translations: Array<{
-        languageCode: LanguageCode;
-        facet: string;
-        value: string;
+    translations: Array<{
+        languageCode: LanguageCode;
+        facet: string;
+        value: string;
     }>;
 }
 ```
@@ -85,7 +85,7 @@ interface ParsedFacet {
 
 ### translations
 
-<MemberInfo kind="property" type={`Array&#60;{
         languageCode: <a href='/reference/typescript-api/common/language-code#languagecode'>LanguageCode</a>;
         facet: string;
         value: string;
     }&#62;`}   />
+<MemberInfo kind="property" type={`Array&#60;{         languageCode: <a href='/reference/typescript-api/common/language-code#languagecode'>LanguageCode</a>;         facet: string;         value: string;     }&#62;`}   />
 
 
 
@@ -97,7 +97,7 @@ interface ParsedFacet {
 
 <GenerationInfo sourceFile="packages/core/src/data-import/providers/import-parser/import-parser.ts" sourceLine="77" packageName="@vendure/core" />
 
-The intermediate representation of a ProductVariant after it has been parsed
+The intermediate representation of a ProductVariant after it has been parsed
 by the <a href='/reference/typescript-api/import-export/import-parser#importparser'>ImportParser</a>.
 
 ```ts title="Signature"
@@ -109,12 +109,12 @@ interface ParsedProductVariant {
     trackInventory: GlobalFlag;
     assetPaths: string[];
     facets: ParsedFacet[];
-    translations: Array<{
-        languageCode: LanguageCode;
-        optionValues: string[];
-        customFields: {
-            [name: string]: string;
-        };
+    translations: Array<{
+        languageCode: LanguageCode;
+        optionValues: string[];
+        customFields: {
+            [name: string]: string;
+        };
     }>;
 }
 ```
@@ -158,7 +158,7 @@ interface ParsedProductVariant {
 
 ### translations
 
-<MemberInfo kind="property" type={`Array&#60;{
         languageCode: <a href='/reference/typescript-api/common/language-code#languagecode'>LanguageCode</a>;
         optionValues: string[];
         customFields: {
             [name: string]: string;
         };
     }&#62;`}   />
+<MemberInfo kind="property" type={`Array&#60;{         languageCode: <a href='/reference/typescript-api/common/language-code#languagecode'>LanguageCode</a>;         optionValues: string[];         customFields: {             [name: string]: string;         };     }&#62;`}   />
 
 
 
@@ -170,7 +170,7 @@ interface ParsedProductVariant {
 
 <GenerationInfo sourceFile="packages/core/src/data-import/providers/import-parser/import-parser.ts" sourceLine="102" packageName="@vendure/core" />
 
-The intermediate representation of a Product after it has been parsed
+The intermediate representation of a Product after it has been parsed
 by the <a href='/reference/typescript-api/import-export/import-parser#importparser'>ImportParser</a>.
 
 ```ts title="Signature"
@@ -178,14 +178,14 @@ interface ParsedProduct {
     assetPaths: string[];
     optionGroups: ParsedOptionGroup[];
     facets: ParsedFacet[];
-    translations: Array<{
-        languageCode: LanguageCode;
-        name: string;
-        slug: string;
-        description: string;
-        customFields: {
-            [name: string]: string;
-        };
+    translations: Array<{
+        languageCode: LanguageCode;
+        name: string;
+        slug: string;
+        description: string;
+        customFields: {
+            [name: string]: string;
+        };
     }>;
 }
 ```
@@ -209,7 +209,7 @@ interface ParsedProduct {
 
 ### translations
 
-<MemberInfo kind="property" type={`Array&#60;{
         languageCode: <a href='/reference/typescript-api/common/language-code#languagecode'>LanguageCode</a>;
         name: string;
         slug: string;
         description: string;
         customFields: {
             [name: string]: string;
         };
     }&#62;`}   />
+<MemberInfo kind="property" type={`Array&#60;{         languageCode: <a href='/reference/typescript-api/common/language-code#languagecode'>LanguageCode</a>;         name: string;         slug: string;         description: string;         customFields: {             [name: string]: string;         };     }&#62;`}   />
 
 
 
@@ -221,7 +221,7 @@ interface ParsedProduct {
 
 <GenerationInfo sourceFile="packages/core/src/data-import/providers/import-parser/import-parser.ts" sourceLine="125" packageName="@vendure/core" />
 
-The data structure into which an import CSV file is parsed by the
+The data structure into which an import CSV file is parsed by the
 <a href='/reference/typescript-api/import-export/import-parser#importparser'>ImportParser</a> `parseProducts()` method.
 
 ```ts title="Signature"

+ 1 - 2
docs/docs/reference/typescript-api/job-queue/types.md

@@ -106,8 +106,7 @@ should resolve when the job is complete, or be rejected in case of an error.
 
 <GenerationInfo sourceFile="packages/core/src/job-queue/types.ts" sourceLine="37" packageName="@vendure/core" />
 
-A JSON-serializable data type which provides a <a href='/reference/typescript-api/job-queue/job#job'>Job</a>
-with the data it needs to be processed.
+A JSON-serializable data type which provides a <a href='/reference/typescript-api/job-queue/job#job'>Job</a>with the data it needs to be processed.
 
 ```ts title="Signature"
 type JobData<T> = JsonCompatible<T>

+ 25 - 25
docs/docs/reference/typescript-api/orders/guest-checkout-strategy.md

@@ -13,33 +13,33 @@ import MemberDescription from '@site/src/components/MemberDescription';
 
 <GenerationInfo sourceFile="packages/core/src/config/order/guest-checkout-strategy.ts" sourceLine="33" packageName="@vendure/core" since="2.0.0" />
 
-A strategy that determines how to deal with guest checkouts - i.e. when a customer
-checks out without being logged in. For example, a strategy could be used to implement
-business rules such as:
-
-- No guest checkouts allowed
-- No guest checkouts allowed for customers who already have an account
-- No guest checkouts allowed for customers who have previously placed an order
-- Allow guest checkouts, but create a new Customer entity if the email address
-  is already in use
-- Allow guest checkouts, but update the existing Customer entity if the email address
-  is already in use
-
-:::info
-
-This is configured via the `orderOptions.guestCheckoutStrategy` property of
-your VendureConfig.
-
+A strategy that determines how to deal with guest checkouts - i.e. when a customer
+checks out without being logged in. For example, a strategy could be used to implement
+business rules such as:
+
+- No guest checkouts allowed
+- No guest checkouts allowed for customers who already have an account
+- No guest checkouts allowed for customers who have previously placed an order
+- Allow guest checkouts, but create a new Customer entity if the email address
+  is already in use
+- Allow guest checkouts, but update the existing Customer entity if the email address
+  is already in use
+
+:::info
+
+This is configured via the `orderOptions.guestCheckoutStrategy` property of
+your VendureConfig.
+
 :::
 
 ```ts title="Signature"
 interface GuestCheckoutStrategy extends InjectableStrategy {
-    setCustomerForOrder(
-        ctx: RequestContext,
-        order: Order,
-        input: CreateCustomerInput,
-    ):
-        | ErrorResultUnion<SetCustomerForOrderResult, Customer>
+    setCustomerForOrder(
+        ctx: RequestContext,
+        order: Order,
+        input: CreateCustomerInput,
+    ):
+        | ErrorResultUnion<SetCustomerForOrderResult, Customer>
         | Promise<ErrorResultUnion<SetCustomerForOrderResult, Customer>>;
 }
 ```
@@ -51,9 +51,9 @@ interface GuestCheckoutStrategy extends InjectableStrategy {
 
 ### setCustomerForOrder
 
-<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, order: <a href='/reference/typescript-api/entities/order#order'>Order</a>, input: CreateCustomerInput) => | <a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;SetCustomerForOrderResult, <a href='/reference/typescript-api/entities/customer#customer'>Customer</a>&#62;
         | Promise&#60;<a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;SetCustomerForOrderResult, <a href='/reference/typescript-api/entities/customer#customer'>Customer</a>&#62;&#62;`}   />
+<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, order: <a href='/reference/typescript-api/entities/order#order'>Order</a>, input: CreateCustomerInput) => | <a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;SetCustomerForOrderResult, <a href='/reference/typescript-api/entities/customer#customer'>Customer</a>&#62;         | Promise&#60;<a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;SetCustomerForOrderResult, <a href='/reference/typescript-api/entities/customer#customer'>Customer</a>&#62;&#62;`}   />
 
-This method is called when the `setCustomerForOrder` mutation is executed.
+This method is called when the `setCustomerForOrder` mutation is executed.
 It should return either a Customer object or an ErrorResult.
 
 

+ 1 - 2
docs/docs/reference/typescript-api/orders/order-item-price-calculation-strategy.md

@@ -87,8 +87,7 @@ Receives the ProductVariant to be added to the Order as well as any OrderLine cu
 the price for a single unit.
 
 Note: if you have any `relation` type custom fields defined on the OrderLine entity, they will only be
-passed in to this method if they are set to `eager: true`. Otherwise, you can use the <a href='/reference/typescript-api/data-access/entity-hydrator#entityhydrator'>EntityHydrator</a>
-to join the missing relations.
+passed in to this method if they are set to `eager: true`. Otherwise, you can use the <a href='/reference/typescript-api/data-access/entity-hydrator#entityhydrator'>EntityHydrator</a>to join the missing relations.
 
 Note: the `quantity` argument was added in v2.0.0
 

+ 13 - 13
docs/docs/reference/typescript-api/request/request-context-service.md

@@ -17,14 +17,14 @@ Creates new <a href='/reference/typescript-api/request/request-context#requestco
 
 ```ts title="Signature"
 class RequestContextService {
-    create(config: {
-        req?: Request;
-        apiType: ApiType;
-        channelOrToken?: Channel | string;
-        languageCode?: LanguageCode;
-        currencyCode?: CurrencyCode;
-        user?: User;
-        activeOrderId?: ID;
+    create(config: {
+        req?: Request;
+        apiType: ApiType;
+        channelOrToken?: Channel | string;
+        languageCode?: LanguageCode;
+        currencyCode?: CurrencyCode;
+        user?: User;
+        activeOrderId?: ID;
     }) => Promise<RequestContext>;
     fromRequest(req: Request, info?: GraphQLResolveInfo, requiredPermissions?: Permission[], session?: CachedSession) => Promise<RequestContext>;
 }
@@ -34,17 +34,17 @@ class RequestContextService {
 
 ### create
 
-<MemberInfo kind="method" type={`(config: {
         req?: Request;
         apiType: <a href='/reference/typescript-api/request/api-type#apitype'>ApiType</a>;
         channelOrToken?: <a href='/reference/typescript-api/entities/channel#channel'>Channel</a> | string;
         languageCode?: <a href='/reference/typescript-api/common/language-code#languagecode'>LanguageCode</a>;
         currencyCode?: <a href='/reference/typescript-api/common/currency-code#currencycode'>CurrencyCode</a>;
         user?: <a href='/reference/typescript-api/entities/user#user'>User</a>;
         activeOrderId?: <a href='/reference/typescript-api/common/id#id'>ID</a>;
     }) => Promise&#60;<a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>&#62;`}  since="1.5.0"  />
+<MemberInfo kind="method" type={`(config: {         req?: Request;         apiType: <a href='/reference/typescript-api/request/api-type#apitype'>ApiType</a>;         channelOrToken?: <a href='/reference/typescript-api/entities/channel#channel'>Channel</a> | string;         languageCode?: <a href='/reference/typescript-api/common/language-code#languagecode'>LanguageCode</a>;         currencyCode?: <a href='/reference/typescript-api/common/currency-code#currencycode'>CurrencyCode</a>;         user?: <a href='/reference/typescript-api/entities/user#user'>User</a>;         activeOrderId?: <a href='/reference/typescript-api/common/id#id'>ID</a>;     }) => Promise&#60;<a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>&#62;`}  since="1.5.0"  />
 
-Creates a RequestContext based on the config provided. This can be useful when interacting
-with services outside the request-response cycle, for example in stand-alone scripts or in
+Creates a RequestContext based on the config provided. This can be useful when interacting
+with services outside the request-response cycle, for example in stand-alone scripts or in
 worker jobs.
 ### fromRequest
 
 <MemberInfo kind="method" type={`(req: Request, info?: GraphQLResolveInfo, requiredPermissions?: <a href='/reference/typescript-api/common/permission#permission'>Permission</a>[], session?: <a href='/reference/typescript-api/auth/session-cache-strategy#cachedsession'>CachedSession</a>) => Promise&#60;<a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>&#62;`}   />
 
-Creates a new RequestContext based on an Express request object. This is used internally
-in the API layer by the AuthGuard, and creates the RequestContext which is then passed
+Creates a new RequestContext based on an Express request object. This is used internally
+in the API layer by the AuthGuard, and creates the RequestContext which is then passed
 to all resolvers & controllers.
 
 

+ 11 - 11
docs/docs/reference/typescript-api/service-helpers/slug-validator.md

@@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription';
 
 <GenerationInfo sourceFile="packages/core/src/service/helpers/slug-validator/slug-validator.ts" sourceLine="44" packageName="@vendure/core" />
 
-Used to validate slugs to ensure they are URL-safe and unique. Designed to be used with translatable
+Used to validate slugs to ensure they are URL-safe and unique. Designed to be used with translatable
 entities such as <a href='/reference/typescript-api/entities/product#product'>Product</a> and <a href='/reference/typescript-api/entities/collection#collection'>Collection</a>.
 
 ```ts title="Signature"
@@ -49,10 +49,10 @@ class SlugValidator {
 ```ts title="Signature"
 type InputWithSlug = {
     id?: ID | null;
-    translations?: Array<{
-        id?: ID | null;
-        languageCode: LanguageCode;
-        slug?: string | null;
+    translations?: Array<{
+        id?: ID | null;
+        languageCode: LanguageCode;
+        slug?: string | null;
     }> | null;
 }
 ```
@@ -66,7 +66,7 @@ type InputWithSlug = {
 
 ### translations
 
-<MemberInfo kind="property" type={`Array&#60;{
         id?: <a href='/reference/typescript-api/common/id#id'>ID</a> | null;
         languageCode: <a href='/reference/typescript-api/common/language-code#languagecode'>LanguageCode</a>;
         slug?: string | null;
     }&#62; | null`}   />
+<MemberInfo kind="property" type={`Array&#60;{         id?: <a href='/reference/typescript-api/common/id#id'>ID</a> | null;         languageCode: <a href='/reference/typescript-api/common/language-code#languagecode'>LanguageCode</a>;         slug?: string | null;     }&#62; | null`}   />
 
 
 
@@ -81,10 +81,10 @@ type InputWithSlug = {
 
 
 ```ts title="Signature"
-type TranslationEntity = VendureEntity & {
-    id: ID;
-    languageCode: LanguageCode;
-    slug: string;
-    base: any;
+type TranslationEntity = VendureEntity & {
+    id: ID;
+    languageCode: LanguageCode;
+    slug: string;
+    base: any;
 }
 ```

+ 25 - 25
docs/docs/reference/typescript-api/services/customer-service.md

@@ -31,8 +31,8 @@ class CustomerService {
     refreshVerificationToken(ctx: RequestContext, emailAddress: string) => Promise<void>;
     verifyCustomerEmailAddress(ctx: RequestContext, verificationToken: string, password?: string) => Promise<ErrorResultUnion<VerifyCustomerAccountResult, Customer>>;
     requestPasswordReset(ctx: RequestContext, emailAddress: string) => Promise<void>;
-    resetPassword(ctx: RequestContext, passwordResetToken: string, password: string) => Promise<
-        User | PasswordResetTokenExpiredError | PasswordResetTokenInvalidError | PasswordValidationError
+    resetPassword(ctx: RequestContext, passwordResetToken: string, password: string) => Promise<
+        User | PasswordResetTokenExpiredError | PasswordResetTokenInvalidError | PasswordValidationError
     >;
     requestUpdateEmailAddress(ctx: RequestContext, userId: ID, newEmailAddress: string) => Promise<boolean | EmailAddressConflictError>;
     updateEmailAddress(ctx: RequestContext, token: string) => Promise<boolean | IdentifierChangeTokenInvalidError | IdentifierChangeTokenExpiredError>;
@@ -69,8 +69,8 @@ class CustomerService {
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, userId: <a href='/reference/typescript-api/common/id#id'>ID</a>, filterOnChannel:  = true) => Promise&#60;<a href='/reference/typescript-api/entities/customer#customer'>Customer</a> | undefined&#62;`}   />
 
-Returns the Customer entity associated with the given userId, if one exists.
-Setting `filterOnChannel` to `true` will limit the results to Customers which are assigned
+Returns the Customer entity associated with the given userId, if one exists.
+Setting `filterOnChannel` to `true` will limit the results to Customers which are assigned
 to the current active Channel only.
 ### findAddressesByCustomerId
 
@@ -86,13 +86,13 @@ Returns a list of all <a href='/reference/typescript-api/entities/customer-group
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, input: CreateCustomerInput, password?: string) => Promise&#60;<a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;CreateCustomerResult, <a href='/reference/typescript-api/entities/customer#customer'>Customer</a>&#62;&#62;`}   />
 
-Creates a new Customer, including creation of a new User with the special `customer` Role.
-
-If the `password` argument is specified, the Customer will be immediately verified. If not,
-then an <a href='/reference/typescript-api/events/event-types#accountregistrationevent'>AccountRegistrationEvent</a> is published, so that the customer can have their
-email address verified and set their password in a later step using the `verifyCustomerEmailAddress()`
-method.
-
+Creates a new Customer, including creation of a new User with the special `customer` Role.
+
+If the `password` argument is specified, the Customer will be immediately verified. If not,
+then an <a href='/reference/typescript-api/events/event-types#accountregistrationevent'>AccountRegistrationEvent</a> is published, so that the customer can have their
+email address verified and set their password in a later step using the `verifyCustomerEmailAddress()`
+method.
+
 This method is intended to be used in admin-created Customer flows.
 ### update
 
@@ -113,47 +113,47 @@ This method is intended to be used in admin-created Customer flows.
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, input: RegisterCustomerInput) => Promise&#60;RegisterCustomerAccountResult | EmailAddressConflictError | PasswordValidationError&#62;`}   />
 
-Registers a new Customer account with the <a href='/reference/typescript-api/auth/native-authentication-strategy#nativeauthenticationstrategy'>NativeAuthenticationStrategy</a> and starts
-the email verification flow (unless <a href='/reference/typescript-api/auth/auth-options#authoptions'>AuthOptions</a> `requireVerification` is set to `false`)
-by publishing an <a href='/reference/typescript-api/events/event-types#accountregistrationevent'>AccountRegistrationEvent</a>.
-
+Registers a new Customer account with the <a href='/reference/typescript-api/auth/native-authentication-strategy#nativeauthenticationstrategy'>NativeAuthenticationStrategy</a> and starts
+the email verification flow (unless <a href='/reference/typescript-api/auth/auth-options#authoptions'>AuthOptions</a> `requireVerification` is set to `false`)
+by publishing an <a href='/reference/typescript-api/events/event-types#accountregistrationevent'>AccountRegistrationEvent</a>.
+
 This method is intended to be used in storefront Customer-creation flows.
 ### refreshVerificationToken
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, emailAddress: string) => Promise&#60;void&#62;`}   />
 
-Refreshes a stale email address verification token by generating a new one and
+Refreshes a stale email address verification token by generating a new one and
 publishing a <a href='/reference/typescript-api/events/event-types#accountregistrationevent'>AccountRegistrationEvent</a>.
 ### verifyCustomerEmailAddress
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, verificationToken: string, password?: string) => Promise&#60;<a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;VerifyCustomerAccountResult, <a href='/reference/typescript-api/entities/customer#customer'>Customer</a>&#62;&#62;`}   />
 
-Given a valid verification token which has been published in an <a href='/reference/typescript-api/events/event-types#accountregistrationevent'>AccountRegistrationEvent</a>, this
+Given a valid verification token which has been published in an <a href='/reference/typescript-api/events/event-types#accountregistrationevent'>AccountRegistrationEvent</a>, this
 method is used to set the Customer as `verified` as part of the account registration flow.
 ### requestPasswordReset
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, emailAddress: string) => Promise&#60;void&#62;`}   />
 
-Publishes a new <a href='/reference/typescript-api/events/event-types#passwordresetevent'>PasswordResetEvent</a> for the given email address. This event creates
+Publishes a new <a href='/reference/typescript-api/events/event-types#passwordresetevent'>PasswordResetEvent</a> for the given email address. This event creates
 a token which can be used in the `resetPassword()` method.
 ### resetPassword
 
-<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, passwordResetToken: string, password: string) => Promise&#60;
         <a href='/reference/typescript-api/entities/user#user'>User</a> | PasswordResetTokenExpiredError | PasswordResetTokenInvalidError | PasswordValidationError
     &#62;`}   />
+<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, passwordResetToken: string, password: string) => Promise&#60;         <a href='/reference/typescript-api/entities/user#user'>User</a> | PasswordResetTokenExpiredError | PasswordResetTokenInvalidError | PasswordValidationError     &#62;`}   />
 
-Given a valid password reset token created by a call to the `requestPasswordReset()` method,
+Given a valid password reset token created by a call to the `requestPasswordReset()` method,
 this method will change the Customer's password to that given as the `password` argument.
 ### requestUpdateEmailAddress
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, userId: <a href='/reference/typescript-api/common/id#id'>ID</a>, newEmailAddress: string) => Promise&#60;boolean | EmailAddressConflictError&#62;`}   />
 
-Publishes a <a href='/reference/typescript-api/events/event-types#identifierchangerequestevent'>IdentifierChangeRequestEvent</a> for the given User. This event contains a token
-which is then used in the `updateEmailAddress()` method to change the email address of the User &
+Publishes a <a href='/reference/typescript-api/events/event-types#identifierchangerequestevent'>IdentifierChangeRequestEvent</a> for the given User. This event contains a token
+which is then used in the `updateEmailAddress()` method to change the email address of the User &
 Customer.
 ### updateEmailAddress
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, token: string) => Promise&#60;boolean | IdentifierChangeTokenInvalidError | IdentifierChangeTokenExpiredError&#62;`}   />
 
-Given a valid email update token published in a <a href='/reference/typescript-api/events/event-types#identifierchangerequestevent'>IdentifierChangeRequestEvent</a>, this method
+Given a valid email update token published in a <a href='/reference/typescript-api/events/event-types#identifierchangerequestevent'>IdentifierChangeRequestEvent</a>, this method
 will update the Customer & User email address.
 ### createOrUpdate
 
@@ -184,8 +184,8 @@ Creates a new <a href='/reference/typescript-api/entities/address#address'>Addre
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, order: <a href='/reference/typescript-api/entities/order#order'>Order</a>) => `}   />
 
-If the Customer associated with the given Order does not yet have any Addresses,
-this method will create new Address(es) based on the Order's shipping & billing
+If the Customer associated with the given Order does not yet have any Addresses,
+this method will create new Address(es) based on the Order's shipping & billing
 addresses.
 ### addNoteToCustomer
 

+ 11 - 11
docs/docs/reference/typescript-api/services/fulfillment-service.md

@@ -21,14 +21,14 @@ class FulfillmentService {
     create(ctx: RequestContext, orders: Order[], lines: OrderLineInput[], handler: ConfigurableOperationInput) => Promise<Fulfillment | InvalidFulfillmentHandlerError | CreateFulfillmentError>;
     getFulfillmentLines(ctx: RequestContext, id: ID) => Promise<FulfillmentLine[]>;
     getFulfillmentsLinesForOrderLine(ctx: RequestContext, orderLineId: ID, relations: RelationPaths<FulfillmentLine> = []) => Promise<FulfillmentLine[]>;
-    transitionToState(ctx: RequestContext, fulfillmentId: ID, state: FulfillmentState) => Promise<
-        | {
-              fulfillment: Fulfillment;
-              orders: Order[];
-              fromState: FulfillmentState;
-              toState: FulfillmentState;
-          }
-        | FulfillmentStateTransitionError
+    transitionToState(ctx: RequestContext, fulfillmentId: ID, state: FulfillmentState) => Promise<
+        | {
+              fulfillment: Fulfillment;
+              orders: Order[];
+              fromState: FulfillmentState;
+              toState: FulfillmentState;
+          }
+        | FulfillmentStateTransitionError
     >;
     getNextStates(fulfillment: Fulfillment) => readonly FulfillmentState[];
 }
@@ -45,7 +45,7 @@ class FulfillmentService {
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, orders: <a href='/reference/typescript-api/entities/order#order'>Order</a>[], lines: OrderLineInput[], handler: ConfigurableOperationInput) => Promise&#60;<a href='/reference/typescript-api/entities/fulfillment#fulfillment'>Fulfillment</a> | InvalidFulfillmentHandlerError | CreateFulfillmentError&#62;`}   />
 
-Creates a new Fulfillment for the given Orders and OrderItems, using the specified
+Creates a new Fulfillment for the given Orders and OrderItems, using the specified
 <a href='/reference/typescript-api/fulfillment/fulfillment-handler#fulfillmenthandler'>FulfillmentHandler</a>.
 ### getFulfillmentLines
 
@@ -59,9 +59,9 @@ Creates a new Fulfillment for the given Orders and OrderItems, using the specifi
 
 ### transitionToState
 
-<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, fulfillmentId: <a href='/reference/typescript-api/common/id#id'>ID</a>, state: <a href='/reference/typescript-api/fulfillment/fulfillment-state#fulfillmentstate'>FulfillmentState</a>) => Promise&#60;
         | {
               fulfillment: <a href='/reference/typescript-api/entities/fulfillment#fulfillment'>Fulfillment</a>;
               orders: <a href='/reference/typescript-api/entities/order#order'>Order</a>[];
               fromState: <a href='/reference/typescript-api/fulfillment/fulfillment-state#fulfillmentstate'>FulfillmentState</a>;
               toState: <a href='/reference/typescript-api/fulfillment/fulfillment-state#fulfillmentstate'>FulfillmentState</a>;
           }
         | FulfillmentStateTransitionError
     &#62;`}   />
+<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, fulfillmentId: <a href='/reference/typescript-api/common/id#id'>ID</a>, state: <a href='/reference/typescript-api/fulfillment/fulfillment-state#fulfillmentstate'>FulfillmentState</a>) => Promise&#60;         | {               fulfillment: <a href='/reference/typescript-api/entities/fulfillment#fulfillment'>Fulfillment</a>;               orders: <a href='/reference/typescript-api/entities/order#order'>Order</a>[];               fromState: <a href='/reference/typescript-api/fulfillment/fulfillment-state#fulfillmentstate'>FulfillmentState</a>;               toState: <a href='/reference/typescript-api/fulfillment/fulfillment-state#fulfillmentstate'>FulfillmentState</a>;           }         | FulfillmentStateTransitionError     &#62;`}   />
 
-Transitions the specified Fulfillment to a new state and upon successful transition
+Transitions the specified Fulfillment to a new state and upon successful transition
 publishes a <a href='/reference/typescript-api/events/event-types#fulfillmentstatetransitionevent'>FulfillmentStateTransitionEvent</a>.
 ### getNextStates
 

+ 72 - 60
docs/docs/reference/typescript-api/services/order-service.md

@@ -36,10 +36,10 @@ class OrderService {
     updateCustomFields(ctx: RequestContext, orderId: ID, customFields: any) => ;
     updateOrderCustomer(ctx: RequestContext, { customerId, orderId, note }: SetOrderCustomerInput) => ;
     addItemToOrder(ctx: RequestContext, orderId: ID, productVariantId: ID, quantity: number, customFields?: { [key: string]: any }, relations?: RelationPaths<Order>) => Promise<ErrorResultUnion<UpdateOrderItemsResult, Order>>;
-    addItemsToOrder(ctx: RequestContext, orderId: ID, items: Array<{
-            productVariantId: ID;
-            quantity: number;
-            customFields?: { [key: string]: any };
+    addItemsToOrder(ctx: RequestContext, orderId: ID, items: Array<{
+            productVariantId: ID;
+            quantity: number;
+            customFields?: { [key: string]: any };
         }>, relations?: RelationPaths<Order>) => Promise<{ order: Order; errorResults: Array<JustErrorResults<UpdateOrderItemsResult>> }>;
     adjustOrderLine(ctx: RequestContext, orderId: ID, orderLineId: ID, quantity: number, customFields?: { [key: string]: any }, relations?: RelationPaths<Order>) => Promise<ErrorResultUnion<UpdateOrderItemsResult, Order>>;
     adjustOrderLines(ctx: RequestContext, orderId: ID, lines: Array<{ orderLineId: ID; quantity: number; customFields?: { [key: string]: any } }>, relations?: RelationPaths<Order>) => Promise<{ order: Order; errorResults: Array<JustErrorResults<UpdateOrderItemsResult>> }>;
@@ -54,6 +54,8 @@ class OrderService {
     getNextOrderStates(order: Order) => readonly OrderState[];
     setShippingAddress(ctx: RequestContext, orderId: ID, input: CreateAddressInput) => Promise<Order>;
     setBillingAddress(ctx: RequestContext, orderId: ID, input: CreateAddressInput) => Promise<Order>;
+    unsetShippingAddress(ctx: RequestContext, orderId: ID) => Promise<Order>;
+    unsetBillingAddress(ctx: RequestContext, orderId: ID) => Promise<Order>;
     getEligibleShippingMethods(ctx: RequestContext, orderId: ID) => Promise<ShippingMethodQuote[]>;
     getEligiblePaymentMethods(ctx: RequestContext, orderId: ID) => Promise<PaymentMethodQuote[]>;
     setShippingMethod(ctx: RequestContext, orderId: ID, shippingMethodIds: ID[]) => Promise<ErrorResultUnion<SetOrderShippingMethodResult, Order>>;
@@ -93,8 +95,8 @@ class OrderService {
 
 <MemberInfo kind="method" type={`() => OrderProcessState[]`}   />
 
-Returns an array of all the configured states and transitions of the order process. This is
-based on the default order process plus all configured <a href='/reference/typescript-api/orders/order-process#orderprocess'>OrderProcess</a> objects
+Returns an array of all the configured states and transitions of the order process. This is
+based on the default order process plus all configured <a href='/reference/typescript-api/orders/order-process#orderprocess'>OrderProcess</a> objects
 defined in the <a href='/reference/typescript-api/orders/order-options#orderoptions'>OrderOptions</a> `process` array.
 ### findAll
 
@@ -155,13 +157,13 @@ Returns any <a href='/reference/typescript-api/entities/refund#refund'>Refund</a
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, userId: <a href='/reference/typescript-api/common/id#id'>ID</a>) => Promise&#60;<a href='/reference/typescript-api/entities/order#order'>Order</a> | undefined&#62;`}   />
 
-Returns any Order associated with the specified User's Customer account
+Returns any Order associated with the specified User's Customer account
 that is still in the `active` state.
 ### create
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, userId?: <a href='/reference/typescript-api/common/id#id'>ID</a>) => Promise&#60;<a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;`}   />
 
-Creates a new, empty Order. If a `userId` is passed, the Order will get associated with that
+Creates a new, empty Order. If a `userId` is passed, the Order will get associated with that
 User's Customer account.
 ### createDraft
 
@@ -177,55 +179,55 @@ Updates the custom fields of an Order.
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, { customerId, orderId, note }: SetOrderCustomerInput) => `}  since="2.2.0"  />
 
-Updates the Customer which is assigned to a given Order. The target Customer must be assigned to the same
+Updates the Customer which is assigned to a given Order. The target Customer must be assigned to the same
 Channels as the Order, otherwise an error will be thrown.
 ### addItemToOrder
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, orderId: <a href='/reference/typescript-api/common/id#id'>ID</a>, productVariantId: <a href='/reference/typescript-api/common/id#id'>ID</a>, quantity: number, customFields?: { [key: string]: any }, relations?: RelationPaths&#60;<a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;) => Promise&#60;<a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;UpdateOrderItemsResult, <a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;&#62;`}   />
 
-Adds an item to the Order, either creating a new OrderLine or
-incrementing an existing one.
-
+Adds an item to the Order, either creating a new OrderLine or
+incrementing an existing one.
+
 If you need to add multiple items to an Order, use `addItemsToOrder()` instead.
 ### addItemsToOrder
 
-<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, orderId: <a href='/reference/typescript-api/common/id#id'>ID</a>, items: Array&#60;{
             productVariantId: <a href='/reference/typescript-api/common/id#id'>ID</a>;
             quantity: number;
             customFields?: { [key: string]: any };
         }&#62;, relations?: RelationPaths&#60;<a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;) => Promise&#60;{ order: <a href='/reference/typescript-api/entities/order#order'>Order</a>; errorResults: Array&#60;JustErrorResults&#60;UpdateOrderItemsResult&#62;&#62; }&#62;`}  since="3.1.0"  />
+<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, orderId: <a href='/reference/typescript-api/common/id#id'>ID</a>, items: Array&#60;{             productVariantId: <a href='/reference/typescript-api/common/id#id'>ID</a>;             quantity: number;             customFields?: { [key: string]: any };         }&#62;, relations?: RelationPaths&#60;<a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;) => Promise&#60;{ order: <a href='/reference/typescript-api/entities/order#order'>Order</a>; errorResults: Array&#60;JustErrorResults&#60;UpdateOrderItemsResult&#62;&#62; }&#62;`}  since="3.1.0"  />
+
+Adds multiple items to an Order. This method is more efficient than calling `addItemToOrder`
+multiple times, as it only needs to fetch the entire Order once, and only performs
+price adjustments once at the end.
 
-Adds multiple items to an Order. This method is more efficient than calling `addItemToOrder`
-multiple times, as it only needs to fetch the entire Order once, and only performs
-price adjustments once at the end.
-
-Since this method can return multiple error results, it is recommended to check the `errorResults`
+Since this method can return multiple error results, it is recommended to check the `errorResults`
 array to determine if any errors occurred.
 ### adjustOrderLine
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, orderId: <a href='/reference/typescript-api/common/id#id'>ID</a>, orderLineId: <a href='/reference/typescript-api/common/id#id'>ID</a>, quantity: number, customFields?: { [key: string]: any }, relations?: RelationPaths&#60;<a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;) => Promise&#60;<a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;UpdateOrderItemsResult, <a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;&#62;`}   />
 
-Adjusts the quantity and/or custom field values of an existing OrderLine.
-
+Adjusts the quantity and/or custom field values of an existing OrderLine.
+
 If you need to adjust multiple OrderLines, use `adjustOrderLines()` instead.
 ### adjustOrderLines
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, orderId: <a href='/reference/typescript-api/common/id#id'>ID</a>, lines: Array&#60;{ orderLineId: <a href='/reference/typescript-api/common/id#id'>ID</a>; quantity: number; customFields?: { [key: string]: any } }&#62;, relations?: RelationPaths&#60;<a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;) => Promise&#60;{ order: <a href='/reference/typescript-api/entities/order#order'>Order</a>; errorResults: Array&#60;JustErrorResults&#60;UpdateOrderItemsResult&#62;&#62; }&#62;`}  since="3.1.0"  />
 
-Adjusts the quantity and/or custom field values of existing OrderLines.
-This method is more efficient than calling `adjustOrderLine` multiple times, as it only needs to fetch
-the entire Order once, and only performs price adjustments once at the end.
-Since this method can return multiple error results, it is recommended to check the `errorResults`
+Adjusts the quantity and/or custom field values of existing OrderLines.
+This method is more efficient than calling `adjustOrderLine` multiple times, as it only needs to fetch
+the entire Order once, and only performs price adjustments once at the end.
+Since this method can return multiple error results, it is recommended to check the `errorResults`
 array to determine if any errors occurred.
 ### removeItemFromOrder
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, orderId: <a href='/reference/typescript-api/common/id#id'>ID</a>, orderLineId: <a href='/reference/typescript-api/common/id#id'>ID</a>) => Promise&#60;<a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;RemoveOrderItemsResult, <a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;&#62;`}   />
 
-Removes the specified OrderLine from the Order.
-
+Removes the specified OrderLine from the Order.
+
 If you need to remove multiple OrderLines, use `removeItemsFromOrder()` instead.
 ### removeItemsFromOrder
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, orderId: <a href='/reference/typescript-api/common/id#id'>ID</a>, orderLineIds: <a href='/reference/typescript-api/common/id#id'>ID</a>[]) => Promise&#60;<a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;RemoveOrderItemsResult, <a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;&#62;`}  since="3.1.0"  />
 
-Removes the specified OrderLines from the Order.
-This method is more efficient than calling `removeItemFromOrder` multiple times, as it only needs to fetch
+Removes the specified OrderLines from the Order.
+This method is more efficient than calling `removeItemFromOrder` multiple times, as it only needs to fetch
 the entire Order once, and only performs price adjustments once at the end.
 ### removeAllItemsFromOrder
 
@@ -246,7 +248,7 @@ Removes a <a href='/reference/typescript-api/entities/surcharge#surcharge'>Surch
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, orderId: <a href='/reference/typescript-api/common/id#id'>ID</a>, couponCode: string) => Promise&#60;<a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;ApplyCouponCodeResult, <a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;&#62;`}   />
 
-Applies a coupon code to the Order, which should be a valid coupon code as specified in the configuration
+Applies a coupon code to the Order, which should be a valid coupon code as specified in the configuration
 of an active <a href='/reference/typescript-api/entities/promotion#promotion'>Promotion</a>.
 ### removeCouponCode
 
@@ -273,14 +275,24 @@ Sets the shipping address for the Order.
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, orderId: <a href='/reference/typescript-api/common/id#id'>ID</a>, input: CreateAddressInput) => Promise&#60;<a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;`}   />
 
 Sets the billing address for the Order.
+### unsetShippingAddress
+
+<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, orderId: <a href='/reference/typescript-api/common/id#id'>ID</a>) => Promise&#60;<a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;`}  since="3.1.0"  />
+
+Unsets the shipping address for the Order.
+### unsetBillingAddress
+
+<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, orderId: <a href='/reference/typescript-api/common/id#id'>ID</a>) => Promise&#60;<a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;`}  since="3.1.0"  />
+
+Unsets the billing address for the Order.
 ### getEligibleShippingMethods
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, orderId: <a href='/reference/typescript-api/common/id#id'>ID</a>) => Promise&#60;ShippingMethodQuote[]&#62;`}   />
 
-Returns an array of quotes stating which <a href='/reference/typescript-api/entities/shipping-method#shippingmethod'>ShippingMethod</a>s may be applied to this Order.
-This is determined by the configured <a href='/reference/typescript-api/shipping/shipping-eligibility-checker#shippingeligibilitychecker'>ShippingEligibilityChecker</a> of each ShippingMethod.
-
-The quote also includes a price for each method, as determined by the configured
+Returns an array of quotes stating which <a href='/reference/typescript-api/entities/shipping-method#shippingmethod'>ShippingMethod</a>s may be applied to this Order.
+This is determined by the configured <a href='/reference/typescript-api/shipping/shipping-eligibility-checker#shippingeligibilitychecker'>ShippingEligibilityChecker</a> of each ShippingMethod.
+
+The quote also includes a price for each method, as determined by the configured
 <a href='/reference/typescript-api/shipping/shipping-calculator#shippingcalculator'>ShippingCalculator</a> of each eligible ShippingMethod.
 ### getEligiblePaymentMethods
 
@@ -301,7 +313,7 @@ Transitions the Order to the given state.
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, fulfillmentId: <a href='/reference/typescript-api/common/id#id'>ID</a>, state: <a href='/reference/typescript-api/fulfillment/fulfillment-state#fulfillmentstate'>FulfillmentState</a>) => Promise&#60;<a href='/reference/typescript-api/entities/fulfillment#fulfillment'>Fulfillment</a> | FulfillmentStateTransitionError&#62;`}   />
 
-Transitions a Fulfillment to the given state and then transitions the Order state based on
+Transitions a Fulfillment to the given state and then transitions the Order state based on
 whether all Fulfillments of the Order are shipped or delivered.
 ### transitionRefundToState
 
@@ -312,51 +324,51 @@ Transitions a Refund to the given state
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, input: ModifyOrderInput) => Promise&#60;<a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;ModifyOrderResult, <a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;&#62;`}   />
 
-Allows the Order to be modified, which allows several aspects of the Order to be changed:
-
-* Changes to OrderLine quantities
-* New OrderLines being added
-* Arbitrary <a href='/reference/typescript-api/entities/surcharge#surcharge'>Surcharge</a>s being added
-* Shipping or billing address changes
-
-Setting the `dryRun` input property to `true` will apply all changes, including updating the price of the
-Order, except history entry and additional payment actions.
-
+Allows the Order to be modified, which allows several aspects of the Order to be changed:
+
+* Changes to OrderLine quantities
+* New OrderLines being added
+* Arbitrary <a href='/reference/typescript-api/entities/surcharge#surcharge'>Surcharge</a>s being added
+* Shipping or billing address changes
+
+Setting the `dryRun` input property to `true` will apply all changes, including updating the price of the
+Order, except history entry and additional payment actions.
+
 __Using dryRun option, you must wrap function call in transaction manually.__
 ### transitionPaymentToState
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, paymentId: <a href='/reference/typescript-api/common/id#id'>ID</a>, state: <a href='/reference/typescript-api/payment/payment-state#paymentstate'>PaymentState</a>) => Promise&#60;<a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;TransitionPaymentToStateResult, <a href='/reference/typescript-api/entities/payment#payment'>Payment</a>&#62;&#62;`}   />
 
-Transitions the given <a href='/reference/typescript-api/entities/payment#payment'>Payment</a> to a new state. If the order totalWithTax price is then
-covered by Payments, the Order state will be automatically transitioned to `PaymentSettled`
+Transitions the given <a href='/reference/typescript-api/entities/payment#payment'>Payment</a> to a new state. If the order totalWithTax price is then
+covered by Payments, the Order state will be automatically transitioned to `PaymentSettled`
 or `PaymentAuthorized`.
 ### addPaymentToOrder
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, orderId: <a href='/reference/typescript-api/common/id#id'>ID</a>, input: PaymentInput) => Promise&#60;<a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;AddPaymentToOrderResult, <a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;&#62;`}   />
 
-Adds a new Payment to the Order. If the Order totalWithTax is covered by Payments, then the Order
+Adds a new Payment to the Order. If the Order totalWithTax is covered by Payments, then the Order
 state will get automatically transitioned to the `PaymentSettled` or `PaymentAuthorized` state.
 ### addManualPaymentToOrder
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, input: ManualPaymentInput) => Promise&#60;<a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;AddManualPaymentToOrderResult, <a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;&#62;`}   />
 
-This method is used after modifying an existing completed order using the `modifyOrder()` method. If the modifications
-cause the order total to increase (such as when adding a new OrderLine), then there will be an outstanding charge to
-pay.
-
-This method allows you to add a new Payment and assumes the actual processing has been done manually, e.g. in the
+This method is used after modifying an existing completed order using the `modifyOrder()` method. If the modifications
+cause the order total to increase (such as when adding a new OrderLine), then there will be an outstanding charge to
+pay.
+
+This method allows you to add a new Payment and assumes the actual processing has been done manually, e.g. in the
 dashboard of your payment provider.
 ### settlePayment
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, paymentId: <a href='/reference/typescript-api/common/id#id'>ID</a>) => Promise&#60;<a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;<a href='/reference/typescript-api/payment/payment-method-types#settlepaymentresult'>SettlePaymentResult</a>, <a href='/reference/typescript-api/entities/payment#payment'>Payment</a>&#62;&#62;`}   />
 
-Settles a payment by invoking the <a href='/reference/typescript-api/payment/payment-method-handler#paymentmethodhandler'>PaymentMethodHandler</a>'s `settlePayment()` method. Automatically
+Settles a payment by invoking the <a href='/reference/typescript-api/payment/payment-method-handler#paymentmethodhandler'>PaymentMethodHandler</a>'s `settlePayment()` method. Automatically
 transitions the Order state if all Payments are settled.
 ### cancelPayment
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, paymentId: <a href='/reference/typescript-api/common/id#id'>ID</a>) => Promise&#60;<a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;<a href='/reference/typescript-api/payment/payment-method-types#cancelpaymentresult'>CancelPaymentResult</a>, <a href='/reference/typescript-api/entities/payment#payment'>Payment</a>&#62;&#62;`}   />
 
-Cancels a payment by invoking the <a href='/reference/typescript-api/payment/payment-method-handler#paymentmethodhandler'>PaymentMethodHandler</a>'s `cancelPayment()` method (if defined), and transitions the Payment to
+Cancels a payment by invoking the <a href='/reference/typescript-api/payment/payment-method-handler#paymentmethodhandler'>PaymentMethodHandler</a>'s `cancelPayment()` method (if defined), and transitions the Payment to
 the `Cancelled` state.
 ### createFulfillment
 
@@ -377,13 +389,13 @@ Returns an array of all Surcharges associated with the Order.
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, input: CancelOrderInput) => Promise&#60;<a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;CancelOrderResult, <a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;&#62;`}   />
 
-Cancels an Order by transitioning it to the `Cancelled` state. If stock is being tracked for the ProductVariants
+Cancels an Order by transitioning it to the `Cancelled` state. If stock is being tracked for the ProductVariants
 in the Order, then new <a href='/reference/typescript-api/entities/stock-movement#stockmovement'>StockMovement</a>s will be created to correct the stock levels.
 ### refundOrder
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, input: RefundOrderInput) => Promise&#60;<a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;RefundOrderResult, <a href='/reference/typescript-api/entities/refund#refund'>Refund</a>&#62;&#62;`}   />
 
-Creates a <a href='/reference/typescript-api/entities/refund#refund'>Refund</a> against the order and in doing so invokes the `createRefund()` method of the
+Creates a <a href='/reference/typescript-api/entities/refund#refund'>Refund</a> against the order and in doing so invokes the `createRefund()` method of the
 <a href='/reference/typescript-api/payment/payment-method-handler#paymentmethodhandler'>PaymentMethodHandler</a>.
 ### settleRefund
 
@@ -419,15 +431,15 @@ Deletes an Order, ensuring that any Sessions that reference this Order are deref
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, user: <a href='/reference/typescript-api/entities/user#user'>User</a>, guestOrder?: <a href='/reference/typescript-api/entities/order#order'>Order</a>, existingOrder?: <a href='/reference/typescript-api/entities/order#order'>Order</a>) => Promise&#60;<a href='/reference/typescript-api/entities/order#order'>Order</a> | undefined&#62;`}   />
 
-When a guest user with an anonymous Order signs in and has an existing Order associated with that Customer,
-we need to reconcile the contents of the two orders.
-
+When a guest user with an anonymous Order signs in and has an existing Order associated with that Customer,
+we need to reconcile the contents of the two orders.
+
 The logic used to do the merging is specified in the <a href='/reference/typescript-api/orders/order-options#orderoptions'>OrderOptions</a> `mergeStrategy` config setting.
 ### applyPriceAdjustments
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, order: <a href='/reference/typescript-api/entities/order#order'>Order</a>, updatedOrderLines?: <a href='/reference/typescript-api/entities/order-line#orderline'>OrderLine</a>[], relations?: RelationPaths&#60;<a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;) => Promise&#60;<a href='/reference/typescript-api/entities/order#order'>Order</a>&#62;`}   />
 
-Applies promotions, taxes and shipping to the Order. If the `updatedOrderLines` argument is passed in,
+Applies promotions, taxes and shipping to the Order. If the `updatedOrderLines` argument is passed in,
 then all of those OrderLines will have their prices re-calculated using the configured <a href='/reference/typescript-api/orders/order-item-price-calculation-strategy#orderitempricecalculationstrategy'>OrderItemPriceCalculationStrategy</a>.
 
 

+ 5 - 5
docs/docs/reference/typescript-api/services/payment-method-service.md

@@ -28,10 +28,10 @@ class PaymentMethodService {
     getPaymentMethodEligibilityCheckers(ctx: RequestContext) => ConfigurableOperationDefinition[];
     getPaymentMethodHandlers(ctx: RequestContext) => ConfigurableOperationDefinition[];
     getEligiblePaymentMethods(ctx: RequestContext, order: Order) => Promise<PaymentMethodQuote[]>;
-    getMethodAndOperations(ctx: RequestContext, method: string) => Promise<{
-        paymentMethod: PaymentMethod;
-        handler: PaymentMethodHandler;
-        checker: PaymentMethodEligibilityChecker | null;
+    getMethodAndOperations(ctx: RequestContext, method: string) => Promise<{
+        paymentMethod: PaymentMethod;
+        handler: PaymentMethodHandler;
+        checker: PaymentMethodEligibilityChecker | null;
     }>;
 }
 ```
@@ -95,7 +95,7 @@ class PaymentMethodService {
 
 ### getMethodAndOperations
 
-<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, method: string) => Promise&#60;{
         paymentMethod: <a href='/reference/typescript-api/entities/payment-method#paymentmethod'>PaymentMethod</a>;
         handler: <a href='/reference/typescript-api/payment/payment-method-handler#paymentmethodhandler'>PaymentMethodHandler</a>;
         checker: <a href='/reference/typescript-api/payment/payment-method-eligibility-checker#paymentmethodeligibilitychecker'>PaymentMethodEligibilityChecker</a> | null;
     }&#62;`}   />
+<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, method: string) => Promise&#60;{         paymentMethod: <a href='/reference/typescript-api/entities/payment-method#paymentmethod'>PaymentMethod</a>;         handler: <a href='/reference/typescript-api/payment/payment-method-handler#paymentmethodhandler'>PaymentMethodHandler</a>;         checker: <a href='/reference/typescript-api/payment/payment-method-eligibility-checker#paymentmethodeligibilitychecker'>PaymentMethodEligibilityChecker</a> | null;     }&#62;`}   />
 
 
 

+ 21 - 21
docs/docs/reference/typescript-api/services/user-service.md

@@ -27,15 +27,15 @@ class UserService {
     setVerificationToken(ctx: RequestContext, user: User) => Promise<User>;
     verifyUserByToken(ctx: RequestContext, verificationToken: string, password?: string) => Promise<ErrorResultUnion<VerifyCustomerAccountResult, User>>;
     setPasswordResetToken(ctx: RequestContext, emailAddress: string) => Promise<User | undefined>;
-    resetPasswordByToken(ctx: RequestContext, passwordResetToken: string, password: string) => Promise<
-        User | PasswordResetTokenExpiredError | PasswordResetTokenInvalidError | PasswordValidationError
+    resetPasswordByToken(ctx: RequestContext, passwordResetToken: string, password: string) => Promise<
+        User | PasswordResetTokenExpiredError | PasswordResetTokenInvalidError | PasswordValidationError
     >;
     changeUserAndNativeIdentifier(ctx: RequestContext, userId: ID, newIdentifier: string) => ;
     setIdentifierChangeToken(ctx: RequestContext, user: User) => Promise<User>;
-    changeIdentifierByToken(ctx: RequestContext, token: string) => Promise<
-        | { user: User; oldIdentifier: string }
-        | IdentifierChangeTokenInvalidError
-        | IdentifierChangeTokenExpiredError
+    changeIdentifierByToken(ctx: RequestContext, token: string) => Promise<
+        | { user: User; oldIdentifier: string }
+        | IdentifierChangeTokenInvalidError
+        | IdentifierChangeTokenExpiredError
     >;
     updatePassword(ctx: RequestContext, userId: ID, currentPassword: string, newPassword: string) => Promise<boolean | InvalidCredentialsError | PasswordValidationError>;
 }
@@ -67,8 +67,8 @@ Creates a new User with the special `customer` Role and using the <a href='/refe
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, user: <a href='/reference/typescript-api/entities/user#user'>User</a>, identifier: string, password?: string) => Promise&#60;<a href='/reference/typescript-api/entities/user#user'>User</a> | PasswordValidationError&#62;`}   />
 
-Adds a new <a href='/reference/typescript-api/entities/authentication-method#nativeauthenticationmethod'>NativeAuthenticationMethod</a> to the User. If the <a href='/reference/typescript-api/auth/auth-options#authoptions'>AuthOptions</a> `requireVerification`
-is set to `true` (as is the default), the User will be marked as unverified until the email verification
+Adds a new <a href='/reference/typescript-api/entities/authentication-method#nativeauthenticationmethod'>NativeAuthenticationMethod</a> to the User. If the <a href='/reference/typescript-api/auth/auth-options#authoptions'>AuthOptions</a> `requireVerification`
+is set to `true` (as is the default), the User will be marked as unverified until the email verification
 flow is completed.
 ### createAdminUser
 
@@ -84,47 +84,47 @@ Creates a new verified User using the <a href='/reference/typescript-api/auth/na
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, user: <a href='/reference/typescript-api/entities/user#user'>User</a>) => Promise&#60;<a href='/reference/typescript-api/entities/user#user'>User</a>&#62;`}   />
 
-Sets the <a href='/reference/typescript-api/entities/authentication-method#nativeauthenticationmethod'>NativeAuthenticationMethod</a> `verificationToken` as part of the User email verification
+Sets the <a href='/reference/typescript-api/entities/authentication-method#nativeauthenticationmethod'>NativeAuthenticationMethod</a> `verificationToken` as part of the User email verification
 flow.
 ### verifyUserByToken
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, verificationToken: string, password?: string) => Promise&#60;<a href='/reference/typescript-api/errors/error-result-union#errorresultunion'>ErrorResultUnion</a>&#60;VerifyCustomerAccountResult, <a href='/reference/typescript-api/entities/user#user'>User</a>&#62;&#62;`}   />
 
-Verifies a verificationToken by looking for a User which has previously had it set using the
-`setVerificationToken()` method, and checks that the token is valid and has not expired.
-
+Verifies a verificationToken by looking for a User which has previously had it set using the
+`setVerificationToken()` method, and checks that the token is valid and has not expired.
+
 If valid, the User will be set to `verified: true`.
 ### setPasswordResetToken
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, emailAddress: string) => Promise&#60;<a href='/reference/typescript-api/entities/user#user'>User</a> | undefined&#62;`}   />
 
-Sets the <a href='/reference/typescript-api/entities/authentication-method#nativeauthenticationmethod'>NativeAuthenticationMethod</a> `passwordResetToken` as part of the User password reset
+Sets the <a href='/reference/typescript-api/entities/authentication-method#nativeauthenticationmethod'>NativeAuthenticationMethod</a> `passwordResetToken` as part of the User password reset
 flow.
 ### resetPasswordByToken
 
-<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, passwordResetToken: string, password: string) => Promise&#60;
         <a href='/reference/typescript-api/entities/user#user'>User</a> | PasswordResetTokenExpiredError | PasswordResetTokenInvalidError | PasswordValidationError
     &#62;`}   />
+<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, passwordResetToken: string, password: string) => Promise&#60;         <a href='/reference/typescript-api/entities/user#user'>User</a> | PasswordResetTokenExpiredError | PasswordResetTokenInvalidError | PasswordValidationError     &#62;`}   />
+
+Verifies a passwordResetToken by looking for a User which has previously had it set using the
+`setPasswordResetToken()` method, and checks that the token is valid and has not expired.
 
-Verifies a passwordResetToken by looking for a User which has previously had it set using the
-`setPasswordResetToken()` method, and checks that the token is valid and has not expired.
-
 If valid, the User's credentials will be updated with the new password.
 ### changeUserAndNativeIdentifier
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, userId: <a href='/reference/typescript-api/common/id#id'>ID</a>, newIdentifier: string) => `}   />
 
-Changes the User identifier without an email verification step, so this should be only used when
+Changes the User identifier without an email verification step, so this should be only used when
 an Administrator is setting a new email address.
 ### setIdentifierChangeToken
 
 <MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, user: <a href='/reference/typescript-api/entities/user#user'>User</a>) => Promise&#60;<a href='/reference/typescript-api/entities/user#user'>User</a>&#62;`}   />
 
-Sets the <a href='/reference/typescript-api/entities/authentication-method#nativeauthenticationmethod'>NativeAuthenticationMethod</a> `identifierChangeToken` as part of the User email address change
+Sets the <a href='/reference/typescript-api/entities/authentication-method#nativeauthenticationmethod'>NativeAuthenticationMethod</a> `identifierChangeToken` as part of the User email address change
 flow.
 ### changeIdentifierByToken
 
-<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, token: string) => Promise&#60;
         | { user: <a href='/reference/typescript-api/entities/user#user'>User</a>; oldIdentifier: string }
         | IdentifierChangeTokenInvalidError
         | IdentifierChangeTokenExpiredError
     &#62;`}   />
+<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, token: string) => Promise&#60;         | { user: <a href='/reference/typescript-api/entities/user#user'>User</a>; oldIdentifier: string }         | IdentifierChangeTokenInvalidError         | IdentifierChangeTokenExpiredError     &#62;`}   />
 
-Changes the User identifier as part of the storefront flow used by Customers to set a
+Changes the User identifier as part of the storefront flow used by Customers to set a
 new email address, with the token previously set using the `setIdentifierChangeToken()` method.
 ### updatePassword
 

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

@@ -1340,7 +1340,7 @@ export type CustomFieldConfig = BooleanCustomFieldConfig | DateTimeCustomFieldCo
 
 /**
  * This type is deprecated in v2.2 in favor of the EntityCustomFields type,
- * which allows custom fields to be defined on user-supplies entities.
+ * which allows custom fields to be defined on user-supplied entities.
  */
 export type CustomFields = {
   __typename?: 'CustomFields';

+ 1 - 1
packages/asset-server-plugin/e2e/graphql/generated-e2e-asset-server-plugin-types.ts

@@ -1325,7 +1325,7 @@ export type CustomFieldConfig =
 
 /**
  * This type is deprecated in v2.2 in favor of the EntityCustomFields type,
- * which allows custom fields to be defined on user-supplies entities.
+ * which allows custom fields to be defined on user-supplied entities.
  */
 export type CustomFields = {
     Address: Array<CustomFieldConfig>;

+ 8 - 4
packages/common/src/generated-shop-types.ts

@@ -1686,7 +1686,7 @@ export type MissingPasswordError = ErrorResult & {
 
 export type Mutation = {
     __typename?: 'Mutation';
-    /** Adds an item to the order. If custom fields are defined on the OrderLine entity, a third argument 'customFields' will be available. */
+    /** Adds an item to the Order. If custom fields are defined on the OrderLine entity, a third argument 'customFields' will be available. */
     addItemToOrder: UpdateOrderItemsResult;
     /** Add a Payment to the Order */
     addPaymentToOrder: AddPaymentToOrderResult;
@@ -1747,11 +1747,11 @@ export type Mutation = {
     resetPassword: ResetPasswordResult;
     /** Set the Customer for the Order. Required only if the Customer is not currently logged in */
     setCustomerForOrder: SetCustomerForOrderResult;
-    /** Sets the billing address for this order */
+    /** Sets the billing address for the active Order */
     setOrderBillingAddress: ActiveOrderResult;
-    /** Allows any custom fields to be set for the active order */
+    /** Allows any custom fields to be set for the active Order */
     setOrderCustomFields: ActiveOrderResult;
-    /** Sets the shipping address for this order */
+    /** Sets the shipping address for the active Order */
     setOrderShippingAddress: ActiveOrderResult;
     /**
      * Sets the shipping method by id, which can be obtained with the `eligibleShippingMethods` query.
@@ -1762,6 +1762,10 @@ export type Mutation = {
     setOrderShippingMethod: SetOrderShippingMethodResult;
     /** Transitions an Order to a new state. Valid next states can be found by querying `nextOrderStates` */
     transitionOrderToState?: Maybe<TransitionOrderToStateResult>;
+    /** Unsets the billing address for the active Order. Available since version 3.1.0 */
+    unsetOrderBillingAddress: ActiveOrderResult;
+    /** Unsets the shipping address for the active Order. Available since version 3.1.0 */
+    unsetOrderShippingAddress: ActiveOrderResult;
     /** Update an existing Customer */
     updateCustomer: Customer;
     /** Update an existing Address */

+ 1 - 1
packages/common/src/generated-types.ts

@@ -1328,7 +1328,7 @@ export type CustomFieldConfig = BooleanCustomFieldConfig | DateTimeCustomFieldCo
 
 /**
  * This type is deprecated in v2.2 in favor of the EntityCustomFields type,
- * which allows custom fields to be defined on user-supplies entities.
+ * which allows custom fields to be defined on user-supplied entities.
  */
 export type CustomFields = {
   __typename?: 'CustomFields';

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

@@ -375,6 +375,56 @@ describe('custom ActiveOrderStrategy', () => {
             });
         });
 
+        it('unsetOrderShippingAddress', async () => {
+            const { unsetOrderShippingAddress } = await shopClient.query(gql`
+                mutation {
+                    unsetOrderShippingAddress(${activeOrderInput}) {
+                        ...on Order {
+                            id
+                            orderToken
+                            shippingAddress {
+                                streetLine1
+                                country
+                            }
+                        }
+                    }
+                }
+            `);
+            expect(unsetOrderShippingAddress).toEqual({
+                id: 'T_1',
+                orderToken: 'token-2',
+                shippingAddress: {
+                    streetLine1: null,
+                    country: null,
+                },
+            });
+        });
+
+        it('unsetOrderBillingAddress', async () => {
+            const { unsetOrderBillingAddress } = await shopClient.query(gql`
+                mutation {
+                    unsetOrderBillingAddress(${activeOrderInput}) {
+                        ...on Order {
+                            id
+                            orderToken
+                            billingAddress {
+                                streetLine1
+                                country
+                            }
+                        }
+                    }
+                }
+            `);
+            expect(unsetOrderBillingAddress).toEqual({
+                id: 'T_1',
+                orderToken: 'token-2',
+                billingAddress: {
+                    streetLine1: null,
+                    country: null,
+                },
+            });
+        });
+
         it('eligibleShippingMethods', async () => {
             const { eligibleShippingMethods } = await shopClient.query(gql`
                 query {

+ 80 - 1
packages/core/e2e/graphql/generated-e2e-admin-types.ts

@@ -1325,7 +1325,7 @@ export type CustomFieldConfig =
 
 /**
  * This type is deprecated in v2.2 in favor of the EntityCustomFields type,
- * which allows custom fields to be defined on user-supplies entities.
+ * which allows custom fields to be defined on user-supplied entities.
  */
 export type CustomFields = {
     Address: Array<CustomFieldConfig>;
@@ -6547,6 +6547,16 @@ export type GetCollectionListAdminQuery = {
     };
 };
 
+export type GetCollectionListWithTranslationsQueryVariables = Exact<{
+    options?: InputMaybe<CollectionListOptions>;
+}>;
+
+export type GetCollectionListWithTranslationsQuery = {
+    collections: {
+        items: Array<{ id: string; name: string; translations: Array<{ id: string; name: string }> }>;
+    };
+};
+
 export type MoveCollectionMutationVariables = Exact<{
     input: MoveCollectionInput;
 }>;
@@ -16032,6 +16042,75 @@ export const GetCollectionListAdminDocument = {
         },
     ],
 } as unknown as DocumentNode<GetCollectionListAdminQuery, GetCollectionListAdminQueryVariables>;
+export const GetCollectionListWithTranslationsDocument = {
+    kind: 'Document',
+    definitions: [
+        {
+            kind: 'OperationDefinition',
+            operation: 'query',
+            name: { kind: 'Name', value: 'GetCollectionListWithTranslations' },
+            variableDefinitions: [
+                {
+                    kind: 'VariableDefinition',
+                    variable: { kind: 'Variable', name: { kind: 'Name', value: 'options' } },
+                    type: { kind: 'NamedType', name: { kind: 'Name', value: 'CollectionListOptions' } },
+                },
+            ],
+            selectionSet: {
+                kind: 'SelectionSet',
+                selections: [
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'collections' },
+                        arguments: [
+                            {
+                                kind: 'Argument',
+                                name: { kind: 'Name', value: 'options' },
+                                value: { kind: 'Variable', name: { kind: 'Name', value: 'options' } },
+                            },
+                        ],
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                {
+                                    kind: 'Field',
+                                    name: { kind: 'Name', value: 'items' },
+                                    selectionSet: {
+                                        kind: 'SelectionSet',
+                                        selections: [
+                                            { kind: 'Field', name: { kind: 'Name', value: 'id' } },
+                                            { kind: 'Field', name: { kind: 'Name', value: 'name' } },
+                                            {
+                                                kind: 'Field',
+                                                name: { kind: 'Name', value: 'translations' },
+                                                selectionSet: {
+                                                    kind: 'SelectionSet',
+                                                    selections: [
+                                                        {
+                                                            kind: 'Field',
+                                                            name: { kind: 'Name', value: 'id' },
+                                                        },
+                                                        {
+                                                            kind: 'Field',
+                                                            name: { kind: 'Name', value: 'name' },
+                                                        },
+                                                    ],
+                                                },
+                                            },
+                                        ],
+                                    },
+                                },
+                            ],
+                        },
+                    },
+                ],
+            },
+        },
+    ],
+} as unknown as DocumentNode<
+    GetCollectionListWithTranslationsQuery,
+    GetCollectionListWithTranslationsQueryVariables
+>;
 export const MoveCollectionDocument = {
     kind: 'Document',
     definitions: [

+ 477 - 106
packages/core/e2e/graphql/generated-e2e-shop-types.ts

@@ -1630,7 +1630,7 @@ export type MissingPasswordError = ErrorResult & {
 };
 
 export type Mutation = {
-    /** Adds an item to the order. If custom fields are defined on the OrderLine entity, a third argument 'customFields' will be available. */
+    /** Adds an item to the Order. If custom fields are defined on the OrderLine entity, a third argument 'customFields' will be available. */
     addItemToOrder: UpdateOrderItemsResult;
     /** Add a Payment to the Order */
     addPaymentToOrder: AddPaymentToOrderResult;
@@ -1691,11 +1691,11 @@ export type Mutation = {
     resetPassword: ResetPasswordResult;
     /** Set the Customer for the Order. Required only if the Customer is not currently logged in */
     setCustomerForOrder: SetCustomerForOrderResult;
-    /** Sets the billing address for this order */
+    /** Sets the billing address for the active Order */
     setOrderBillingAddress: ActiveOrderResult;
-    /** Allows any custom fields to be set for the active order */
+    /** Allows any custom fields to be set for the active Order */
     setOrderCustomFields: ActiveOrderResult;
-    /** Sets the shipping address for this order */
+    /** Sets the shipping address for the active Order */
     setOrderShippingAddress: ActiveOrderResult;
     /**
      * Sets the shipping method by id, which can be obtained with the `eligibleShippingMethods` query.
@@ -1706,6 +1706,10 @@ export type Mutation = {
     setOrderShippingMethod: SetOrderShippingMethodResult;
     /** Transitions an Order to a new state. Valid next states can be found by querying `nextOrderStates` */
     transitionOrderToState?: Maybe<TransitionOrderToStateResult>;
+    /** Unsets the billing address for the active Order. Available since version 3.1.0 */
+    unsetOrderBillingAddress: ActiveOrderResult;
+    /** Unsets the shipping address for the active Order. Available since version 3.1.0 */
+    unsetOrderShippingAddress: ActiveOrderResult;
     /** Update an existing Customer */
     updateCustomer: Customer;
     /** Update an existing Address */
@@ -4128,6 +4132,32 @@ export type TransitionToStateMutation = {
         | null;
 };
 
+export type OrderWithAddressesFragment = {
+    lines: Array<{ id: string }>;
+    shippingAddress?: {
+        fullName?: string | null;
+        company?: string | null;
+        streetLine1?: string | null;
+        streetLine2?: string | null;
+        city?: string | null;
+        province?: string | null;
+        postalCode?: string | null;
+        country?: string | null;
+        phoneNumber?: string | null;
+    } | null;
+    billingAddress?: {
+        fullName?: string | null;
+        company?: string | null;
+        streetLine1?: string | null;
+        streetLine2?: string | null;
+        city?: string | null;
+        province?: string | null;
+        postalCode?: string | null;
+        country?: string | null;
+        phoneNumber?: string | null;
+    } | null;
+};
+
 export type SetShippingAddressMutationVariables = Exact<{
     input: CreateAddressInput;
 }>;
@@ -4136,6 +4166,7 @@ export type SetShippingAddressMutation = {
     setOrderShippingAddress:
         | { errorCode: ErrorCode; message: string }
         | {
+              lines: Array<{ id: string }>;
               shippingAddress?: {
                   fullName?: string | null;
                   company?: string | null;
@@ -4147,6 +4178,17 @@ export type SetShippingAddressMutation = {
                   country?: string | null;
                   phoneNumber?: string | null;
               } | null;
+              billingAddress?: {
+                  fullName?: string | null;
+                  company?: string | null;
+                  streetLine1?: string | null;
+                  streetLine2?: string | null;
+                  city?: string | null;
+                  province?: string | null;
+                  postalCode?: string | null;
+                  country?: string | null;
+                  phoneNumber?: string | null;
+              } | null;
           };
 };
 
@@ -4158,6 +4200,82 @@ export type SetBillingAddressMutation = {
     setOrderBillingAddress:
         | { errorCode: ErrorCode; message: string }
         | {
+              lines: Array<{ id: string }>;
+              shippingAddress?: {
+                  fullName?: string | null;
+                  company?: string | null;
+                  streetLine1?: string | null;
+                  streetLine2?: string | null;
+                  city?: string | null;
+                  province?: string | null;
+                  postalCode?: string | null;
+                  country?: string | null;
+                  phoneNumber?: string | null;
+              } | null;
+              billingAddress?: {
+                  fullName?: string | null;
+                  company?: string | null;
+                  streetLine1?: string | null;
+                  streetLine2?: string | null;
+                  city?: string | null;
+                  province?: string | null;
+                  postalCode?: string | null;
+                  country?: string | null;
+                  phoneNumber?: string | null;
+              } | null;
+          };
+};
+
+export type UnsetShippingAddressMutationVariables = Exact<{ [key: string]: never }>;
+
+export type UnsetShippingAddressMutation = {
+    unsetOrderShippingAddress:
+        | { errorCode: ErrorCode; message: string }
+        | {
+              lines: Array<{ id: string }>;
+              shippingAddress?: {
+                  fullName?: string | null;
+                  company?: string | null;
+                  streetLine1?: string | null;
+                  streetLine2?: string | null;
+                  city?: string | null;
+                  province?: string | null;
+                  postalCode?: string | null;
+                  country?: string | null;
+                  phoneNumber?: string | null;
+              } | null;
+              billingAddress?: {
+                  fullName?: string | null;
+                  company?: string | null;
+                  streetLine1?: string | null;
+                  streetLine2?: string | null;
+                  city?: string | null;
+                  province?: string | null;
+                  postalCode?: string | null;
+                  country?: string | null;
+                  phoneNumber?: string | null;
+              } | null;
+          };
+};
+
+export type UnsetBillingAddressMutationVariables = Exact<{ [key: string]: never }>;
+
+export type UnsetBillingAddressMutation = {
+    unsetOrderBillingAddress:
+        | { errorCode: ErrorCode; message: string }
+        | {
+              lines: Array<{ id: string }>;
+              shippingAddress?: {
+                  fullName?: string | null;
+                  company?: string | null;
+                  streetLine1?: string | null;
+                  streetLine2?: string | null;
+                  city?: string | null;
+                  province?: string | null;
+                  postalCode?: string | null;
+                  country?: string | null;
+                  phoneNumber?: string | null;
+              } | null;
               billingAddress?: {
                   fullName?: string | null;
                   company?: string | null;
@@ -4847,6 +4965,65 @@ export const ActiveOrderCustomerFragmentDoc = {
         },
     ],
 } as unknown as DocumentNode<ActiveOrderCustomerFragment, unknown>;
+export const OrderWithAddressesFragmentDoc = {
+    kind: 'Document',
+    definitions: [
+        {
+            kind: 'FragmentDefinition',
+            name: { kind: 'Name', value: 'OrderWithAddresses' },
+            typeCondition: { kind: 'NamedType', name: { kind: 'Name', value: 'Order' } },
+            selectionSet: {
+                kind: 'SelectionSet',
+                selections: [
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'lines' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [{ kind: 'Field', name: { kind: 'Name', value: 'id' } }],
+                        },
+                    },
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'shippingAddress' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                { kind: 'Field', name: { kind: 'Name', value: 'fullName' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'company' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine1' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine2' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'city' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'province' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'postalCode' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'country' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'phoneNumber' } },
+                            ],
+                        },
+                    },
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'billingAddress' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                { kind: 'Field', name: { kind: 'Name', value: 'fullName' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'company' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine1' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine2' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'city' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'province' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'postalCode' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'country' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'phoneNumber' } },
+                            ],
+                        },
+                    },
+                ],
+            },
+        },
+    ],
+} as unknown as DocumentNode<OrderWithAddressesFragment, unknown>;
 export const TestOrderFragmentFragmentDoc = {
     kind: 'Document',
     definitions: [
@@ -8264,61 +8441,8 @@ export const SetShippingAddressDocument = {
                             kind: 'SelectionSet',
                             selections: [
                                 {
-                                    kind: 'InlineFragment',
-                                    typeCondition: {
-                                        kind: 'NamedType',
-                                        name: { kind: 'Name', value: 'Order' },
-                                    },
-                                    selectionSet: {
-                                        kind: 'SelectionSet',
-                                        selections: [
-                                            {
-                                                kind: 'Field',
-                                                name: { kind: 'Name', value: 'shippingAddress' },
-                                                selectionSet: {
-                                                    kind: 'SelectionSet',
-                                                    selections: [
-                                                        {
-                                                            kind: 'Field',
-                                                            name: { kind: 'Name', value: 'fullName' },
-                                                        },
-                                                        {
-                                                            kind: 'Field',
-                                                            name: { kind: 'Name', value: 'company' },
-                                                        },
-                                                        {
-                                                            kind: 'Field',
-                                                            name: { kind: 'Name', value: 'streetLine1' },
-                                                        },
-                                                        {
-                                                            kind: 'Field',
-                                                            name: { kind: 'Name', value: 'streetLine2' },
-                                                        },
-                                                        {
-                                                            kind: 'Field',
-                                                            name: { kind: 'Name', value: 'city' },
-                                                        },
-                                                        {
-                                                            kind: 'Field',
-                                                            name: { kind: 'Name', value: 'province' },
-                                                        },
-                                                        {
-                                                            kind: 'Field',
-                                                            name: { kind: 'Name', value: 'postalCode' },
-                                                        },
-                                                        {
-                                                            kind: 'Field',
-                                                            name: { kind: 'Name', value: 'country' },
-                                                        },
-                                                        {
-                                                            kind: 'Field',
-                                                            name: { kind: 'Name', value: 'phoneNumber' },
-                                                        },
-                                                    ],
-                                                },
-                                            },
-                                        ],
-                                    },
+                                    kind: 'FragmentSpread',
+                                    name: { kind: 'Name', value: 'OrderWithAddresses' },
                                 },
                                 {
                                     kind: 'InlineFragment',
@@ -8340,6 +8464,60 @@ export const SetShippingAddressDocument = {
                 ],
             },
         },
+        {
+            kind: 'FragmentDefinition',
+            name: { kind: 'Name', value: 'OrderWithAddresses' },
+            typeCondition: { kind: 'NamedType', name: { kind: 'Name', value: 'Order' } },
+            selectionSet: {
+                kind: 'SelectionSet',
+                selections: [
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'lines' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [{ kind: 'Field', name: { kind: 'Name', value: 'id' } }],
+                        },
+                    },
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'shippingAddress' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                { kind: 'Field', name: { kind: 'Name', value: 'fullName' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'company' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine1' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine2' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'city' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'province' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'postalCode' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'country' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'phoneNumber' } },
+                            ],
+                        },
+                    },
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'billingAddress' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                { kind: 'Field', name: { kind: 'Name', value: 'fullName' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'company' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine1' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine2' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'city' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'province' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'postalCode' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'country' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'phoneNumber' } },
+                            ],
+                        },
+                    },
+                ],
+            },
+        },
     ],
 } as unknown as DocumentNode<SetShippingAddressMutation, SetShippingAddressMutationVariables>;
 export const SetBillingAddressDocument = {
@@ -8375,63 +8553,106 @@ export const SetBillingAddressDocument = {
                         selectionSet: {
                             kind: 'SelectionSet',
                             selections: [
+                                {
+                                    kind: 'FragmentSpread',
+                                    name: { kind: 'Name', value: 'OrderWithAddresses' },
+                                },
                                 {
                                     kind: 'InlineFragment',
                                     typeCondition: {
                                         kind: 'NamedType',
-                                        name: { kind: 'Name', value: 'Order' },
+                                        name: { kind: 'Name', value: 'ErrorResult' },
                                     },
                                     selectionSet: {
                                         kind: 'SelectionSet',
                                         selections: [
-                                            {
-                                                kind: 'Field',
-                                                name: { kind: 'Name', value: 'billingAddress' },
-                                                selectionSet: {
-                                                    kind: 'SelectionSet',
-                                                    selections: [
-                                                        {
-                                                            kind: 'Field',
-                                                            name: { kind: 'Name', value: 'fullName' },
-                                                        },
-                                                        {
-                                                            kind: 'Field',
-                                                            name: { kind: 'Name', value: 'company' },
-                                                        },
-                                                        {
-                                                            kind: 'Field',
-                                                            name: { kind: 'Name', value: 'streetLine1' },
-                                                        },
-                                                        {
-                                                            kind: 'Field',
-                                                            name: { kind: 'Name', value: 'streetLine2' },
-                                                        },
-                                                        {
-                                                            kind: 'Field',
-                                                            name: { kind: 'Name', value: 'city' },
-                                                        },
-                                                        {
-                                                            kind: 'Field',
-                                                            name: { kind: 'Name', value: 'province' },
-                                                        },
-                                                        {
-                                                            kind: 'Field',
-                                                            name: { kind: 'Name', value: 'postalCode' },
-                                                        },
-                                                        {
-                                                            kind: 'Field',
-                                                            name: { kind: 'Name', value: 'country' },
-                                                        },
-                                                        {
-                                                            kind: 'Field',
-                                                            name: { kind: 'Name', value: 'phoneNumber' },
-                                                        },
-                                                    ],
-                                                },
-                                            },
+                                            { kind: 'Field', name: { kind: 'Name', value: 'errorCode' } },
+                                            { kind: 'Field', name: { kind: 'Name', value: 'message' } },
                                         ],
                                     },
                                 },
+                            ],
+                        },
+                    },
+                ],
+            },
+        },
+        {
+            kind: 'FragmentDefinition',
+            name: { kind: 'Name', value: 'OrderWithAddresses' },
+            typeCondition: { kind: 'NamedType', name: { kind: 'Name', value: 'Order' } },
+            selectionSet: {
+                kind: 'SelectionSet',
+                selections: [
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'lines' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [{ kind: 'Field', name: { kind: 'Name', value: 'id' } }],
+                        },
+                    },
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'shippingAddress' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                { kind: 'Field', name: { kind: 'Name', value: 'fullName' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'company' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine1' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine2' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'city' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'province' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'postalCode' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'country' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'phoneNumber' } },
+                            ],
+                        },
+                    },
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'billingAddress' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                { kind: 'Field', name: { kind: 'Name', value: 'fullName' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'company' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine1' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine2' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'city' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'province' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'postalCode' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'country' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'phoneNumber' } },
+                            ],
+                        },
+                    },
+                ],
+            },
+        },
+    ],
+} as unknown as DocumentNode<SetBillingAddressMutation, SetBillingAddressMutationVariables>;
+export const UnsetShippingAddressDocument = {
+    kind: 'Document',
+    definitions: [
+        {
+            kind: 'OperationDefinition',
+            operation: 'mutation',
+            name: { kind: 'Name', value: 'UnsetShippingAddress' },
+            selectionSet: {
+                kind: 'SelectionSet',
+                selections: [
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'unsetOrderShippingAddress' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                {
+                                    kind: 'FragmentSpread',
+                                    name: { kind: 'Name', value: 'OrderWithAddresses' },
+                                },
                                 {
                                     kind: 'InlineFragment',
                                     typeCondition: {
@@ -8452,8 +8673,158 @@ export const SetBillingAddressDocument = {
                 ],
             },
         },
+        {
+            kind: 'FragmentDefinition',
+            name: { kind: 'Name', value: 'OrderWithAddresses' },
+            typeCondition: { kind: 'NamedType', name: { kind: 'Name', value: 'Order' } },
+            selectionSet: {
+                kind: 'SelectionSet',
+                selections: [
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'lines' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [{ kind: 'Field', name: { kind: 'Name', value: 'id' } }],
+                        },
+                    },
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'shippingAddress' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                { kind: 'Field', name: { kind: 'Name', value: 'fullName' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'company' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine1' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine2' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'city' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'province' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'postalCode' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'country' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'phoneNumber' } },
+                            ],
+                        },
+                    },
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'billingAddress' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                { kind: 'Field', name: { kind: 'Name', value: 'fullName' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'company' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine1' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine2' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'city' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'province' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'postalCode' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'country' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'phoneNumber' } },
+                            ],
+                        },
+                    },
+                ],
+            },
+        },
     ],
-} as unknown as DocumentNode<SetBillingAddressMutation, SetBillingAddressMutationVariables>;
+} as unknown as DocumentNode<UnsetShippingAddressMutation, UnsetShippingAddressMutationVariables>;
+export const UnsetBillingAddressDocument = {
+    kind: 'Document',
+    definitions: [
+        {
+            kind: 'OperationDefinition',
+            operation: 'mutation',
+            name: { kind: 'Name', value: 'UnsetBillingAddress' },
+            selectionSet: {
+                kind: 'SelectionSet',
+                selections: [
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'unsetOrderBillingAddress' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                {
+                                    kind: 'FragmentSpread',
+                                    name: { kind: 'Name', value: 'OrderWithAddresses' },
+                                },
+                                {
+                                    kind: 'InlineFragment',
+                                    typeCondition: {
+                                        kind: 'NamedType',
+                                        name: { kind: 'Name', value: 'ErrorResult' },
+                                    },
+                                    selectionSet: {
+                                        kind: 'SelectionSet',
+                                        selections: [
+                                            { kind: 'Field', name: { kind: 'Name', value: 'errorCode' } },
+                                            { kind: 'Field', name: { kind: 'Name', value: 'message' } },
+                                        ],
+                                    },
+                                },
+                            ],
+                        },
+                    },
+                ],
+            },
+        },
+        {
+            kind: 'FragmentDefinition',
+            name: { kind: 'Name', value: 'OrderWithAddresses' },
+            typeCondition: { kind: 'NamedType', name: { kind: 'Name', value: 'Order' } },
+            selectionSet: {
+                kind: 'SelectionSet',
+                selections: [
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'lines' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [{ kind: 'Field', name: { kind: 'Name', value: 'id' } }],
+                        },
+                    },
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'shippingAddress' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                { kind: 'Field', name: { kind: 'Name', value: 'fullName' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'company' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine1' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine2' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'city' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'province' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'postalCode' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'country' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'phoneNumber' } },
+                            ],
+                        },
+                    },
+                    {
+                        kind: 'Field',
+                        name: { kind: 'Name', value: 'billingAddress' },
+                        selectionSet: {
+                            kind: 'SelectionSet',
+                            selections: [
+                                { kind: 'Field', name: { kind: 'Name', value: 'fullName' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'company' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine1' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'streetLine2' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'city' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'province' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'postalCode' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'country' } },
+                                { kind: 'Field', name: { kind: 'Name', value: 'phoneNumber' } },
+                            ],
+                        },
+                    },
+                ],
+            },
+        },
+    ],
+} as unknown as DocumentNode<UnsetBillingAddressMutation, UnsetBillingAddressMutationVariables>;
 export const GetActiveOrderWithPaymentsDocument = {
     kind: 'Document',
     definitions: [

+ 58 - 25
packages/core/e2e/graphql/shop-definitions.ts

@@ -502,52 +502,85 @@ export const TRANSITION_TO_STATE = gql`
     ${TEST_ORDER_FRAGMENT}
 `;
 
+export const ORDER_WITH_ADDRESSES_FRAGMENT = gql`
+    fragment OrderWithAddresses on Order {
+        lines {
+            id
+        }
+        shippingAddress {
+            fullName
+            company
+            streetLine1
+            streetLine2
+            city
+            province
+            postalCode
+            country
+            phoneNumber
+        }
+        billingAddress {
+            fullName
+            company
+            streetLine1
+            streetLine2
+            city
+            province
+            postalCode
+            country
+            phoneNumber
+        }
+    }
+`;
+
 export const SET_SHIPPING_ADDRESS = gql`
     mutation SetShippingAddress($input: CreateAddressInput!) {
         setOrderShippingAddress(input: $input) {
-            ... on Order {
-                shippingAddress {
-                    fullName
-                    company
-                    streetLine1
-                    streetLine2
-                    city
-                    province
-                    postalCode
-                    country
-                    phoneNumber
-                }
-            }
+            ...OrderWithAddresses
             ... on ErrorResult {
                 errorCode
                 message
             }
         }
     }
+    ${ORDER_WITH_ADDRESSES_FRAGMENT}
 `;
 
 export const SET_BILLING_ADDRESS = gql`
     mutation SetBillingAddress($input: CreateAddressInput!) {
         setOrderBillingAddress(input: $input) {
-            ... on Order {
-                billingAddress {
-                    fullName
-                    company
-                    streetLine1
-                    streetLine2
-                    city
-                    province
-                    postalCode
-                    country
-                    phoneNumber
-                }
+            ...OrderWithAddresses
+            ... on ErrorResult {
+                errorCode
+                message
+            }
+        }
+    }
+    ${ORDER_WITH_ADDRESSES_FRAGMENT}
+`;
+
+export const UNSET_SHIPPING_ADDRESS = gql`
+    mutation UnsetShippingAddress {
+        unsetOrderShippingAddress {
+            ...OrderWithAddresses
+            ... on ErrorResult {
+                errorCode
+                message
             }
+        }
+    }
+    ${ORDER_WITH_ADDRESSES_FRAGMENT}
+`;
+export const UNSET_BILLING_ADDRESS = gql`
+    mutation UnsetBillingAddress {
+        unsetOrderBillingAddress {
+            ...OrderWithAddresses
             ... on ErrorResult {
                 errorCode
                 message
             }
         }
     }
+    ${ORDER_WITH_ADDRESSES_FRAGMENT}
 `;
 
 export const TEST_ORDER_WITH_PAYMENTS_FRAGMENT = gql`

+ 108 - 39
packages/core/e2e/shop-order.e2e-spec.ts

@@ -71,6 +71,8 @@ import {
     SET_SHIPPING_ADDRESS,
     SET_SHIPPING_METHOD,
     TRANSITION_TO_STATE,
+    UNSET_BILLING_ADDRESS,
+    UNSET_SHIPPING_ADDRESS,
     UPDATED_ORDER_FRAGMENT,
 } from './graphql/shop-definitions';
 import { assertThrowsWithMessage } from './utils/assert-throws-with-message';
@@ -115,7 +117,8 @@ describe('Shop orders', () => {
         | CodegenShop.UpdatedOrderFragment
         | CodegenShop.TestOrderFragmentFragment
         | CodegenShop.TestOrderWithPaymentsFragment
-        | CodegenShop.ActiveOrderCustomerFragment;
+        | CodegenShop.ActiveOrderCustomerFragment
+        | CodegenShop.OrderWithAddressesFragment;
     const orderResultGuard: ErrorResultGuard<OrderSuccessResult> = createErrorResultGuard(
         input => !!input.lines,
     );
@@ -1125,8 +1128,8 @@ describe('Shop orders', () => {
             expect(customer.id).toBe(createdCustomerId);
         });
 
-        it('setOrderShippingAddress sets shipping address', async () => {
-            const address: CreateAddressInput = {
+        describe('address handling', () => {
+            const shippingAddress: CreateAddressInput = {
                 fullName: 'name',
                 company: 'company',
                 streetLine1: '12 Shipping Street',
@@ -1137,28 +1140,8 @@ describe('Shop orders', () => {
                 countryCode: 'US',
                 phoneNumber: '4444444',
             };
-            const { setOrderShippingAddress } = await shopClient.query<
-                CodegenShop.SetShippingAddressMutation,
-                CodegenShop.SetShippingAddressMutationVariables
-            >(SET_SHIPPING_ADDRESS, {
-                input: address,
-            });
-
-            expect(setOrderShippingAddress.shippingAddress).toEqual({
-                fullName: 'name',
-                company: 'company',
-                streetLine1: '12 Shipping Street',
-                streetLine2: null,
-                city: 'foo',
-                province: 'bar',
-                postalCode: '123456',
-                country: 'United States of America',
-                phoneNumber: '4444444',
-            });
-        });
 
-        it('setOrderBillingAddress sets billing address', async () => {
-            const address: CreateAddressInput = {
+            const billingAddress: CreateAddressInput = {
                 fullName: 'name',
                 company: 'company',
                 streetLine1: '22 Billing Avenue',
@@ -1169,23 +1152,109 @@ describe('Shop orders', () => {
                 countryCode: 'US',
                 phoneNumber: '4444444',
             };
-            const { setOrderBillingAddress } = await shopClient.query<
-                Codegen.SetBillingAddressMutation,
-                Codegen.SetBillingAddressMutationVariables
-            >(SET_BILLING_ADDRESS, {
-                input: address,
+
+            it('setOrderShippingAddress sets shipping address', async () => {
+                const { setOrderShippingAddress } = await shopClient.query<
+                    CodegenShop.SetShippingAddressMutation,
+                    CodegenShop.SetShippingAddressMutationVariables
+                >(SET_SHIPPING_ADDRESS, {
+                    input: shippingAddress,
+                });
+
+                orderResultGuard.assertSuccess(setOrderShippingAddress);
+
+                expect(setOrderShippingAddress.shippingAddress).toEqual({
+                    fullName: 'name',
+                    company: 'company',
+                    streetLine1: '12 Shipping Street',
+                    streetLine2: null,
+                    city: 'foo',
+                    province: 'bar',
+                    postalCode: '123456',
+                    country: 'United States of America',
+                    phoneNumber: '4444444',
+                });
             });
 
-            expect(setOrderBillingAddress.billingAddress).toEqual({
-                fullName: 'name',
-                company: 'company',
-                streetLine1: '22 Billing Avenue',
-                streetLine2: null,
-                city: 'foo',
-                province: 'bar',
-                postalCode: '123456',
-                country: 'United States of America',
-                phoneNumber: '4444444',
+            it('setOrderBillingAddress sets billing address', async () => {
+                const { setOrderBillingAddress } = await shopClient.query<
+                    CodegenShop.SetBillingAddressMutation,
+                    CodegenShop.SetBillingAddressMutationVariables
+                >(SET_BILLING_ADDRESS, {
+                    input: billingAddress,
+                });
+
+                orderResultGuard.assertSuccess(setOrderBillingAddress);
+
+                expect(setOrderBillingAddress.billingAddress).toEqual({
+                    fullName: 'name',
+                    company: 'company',
+                    streetLine1: '22 Billing Avenue',
+                    streetLine2: null,
+                    city: 'foo',
+                    province: 'bar',
+                    postalCode: '123456',
+                    country: 'United States of America',
+                    phoneNumber: '4444444',
+                });
+            });
+
+            it('unsetOrderShippingAddress unsets shipping address', async () => {
+                const { unsetOrderShippingAddress } = await shopClient.query<
+                    CodegenShop.UnsetShippingAddressMutation,
+                    CodegenShop.UnsetShippingAddressMutationVariables
+                >(UNSET_SHIPPING_ADDRESS);
+
+                orderResultGuard.assertSuccess(unsetOrderShippingAddress);
+
+                expect(unsetOrderShippingAddress.shippingAddress).toEqual({
+                    fullName: null,
+                    company: null,
+                    streetLine1: null,
+                    streetLine2: null,
+                    city: null,
+                    province: null,
+                    postalCode: null,
+                    country: null,
+                    phoneNumber: null,
+                });
+
+                // Reset the shipping address for subsequent tests
+                await shopClient.query<
+                    CodegenShop.SetShippingAddressMutation,
+                    CodegenShop.SetShippingAddressMutationVariables
+                >(SET_SHIPPING_ADDRESS, {
+                    input: shippingAddress,
+                });
+            });
+
+            it('unsetOrderBillingAddress unsets billing address', async () => {
+                const { unsetOrderBillingAddress } = await shopClient.query<
+                    CodegenShop.UnsetBillingAddressMutation,
+                    CodegenShop.UnsetBillingAddressMutationVariables
+                >(UNSET_BILLING_ADDRESS);
+
+                orderResultGuard.assertSuccess(unsetOrderBillingAddress);
+
+                expect(unsetOrderBillingAddress.billingAddress).toEqual({
+                    fullName: null,
+                    company: null,
+                    streetLine1: null,
+                    streetLine2: null,
+                    city: null,
+                    province: null,
+                    postalCode: null,
+                    country: null,
+                    phoneNumber: null,
+                });
+
+                // Reset the billing address for subsequent tests
+                await shopClient.query<
+                    CodegenShop.SetBillingAddressMutation,
+                    CodegenShop.SetBillingAddressMutationVariables
+                >(SET_BILLING_ADDRESS, {
+                    input: billingAddress,
+                });
             });
         });
 

+ 2 - 0
packages/core/src/api/config/generate-active-order-types.ts

@@ -73,6 +73,8 @@ export function generateActiveOrderTypes(
         { name: 'setOrderShippingMethod', isMutation: true },
         { name: 'setOrderCustomFields', isMutation: true },
         { name: 'transitionOrderToState', isMutation: true },
+        { name: 'unsetOrderShippingAddress', isMutation: true },
+        { name: 'unsetOrderBillingAddress', isMutation: true },
     ];
 
     const queryType = schema.getQueryType();

+ 38 - 0
packages/core/src/api/resolvers/shop/shop-order.resolver.ts

@@ -182,6 +182,44 @@ export class ShopOrderResolver {
         return new NoActiveOrderError();
     }
 
+    @Transaction()
+    @Mutation()
+    @Allow(Permission.Owner)
+    async unsetOrderShippingAddress(
+        @Ctx() ctx: RequestContext,
+        @Args() args: ActiveOrderArgs,
+    ): Promise<ErrorResultUnion<ActiveOrderResult, Order>> {
+        if (ctx.authorizedAsOwnerOnly) {
+            const sessionOrder = await this.activeOrderService.getActiveOrder(
+                ctx,
+                args[ACTIVE_ORDER_INPUT_FIELD_NAME],
+            );
+            if (sessionOrder) {
+                return this.orderService.unsetShippingAddress(ctx, sessionOrder.id);
+            }
+        }
+        return new NoActiveOrderError();
+    }
+
+    @Transaction()
+    @Mutation()
+    @Allow(Permission.Owner)
+    async unsetOrderBillingAddress(
+        @Ctx() ctx: RequestContext,
+        @Args() args: ActiveOrderArgs,
+    ): Promise<ErrorResultUnion<ActiveOrderResult, Order>> {
+        if (ctx.authorizedAsOwnerOnly) {
+            const sessionOrder = await this.activeOrderService.getActiveOrder(
+                ctx,
+                args[ACTIVE_ORDER_INPUT_FIELD_NAME],
+            );
+            if (sessionOrder) {
+                return this.orderService.unsetBillingAddress(ctx, sessionOrder.id);
+            }
+        }
+        return new NoActiveOrderError();
+    }
+
     @Query()
     @Allow(Permission.Owner)
     async eligibleShippingMethods(

+ 30 - 13
packages/core/src/api/schema/shop-api/shop.api.graphql

@@ -48,7 +48,7 @@ type Query {
 }
 
 type Mutation {
-    "Adds an item to the order. If custom fields are defined on the OrderLine entity, a third argument 'customFields' will be available."
+    "Adds an item to the Order. If custom fields are defined on the OrderLine entity, a third argument 'customFields' will be available."
     addItemToOrder(productVariantId: ID!, quantity: Int!): UpdateOrderItemsResult!
     "Remove an OrderLine from the Order"
     removeOrderLine(orderLineId: ID!): RemoveOrderItemsResult!
@@ -62,11 +62,15 @@ type Mutation {
     removeCouponCode(couponCode: String!): Order
     "Transitions an Order to a new state. Valid next states can be found by querying `nextOrderStates`"
     transitionOrderToState(state: String!): TransitionOrderToStateResult
-    "Sets the shipping address for this order"
+    "Sets the shipping address for the active Order"
     setOrderShippingAddress(input: CreateAddressInput!): ActiveOrderResult!
-    "Sets the billing address for this order"
+    "Sets the billing address for the active Order"
     setOrderBillingAddress(input: CreateAddressInput!): ActiveOrderResult!
-    "Allows any custom fields to be set for the active order"
+    "Unsets the shipping address for the active Order. Available since version 3.1.0"
+    unsetOrderShippingAddress: ActiveOrderResult!
+    "Unsets the billing address for the active Order. Available since version 3.1.0"
+    unsetOrderBillingAddress: ActiveOrderResult!
+    "Allows any custom fields to be set for the active Order"
     setOrderCustomFields(input: UpdateOrderInput!): ActiveOrderResult!
     """
     Sets the shipping method by id, which can be obtained with the `eligibleShippingMethods` query.
@@ -203,7 +207,7 @@ input ProductListOptions
 input ProductVariantListOptions
 
 union AddPaymentToOrderResult =
-      Order
+    | Order
     | OrderPaymentStateError
     | IneligiblePaymentMethodError
     | PaymentFailedError
@@ -211,38 +215,51 @@ union AddPaymentToOrderResult =
     | OrderStateTransitionError
     | NoActiveOrderError
 union TransitionOrderToStateResult = Order | OrderStateTransitionError
-union SetCustomerForOrderResult = Order | AlreadyLoggedInError | EmailAddressConflictError | NoActiveOrderError | GuestCheckoutError
-union RegisterCustomerAccountResult = Success | MissingPasswordError | PasswordValidationError | NativeAuthStrategyError
+union SetCustomerForOrderResult =
+    | Order
+    | AlreadyLoggedInError
+    | EmailAddressConflictError
+    | NoActiveOrderError
+    | GuestCheckoutError
+union RegisterCustomerAccountResult =
+    | Success
+    | MissingPasswordError
+    | PasswordValidationError
+    | NativeAuthStrategyError
 union RefreshCustomerVerificationResult = Success | NativeAuthStrategyError
 union VerifyCustomerAccountResult =
-      CurrentUser
+    | CurrentUser
     | VerificationTokenInvalidError
     | VerificationTokenExpiredError
     | MissingPasswordError
     | PasswordValidationError
     | PasswordAlreadySetError
     | NativeAuthStrategyError
-union UpdateCustomerPasswordResult = Success | InvalidCredentialsError | PasswordValidationError | NativeAuthStrategyError
+union UpdateCustomerPasswordResult =
+    | Success
+    | InvalidCredentialsError
+    | PasswordValidationError
+    | NativeAuthStrategyError
 union RequestUpdateCustomerEmailAddressResult =
-      Success
+    | Success
     | InvalidCredentialsError
     | EmailAddressConflictError
     | NativeAuthStrategyError
 union UpdateCustomerEmailAddressResult =
-      Success
+    | Success
     | IdentifierChangeTokenInvalidError
     | IdentifierChangeTokenExpiredError
     | NativeAuthStrategyError
 union RequestPasswordResetResult = Success | NativeAuthStrategyError
 union ResetPasswordResult =
-      CurrentUser
+    | CurrentUser
     | PasswordResetTokenInvalidError
     | PasswordResetTokenExpiredError
     | PasswordValidationError
     | NativeAuthStrategyError
     | NotVerifiedError
 union NativeAuthenticationResult =
-      CurrentUser
+    | CurrentUser
     | InvalidCredentialsError
     | NotVerifiedError
     | NativeAuthStrategyError

+ 48 - 0
packages/core/src/service/services/order.service.ts

@@ -1030,6 +1030,54 @@ export class OrderService {
         return this.applyPriceAdjustments(ctx, order, order.lines);
     }
 
+    /**
+     * @description
+     * Unsets the shipping address for the Order.
+     *
+     * @since 3.1.0
+     */
+    async unsetShippingAddress(ctx: RequestContext, orderId: ID): Promise<Order> {
+        const order = await this.getOrderOrThrow(ctx, orderId);
+        await this.connection
+            .getRepository(ctx, Order)
+            .createQueryBuilder('order')
+            .update(Order)
+            .set({ shippingAddress: {} })
+            .where('id = :id', { id: order.id })
+            .execute();
+        order.shippingAddress = {};
+        // Since a changed ShippingAddress could alter the activeTaxZone,
+        // we will remove any cached activeTaxZone, so it can be re-calculated
+        // as needed.
+        this.requestCache.set(ctx, CacheKey.ActiveTaxZone, undefined);
+        this.requestCache.set(ctx, CacheKey.ActiveTaxZone_PPA, undefined);
+        return this.applyPriceAdjustments(ctx, order, order.lines);
+    }
+
+    /**
+     * @description
+     * Unsets the billing address for the Order.
+     *
+     * @since 3.1.0
+     */
+    async unsetBillingAddress(ctx: RequestContext, orderId: ID): Promise<Order> {
+        const order = await this.getOrderOrThrow(ctx, orderId);
+        await this.connection
+            .getRepository(ctx, Order)
+            .createQueryBuilder('order')
+            .update(Order)
+            .set({ billingAddress: {} })
+            .where('id = :id', { id: order.id })
+            .execute();
+        order.billingAddress = {};
+        // Since a changed BillingAddress could alter the activeTaxZone,
+        // we will remove any cached activeTaxZone, so it can be re-calculated
+        // as needed.
+        this.requestCache.set(ctx, CacheKey.ActiveTaxZone, undefined);
+        this.requestCache.set(ctx, CacheKey.ActiveTaxZone_PPA, undefined);
+        return this.applyPriceAdjustments(ctx, order, order.lines);
+    }
+
     /**
      * @description
      * Returns an array of quotes stating which {@link ShippingMethod}s may be applied to this Order.

+ 1 - 16
packages/dev-server/dev-config.ts

@@ -63,22 +63,7 @@ export const devConfig: VendureConfig = {
         paymentMethodHandlers: [dummyPaymentHandler],
     },
 
-    customFields: {
-        Product: [
-            {
-                name: 'test',
-                type: 'relation',
-                entity: Asset,
-            },
-        ],
-        FacetValue: [
-            {
-                name: 'childFacetValue',
-                type: 'relation',
-                entity: FacetValue,
-            },
-        ],
-    },
+    customFields: {},
     logger: new DefaultLogger({ level: LogLevel.Info }),
     importExportOptions: {
         importAssetsDir: path.join(__dirname, 'import-assets'),

+ 10 - 12
packages/dev-server/tsconfig.json

@@ -1,14 +1,12 @@
 {
-  "extends": "../../tsconfig",
-  "compilerOptions": {
-    "module": "commonjs",
-    "sourceMap": true,
-    "jsx": "react",
-    "paths": {
-      "@vendure/admin-ui/*": ["../admin-ui/package/*"]
-    }
-  },
-  "exclude": [
-    "node_modules"
-  ],
+    "extends": "../../tsconfig",
+    "compilerOptions": {
+        "module": "NodeNext",
+        "sourceMap": true,
+        "jsx": "react",
+        "paths": {
+            "@vendure/admin-ui/*": ["../admin-ui/package/*"]
+        }
+    },
+    "exclude": ["node_modules"]
 }

+ 1 - 1
packages/elasticsearch-plugin/e2e/graphql/generated-e2e-elasticsearch-plugin-types.ts

@@ -1325,7 +1325,7 @@ export type CustomFieldConfig =
 
 /**
  * This type is deprecated in v2.2 in favor of the EntityCustomFields type,
- * which allows custom fields to be defined on user-supplies entities.
+ * which allows custom fields to be defined on user-supplied entities.
  */
 export type CustomFields = {
     Address: Array<CustomFieldConfig>;

+ 1 - 1
packages/payments-plugin/e2e/graphql/generated-admin-types.ts

@@ -1329,7 +1329,7 @@ export type CustomFieldConfig =
 
 /**
  * This type is deprecated in v2.2 in favor of the EntityCustomFields type,
- * which allows custom fields to be defined on user-supplies entities.
+ * which allows custom fields to be defined on user-supplied entities.
  */
 export type CustomFields = {
     Address: Array<CustomFieldConfig>;

+ 8 - 4
packages/payments-plugin/e2e/graphql/generated-shop-types.ts

@@ -1694,7 +1694,7 @@ export type MolliePaymentMethodsInput = {
 };
 
 export type Mutation = {
-    /** Adds an item to the order. If custom fields are defined on the OrderLine entity, a third argument 'customFields' will be available. */
+    /** Adds an item to the Order. If custom fields are defined on the OrderLine entity, a third argument 'customFields' will be available. */
     addItemToOrder: UpdateOrderItemsResult;
     /** Add a Payment to the Order */
     addPaymentToOrder: AddPaymentToOrderResult;
@@ -1756,11 +1756,11 @@ export type Mutation = {
     resetPassword: ResetPasswordResult;
     /** Set the Customer for the Order. Required only if the Customer is not currently logged in */
     setCustomerForOrder: SetCustomerForOrderResult;
-    /** Sets the billing address for this order */
+    /** Sets the billing address for the active Order */
     setOrderBillingAddress: ActiveOrderResult;
-    /** Allows any custom fields to be set for the active order */
+    /** Allows any custom fields to be set for the active Order */
     setOrderCustomFields: ActiveOrderResult;
-    /** Sets the shipping address for this order */
+    /** Sets the shipping address for the active Order */
     setOrderShippingAddress: ActiveOrderResult;
     /**
      * Sets the shipping method by id, which can be obtained with the `eligibleShippingMethods` query.
@@ -1771,6 +1771,10 @@ export type Mutation = {
     setOrderShippingMethod: SetOrderShippingMethodResult;
     /** Transitions an Order to a new state. Valid next states can be found by querying `nextOrderStates` */
     transitionOrderToState?: Maybe<TransitionOrderToStateResult>;
+    /** Unsets the billing address for the active Order. Available since version 3.1.0 */
+    unsetOrderBillingAddress: ActiveOrderResult;
+    /** Unsets the shipping address for the active Order. Available since version 3.1.0 */
+    unsetOrderShippingAddress: ActiveOrderResult;
     /** Update an existing Customer */
     updateCustomer: Customer;
     /** Update an existing Address */

+ 8 - 4
packages/payments-plugin/src/mollie/graphql/generated-shop-types.ts

@@ -1755,7 +1755,7 @@ export type MolliePaymentMethodsInput = {
 
 export type Mutation = {
     __typename?: 'Mutation';
-    /** Adds an item to the order. If custom fields are defined on the OrderLine entity, a third argument 'customFields' will be available. */
+    /** Adds an item to the Order. If custom fields are defined on the OrderLine entity, a third argument 'customFields' will be available. */
     addItemToOrder: UpdateOrderItemsResult;
     /** Add a Payment to the Order */
     addPaymentToOrder: AddPaymentToOrderResult;
@@ -1817,11 +1817,11 @@ export type Mutation = {
     resetPassword: ResetPasswordResult;
     /** Set the Customer for the Order. Required only if the Customer is not currently logged in */
     setCustomerForOrder: SetCustomerForOrderResult;
-    /** Sets the billing address for this order */
+    /** Sets the billing address for the active Order */
     setOrderBillingAddress: ActiveOrderResult;
-    /** Allows any custom fields to be set for the active order */
+    /** Allows any custom fields to be set for the active Order */
     setOrderCustomFields: ActiveOrderResult;
-    /** Sets the shipping address for this order */
+    /** Sets the shipping address for the active Order */
     setOrderShippingAddress: ActiveOrderResult;
     /**
      * Sets the shipping method by id, which can be obtained with the `eligibleShippingMethods` query.
@@ -1832,6 +1832,10 @@ export type Mutation = {
     setOrderShippingMethod: SetOrderShippingMethodResult;
     /** Transitions an Order to a new state. Valid next states can be found by querying `nextOrderStates` */
     transitionOrderToState?: Maybe<TransitionOrderToStateResult>;
+    /** Unsets the billing address for the active Order. Available since version 3.1.0 */
+    unsetOrderBillingAddress: ActiveOrderResult;
+    /** Unsets the shipping address for the active Order. Available since version 3.1.0 */
+    unsetOrderShippingAddress: ActiveOrderResult;
     /** Update an existing Customer */
     updateCustomer: Customer;
     /** Update an existing Address */

File diff suppressed because it is too large
+ 0 - 0
schema-admin.json


File diff suppressed because it is too large
+ 0 - 0
schema-shop.json


Some files were not shown because too many files changed in this diff