Browse Source

refactor(server): Group assets & promotions config options

Michael Bromley 7 years ago
parent
commit
1e6d6a07b0

+ 7 - 2
server/e2e/config/test-config.ts

@@ -1,5 +1,6 @@
 import { API_PATH } from 'shared/shared-constants';
 
+import { DefaultAssetNamingStrategy } from '../../src/config/asset-naming-strategy/default-asset-naming-strategy';
 import { VendureConfig } from '../../src/config/vendure-config';
 
 import { TestingAssetPreviewStrategy } from './testing-asset-preview-strategy';
@@ -32,8 +33,12 @@ export const testConfig: VendureConfig = {
         autoSave: false,
         logging: false,
     },
+    promotionOptions: {},
     customFields: {},
     entityIdStrategy: new TestingEntityIdStrategy(),
-    assetStorageStrategy: new TestingAssetStorageStrategy(),
-    assetPreviewStrategy: new TestingAssetPreviewStrategy(),
+    assetOptions: {
+        assetNamingStrategy: new DefaultAssetNamingStrategy(),
+        assetStorageStrategy: new TestingAssetStorageStrategy(),
+        assetPreviewStrategy: new TestingAssetPreviewStrategy(),
+    },
 };

+ 4 - 2
server/e2e/promotion.e2e-spec.ts

@@ -45,8 +45,10 @@ describe('Promotion resolver', () => {
                 customerCount: 1,
             },
             {
-                promotionConditions: [promoCondition, promoCondition2],
-                promotionActions: [promoAction],
+                promotionOptions: {
+                    promotionConditions: [promoCondition, promoCondition2],
+                    promotionActions: [promoAction],
+                },
             },
         );
         await client.init();

+ 1 - 1
server/src/api/config/graphql-config.service.ts

@@ -40,7 +40,7 @@ export class GraphqlConfigService implements GqlOptionsFactory {
                 Upload: GraphQLUpload,
             },
             uploads: {
-                maxFileSize: this.configService.uploadMaxFileSize,
+                maxFileSize: this.configService.assetOptions.uploadMaxFileSize,
             },
             playground: true,
             debug: true,

+ 1 - 1
server/src/api/middleware/asset-interceptor.spec.ts

@@ -14,7 +14,7 @@ describe('AssetInterceptor', () => {
         return (done: jest.DoneCallback) => {
             const toAbsoluteUrl = jest.fn().mockReturnValue('visited');
             const configService = new MockConfigService();
-            configService.assetStorageStrategy = { toAbsoluteUrl };
+            configService.assetOptions.assetStorageStrategy = { toAbsoluteUrl };
             const interceptor = new AssetInterceptor(configService as any);
             const executionContext = new ExecutionContextHost([0, 0, { req: {} }]);
             const call$ = of(response);

+ 5 - 3
server/src/api/middleware/asset-interceptor.ts

@@ -17,9 +17,11 @@ export class AssetInterceptor implements NestInterceptor {
     private readonly toAbsoluteUrl: AssetStorageStrategy['toAbsoluteUrl'] | undefined;
 
     constructor(private configService: ConfigService) {
-        const { assetStorageStrategy } = this.configService;
-        if (assetStorageStrategy.toAbsoluteUrl) {
-            this.toAbsoluteUrl = assetStorageStrategy.toAbsoluteUrl.bind(assetStorageStrategy);
+        const { assetOptions } = this.configService;
+        if (assetOptions.assetStorageStrategy.toAbsoluteUrl) {
+            this.toAbsoluteUrl = assetOptions.assetStorageStrategy.toAbsoluteUrl.bind(
+                assetOptions.assetStorageStrategy,
+            );
         }
     }
 

+ 9 - 5
server/src/config/config.service.mock.ts

@@ -14,13 +14,17 @@ export class MockConfigService implements MockClass<ConfigService> {
     defaultLanguageCode: jest.Mock<any>;
     roundingStrategy: {};
     entityIdStrategy = new MockIdStrategy();
-    assetNamingStrategy = {} as any;
-    assetStorageStrategy = {} as any;
-    assetPreviewStrategy = {} as any;
+    assetOptions = {
+        assetNamingStrategy: {} as any,
+        assetStorageStrategy: {} as any,
+        assetPreviewStrategy: {} as any,
+    };
     uploadMaxFileSize = 1024;
     dbConnectionOptions = {};
-    promotionConditions = [];
-    promotionActions = [];
+    promotionOptions = {
+        promotionConditions: [],
+        promotionActions: [],
+    };
     orderMergeOptions = {};
     orderProcessOptions = {};
     customFields = {};

+ 6 - 25
server/src/config/config.service.ts

@@ -7,17 +7,14 @@ import { ConnectionOptions } from 'typeorm';
 
 import { ReadOnlyRequired } from '../common/types/common-types';
 
-import { AssetNamingStrategy } from './asset-naming-strategy/asset-naming-strategy';
-import { AssetPreviewStrategy } from './asset-preview-strategy/asset-preview-strategy';
-import { AssetStorageStrategy } from './asset-storage-strategy/asset-storage-strategy';
 import { EntityIdStrategy } from './entity-id-strategy/entity-id-strategy';
-import { PromotionAction } from './promotion/promotion-action';
-import { PromotionCondition } from './promotion/promotion-condition';
 import {
+    AssetOptions,
     AuthOptions,
     getConfig,
     OrderMergeOptions,
     OrderProcessOptions,
+    PromotionOptions,
     VendureConfig,
 } from './vendure-config';
 import { VendurePlugin } from './vendure-plugin/vendure-plugin';
@@ -68,32 +65,16 @@ export class ConfigService implements VendureConfig {
         return this.activeConfig.entityIdStrategy;
     }
 
-    get assetNamingStrategy(): AssetNamingStrategy {
-        return this.activeConfig.assetNamingStrategy;
-    }
-
-    get assetStorageStrategy(): AssetStorageStrategy {
-        return this.activeConfig.assetStorageStrategy;
-    }
-
-    get assetPreviewStrategy(): AssetPreviewStrategy {
-        return this.activeConfig.assetPreviewStrategy;
+    get assetOptions(): AssetOptions {
+        return this.activeConfig.assetOptions;
     }
 
     get dbConnectionOptions(): ConnectionOptions {
         return this.activeConfig.dbConnectionOptions;
     }
 
-    get uploadMaxFileSize(): number {
-        return this.activeConfig.uploadMaxFileSize;
-    }
-
-    get promotionConditions(): PromotionCondition[] {
-        return this.activeConfig.promotionConditions;
-    }
-
-    get promotionActions(): PromotionAction[] {
-        return this.activeConfig.promotionActions;
+    get promotionOptions(): PromotionOptions {
+        return this.activeConfig.promotionOptions;
     }
 
     get orderMergeOptions(): OrderMergeOptions {

+ 10 - 6
server/src/config/default-config.ts

@@ -35,15 +35,19 @@ export const defaultConfig: ReadOnlyRequired<VendureConfig> = {
     },
     apiPath: API_PATH,
     entityIdStrategy: new AutoIncrementIdStrategy(),
-    assetNamingStrategy: new DefaultAssetNamingStrategy(),
-    assetStorageStrategy: new NoAssetStorageStrategy(),
-    assetPreviewStrategy: new NoAssetPreviewStrategy(),
+    assetOptions: {
+        assetNamingStrategy: new DefaultAssetNamingStrategy(),
+        assetStorageStrategy: new NoAssetStorageStrategy(),
+        assetPreviewStrategy: new NoAssetPreviewStrategy(),
+        uploadMaxFileSize: 20971520,
+    },
     dbConnectionOptions: {
         type: 'mysql',
     },
-    uploadMaxFileSize: 20971520,
-    promotionConditions: defaultPromotionConditions,
-    promotionActions: defaultPromotionActions,
+    promotionOptions: {
+        promotionConditions: defaultPromotionConditions,
+        promotionActions: defaultPromotionActions,
+    },
     orderProcessOptions: {},
     orderMergeOptions: {
         mergeStrategy: new MergeOrdersStrategy(),

+ 54 - 23
server/src/config/vendure-config.ts

@@ -19,6 +19,8 @@ import { mergeConfig } from './merge-config';
 import { OrderMergeStrategy } from './order-merge-strategy/order-merge-strategy';
 import { PromotionAction } from './promotion/promotion-action';
 import { PromotionCondition } from './promotion/promotion-condition';
+import { ShippingCalculator } from './shipping-method/shipping-calculator';
+import { ShippingEligibilityChecker } from './shipping-method/shipping-eligibility-checker';
 import { VendurePlugin } from './vendure-plugin/vendure-plugin';
 
 export interface AuthOptions {
@@ -100,6 +102,50 @@ export interface OrderMergeOptions {
     checkoutMergeStrategy: OrderMergeStrategy;
 }
 
+export interface AssetOptions {
+    /**
+     * Defines how asset files and preview images are named before being saved.
+     */
+    assetNamingStrategy: AssetNamingStrategy;
+    /**
+     * Defines the strategy used for storing uploaded binary files. By default files are
+     * persisted to the local file system.
+     */
+    assetStorageStrategy: AssetStorageStrategy;
+    /**
+     * Defines the strategy used for creating preview images of uploaded assets. The default
+     * strategy resizes images based on maximum dimensions and outputs a sensible default
+     * preview image for other file types.
+     */
+    assetPreviewStrategy: AssetPreviewStrategy;
+    /**
+     * The max file size in bytes for uploaded assets.
+     */
+    uploadMaxFileSize?: number;
+}
+
+export interface PromotionOptions {
+    /**
+     * An array of conditions which can be used to construct Promotions
+     */
+    promotionConditions?: Array<PromotionCondition<any>>;
+    /**
+     * An array of actions which can be used to construct Promotions
+     */
+    promotionActions?: Array<PromotionAction<any>>;
+}
+
+export interface ShippingOptions {
+    /**
+     * An array of available ShippingEligibilityCheckers for use in configuring ShippingMethods
+     */
+    shippingEligibilityCheckers?: ShippingEligibilityChecker[];
+    /**
+     * An array of available ShippingCalculator for use in configuring ShippingMethods
+     */
+    shippingCalculators?: ShippingCalculator[];
+}
+
 export interface VendureConfig {
     /**
      * The name of the property which contains the token of the
@@ -132,6 +178,10 @@ export interface VendureConfig {
      * Configuration for authorization.
      */
     authOptions: AuthOptions;
+    /**
+     * Configuration for the handling of Assets.
+     */
+    assetOptions?: AssetOptions;
     /**
      * Defines the strategy used for both storing the primary keys of entities
      * in the database, and the encoding & decoding of those ids when exposing
@@ -139,33 +189,18 @@ export interface VendureConfig {
      * strategy.
      */
     entityIdStrategy?: EntityIdStrategy<any>;
-    /**
-     * Defines how asset files and preview images are named before being saved.
-     */
-    assetNamingStrategy?: AssetNamingStrategy;
-    /**
-     * Defines the strategy used for storing uploaded binary files. By default files are
-     * persisted to the local file system.
-     */
-    assetStorageStrategy?: AssetStorageStrategy;
-    /**
-     * Defines the strategy used for creating preview images of uploaded assets. The default
-     * strategy resizes images based on maximum dimensions and outputs a sensible default
-     * preview image for other file types.
-     */
-    assetPreviewStrategy?: AssetPreviewStrategy;
     /**
      * The connection options used by TypeORM to connect to the database.
      */
     dbConnectionOptions: ConnectionOptions;
     /**
-     * An array of conditions which can be used to construct Promotions
+     * Configures the Conditions and Actions available when creating Promotions.
      */
-    promotionConditions?: Array<PromotionCondition<any>>;
+    promotionOptions?: PromotionOptions;
     /**
-     * An array of actions which can be used to construct Promotions
+     * Configures the available checkers and calculators for ShippingMethods.
      */
-    promotionActions?: Array<PromotionAction<any>>;
+    shippingOptions?: ShippingOptions;
     /**
      * Defines custom fields which can be used to extend the built-in entities.
      */
@@ -179,10 +214,6 @@ export interface VendureConfig {
      * Customer signs in.
      */
     orderMergeOptions?: OrderMergeOptions;
-    /**
-     * The max file size in bytes for uploaded assets.
-     */
-    uploadMaxFileSize?: number;
     /**
      * Custom Express middleware for the server.
      */

+ 4 - 5
server/src/entity/promotion/promotion.entity.ts

@@ -19,11 +19,10 @@ export class Promotion extends AdjustmentSource {
 
     constructor(input?: DeepPartial<Promotion>) {
         super(input);
-        this.allConditions = getConfig().promotionConditions.reduce(
-            (hash, o) => ({ ...hash, [o.code]: o }),
-            {},
-        );
-        this.allActions = getConfig().promotionActions.reduce((hash, o) => ({ ...hash, [o.code]: o }), {});
+        const conditions = getConfig().promotionOptions.promotionConditions || [];
+        const actions = getConfig().promotionOptions.promotionActions || [];
+        this.allConditions = conditions.reduce((hash, o) => ({ ...hash, [o.code]: o }), {});
+        this.allActions = actions.reduce((hash, o) => ({ ...hash, [o.code]: o }), {});
     }
 
     @Column() name: string;

+ 2 - 2
server/src/plugin/default-asset-server/default-asset-server-plugin.ts

@@ -44,11 +44,11 @@ export class DefaultAssetServerPlugin implements VendurePlugin {
     init(config: Required<VendureConfig>) {
         this.createAssetServer();
         this.assetStorage = new DefaultAssetStorageStrategy(this.options.assetUploadDir, this.options.route);
-        config.assetPreviewStrategy = new DefaultAssetPreviewStrategy({
+        config.assetOptions.assetPreviewStrategy = new DefaultAssetPreviewStrategy({
             maxWidth: this.options.previewMaxWidth,
             maxHeight: this.options.previewMaxHeight,
         });
-        config.assetStorageStrategy = this.assetStorage;
+        config.assetOptions.assetStorageStrategy = this.assetStorage;
         config.middleware.push({
             handler: this.createProxyHandler(),
             route: this.options.route,

+ 8 - 7
server/src/service/services/asset.service.ts

@@ -38,7 +38,8 @@ export class AssetService {
 
     async create(input: CreateAssetInput): Promise<Asset> {
         const { stream, filename, mimetype, encoding } = await input.file;
-        const { assetPreviewStrategy, assetStorageStrategy } = this.configService;
+        const { assetOptions } = this.configService;
+        const { assetPreviewStrategy, assetStorageStrategy } = assetOptions;
         const sourceFileName = await this.getSourceFileName(filename);
         const previewFileName = await this.getPreviewFileName(sourceFileName);
 
@@ -62,16 +63,16 @@ export class AssetService {
     }
 
     private async getSourceFileName(fileName: string): Promise<string> {
-        const { assetNamingStrategy } = this.configService;
+        const { assetOptions } = this.configService;
         return this.generateUniqueName(fileName, (name, conflict) =>
-            assetNamingStrategy.generateSourceFileName(name, conflict),
+            assetOptions.assetNamingStrategy.generateSourceFileName(name, conflict),
         );
     }
 
     private async getPreviewFileName(fileName: string): Promise<string> {
-        const { assetNamingStrategy } = this.configService;
+        const { assetOptions } = this.configService;
         return this.generateUniqueName(fileName, (name, conflict) =>
-            assetNamingStrategy.generatePreviewFileName(name, conflict),
+            assetOptions.assetNamingStrategy.generatePreviewFileName(name, conflict),
         );
     }
 
@@ -79,11 +80,11 @@ export class AssetService {
         inputFileName: string,
         generateNameFn: (fileName: string, conflictName?: string) => string,
     ): Promise<string> {
-        const { assetStorageStrategy } = this.configService;
+        const { assetOptions } = this.configService;
         let outputFileName: string | undefined;
         do {
             outputFileName = generateNameFn(inputFileName, outputFileName);
-        } while (await assetStorageStrategy.fileExists(outputFileName));
+        } while (await assetOptions.assetStorageStrategy.fileExists(outputFileName));
         return outputFileName;
     }
 }

+ 2 - 2
server/src/service/services/promotion.service.ts

@@ -40,8 +40,8 @@ export class PromotionService {
         private channelService: ChannelService,
         private listQueryBuilder: ListQueryBuilder,
     ) {
-        this.availableConditions = this.configService.promotionConditions;
-        this.availableActions = this.configService.promotionActions;
+        this.availableConditions = this.configService.promotionOptions.promotionConditions || [];
+        this.availableActions = this.configService.promotionOptions.promotionActions || [];
     }
 
     findAll(options?: ListQueryOptions<Promotion>): Promise<PaginatedList<Promotion>> {