Jelajahi Sumber

feat(core): Expose new RuntimeVendureConfig interface

This interface more accurately represents the config object at runtime (once the default config has been merged during bootstrap).
Michael Bromley 6 tahun lalu
induk
melakukan
6ea71242a8

+ 1 - 1
docs/content/docs/plugins/_index.md

@@ -8,7 +8,7 @@ showtoc: true
 
 Plugins are the method by which the built-in functionality of Vendure can be extended. Plugins in Vendure allow one to:
 
-1. Modify the [VendureConfig]({{< relref "vendure-config" >}}) object.
+1. Modify the [VendureConfig]({{< ref "/docs/typescript-api/configuration" >}}#vendureconfig) object.
 2. Extend the GraphQL API, including modifying existing types and adding completely new queries and mutations.
 3. Define new database entities and interact directly with the database.
 4. Run code before the server bootstraps, such as starting webservers.

+ 1 - 1
docs/content/docs/typescript-api/_index.md

@@ -6,7 +6,7 @@ showtoc: false
 
 # Vendure TypeScript API Docs
 
-The Vendure TypeScript API is used when configuring the server (via the [`VendureConfig`]({{< ref "vendure-config" >}}) object) and when writing plugins that extend the functionality of Vendure core.
+The Vendure TypeScript API is used when configuring the server (via the [`VendureConfig`]({{< ref "configuration" >}}#vendureconfig) object) and when writing plugins that extend the functionality of Vendure core.
 
 {{% alert %}}
 All documentation in this section is auto-generated from the TypeScript source of the Vendure server.

+ 1 - 1
packages/core/e2e/fixtures/test-plugins.ts

@@ -109,7 +109,7 @@ export class TestPluginWithProvider {}
 
 @VendurePlugin({
     imports: [ConfigModule],
-    configuration(config: Required<VendureConfig>): Required<VendureConfig> {
+    configuration: config => {
         // tslint:disable-next-line:no-non-null-assertion
         config.defaultLanguageCode = LanguageCode.zh;
         return config;

+ 13 - 18
packages/core/src/api/middleware/validate-custom-fields-interceptor.ts

@@ -73,24 +73,19 @@ export class ValidateCustomFieldsInterceptor implements NestInterceptor {
         if (variableValues) {
             const entityName = typeName.replace(/(Create|Update)(.+)Input/, '$2');
             const customFieldConfig = this.configService.customFields[entityName as keyof CustomFields];
-            if (customFieldConfig) {
-                if (variableValues.customFields) {
-                    this.validateCustomFieldsObject(
-                        customFieldConfig,
-                        languageCode,
-                        variableValues.customFields,
-                    );
-                }
-                const translations = variableValues.translations;
-                if (Array.isArray(translations)) {
-                    for (const translation of translations) {
-                        if (translation.customFields) {
-                            this.validateCustomFieldsObject(
-                                customFieldConfig,
-                                languageCode,
-                                translation.customFields,
-                            );
-                        }
+
+            if (variableValues.customFields) {
+                this.validateCustomFieldsObject(customFieldConfig, languageCode, variableValues.customFields);
+            }
+            const translations = variableValues.translations;
+            if (Array.isArray(translations)) {
+                for (const translation of translations) {
+                    if (translation.customFields) {
+                        this.validateCustomFieldsObject(
+                            customFieldConfig,
+                            languageCode,
+                            translation.customFields,
+                        );
                     }
                 }
             }

+ 3 - 10
packages/core/src/bootstrap.ts

@@ -9,15 +9,10 @@ import { ReadOnlyRequired } from './common/types/common-types';
 import { getConfig, setConfig } from './config/config-helpers';
 import { DefaultLogger } from './config/logger/default-logger';
 import { Logger } from './config/logger/vendure-logger';
-import { VendureConfig } from './config/vendure-config';
+import { RuntimeVendureConfig, VendureConfig } from './config/vendure-config';
 import { registerCustomEntityFields } from './entity/register-custom-entity-fields';
 import { validateCustomFieldsConfig } from './entity/validate-custom-fields-config';
-import {
-    getConfigurationFunction,
-    getEntitiesFromPlugins,
-    getPluginModules,
-    hasLifecycleMethod,
-} from './plugin/plugin-metadata';
+import { getConfigurationFunction, getEntitiesFromPlugins } from './plugin/plugin-metadata';
 import { logProxyMiddlewares } from './plugin/plugin-utils';
 
 export type VendureBootstrapFunction = (config: VendureConfig) => Promise<INestApplication>;
@@ -172,9 +167,7 @@ export async function preBootstrapConfig(
 /**
  * Initialize any configured plugins.
  */
-async function runPluginConfigurations(
-    config: ReadOnlyRequired<VendureConfig>,
-): Promise<ReadOnlyRequired<VendureConfig>> {
+async function runPluginConfigurations(config: RuntimeVendureConfig): Promise<RuntimeVendureConfig> {
     for (const plugin of config.plugins) {
         const configFn = getConfigurationFunction(plugin);
         if (typeof configFn === 'function') {

+ 2 - 2
packages/core/src/config/config-helpers.ts

@@ -4,7 +4,7 @@ import { ReadOnlyRequired } from '../common/types/common-types';
 
 import { defaultConfig } from './default-config';
 import { mergeConfig } from './merge-config';
-import { VendureConfig } from './vendure-config';
+import { RuntimeVendureConfig, VendureConfig } from './vendure-config';
 
 let activeConfig = defaultConfig;
 
@@ -21,7 +21,7 @@ export function setConfig(userConfig: DeepPartial<VendureConfig>): void {
  * used before bootstrapping the app. In all other contexts, the {@link ConfigService}
  * should be used to access config settings.
  */
-export function getConfig(): ReadOnlyRequired<VendureConfig> {
+export function getConfig(): Readonly<RuntimeVendureConfig> {
     return activeConfig;
 }
 

+ 6 - 7
packages/core/src/config/config.service.ts

@@ -4,8 +4,6 @@ import { LanguageCode } from '@vendure/common/lib/generated-types';
 import { RequestHandler } from 'express';
 import { ConnectionOptions } from 'typeorm';
 
-import { ReadOnlyRequired } from '../common/types/common-types';
-
 import { getConfig } from './config-helpers';
 import { CustomFields } from './custom-field/custom-field-types';
 import { EntityIdStrategy } from './entity-id-strategy/entity-id-strategy';
@@ -17,6 +15,7 @@ import {
     OrderOptions,
     PaymentOptions,
     PromotionOptions,
+    RuntimeVendureConfig,
     ShippingOptions,
     TaxOptions,
     VendureConfig,
@@ -25,7 +24,7 @@ import {
 
 @Injectable()
 export class ConfigService implements VendureConfig {
-    private activeConfig: ReadOnlyRequired<VendureConfig>;
+    private activeConfig: RuntimeVendureConfig;
 
     constructor() {
         this.activeConfig = getConfig();
@@ -36,7 +35,7 @@ export class ConfigService implements VendureConfig {
     }
 
     get authOptions(): Required<AuthOptions> {
-        return this.activeConfig.authOptions as Required<AuthOptions>;
+        return this.activeConfig.authOptions;
     }
 
     get defaultChannelToken(): string | null {
@@ -100,10 +99,10 @@ export class ConfigService implements VendureConfig {
     }
 
     get importExportOptions(): Required<ImportExportOptions> {
-        return this.activeConfig.importExportOptions as Required<ImportExportOptions>;
+        return this.activeConfig.importExportOptions;
     }
 
-    get customFields(): CustomFields {
+    get customFields(): Required<CustomFields> {
         return this.activeConfig.customFields;
     }
 
@@ -120,6 +119,6 @@ export class ConfigService implements VendureConfig {
     }
 
     get workerOptions(): WorkerOptions {
-        return this.activeConfig.workerOptions as Required<WorkerOptions>;
+        return this.activeConfig.workerOptions;
     }
 }

+ 7 - 6
packages/core/src/config/default-config.ts

@@ -2,12 +2,9 @@ import { Transport } from '@nestjs/microservices';
 import { LanguageCode } from '@vendure/common/lib/generated-types';
 import { DEFAULT_AUTH_TOKEN_HEADER_KEY } from '@vendure/common/lib/shared-constants';
 
-import { ReadOnlyRequired } from '../common/types/common-types';
-
 import { DefaultAssetNamingStrategy } from './asset-naming-strategy/default-asset-naming-strategy';
 import { NoAssetPreviewStrategy } from './asset-preview-strategy/no-asset-preview-strategy';
 import { NoAssetStorageStrategy } from './asset-storage-strategy/no-asset-storage-strategy';
-import { CustomFields } from './custom-field/custom-field-types';
 import { AutoIncrementIdStrategy } from './entity-id-strategy/auto-increment-id-strategy';
 import { DefaultLogger } from './logger/default-logger';
 import { TypeOrmLogger } from './logger/typeorm-logger';
@@ -19,12 +16,16 @@ import { defaultShippingCalculator } from './shipping-method/default-shipping-ca
 import { defaultShippingEligibilityChecker } from './shipping-method/default-shipping-eligibility-checker';
 import { DefaultTaxCalculationStrategy } from './tax/default-tax-calculation-strategy';
 import { DefaultTaxZoneStrategy } from './tax/default-tax-zone-strategy';
-import { VendureConfig } from './vendure-config';
+import { RuntimeVendureConfig } from './vendure-config';
 
 /**
+ * @description
  * The default configuration settings which are used if not explicitly overridden in the bootstrap() call.
+ *
+ * @docsCategory configuration
+ * @docsPage Configuration
  */
-export const defaultConfig: ReadOnlyRequired<VendureConfig> = {
+export const defaultConfig: RuntimeVendureConfig = {
     channelTokenKey: 'vendure-token',
     defaultChannelToken: null,
     defaultLanguageCode: LanguageCode.en,
@@ -101,7 +102,7 @@ export const defaultConfig: ReadOnlyRequired<VendureConfig> = {
         ProductOptionGroup: [],
         ProductVariant: [],
         User: [],
-    } as ReadOnlyRequired<CustomFields>,
+    },
     middleware: [],
     plugins: [],
 };

+ 19 - 1
packages/core/src/config/vendure-config.ts

@@ -372,7 +372,8 @@ export interface WorkerOptions {
  * All possible configuration options are defined by the
  * [`VendureConfig`](https://github.com/vendure-ecommerce/vendure/blob/master/server/src/config/vendure-config.ts) interface.
  *
- * @docsCategory
+ * @docsCategory configuration
+ * @docsPage Configuration
  * */
 export interface VendureConfig {
     /**
@@ -523,3 +524,20 @@ export interface VendureConfig {
      */
     workerOptions?: WorkerOptions;
 }
+
+/**
+ * @description
+ * This interface represents the VendureConfig object available at run-time, i.e. the user-supplied
+ * config values have been merged with the {@link defaultConfig} values.
+ *
+ * @docsCategory configuration
+ * @docsPage Configuration
+ */
+export interface RuntimeVendureConfig extends Required<VendureConfig> {
+    assetOptions: Required<AssetOptions>;
+    authOptions: Required<AuthOptions>;
+    customFields: Required<CustomFields>;
+    importExportOptions: Required<ImportExportOptions>;
+    orderOptions: Required<OrderOptions>;
+    workerOptions: Required<WorkerOptions>;
+}

+ 3 - 3
packages/core/src/plugin/vendure-plugin.ts

@@ -5,7 +5,7 @@ import { pick } from '@vendure/common/lib/pick';
 import { Type } from '@vendure/common/lib/shared-types';
 import { DocumentNode } from 'graphql';
 
-import { VendureConfig } from '../config/vendure-config';
+import { RuntimeVendureConfig } from '../config/vendure-config';
 
 import { PLUGIN_METADATA } from './plugin-metadata';
 
@@ -87,8 +87,8 @@ export interface APIExtensionDefinition {
  * @docsPage VendurePluginMetadata
  */
 export type PluginConfigurationFn = (
-    config: Required<VendureConfig>,
-) => Required<VendureConfig> | Promise<Required<VendureConfig>>;
+    config: RuntimeVendureConfig,
+) => RuntimeVendureConfig | Promise<RuntimeVendureConfig>;
 
 /**
  * @description