Browse Source

feat(asset-server-plugin): Make the AssetStorageStrategy configurable

Relates to #258. The developer can now provide a custom AssetStorageStrategy e.g. to store files with a cloud storage provider.

BREAKING CHANGE: The `LocalAssetStorageStrategy` class has been removed from `@vendure/core` and now lives in the `@vendure/asset-server-plugin` package.
Michael Bromley 6 years ago
parent
commit
a13a504de6

+ 19 - 0
packages/asset-server-plugin/src/default-asset-storage-strategy-factory.ts

@@ -0,0 +1,19 @@
+import { Request } from 'express';
+
+import { LocalAssetStorageStrategy } from './local-asset-storage-strategy';
+import { AssetServerOptions } from './types';
+
+/**
+ * By default the AssetServerPlugin will configure and use the LocalStorageStrategy to persist Assets.
+ */
+export function defaultAssetStorageStrategyFactory(options: AssetServerOptions) {
+    const { assetUrlPrefix, assetUploadDir, route } = options;
+    const toAbsoluteUrlFn = (request: Request, identifier: string): string => {
+        if (!identifier) {
+            return '';
+        }
+        const prefix = assetUrlPrefix || `${request.protocol}://${request.get('host')}/${route}/`;
+        return identifier.startsWith(prefix) ? identifier : `${prefix}${identifier}`;
+    };
+    return new LocalAssetStorageStrategy(assetUploadDir, toAbsoluteUrlFn);
+}

+ 5 - 3
packages/core/src/config/asset-storage-strategy/local-asset-storage-strategy.ts → packages/asset-server-plugin/src/local-asset-storage-strategy.ts

@@ -1,18 +1,20 @@
+import { AssetStorageStrategy } from '@vendure/core';
 import { Request } from 'express';
 import { ReadStream } from 'fs';
 import fs from 'fs-extra';
 import path from 'path';
 import { Stream } from 'stream';
 
-import { AssetStorageStrategy } from './asset-storage-strategy';
-
 /**
  * A persistence strategy which saves files to the local file system.
  */
 export class LocalAssetStorageStrategy implements AssetStorageStrategy {
     toAbsoluteUrl: ((reqest: Request, identifier: string) => string) | undefined;
 
-    constructor(private readonly uploadPath: string, private readonly toAbsoluteUrlFn?: (reqest: Request, identifier: string) => string) {
+    constructor(
+        private readonly uploadPath: string,
+        private readonly toAbsoluteUrlFn?: (reqest: Request, identifier: string) => string,
+    ) {
         this.ensureUploadPathExists(this.uploadPath);
         if (toAbsoluteUrlFn) {
             this.toAbsoluteUrl = toAbsoluteUrlFn;

+ 5 - 15
packages/asset-server-plugin/src/plugin.ts

@@ -2,7 +2,6 @@ import { Type } from '@vendure/common/lib/shared-types';
 import {
     AssetStorageStrategy,
     createProxyHandler,
-    LocalAssetStorageStrategy,
     Logger,
     OnVendureBootstrap,
     OnVendureClose,
@@ -13,6 +12,7 @@ import express, { NextFunction, Request, Response } from 'express';
 import { Server } from 'http';
 import path from 'path';
 
+import { defaultAssetStorageStrategyFactory } from './default-asset-storage-strategy-factory';
 import { SharpAssetPreviewStrategy } from './sharp-asset-preview-strategy';
 import { transformImage } from './transform-image';
 import { AssetServerOptions, ImageTransformPreset } from './types';
@@ -136,8 +136,10 @@ export class AssetServerPlugin implements OnVendureBootstrap, OnVendureClose {
     }
 
     /** @internal */
-    static configure(config: RuntimeVendureConfig) {
-        this.assetStorage = this.createAssetStorageStrategy(this.options);
+    static async configure(config: RuntimeVendureConfig) {
+        const storageStrategyFactory =
+            this.options.storageStrategyFactory || defaultAssetStorageStrategyFactory;
+        this.assetStorage = await storageStrategyFactory(this.options);
         config.assetOptions.assetPreviewStrategy = new SharpAssetPreviewStrategy({
             maxWidth: this.options.previewMaxWidth || 1600,
             maxHeight: this.options.previewMaxHeight || 1600,
@@ -172,18 +174,6 @@ export class AssetServerPlugin implements OnVendureBootstrap, OnVendureClose {
         });
     }
 
-    private static createAssetStorageStrategy(options: AssetServerOptions) {
-        const { assetUrlPrefix, assetUploadDir, route } = options;
-        const toAbsoluteUrlFn = (request: Request, identifier: string): string => {
-            if (!identifier) {
-                return '';
-            }
-            const prefix = assetUrlPrefix || `${request.protocol}://${request.get('host')}/${route}/`;
-            return identifier.startsWith(prefix) ? identifier : `${prefix}${identifier}`;
-        };
-        return new LocalAssetStorageStrategy(assetUploadDir, toAbsoluteUrlFn);
-    }
-
     /**
      * Creates the image server instance
      */

+ 13 - 0
packages/asset-server-plugin/src/types.ts

@@ -1,3 +1,5 @@
+import { AssetStorageStrategy } from '@vendure/core';
+
 /**
  * @description
  * Specifies the way in which an asset preview image will be resized to fit in the
@@ -9,6 +11,7 @@
  *
  * @docsCategory AssetServerPlugin
  */
+
 export type ImageTransformMode = 'crop' | 'resize';
 
 /**
@@ -87,4 +90,14 @@ export interface AssetServerOptions {
      * An array of additional {@link ImageTransformPreset} objects.
      */
     presets?: ImageTransformPreset[];
+    /**
+     * @description
+     * A function which can be used to configure an {@link AssetStorageStrategy}. This is useful e.g. if you wish to store your assets
+     * using a cloud storage provider. By default, the {@link LocalAssetStorageStrategy} is used.
+     *
+     * @default () => LocalAssetStorageStrategy
+     */
+    storageStrategyFactory?: (
+        options: AssetServerOptions,
+    ) => AssetStorageStrategy | Promise<AssetStorageStrategy>;
 }

+ 0 - 1
packages/core/src/config/index.ts

@@ -2,7 +2,6 @@ export * from './asset-naming-strategy/asset-naming-strategy';
 export * from './asset-naming-strategy/default-asset-naming-strategy';
 export * from './asset-preview-strategy/asset-preview-strategy';
 export * from './asset-storage-strategy/asset-storage-strategy';
-export * from './asset-storage-strategy/local-asset-storage-strategy';
 export * from './entity-id-strategy/auto-increment-id-strategy';
 export * from './config.service';
 export * from './entity-id-strategy/entity-id-strategy';