Browse Source

feat(core): Get DefaultSearchPlugin working with new Worker architecture

Relates to #115
Michael Bromley 6 years ago
parent
commit
6ca2ab4b0f

+ 11 - 0
packages/core/e2e/config/test-config.ts

@@ -1,7 +1,10 @@
+import { Transport } from '@nestjs/microservices';
 import { ADMIN_API_PATH, SHOP_API_PATH } from '@vendure/common/lib/shared-constants';
 import path from 'path';
 
 import { DefaultAssetNamingStrategy } from '../../src/config/asset-naming-strategy/default-asset-naming-strategy';
+import { DefaultLogger } from '../../src/config/logger/default-logger';
+import { LogLevel } from '../../src/config/logger/vendure-logger';
 import { VendureConfig } from '../../src/config/vendure-config';
 
 import { TestingAssetPreviewStrategy } from './testing-asset-preview-strategy';
@@ -52,6 +55,7 @@ export const testConfig: VendureConfig = {
     paymentOptions: {
         paymentMethodHandlers: [],
     },
+    logger: new DefaultLogger({ level: LogLevel.Error }),
     importExportOptions: {
         importAssetsDir: path.join(__dirname, '..', 'fixtures/assets'),
     },
@@ -60,4 +64,11 @@ export const testConfig: VendureConfig = {
         assetStorageStrategy: new TestingAssetStorageStrategy(),
         assetPreviewStrategy: new TestingAssetPreviewStrategy(),
     },
+    workerOptions: {
+        runInMainProcess: true,
+        transport: Transport.TCP,
+        options: {
+            port: 3051,
+        },
+    },
 };

+ 33 - 4
packages/core/e2e/default-search-plugin.e2e-spec.ts

@@ -11,6 +11,8 @@ import {
     ConfigArgType,
     CreateCollection,
     CreateFacet,
+    GetRunningJobs,
+    JobState,
     LanguageCode,
     SearchFacetValues,
     SearchGetPrices,
@@ -45,7 +47,7 @@ describe('Default search plugin', () => {
                 customerCount: 1,
             },
             {
-                plugins: [new DefaultSearchPlugin({ runInForkedProcess: false })],
+                plugins: [new DefaultSearchPlugin()],
             },
         );
         await adminClient.init();
@@ -269,6 +271,7 @@ describe('Default search plugin', () => {
                     { id: 'T_3', enabled: false },
                 ],
             });
+            await awaitRunningJobs();
             const result = await shopClient.query<SearchProductsShop.Query, SearchProductsShop.Variables>(SEARCH_PRODUCTS_SHOP, {
                 input: {
                     groupByProduct: false,
@@ -313,7 +316,7 @@ describe('Default search plugin', () => {
                     facetValueIds: [],
                 },
             });
-
+            await awaitRunningJobs();
             const result = await adminClient.query<SearchProductsShop.Query, SearchProductsShop.Variables>(
                 SEARCH_PRODUCTS,
                 {
@@ -358,7 +361,7 @@ describe('Default search plugin', () => {
                     },
                 },
             );
-
+            await awaitRunningJobs();
             const result = await adminClient.query<SearchProductsShop.Query, SearchProductsShop.Variables>(
                 SEARCH_PRODUCTS,
                 {
@@ -411,7 +414,7 @@ describe('Default search plugin', () => {
                     ],
                 },
             });
-
+            await awaitRunningJobs();
             const result = await adminClient.query<SearchProductsShop.Query, SearchProductsShop.Variables>(
                 SEARCH_PRODUCTS,
                 {
@@ -438,6 +441,7 @@ describe('Default search plugin', () => {
                     value: 50,
                 },
             });
+            await awaitRunningJobs();
             const result = await adminClient.query<SearchGetPrices.Query, SearchGetPrices.Variables>(SEARCH_GET_PRICES, {
                 input: {
                     groupByProduct: true,
@@ -473,6 +477,7 @@ describe('Default search plugin', () => {
                     { id: 'T_2', enabled: false },
                 ],
             });
+            await awaitRunningJobs();
             const result = await adminClient.query<SearchProductsShop.Query, SearchProductsShop.Variables>(SEARCH_PRODUCTS, {
                 input: {
                     groupByProduct: true,
@@ -492,6 +497,7 @@ describe('Default search plugin', () => {
                     { id: 'T_4', enabled: false },
                 ],
             });
+            await awaitRunningJobs();
             const result = await adminClient.query<SearchProductsShop.Query, SearchProductsShop.Variables>(SEARCH_PRODUCTS, {
                 input: {
                     groupByProduct: true,
@@ -512,6 +518,7 @@ describe('Default search plugin', () => {
                     enabled: false,
                 },
             });
+            await awaitRunningJobs();
             const result = await adminClient.query<SearchProductsShop.Query, SearchProductsShop.Variables>(SEARCH_PRODUCTS, {
                 input: {
                     groupByProduct: true,
@@ -525,8 +532,30 @@ describe('Default search plugin', () => {
             ]);
         });
     });
+
+    /**
+     * Since the updates to the search index are performed in the background, we need
+     * to ensure that any running background jobs are completed before continuing certain
+     * tests.
+     */
+    async function awaitRunningJobs() {
+        let runningJobs = 0;
+        do {
+            const { jobs } = await adminClient.query<GetRunningJobs.Query>(GET_RUNNING_JOBS);
+            runningJobs = jobs.filter(job => job.state !== JobState.COMPLETED);
+        } while (runningJobs > 0);
+    }
 });
 
+export const GET_RUNNING_JOBS = gql`
+    query GetRunningJobs {
+        jobs {
+            name
+            state
+        }
+    }
+`;
+
 export const SEARCH_PRODUCTS = gql`
     query SearchProductsAdmin($input: SearchInput!) {
         search(input: $input) {

+ 164 - 76
packages/core/e2e/graphql/generated-e2e-admin-types.ts

@@ -1,5 +1,4 @@
 // tslint:disable
-
 export type Maybe<T> = T | null;
 /** All built-in and custom scalars, mapped to their actual values */
 export type Scalars = {
@@ -20,6 +19,7 @@ export type Scalars = {
 };
 
 export type Address = Node & {
+    __typename?: 'Address';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -38,6 +38,7 @@ export type Address = Node & {
 };
 
 export type Adjustment = {
+    __typename?: 'Adjustment';
     adjustmentSource: Scalars['String'];
     type: AdjustmentType;
     description: Scalars['String'];
@@ -45,6 +46,7 @@ export type Adjustment = {
 };
 
 export type AdjustmentOperations = {
+    __typename?: 'AdjustmentOperations';
     conditions: Array<ConfigurableOperation>;
     actions: Array<ConfigurableOperation>;
 };
@@ -60,6 +62,7 @@ export enum AdjustmentType {
 }
 
 export type Administrator = Node & {
+    __typename?: 'Administrator';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -78,6 +81,7 @@ export type AdministratorFilterParameter = {
 };
 
 export type AdministratorList = PaginatedList & {
+    __typename?: 'AdministratorList';
     items: Array<Administrator>;
     totalItems: Scalars['Int'];
 };
@@ -99,6 +103,7 @@ export type AdministratorSortParameter = {
 };
 
 export type Asset = Node & {
+    __typename?: 'Asset';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -122,6 +127,7 @@ export type AssetFilterParameter = {
 };
 
 export type AssetList = PaginatedList & {
+    __typename?: 'AssetList';
     items: Array<Asset>;
     totalItems: Scalars['Int'];
 };
@@ -156,6 +162,7 @@ export type BooleanOperators = {
 
 export type Cancellation = Node &
     StockMovement & {
+        __typename?: 'Cancellation';
         id: Scalars['ID'];
         createdAt: Scalars['DateTime'];
         updatedAt: Scalars['DateTime'];
@@ -166,6 +173,7 @@ export type Cancellation = Node &
     };
 
 export type Channel = Node & {
+    __typename?: 'Channel';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -179,6 +187,7 @@ export type Channel = Node & {
 };
 
 export type Collection = Node & {
+    __typename?: 'Collection';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -203,6 +212,7 @@ export type CollectionProductVariantsArgs = {
 };
 
 export type CollectionBreadcrumb = {
+    __typename?: 'CollectionBreadcrumb';
     id: Scalars['ID'];
     name: Scalars['String'];
 };
@@ -218,6 +228,7 @@ export type CollectionFilterParameter = {
 };
 
 export type CollectionList = PaginatedList & {
+    __typename?: 'CollectionList';
     items: Array<Collection>;
     totalItems: Scalars['Int'];
 };
@@ -239,6 +250,7 @@ export type CollectionSortParameter = {
 };
 
 export type CollectionTranslation = {
+    __typename?: 'CollectionTranslation';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -256,6 +268,7 @@ export type CollectionTranslationInput = {
 };
 
 export type ConfigArg = {
+    __typename?: 'ConfigArg';
     name: Scalars['String'];
     type: ConfigArgType;
     value?: Maybe<Scalars['String']>;
@@ -286,6 +299,7 @@ export enum ConfigArgType {
 }
 
 export type ConfigurableOperation = {
+    __typename?: 'ConfigurableOperation';
     code: Scalars['String'];
     args: Array<ConfigArg>;
     description: Scalars['String'];
@@ -297,6 +311,7 @@ export type ConfigurableOperationInput = {
 };
 
 export type Country = Node & {
+    __typename?: 'Country';
     id: Scalars['ID'];
     languageCode: LanguageCode;
     code: Scalars['String'];
@@ -313,6 +328,7 @@ export type CountryFilterParameter = {
 };
 
 export type CountryList = PaginatedList & {
+    __typename?: 'CountryList';
     items: Array<Country>;
     totalItems: Scalars['Int'];
 };
@@ -331,6 +347,7 @@ export type CountrySortParameter = {
 };
 
 export type CountryTranslation = {
+    __typename?: 'CountryTranslation';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -823,12 +840,14 @@ export enum CurrencyCode {
 }
 
 export type CurrentUser = {
+    __typename?: 'CurrentUser';
     id: Scalars['ID'];
     identifier: Scalars['String'];
     channelTokens: Array<Scalars['String']>;
 };
 
 export type Customer = Node & {
+    __typename?: 'Customer';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -858,6 +877,7 @@ export type CustomerFilterParameter = {
 };
 
 export type CustomerGroup = Node & {
+    __typename?: 'CustomerGroup';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -865,6 +885,7 @@ export type CustomerGroup = Node & {
 };
 
 export type CustomerList = PaginatedList & {
+    __typename?: 'CustomerList';
     items: Array<Customer>;
     totalItems: Scalars['Int'];
 };
@@ -900,6 +921,7 @@ export type DateRange = {
 };
 
 export type DeletionResponse = {
+    __typename?: 'DeletionResponse';
     result: DeletionResult;
     message?: Maybe<Scalars['String']>;
 };
@@ -912,6 +934,7 @@ export enum DeletionResult {
 }
 
 export type Facet = Node & {
+    __typename?: 'Facet';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -934,6 +957,7 @@ export type FacetFilterParameter = {
 };
 
 export type FacetList = PaginatedList & {
+    __typename?: 'FacetList';
     items: Array<Facet>;
     totalItems: Scalars['Int'];
 };
@@ -954,6 +978,7 @@ export type FacetSortParameter = {
 };
 
 export type FacetTranslation = {
+    __typename?: 'FacetTranslation';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -969,6 +994,7 @@ export type FacetTranslationInput = {
 };
 
 export type FacetValue = Node & {
+    __typename?: 'FacetValue';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -984,11 +1010,13 @@ export type FacetValue = Node & {
  * by the search, and in what quantity.
  */
 export type FacetValueResult = {
+    __typename?: 'FacetValueResult';
     facetValue: FacetValue;
     count: Scalars['Int'];
 };
 
 export type FacetValueTranslation = {
+    __typename?: 'FacetValueTranslation';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1004,6 +1032,7 @@ export type FacetValueTranslationInput = {
 };
 
 export type GlobalSettings = {
+    __typename?: 'GlobalSettings';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1014,12 +1043,14 @@ export type GlobalSettings = {
 };
 
 export type ImportInfo = {
+    __typename?: 'ImportInfo';
     errors?: Maybe<Array<Scalars['String']>>;
     processed: Scalars['Int'];
     imported: Scalars['Int'];
 };
 
 export type JobInfo = {
+    __typename?: 'JobInfo';
     id: Scalars['String'];
     name: Scalars['String'];
     state: JobState;
@@ -1415,6 +1446,7 @@ export enum LanguageCode {
 }
 
 export type LoginResult = {
+    __typename?: 'LoginResult';
     user: CurrentUser;
 };
 
@@ -1425,6 +1457,7 @@ export type MoveCollectionInput = {
 };
 
 export type Mutation = {
+    __typename?: 'Mutation';
     /** Create a new Administrator */
     createAdministrator: Administrator;
     /** Update an existing Administrator */
@@ -1439,6 +1472,12 @@ export type Mutation = {
     createChannel: Channel;
     /** Update an existing Channel */
     updateChannel: Channel;
+    /** Create a new Collection */
+    createCollection: Collection;
+    /** Update an existing Collection */
+    updateCollection: Collection;
+    /** Move a Collection to a different parent or index */
+    moveCollection: Collection;
     /** Create a new Country */
     createCountry: Country;
     /** Update an existing Country */
@@ -1453,12 +1492,18 @@ export type Mutation = {
     addCustomersToGroup: CustomerGroup;
     /** Remove Customers from a CustomerGroup */
     removeCustomersFromGroup: CustomerGroup;
-    /** Create a new Collection */
-    createCollection: Collection;
-    /** Update an existing Collection */
-    updateCollection: Collection;
-    /** Move a Collection to a different parent or index */
-    moveCollection: Collection;
+    /** Create a new Customer. If a password is provided, a new User will also be created an linked to the Customer. */
+    createCustomer: Customer;
+    /** Update an existing Customer */
+    updateCustomer: Customer;
+    /** Delete a Customer */
+    deleteCustomer: DeletionResponse;
+    /** Create a new Address and associate it with the Customer specified by customerId */
+    createCustomerAddress: Address;
+    /** Update an existing Address */
+    updateCustomerAddress: Address;
+    /** Update an existing Address */
+    deleteCustomerAddress: Scalars['Boolean'];
     /** Create a new Facet */
     createFacet: Facet;
     /** Update an existing Facet */
@@ -1472,18 +1517,6 @@ export type Mutation = {
     /** Delete one or more FacetValues */
     deleteFacetValues: Array<DeletionResponse>;
     updateGlobalSettings: GlobalSettings;
-    /** Create a new Customer. If a password is provided, a new User will also be created an linked to the Customer. */
-    createCustomer: Customer;
-    /** Update an existing Customer */
-    updateCustomer: Customer;
-    /** Delete a Customer */
-    deleteCustomer: DeletionResponse;
-    /** Create a new Address and associate it with the Customer specified by customerId */
-    createCustomerAddress: Address;
-    /** Update an existing Address */
-    updateCustomerAddress: Address;
-    /** Update an existing Address */
-    deleteCustomerAddress: Scalars['Boolean'];
     importProducts?: Maybe<ImportInfo>;
     /** Update an existing PaymentMethod */
     updatePaymentMethod: PaymentMethod;
@@ -1568,6 +1601,18 @@ export type MutationUpdateChannelArgs = {
     input: UpdateChannelInput;
 };
 
+export type MutationCreateCollectionArgs = {
+    input: CreateCollectionInput;
+};
+
+export type MutationUpdateCollectionArgs = {
+    input: UpdateCollectionInput;
+};
+
+export type MutationMoveCollectionArgs = {
+    input: MoveCollectionInput;
+};
+
 export type MutationCreateCountryArgs = {
     input: CreateCountryInput;
 };
@@ -1598,16 +1643,30 @@ export type MutationRemoveCustomersFromGroupArgs = {
     customerIds: Array<Scalars['ID']>;
 };
 
-export type MutationCreateCollectionArgs = {
-    input: CreateCollectionInput;
+export type MutationCreateCustomerArgs = {
+    input: CreateCustomerInput;
+    password?: Maybe<Scalars['String']>;
 };
 
-export type MutationUpdateCollectionArgs = {
-    input: UpdateCollectionInput;
+export type MutationUpdateCustomerArgs = {
+    input: UpdateCustomerInput;
 };
 
-export type MutationMoveCollectionArgs = {
-    input: MoveCollectionInput;
+export type MutationDeleteCustomerArgs = {
+    id: Scalars['ID'];
+};
+
+export type MutationCreateCustomerAddressArgs = {
+    customerId: Scalars['ID'];
+    input: CreateAddressInput;
+};
+
+export type MutationUpdateCustomerAddressArgs = {
+    input: UpdateAddressInput;
+};
+
+export type MutationDeleteCustomerAddressArgs = {
+    id: Scalars['ID'];
 };
 
 export type MutationCreateFacetArgs = {
@@ -1640,32 +1699,6 @@ export type MutationUpdateGlobalSettingsArgs = {
     input: UpdateGlobalSettingsInput;
 };
 
-export type MutationCreateCustomerArgs = {
-    input: CreateCustomerInput;
-    password?: Maybe<Scalars['String']>;
-};
-
-export type MutationUpdateCustomerArgs = {
-    input: UpdateCustomerInput;
-};
-
-export type MutationDeleteCustomerArgs = {
-    id: Scalars['ID'];
-};
-
-export type MutationCreateCustomerAddressArgs = {
-    customerId: Scalars['ID'];
-    input: CreateAddressInput;
-};
-
-export type MutationUpdateCustomerAddressArgs = {
-    input: UpdateAddressInput;
-};
-
-export type MutationDeleteCustomerAddressArgs = {
-    id: Scalars['ID'];
-};
-
 export type MutationImportProductsArgs = {
     csvFile: Scalars['Upload'];
 };
@@ -1782,6 +1815,7 @@ export type MutationRemoveMembersFromZoneArgs = {
 };
 
 export type Node = {
+    __typename?: 'Node';
     id: Scalars['ID'];
 };
 
@@ -1800,6 +1834,7 @@ export type NumberRange = {
 };
 
 export type Order = Node & {
+    __typename?: 'Order';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1823,6 +1858,7 @@ export type Order = Node & {
 };
 
 export type OrderAddress = {
+    __typename?: 'OrderAddress';
     fullName?: Maybe<Scalars['String']>;
     company?: Maybe<Scalars['String']>;
     streetLine1?: Maybe<Scalars['String']>;
@@ -1851,6 +1887,7 @@ export type OrderFilterParameter = {
 };
 
 export type OrderItem = Node & {
+    __typename?: 'OrderItem';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1862,6 +1899,7 @@ export type OrderItem = Node & {
 };
 
 export type OrderLine = Node & {
+    __typename?: 'OrderLine';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1878,6 +1916,7 @@ export type OrderLine = Node & {
 };
 
 export type OrderList = PaginatedList & {
+    __typename?: 'OrderList';
     items: Array<Order>;
     totalItems: Scalars['Int'];
 };
@@ -1904,11 +1943,13 @@ export type OrderSortParameter = {
 };
 
 export type PaginatedList = {
+    __typename?: 'PaginatedList';
     items: Array<Node>;
     totalItems: Scalars['Int'];
 };
 
 export type Payment = Node & {
+    __typename?: 'Payment';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1920,6 +1961,7 @@ export type Payment = Node & {
 };
 
 export type PaymentMethod = Node & {
+    __typename?: 'PaymentMethod';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1936,6 +1978,7 @@ export type PaymentMethodFilterParameter = {
 };
 
 export type PaymentMethodList = PaginatedList & {
+    __typename?: 'PaymentMethodList';
     items: Array<PaymentMethod>;
     totalItems: Scalars['Int'];
 };
@@ -1988,11 +2031,13 @@ export enum Permission {
 
 /** The price range where the result has more than one price */
 export type PriceRange = {
+    __typename?: 'PriceRange';
     min: Scalars['Int'];
     max: Scalars['Int'];
 };
 
 export type Product = Node & {
+    __typename?: 'Product';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -2022,6 +2067,7 @@ export type ProductFilterParameter = {
 };
 
 export type ProductList = PaginatedList & {
+    __typename?: 'ProductList';
     items: Array<Product>;
     totalItems: Scalars['Int'];
 };
@@ -2034,6 +2080,7 @@ export type ProductListOptions = {
 };
 
 export type ProductOption = Node & {
+    __typename?: 'ProductOption';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -2045,6 +2092,7 @@ export type ProductOption = Node & {
 };
 
 export type ProductOptionGroup = Node & {
+    __typename?: 'ProductOptionGroup';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -2057,6 +2105,7 @@ export type ProductOptionGroup = Node & {
 };
 
 export type ProductOptionGroupTranslation = {
+    __typename?: 'ProductOptionGroupTranslation';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -2072,6 +2121,7 @@ export type ProductOptionGroupTranslationInput = {
 };
 
 export type ProductOptionTranslation = {
+    __typename?: 'ProductOptionTranslation';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -2096,6 +2146,7 @@ export type ProductSortParameter = {
 };
 
 export type ProductTranslation = {
+    __typename?: 'ProductTranslation';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -2115,6 +2166,7 @@ export type ProductTranslationInput = {
 };
 
 export type ProductVariant = Node & {
+    __typename?: 'ProductVariant';
     id: Scalars['ID'];
     productId: Scalars['ID'];
     createdAt: Scalars['DateTime'];
@@ -2160,6 +2212,7 @@ export type ProductVariantFilterParameter = {
 };
 
 export type ProductVariantList = PaginatedList & {
+    __typename?: 'ProductVariantList';
     items: Array<ProductVariant>;
     totalItems: Scalars['Int'];
 };
@@ -2184,6 +2237,7 @@ export type ProductVariantSortParameter = {
 };
 
 export type ProductVariantTranslation = {
+    __typename?: 'ProductVariantTranslation';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -2199,6 +2253,7 @@ export type ProductVariantTranslationInput = {
 };
 
 export type Promotion = Node & {
+    __typename?: 'Promotion';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -2216,6 +2271,7 @@ export type PromotionFilterParameter = {
 };
 
 export type PromotionList = PaginatedList & {
+    __typename?: 'PromotionList';
     items: Array<Promotion>;
     totalItems: Scalars['Int'];
 };
@@ -2235,6 +2291,7 @@ export type PromotionSortParameter = {
 };
 
 export type Query = {
+    __typename?: 'Query';
     administrators: AdministratorList;
     administrator?: Maybe<Administrator>;
     assets: AssetList;
@@ -2243,22 +2300,22 @@ export type Query = {
     channels: Array<Channel>;
     channel?: Maybe<Channel>;
     activeChannel: Channel;
+    collections: CollectionList;
+    collection?: Maybe<Collection>;
+    collectionFilters: Array<ConfigurableOperation>;
     countries: CountryList;
     country?: Maybe<Country>;
     customerGroups: Array<CustomerGroup>;
     customerGroup?: Maybe<CustomerGroup>;
-    collections: CollectionList;
-    collection?: Maybe<Collection>;
-    collectionFilters: Array<ConfigurableOperation>;
+    customers: CustomerList;
+    customer?: Maybe<Customer>;
     facets: FacetList;
     facet?: Maybe<Facet>;
     globalSettings: GlobalSettings;
-    customers: CustomerList;
-    customer?: Maybe<Customer>;
-    order?: Maybe<Order>;
-    orders: OrderList;
     job?: Maybe<JobInfo>;
     jobs: Array<JobInfo>;
+    order?: Maybe<Order>;
+    orders: OrderList;
     paymentMethods: PaymentMethodList;
     paymentMethod?: Maybe<PaymentMethod>;
     productOptionGroups: Array<ProductOptionGroup>;
@@ -2282,7 +2339,6 @@ export type Query = {
     taxRate?: Maybe<TaxRate>;
     zones: Array<Zone>;
     zone?: Maybe<Zone>;
-    temp__?: Maybe<Scalars['Boolean']>;
 };
 
 export type QueryAdministratorsArgs = {
@@ -2305,6 +2361,16 @@ export type QueryChannelArgs = {
     id: Scalars['ID'];
 };
 
+export type QueryCollectionsArgs = {
+    languageCode?: Maybe<LanguageCode>;
+    options?: Maybe<CollectionListOptions>;
+};
+
+export type QueryCollectionArgs = {
+    id: Scalars['ID'];
+    languageCode?: Maybe<LanguageCode>;
+};
+
 export type QueryCountriesArgs = {
     options?: Maybe<CountryListOptions>;
 };
@@ -2317,14 +2383,12 @@ export type QueryCustomerGroupArgs = {
     id: Scalars['ID'];
 };
 
-export type QueryCollectionsArgs = {
-    languageCode?: Maybe<LanguageCode>;
-    options?: Maybe<CollectionListOptions>;
+export type QueryCustomersArgs = {
+    options?: Maybe<CustomerListOptions>;
 };
 
-export type QueryCollectionArgs = {
+export type QueryCustomerArgs = {
     id: Scalars['ID'];
-    languageCode?: Maybe<LanguageCode>;
 };
 
 export type QueryFacetsArgs = {
@@ -2337,12 +2401,12 @@ export type QueryFacetArgs = {
     languageCode?: Maybe<LanguageCode>;
 };
 
-export type QueryCustomersArgs = {
-    options?: Maybe<CustomerListOptions>;
+export type QueryJobArgs = {
+    jobId: Scalars['String'];
 };
 
-export type QueryCustomerArgs = {
-    id: Scalars['ID'];
+export type QueryJobsArgs = {
+    input?: Maybe<JobListInput>;
 };
 
 export type QueryOrderArgs = {
@@ -2353,14 +2417,6 @@ export type QueryOrdersArgs = {
     options?: Maybe<OrderListOptions>;
 };
 
-export type QueryJobArgs = {
-    jobId: Scalars['String'];
-};
-
-export type QueryJobsArgs = {
-    input?: Maybe<JobListInput>;
-};
-
 export type QueryPaymentMethodsArgs = {
     options?: Maybe<PaymentMethodListOptions>;
 };
@@ -2436,6 +2492,7 @@ export type QueryZoneArgs = {
 
 export type Return = Node &
     StockMovement & {
+        __typename?: 'Return';
         id: Scalars['ID'];
         createdAt: Scalars['DateTime'];
         updatedAt: Scalars['DateTime'];
@@ -2446,6 +2503,7 @@ export type Return = Node &
     };
 
 export type Role = Node & {
+    __typename?: 'Role';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -2463,6 +2521,7 @@ export type RoleFilterParameter = {
 };
 
 export type RoleList = PaginatedList & {
+    __typename?: 'RoleList';
     items: Array<Role>;
     totalItems: Scalars['Int'];
 };
@@ -2484,6 +2543,7 @@ export type RoleSortParameter = {
 
 export type Sale = Node &
     StockMovement & {
+        __typename?: 'Sale';
         id: Scalars['ID'];
         createdAt: Scalars['DateTime'];
         updatedAt: Scalars['DateTime'];
@@ -2504,18 +2564,21 @@ export type SearchInput = {
 };
 
 export type SearchReindexResponse = {
+    __typename?: 'SearchReindexResponse';
     success: Scalars['Boolean'];
     timeTaken: Scalars['Int'];
     indexedItemCount: Scalars['Int'];
 };
 
 export type SearchResponse = {
+    __typename?: 'SearchResponse';
     items: Array<SearchResult>;
     totalItems: Scalars['Int'];
     facetValues: Array<FacetValueResult>;
 };
 
 export type SearchResult = {
+    __typename?: 'SearchResult';
     sku: Scalars['String'];
     slug: Scalars['String'];
     productId: Scalars['ID'];
@@ -2546,10 +2609,12 @@ export type SearchResultSortParameter = {
 };
 
 export type ServerConfig = {
+    __typename?: 'ServerConfig';
     customFields?: Maybe<Scalars['JSON']>;
 };
 
 export type ShippingMethod = Node & {
+    __typename?: 'ShippingMethod';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -2567,6 +2632,7 @@ export type ShippingMethodFilterParameter = {
 };
 
 export type ShippingMethodList = PaginatedList & {
+    __typename?: 'ShippingMethodList';
     items: Array<ShippingMethod>;
     totalItems: Scalars['Int'];
 };
@@ -2579,6 +2645,7 @@ export type ShippingMethodListOptions = {
 };
 
 export type ShippingMethodQuote = {
+    __typename?: 'ShippingMethodQuote';
     id: Scalars['ID'];
     price: Scalars['Int'];
     priceWithTax: Scalars['Int'];
@@ -2595,6 +2662,7 @@ export type ShippingMethodSortParameter = {
 
 /** The price value where the result has a single price */
 export type SinglePrice = {
+    __typename?: 'SinglePrice';
     value: Scalars['Int'];
 };
 
@@ -2605,6 +2673,7 @@ export enum SortOrder {
 
 export type StockAdjustment = Node &
     StockMovement & {
+        __typename?: 'StockAdjustment';
         id: Scalars['ID'];
         createdAt: Scalars['DateTime'];
         updatedAt: Scalars['DateTime'];
@@ -2614,6 +2683,7 @@ export type StockAdjustment = Node &
     };
 
 export type StockMovement = {
+    __typename?: 'StockMovement';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -2625,6 +2695,7 @@ export type StockMovement = {
 export type StockMovementItem = StockAdjustment | Sale | Cancellation | Return;
 
 export type StockMovementList = {
+    __typename?: 'StockMovementList';
     items: Array<StockMovementItem>;
     totalItems: Scalars['Int'];
 };
@@ -2648,6 +2719,7 @@ export type StringOperators = {
 };
 
 export type TaxCategory = Node & {
+    __typename?: 'TaxCategory';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -2655,6 +2727,7 @@ export type TaxCategory = Node & {
 };
 
 export type TaxRate = Node & {
+    __typename?: 'TaxRate';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -2675,6 +2748,7 @@ export type TaxRateFilterParameter = {
 };
 
 export type TaxRateList = PaginatedList & {
+    __typename?: 'TaxRateList';
     items: Array<TaxRate>;
     totalItems: Scalars['Int'];
 };
@@ -2867,6 +2941,7 @@ export type UpdateZoneInput = {
 };
 
 export type User = Node & {
+    __typename?: 'User';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -2878,6 +2953,7 @@ export type User = Node & {
 };
 
 export type Zone = Node & {
+    __typename?: 'Zone';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -3129,6 +3205,12 @@ export type DeleteCustomerMutation = { __typename?: 'Mutation' } & {
     deleteCustomer: { __typename?: 'DeletionResponse' } & Pick<DeletionResponse, 'result'>;
 };
 
+export type GetRunningJobsQueryVariables = {};
+
+export type GetRunningJobsQuery = { __typename?: 'Query' } & {
+    jobs: Array<{ __typename?: 'JobInfo' } & Pick<JobInfo, 'name' | 'state'>>;
+};
+
 export type SearchProductsAdminQueryVariables = {
     input: SearchInput;
 };
@@ -4285,6 +4367,12 @@ export namespace DeleteCustomer {
     export type DeleteCustomer = DeleteCustomerMutation['deleteCustomer'];
 }
 
+export namespace GetRunningJobs {
+    export type Variables = GetRunningJobsQueryVariables;
+    export type Query = GetRunningJobsQuery;
+    export type Jobs = NonNullable<GetRunningJobsQuery['jobs'][0]>;
+}
+
 export namespace SearchProductsAdmin {
     export type Variables = SearchProductsAdminQueryVariables;
     export type Query = SearchProductsAdminQuery;

+ 76 - 2
packages/core/e2e/graphql/generated-e2e-shop-types.ts

@@ -1,5 +1,4 @@
 // tslint:disable
-
 export type Maybe<T> = T | null;
 /** All built-in and custom scalars, mapped to their actual values */
 export type Scalars = {
@@ -20,6 +19,7 @@ export type Scalars = {
 };
 
 export type Address = Node & {
+    __typename?: 'Address';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -38,6 +38,7 @@ export type Address = Node & {
 };
 
 export type Adjustment = {
+    __typename?: 'Adjustment';
     adjustmentSource: Scalars['String'];
     type: AdjustmentType;
     description: Scalars['String'];
@@ -45,6 +46,7 @@ export type Adjustment = {
 };
 
 export type AdjustmentOperations = {
+    __typename?: 'AdjustmentOperations';
     conditions: Array<ConfigurableOperation>;
     actions: Array<ConfigurableOperation>;
 };
@@ -60,6 +62,7 @@ export enum AdjustmentType {
 }
 
 export type Administrator = Node & {
+    __typename?: 'Administrator';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -70,11 +73,13 @@ export type Administrator = Node & {
 };
 
 export type AdministratorList = PaginatedList & {
+    __typename?: 'AdministratorList';
     items: Array<Administrator>;
     totalItems: Scalars['Int'];
 };
 
 export type Asset = Node & {
+    __typename?: 'Asset';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -87,6 +92,7 @@ export type Asset = Node & {
 };
 
 export type AssetList = PaginatedList & {
+    __typename?: 'AssetList';
     items: Array<Asset>;
     totalItems: Scalars['Int'];
 };
@@ -103,6 +109,7 @@ export type BooleanOperators = {
 
 export type Cancellation = Node &
     StockMovement & {
+        __typename?: 'Cancellation';
         id: Scalars['ID'];
         createdAt: Scalars['DateTime'];
         updatedAt: Scalars['DateTime'];
@@ -113,6 +120,7 @@ export type Cancellation = Node &
     };
 
 export type Channel = Node & {
+    __typename?: 'Channel';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -126,6 +134,7 @@ export type Channel = Node & {
 };
 
 export type Collection = Node & {
+    __typename?: 'Collection';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -149,6 +158,7 @@ export type CollectionProductVariantsArgs = {
 };
 
 export type CollectionBreadcrumb = {
+    __typename?: 'CollectionBreadcrumb';
     id: Scalars['ID'];
     name: Scalars['String'];
 };
@@ -163,6 +173,7 @@ export type CollectionFilterParameter = {
 };
 
 export type CollectionList = PaginatedList & {
+    __typename?: 'CollectionList';
     items: Array<Collection>;
     totalItems: Scalars['Int'];
 };
@@ -184,6 +195,7 @@ export type CollectionSortParameter = {
 };
 
 export type CollectionTranslation = {
+    __typename?: 'CollectionTranslation';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -193,6 +205,7 @@ export type CollectionTranslation = {
 };
 
 export type ConfigArg = {
+    __typename?: 'ConfigArg';
     name: Scalars['String'];
     type: ConfigArgType;
     value?: Maybe<Scalars['String']>;
@@ -223,6 +236,7 @@ export enum ConfigArgType {
 }
 
 export type ConfigurableOperation = {
+    __typename?: 'ConfigurableOperation';
     code: Scalars['String'];
     args: Array<ConfigArg>;
     description: Scalars['String'];
@@ -234,6 +248,7 @@ export type ConfigurableOperationInput = {
 };
 
 export type Country = Node & {
+    __typename?: 'Country';
     id: Scalars['ID'];
     languageCode: LanguageCode;
     code: Scalars['String'];
@@ -243,11 +258,13 @@ export type Country = Node & {
 };
 
 export type CountryList = PaginatedList & {
+    __typename?: 'CountryList';
     items: Array<Country>;
     totalItems: Scalars['Int'];
 };
 
 export type CountryTranslation = {
+    __typename?: 'CountryTranslation';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -598,12 +615,14 @@ export enum CurrencyCode {
 }
 
 export type CurrentUser = {
+    __typename?: 'CurrentUser';
     id: Scalars['ID'];
     identifier: Scalars['String'];
     channelTokens: Array<Scalars['String']>;
 };
 
 export type Customer = Node & {
+    __typename?: 'Customer';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -623,6 +642,7 @@ export type CustomerOrdersArgs = {
 };
 
 export type CustomerGroup = Node & {
+    __typename?: 'CustomerGroup';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -630,6 +650,7 @@ export type CustomerGroup = Node & {
 };
 
 export type CustomerList = PaginatedList & {
+    __typename?: 'CustomerList';
     items: Array<Customer>;
     totalItems: Scalars['Int'];
 };
@@ -647,6 +668,7 @@ export type DateRange = {
 };
 
 export type DeletionResponse = {
+    __typename?: 'DeletionResponse';
     result: DeletionResult;
     message?: Maybe<Scalars['String']>;
 };
@@ -659,6 +681,7 @@ export enum DeletionResult {
 }
 
 export type Facet = Node & {
+    __typename?: 'Facet';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -671,11 +694,13 @@ export type Facet = Node & {
 };
 
 export type FacetList = PaginatedList & {
+    __typename?: 'FacetList';
     items: Array<Facet>;
     totalItems: Scalars['Int'];
 };
 
 export type FacetTranslation = {
+    __typename?: 'FacetTranslation';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -684,6 +709,7 @@ export type FacetTranslation = {
 };
 
 export type FacetValue = Node & {
+    __typename?: 'FacetValue';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -699,11 +725,13 @@ export type FacetValue = Node & {
  * by the search, and in what quantity.
  */
 export type FacetValueResult = {
+    __typename?: 'FacetValueResult';
     facetValue: FacetValue;
     count: Scalars['Int'];
 };
 
 export type FacetValueTranslation = {
+    __typename?: 'FacetValueTranslation';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -712,6 +740,7 @@ export type FacetValueTranslation = {
 };
 
 export type GlobalSettings = {
+    __typename?: 'GlobalSettings';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -722,6 +751,7 @@ export type GlobalSettings = {
 };
 
 export type ImportInfo = {
+    __typename?: 'ImportInfo';
     errors?: Maybe<Array<Scalars['String']>>;
     processed: Scalars['Int'];
     imported: Scalars['Int'];
@@ -1100,10 +1130,12 @@ export enum LanguageCode {
 }
 
 export type LoginResult = {
+    __typename?: 'LoginResult';
     user: CurrentUser;
 };
 
 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.
      */
@@ -1249,6 +1281,7 @@ export type MutationResetPasswordArgs = {
 };
 
 export type Node = {
+    __typename?: 'Node';
     id: Scalars['ID'];
 };
 
@@ -1267,6 +1300,7 @@ export type NumberRange = {
 };
 
 export type Order = Node & {
+    __typename?: 'Order';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1290,6 +1324,7 @@ export type Order = Node & {
 };
 
 export type OrderAddress = {
+    __typename?: 'OrderAddress';
     fullName?: Maybe<Scalars['String']>;
     company?: Maybe<Scalars['String']>;
     streetLine1?: Maybe<Scalars['String']>;
@@ -1318,6 +1353,7 @@ export type OrderFilterParameter = {
 };
 
 export type OrderItem = Node & {
+    __typename?: 'OrderItem';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1329,6 +1365,7 @@ export type OrderItem = Node & {
 };
 
 export type OrderLine = Node & {
+    __typename?: 'OrderLine';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1345,6 +1382,7 @@ export type OrderLine = Node & {
 };
 
 export type OrderList = PaginatedList & {
+    __typename?: 'OrderList';
     items: Array<Order>;
     totalItems: Scalars['Int'];
 };
@@ -1371,11 +1409,13 @@ export type OrderSortParameter = {
 };
 
 export type PaginatedList = {
+    __typename?: 'PaginatedList';
     items: Array<Node>;
     totalItems: Scalars['Int'];
 };
 
 export type Payment = Node & {
+    __typename?: 'Payment';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1392,6 +1432,7 @@ export type PaymentInput = {
 };
 
 export type PaymentMethod = Node & {
+    __typename?: 'PaymentMethod';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1434,11 +1475,13 @@ export enum Permission {
 
 /** The price range where the result has more than one price */
 export type PriceRange = {
+    __typename?: 'PriceRange';
     min: Scalars['Int'];
     max: Scalars['Int'];
 };
 
 export type Product = Node & {
+    __typename?: 'Product';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1466,6 +1509,7 @@ export type ProductFilterParameter = {
 };
 
 export type ProductList = PaginatedList & {
+    __typename?: 'ProductList';
     items: Array<Product>;
     totalItems: Scalars['Int'];
 };
@@ -1478,6 +1522,7 @@ export type ProductListOptions = {
 };
 
 export type ProductOption = Node & {
+    __typename?: 'ProductOption';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1489,6 +1534,7 @@ export type ProductOption = Node & {
 };
 
 export type ProductOptionGroup = Node & {
+    __typename?: 'ProductOptionGroup';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1501,6 +1547,7 @@ export type ProductOptionGroup = Node & {
 };
 
 export type ProductOptionGroupTranslation = {
+    __typename?: 'ProductOptionGroupTranslation';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1509,6 +1556,7 @@ export type ProductOptionGroupTranslation = {
 };
 
 export type ProductOptionTranslation = {
+    __typename?: 'ProductOptionTranslation';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1526,6 +1574,7 @@ export type ProductSortParameter = {
 };
 
 export type ProductTranslation = {
+    __typename?: 'ProductTranslation';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1536,6 +1585,7 @@ export type ProductTranslation = {
 };
 
 export type ProductVariant = Node & {
+    __typename?: 'ProductVariant';
     id: Scalars['ID'];
     productId: Scalars['ID'];
     createdAt: Scalars['DateTime'];
@@ -1570,6 +1620,7 @@ export type ProductVariantFilterParameter = {
 };
 
 export type ProductVariantList = PaginatedList & {
+    __typename?: 'ProductVariantList';
     items: Array<ProductVariant>;
     totalItems: Scalars['Int'];
 };
@@ -1593,6 +1644,7 @@ export type ProductVariantSortParameter = {
 };
 
 export type ProductVariantTranslation = {
+    __typename?: 'ProductVariantTranslation';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1601,6 +1653,7 @@ export type ProductVariantTranslation = {
 };
 
 export type Promotion = Node & {
+    __typename?: 'Promotion';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1611,11 +1664,13 @@ export type Promotion = Node & {
 };
 
 export type PromotionList = PaginatedList & {
+    __typename?: 'PromotionList';
     items: Array<Promotion>;
     totalItems: Scalars['Int'];
 };
 
 export type Query = {
+    __typename?: 'Query';
     activeChannel: Channel;
     activeCustomer?: Maybe<Customer>;
     activeOrder?: Maybe<Order>;
@@ -1631,7 +1686,6 @@ export type Query = {
     product?: Maybe<Product>;
     products: ProductList;
     search: SearchResponse;
-    temp__?: Maybe<Scalars['Boolean']>;
 };
 
 export type QueryCollectionsArgs = {
@@ -1677,6 +1731,7 @@ export type RegisterCustomerInput = {
 
 export type Return = Node &
     StockMovement & {
+        __typename?: 'Return';
         id: Scalars['ID'];
         createdAt: Scalars['DateTime'];
         updatedAt: Scalars['DateTime'];
@@ -1687,6 +1742,7 @@ export type Return = Node &
     };
 
 export type Role = Node & {
+    __typename?: 'Role';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1697,12 +1753,14 @@ export type Role = Node & {
 };
 
 export type RoleList = PaginatedList & {
+    __typename?: 'RoleList';
     items: Array<Role>;
     totalItems: Scalars['Int'];
 };
 
 export type Sale = Node &
     StockMovement & {
+        __typename?: 'Sale';
         id: Scalars['ID'];
         createdAt: Scalars['DateTime'];
         updatedAt: Scalars['DateTime'];
@@ -1723,18 +1781,21 @@ export type SearchInput = {
 };
 
 export type SearchReindexResponse = {
+    __typename?: 'SearchReindexResponse';
     success: Scalars['Boolean'];
     timeTaken: Scalars['Int'];
     indexedItemCount: Scalars['Int'];
 };
 
 export type SearchResponse = {
+    __typename?: 'SearchResponse';
     items: Array<SearchResult>;
     totalItems: Scalars['Int'];
     facetValues: Array<FacetValueResult>;
 };
 
 export type SearchResult = {
+    __typename?: 'SearchResult';
     sku: Scalars['String'];
     slug: Scalars['String'];
     productId: Scalars['ID'];
@@ -1764,10 +1825,12 @@ export type SearchResultSortParameter = {
 };
 
 export type ServerConfig = {
+    __typename?: 'ServerConfig';
     customFields?: Maybe<Scalars['JSON']>;
 };
 
 export type ShippingMethod = Node & {
+    __typename?: 'ShippingMethod';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1778,11 +1841,13 @@ export type ShippingMethod = Node & {
 };
 
 export type ShippingMethodList = PaginatedList & {
+    __typename?: 'ShippingMethodList';
     items: Array<ShippingMethod>;
     totalItems: Scalars['Int'];
 };
 
 export type ShippingMethodQuote = {
+    __typename?: 'ShippingMethodQuote';
     id: Scalars['ID'];
     price: Scalars['Int'];
     priceWithTax: Scalars['Int'];
@@ -1791,6 +1856,7 @@ export type ShippingMethodQuote = {
 
 /** The price value where the result has a single price */
 export type SinglePrice = {
+    __typename?: 'SinglePrice';
     value: Scalars['Int'];
 };
 
@@ -1801,6 +1867,7 @@ export enum SortOrder {
 
 export type StockAdjustment = Node &
     StockMovement & {
+        __typename?: 'StockAdjustment';
         id: Scalars['ID'];
         createdAt: Scalars['DateTime'];
         updatedAt: Scalars['DateTime'];
@@ -1810,6 +1877,7 @@ export type StockAdjustment = Node &
     };
 
 export type StockMovement = {
+    __typename?: 'StockMovement';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1821,6 +1889,7 @@ export type StockMovement = {
 export type StockMovementItem = StockAdjustment | Sale | Cancellation | Return;
 
 export type StockMovementList = {
+    __typename?: 'StockMovementList';
     items: Array<StockMovementItem>;
     totalItems: Scalars['Int'];
 };
@@ -1838,6 +1907,7 @@ export type StringOperators = {
 };
 
 export type TaxCategory = Node & {
+    __typename?: 'TaxCategory';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1845,6 +1915,7 @@ export type TaxCategory = Node & {
 };
 
 export type TaxRate = Node & {
+    __typename?: 'TaxRate';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1857,6 +1928,7 @@ export type TaxRate = Node & {
 };
 
 export type TaxRateList = PaginatedList & {
+    __typename?: 'TaxRateList';
     items: Array<TaxRate>;
     totalItems: Scalars['Int'];
 };
@@ -1886,6 +1958,7 @@ export type UpdateCustomerInput = {
 };
 
 export type User = Node & {
+    __typename?: 'User';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
@@ -1897,6 +1970,7 @@ export type User = Node & {
 };
 
 export type Zone = Node & {
+    __typename?: 'Zone';
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];

+ 40 - 8
packages/core/e2e/test-server.ts

@@ -1,4 +1,4 @@
-import { INestApplication } from '@nestjs/common';
+import { INestApplication, INestMicroservice } from '@nestjs/common';
 import { NestFactory } from '@nestjs/core';
 import { Omit } from '@vendure/common/lib/omit';
 import fs from 'fs';
@@ -9,6 +9,7 @@ import { SqljsConnectionOptions } from 'typeorm/driver/sqljs/SqljsConnectionOpti
 import { populateForTesting, PopulateOptions } from '../mock-data/populate-for-testing';
 import { preBootstrapConfig, runPluginOnBootstrapMethods } from '../src/bootstrap';
 import { Mutable } from '../src/common/types/common-types';
+import { Logger } from '../src/config/logger/vendure-logger';
 import { VendureConfig } from '../src/config/vendure-config';
 
 import { testConfig } from './config/test-config';
@@ -20,6 +21,7 @@ import { setTestEnvironment } from './utils/test-environment';
  */
 export class TestServer {
     app: INestApplication;
+    worker?: INestMicroservice;
 
     /**
      * Bootstraps an instance of Vendure server and populates the database according to the options
@@ -48,7 +50,16 @@ export class TestServer {
         if (options.logging) {
             console.log(`Loading test data from "${dbFilePath}"`);
         }
-        this.app = await this.bootstrapForTesting(testingConfig);
+        const [app, worker] = await this.bootstrapForTesting(testingConfig);
+        if (app) {
+            this.app = app;
+        } else {
+            console.error(`Could not bootstrap app`);
+            process.exit(1);
+        }
+        if (worker) {
+            this.worker = worker;
+        }
     }
 
     /**
@@ -56,6 +67,9 @@ export class TestServer {
      */
     async destroy() {
         await this.app.close();
+        if (this.worker) {
+            await this.worker.close();
+        }
     }
 
     private getDbFilePath() {
@@ -76,7 +90,7 @@ export class TestServer {
     ): Promise<void> {
         (testingConfig.dbConnectionOptions as Mutable<SqljsConnectionOptions>).autoSave = true;
 
-        const app = await populateForTesting(testingConfig, this.bootstrapForTesting, {
+        const [app, worker] = await populateForTesting(testingConfig, this.bootstrapForTesting, {
             logging: false,
             ...{
                 ...options,
@@ -84,6 +98,9 @@ export class TestServer {
             },
         });
         await app.close();
+        if (worker) {
+            await worker.close();
+        }
 
         (testingConfig.dbConnectionOptions as Mutable<SqljsConnectionOptions>).autoSave = false;
     }
@@ -91,12 +108,27 @@ export class TestServer {
     /**
      * Bootstraps an instance of the Vendure server for testing against.
      */
-    private async bootstrapForTesting(userConfig: Partial<VendureConfig>): Promise<INestApplication> {
+    private async bootstrapForTesting(userConfig: Partial<VendureConfig>): Promise<[INestApplication, INestMicroservice | undefined]> {
         const config = await preBootstrapConfig(userConfig);
         const appModule = await import('../src/app.module');
-        const app = await NestFactory.create(appModule.AppModule, { cors: config.cors, logger: false });
-        await runPluginOnBootstrapMethods(config, app);
-        await app.listen(config.port);
-        return app;
+        try {
+            const app = await NestFactory.create(appModule.AppModule, {cors: config.cors, logger: false});
+            let worker: INestMicroservice | undefined;
+            await runPluginOnBootstrapMethods(config, app);
+            await app.listen(config.port);
+            if (config.workerOptions.runInMainProcess) {
+                const workerModule = await import('../src/worker/worker.module');
+                worker = await NestFactory.createMicroservice(workerModule.WorkerModule, {
+                    transport: config.workerOptions.transport,
+                    logger: new Logger(),
+                    options: config.workerOptions.options,
+                });
+                await worker.listenAsync();
+            }
+            return [app, worker];
+        } catch (e) {
+            console.log(e);
+            throw e;
+        }
     }
 }

+ 5 - 5
packages/core/mock-data/populate-for-testing.ts

@@ -1,5 +1,5 @@
 /* tslint:disable:no-console */
-import { INestApplication } from '@nestjs/common';
+import { INestApplication, INestMicroservice } from '@nestjs/common';
 import { LanguageCode } from '@vendure/common/lib/generated-types';
 import fs from 'fs-extra';
 
@@ -23,9 +23,9 @@ export interface PopulateOptions {
  */
 export async function populateForTesting(
     config: VendureConfig,
-    bootstrapFn: VendureBootstrapFunction,
+    bootstrapFn: (config: VendureConfig) => Promise<[INestApplication, INestMicroservice | undefined]>,
     options: PopulateOptions,
-): Promise<INestApplication> {
+): Promise<[INestApplication, INestMicroservice | undefined]> {
     (config.dbConnectionOptions as any).logging = false;
     const logging = options.logging === undefined ? true : options.logging;
     const originalRequireVerification = config.authOptions.requireVerification;
@@ -33,7 +33,7 @@ export async function populateForTesting(
 
     setConfig(config);
     await clearAllTables(config.dbConnectionOptions, logging);
-    const app = await bootstrapFn(config);
+    const [app, worker] = await bootstrapFn(config);
 
     await populateInitialData(app, options.initialDataPath, logging);
     await populateProducts(app, options.productsCsvPath, logging);
@@ -41,7 +41,7 @@ export async function populateForTesting(
     await populateCustomers(options.customerCount, config, logging);
 
     config.authOptions.requireVerification = originalRequireVerification;
-    return app;
+    return [app, worker];
 }
 
 async function populateInitialData(app: INestApplication, initialDataPath: string, logging: boolean) {

+ 1 - 1
packages/core/src/bootstrap.ts

@@ -46,7 +46,7 @@ export async function bootstrap(userConfig: Partial<VendureConfig>): Promise<INe
 
 export async function bootstrapWorker(userConfig: Partial<VendureConfig>): Promise<INestMicroservice> {
     const config = await preBootstrapConfig(userConfig);
-    if ((config.logger as any).setDefaultContext) {
+    if (!config.workerOptions.runInMainProcess && (config.logger as any).setDefaultContext) {
         (config.logger as any).setDefaultContext('Vendure Worker');
     }
     Logger.useLogger(config.logger);

+ 3 - 1
packages/core/src/config/default-config.ts

@@ -83,7 +83,9 @@ export const defaultConfig: ReadOnlyRequired<VendureConfig> = {
     workerOptions: {
         runInMainProcess: true,
         transport: Transport.TCP,
-        options: {},
+        options: {
+            port: 3001,
+        },
     },
     customFields: {
         Address: [],

+ 2 - 2
packages/core/src/plugin/default-search-plugin/default-search-plugin.ts

@@ -62,11 +62,11 @@ export class DefaultSearchPlugin implements VendurePlugin {
         const searchIndexService = inject(SearchIndexService);
         eventBus.subscribe(CatalogModificationEvent, event => {
             if (event.entity instanceof Product || event.entity instanceof ProductVariant) {
-                return searchIndexService.updateProductOrVariant(event.ctx, event.entity);
+                return searchIndexService.updateProductOrVariant(event.ctx, event.entity).start();
             }
         });
         eventBus.subscribe(CollectionModificationEvent, event => {
-            return searchIndexService.updateVariantsById(event.ctx, event.productVariantIds);
+            return searchIndexService.updateVariantsById(event.ctx, event.productVariantIds).start();
         });
         eventBus.subscribe(TaxRateModificationEvent, event => {
             const defaultTaxZone = event.ctx.channel.defaultTaxZone;

+ 8 - 4
packages/core/src/plugin/default-search-plugin/indexer/indexer.controller.ts

@@ -15,6 +15,7 @@ import { ProductVariant } from '../../../entity/product-variant/product-variant.
 import { Product } from '../../../entity/product/product.entity';
 import { translateDeep } from '../../../service/helpers/utils/translate-entity';
 import { ProductVariantService } from '../../../service/services/product-variant.service';
+import { TaxRateService } from '../../../service/services/tax-rate.service';
 import { AsyncQueue } from '../async-queue';
 import { loggerCtx, Message } from '../constants';
 import { SearchIndexItem } from '../search-index-item.entity';
@@ -45,9 +46,8 @@ export class IndexerController {
     constructor(
         @InjectConnection() private connection: Connection,
         private productVariantService: ProductVariantService,
-    ) {
-        console.log('IndexerController tolo bolo');
-    }
+        private taxRateService: TaxRateService,
+    ) {}
 
     @MessagePattern(Message.Reindex)
     reindex({ ctx: rawContext }: { ctx: any}): Observable<ReindexMessageResponse> {
@@ -60,6 +60,9 @@ export class IndexerController {
                 Logger.verbose(`Reindexing ${count} variants`, loggerCtx);
                 const batches = Math.ceil(count / BATCH_SIZE);
 
+                // Ensure tax rates are up-to-date.
+                await this.taxRateService.updateActiveTaxRates();
+
                 await this.connection.getRepository(SearchIndexItem).delete({ languageCode: ctx.languageCode });
                 Logger.verbose('Deleted existing index items', loggerCtx);
 
@@ -165,6 +168,7 @@ export class IndexerController {
                 }
             }
             Logger.verbose(`Updating ${updatedVariants.length} variants`, loggerCtx);
+            updatedVariants = this.hydrateVariants(ctx, updatedVariants);
             if (updatedVariants.length) {
                 await this.saveVariants(ctx, updatedVariants);
             }
@@ -239,6 +243,6 @@ export class IndexerController {
             productVariantId: id,
             languageCode,
         })) as any[];
-        await this.connection.getRepository(SearchIndexItem).delete(compositeKeys);
+        await this.queue.push(() => this.connection.getRepository(SearchIndexItem).delete(compositeKeys));
     }
 }

+ 21 - 10
packages/core/src/plugin/default-search-plugin/indexer/search-index.service.ts

@@ -1,4 +1,4 @@
-import { Inject, Injectable } from '@nestjs/common';
+import { Inject, Injectable, OnModuleDestroy } from '@nestjs/common';
 import { ClientProxy } from '@nestjs/microservices';
 import { InjectConnection } from '@nestjs/typeorm';
 import { ID } from '@vendure/common/lib/shared-types';
@@ -21,7 +21,7 @@ import { ReindexMessageResponse } from './indexer.controller';
  * This service is responsible for messaging the {@link IndexerController} with search index updates.
  */
 @Injectable()
-export class SearchIndexService {
+export class SearchIndexService implements OnModuleDestroy {
 
     constructor(@InjectConnection() private connection: Connection,
                 @Inject(VENDURE_WORKER_CLIENT) private readonly client: ClientProxy,
@@ -75,19 +75,26 @@ export class SearchIndexService {
      * Updates the search index only for the affected entities.
      */
     updateProductOrVariant(ctx: RequestContext, updatedEntity: Product | ProductVariant) {
-        if (updatedEntity instanceof Product) {
-            return this.client.send(Message.UpdateProductOrVariant, { ctx, productId: updatedEntity.id })
-                .subscribe({ error: err => Logger.error(err) });
-        } else {
-            return this.client.send(Message.UpdateProductOrVariant, { ctx, variantId: updatedEntity.id })
-                .subscribe({ error: err => Logger.error(err) });
-        }
+        return this.jobService.createJob({
+            name: 'update-index',
+            work: async () => {
+                if (updatedEntity instanceof Product) {
+                    return this.client.send(Message.UpdateProductOrVariant, { ctx, productId: updatedEntity.id })
+                        .toPromise()
+                        .catch(err => Logger.error(err));
+                } else {
+                    return this.client.send(Message.UpdateProductOrVariant, { ctx, variantId: updatedEntity.id })
+                        .toPromise()
+                        .catch(err => Logger.error(err));
+                }
+            },
+        });
+
     }
 
     updateVariantsById(ctx: RequestContext, ids: ID[]) {
         return this.jobService.createJob({
             name: 'update-index',
-            singleInstance: true,
             work: async reporter => {
                 return new Promise((resolve, reject) => {
                     Logger.verbose(`sending reindex message`);
@@ -125,4 +132,8 @@ export class SearchIndexService {
             },
         });
     }
+
+    onModuleDestroy(): any {
+        this.client.close();
+    }
 }

+ 38 - 17
packages/core/src/service/service.module.ts

@@ -1,8 +1,8 @@
 import { DynamicModule, Module, OnModuleInit } from '@nestjs/common';
 import { TypeOrmModule } from '@nestjs/typeorm';
 
-import { getConfig } from '../config/config-helpers';
 import { ConfigModule } from '../config/config.module';
+import { ConfigService } from '../config/config.service';
 import { EventBusModule } from '../event-bus/event-bus.module';
 
 import { AssetUpdater } from './helpers/asset-updater/asset-updater';
@@ -73,6 +73,9 @@ const exportedProviders = [
     ZoneService,
 ];
 
+let defaultTypeOrmModule: DynamicModule;
+let workerTypeOrmModule: DynamicModule;
+
 /**
  * The ServiceModule is responsible for the service layer, i.e. accessing the database
  * and implementing the main business logic of the application.
@@ -128,32 +131,50 @@ export class ServiceModule implements OnModuleInit {
     }
 
     static forRoot(): DynamicModule {
+        if (!defaultTypeOrmModule) {
+            defaultTypeOrmModule = TypeOrmModule.forRootAsync({
+                imports: [ConfigModule],
+                useFactory: (configService: ConfigService) => {
+                    return configService.dbConnectionOptions;
+                },
+                inject: [ConfigService],
+            });
+        }
         return {
             module: ServiceModule,
             imports: [
-                TypeOrmModule.forRootAsync({
-                    useFactory: () => {
-                        console.log('typeorn forRootAsync');
-                        return getConfig().dbConnectionOptions;
-                    },
-                }),
+                defaultTypeOrmModule,
             ],
         };
     }
 
     static forWorker(): DynamicModule {
-        const { dbConnectionOptions, workerOptions } = getConfig();
-        const connectionOptions = { ...dbConnectionOptions, name: 'worker' };
+        if (!workerTypeOrmModule) {
+            workerTypeOrmModule = TypeOrmModule.forRootAsync({
+                imports: [ConfigModule],
+                useFactory: (configService: ConfigService) => {
+                    const { dbConnectionOptions, workerOptions } = configService;
+                    if (workerOptions.runInMainProcess) {
+                        // When running in the main process, we can re-use the existing
+                        // default connection.
+                        return {
+                            ...dbConnectionOptions,
+                            name: 'default',
+                            keepConnectionAlive: true,
+                        };
+                    } else {
+                        return {
+                            ...dbConnectionOptions,
+                            name: 'worker',
+                        };
+                    }
+                },
+                inject: [ConfigService],
+            });
+        }
         return {
             module: ServiceModule,
-            imports: [
-                TypeOrmModule.forRootAsync({
-                    useFactory: () => {
-                        console.log('typeorm forRootAsync Worker');
-                        return { ...connectionOptions, keepConnectionAlive: true };
-                    },
-                }),
-            ],
+            imports: [workerTypeOrmModule],
         };
     }
 }

+ 1 - 1
packages/core/src/service/services/tax-rate.service.ts

@@ -107,7 +107,7 @@ export class TaxRateService {
         return rate || this.defaultTaxRate;
     }
 
-    private async updateActiveTaxRates() {
+    async updateActiveTaxRates() {
         this.activeTaxRates = await this.connection.getRepository(TaxRate).find({
             relations: ['category', 'zone', 'customerGroup'],
             where: {

+ 1 - 5
packages/core/src/worker/worker.module.ts

@@ -11,8 +11,4 @@ import { ServiceModule } from '../service/service.module';
         PluginModule.forWorker(),
     ],
 })
-export class WorkerModule {
-    constructor() {
-        console.log('Worker module constructed!');
-    }
-}
+export class WorkerModule {}