From 3845374097222242d1d826672bee90a2760b8652 Mon Sep 17 00:00:00 2001 From: Brandon Phillips Date: Mon, 8 Apr 2019 09:47:13 -0600 Subject: [PATCH] feat(core): support storing the resolved disk name in the disk --- README.md | 2 + src/drivers/s3/S3Disk.ts | 5 ++- src/lib/Disk.ts | 16 ++++++- src/lib/DiskManager.test.ts | 17 ++++++++ src/lib/DiskManager.ts | 85 ++++++++++++++++++++++++------------- src/lib/fs/FSDisk.ts | 4 +- 6 files changed, 95 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index f36a11b..1b30295 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,8 @@ Important public methods: - `async delete(path: string): Promise` to delete a file (not a directory) - `async list(path: string): Promise` to obtain a list of objects in a directory on the disk. +- `getName(): string | null` to get the name of the disk if it was created with one. The `DiskManager` will + automatically and appropriately set this to the actual resolved name of the disk from the config. ### `DiskManager` diff --git a/src/drivers/s3/S3Disk.ts b/src/drivers/s3/S3Disk.ts index 3fb88c1..883669b 100644 --- a/src/drivers/s3/S3Disk.ts +++ b/src/drivers/s3/S3Disk.ts @@ -37,10 +37,11 @@ export class S3Disk extends Disk { /** * Create the disk, optionally using an existing S3 client * @param config + * @param name * @param s3Client */ - public constructor(config: S3DiskConfig, s3Client: AWS.S3 | null = null) { - super(config); + public constructor(config: S3DiskConfig, name?: string, s3Client?: AWS.S3) { + super(config, name); const { clientConfig = {}, bucket = null } = config; if (!bucket) { throw new Error('Missing config value `bucket` for `s3` disk.'); diff --git a/src/lib/Disk.ts b/src/lib/Disk.ts index 177dae6..1ddf175 100644 --- a/src/lib/Disk.ts +++ b/src/lib/Disk.ts @@ -43,11 +43,25 @@ export abstract class Disk { */ protected config: DiskConfig; + /** + * The optional name of the disk for organizational use. + */ + protected name: string | null; + /** * @param config The disk's configuration. + * @param name The optional name of the disk for organizational use. */ - public constructor(config: DiskConfig) { + protected constructor(config: DiskConfig, name?: string) { this.config = config; + this.name = name || null; + } + + /** + * Get the optional name of the disk. + */ + public getName(): string | null { + return this.name; } /** diff --git a/src/lib/DiskManager.test.ts b/src/lib/DiskManager.test.ts index 5b988fb..e511b60 100644 --- a/src/lib/DiskManager.test.ts +++ b/src/lib/DiskManager.test.ts @@ -5,13 +5,30 @@ test('getDisk returns the same disk instance for the same disk name', () => { const diskMan = new DiskManager({ default: { driver: DiskDriver.Memory }, foo: { driver: DiskDriver.Memory }, + bar: 'foo', }); const defaultDisk1 = diskMan.getDisk(); const defaultDisk2 = diskMan.getDisk(); const fooDisk1 = diskMan.getDisk('foo'); const fooDisk2 = diskMan.getDisk('foo'); + const barDisk = diskMan.getDisk('bar'); expect(defaultDisk1).toBe(defaultDisk2); expect(fooDisk1).toBe(fooDisk2); expect(defaultDisk1).not.toBe(fooDisk1); + expect(barDisk).toBe(fooDisk1); +}); + +test('getDisk uses resolved name and not alias for the name of resolved disks', () => { + const diskMan = new DiskManager({ + default: { driver: DiskDriver.Memory }, + foo: { driver: DiskDriver.Memory }, + bar: 'foo', + }); + const defaultDisk = diskMan.getDisk(); + const fooDisk = diskMan.getDisk('foo'); + const barDisk = diskMan.getDisk('bar'); + expect(defaultDisk.getName()).toBe('default'); + expect(fooDisk.getName()).toBe('foo'); + expect(barDisk.getName()).toBe('foo'); }); diff --git a/src/lib/DiskManager.ts b/src/lib/DiskManager.ts index b0de344..46ff955 100644 --- a/src/lib/DiskManager.ts +++ b/src/lib/DiskManager.ts @@ -7,11 +7,20 @@ import { DiskManagerConfig, DiskManagerOptions, } from './types'; -import { S3Disk, LocalDisk, MemoryDisk } from '..'; -import { S3DiskConfig } from '../drivers/s3/types'; -import { LocalDiskConfig } from '../drivers/local/types'; +import { + S3Disk, + LocalDisk, + MemoryDisk, + S3DiskConfig, + LocalDiskConfig, +} from '..'; + +export type AnyDiskConfig = DiskConfig | S3DiskConfig | LocalDiskConfig; -export type AnyDiskConfig = DiskConfig | S3DiskConfig | LocalDiskConfig | null; +export interface AnyNamedDiskConfig { + name: string; + config: AnyDiskConfig; +} export interface DiskManagerDiskRegistry { [key: string]: Disk; @@ -43,12 +52,12 @@ export class DiskManager { * @param name The name of the disk to lookup in the config. * @param maxLookup The max number of times to recurse to avoid infinite * loops when resolving aliases. - * @returns The disk config or null if it couldn't be resolved. + * @returns The disk config or null if it couldn't be resolved along with the finally resolved name. */ public resolveDiskConfig = ( name: string, maxLookup: number = 10, - ): AnyDiskConfig => { + ): AnyNamedDiskConfig | null => { if (has(name, this.config) && maxLookup > 0) { // If the value of the disk in config is a string, assume it's an alias. return typeof this.config[name] === 'string' @@ -56,7 +65,7 @@ export class DiskManager { this.config[name] as string, maxLookup - 1, ) - : (this.config[name] as DiskConfig); + : { name, config: this.config[name] as DiskConfig }; } return null; }; @@ -85,28 +94,46 @@ export class DiskManager { name: string = 'default', options: DiskManagerOptions = {}, ): Disk => { - if (has(name, this.disks)) { - return this.disks[name]; - } - const { s3Client = null } = options; - const diskConfig: AnyDiskConfig = this.resolveDiskConfig(name); - if (diskConfig) { - const { driver = null } = diskConfig; - switch (driver) { - case DiskDriver.Local: - return this.registerDisk( - name, - new LocalDisk(diskConfig as LocalDiskConfig), - ); - case DiskDriver.Memory: - return this.registerDisk(name, new MemoryDisk(diskConfig)); - case DiskDriver.S3: - return this.registerDisk( - name, - new S3Disk(diskConfig as S3DiskConfig, s3Client), - ); - default: - throw new BadDriverError(name, driver); + const namedDiskConfig = this.resolveDiskConfig(name); + if (namedDiskConfig) { + const { name: resolvedName, config: diskConfig } = namedDiskConfig; + if (has(resolvedName, this.disks)) { + return this.disks[resolvedName]; + } + const { s3Client = null } = options; + if (diskConfig) { + const { driver = null } = diskConfig; + switch (driver) { + case DiskDriver.Local: + return this.registerDisk( + resolvedName, + new LocalDisk( + diskConfig as LocalDiskConfig, + resolvedName, + ), + ); + case DiskDriver.Memory: + return this.registerDisk( + resolvedName, + new MemoryDisk(diskConfig, resolvedName), + ); + case DiskDriver.S3: + return this.registerDisk( + resolvedName, + s3Client + ? new S3Disk( + diskConfig as S3DiskConfig, + resolvedName, + s3Client, + ) + : new S3Disk( + diskConfig as S3DiskConfig, + resolvedName, + ), + ); + default: + throw new BadDriverError(resolvedName, driver); + } } } throw new DiskNotFoundError(name); diff --git a/src/lib/fs/FSDisk.ts b/src/lib/fs/FSDisk.ts index 4c9dca4..158efe3 100644 --- a/src/lib/fs/FSDisk.ts +++ b/src/lib/fs/FSDisk.ts @@ -26,8 +26,8 @@ export abstract class FSDisk extends Disk { */ protected fs: AsyncFSModule; - public constructor(config: DiskConfig) { - super(config); + public constructor(config: DiskConfig, name?: string) { + super(config, name); // Set the fs module to use internally this.fs = this.getAsyncFsModule(); }