Skip to content

Commit

Permalink
feat(core): support storing the resolved disk name in the disk
Browse files Browse the repository at this point in the history
  • Loading branch information
bericp1 committed Apr 8, 2019
1 parent b1b6211 commit 3845374
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 34 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ Important public methods:
- `async delete(path: string): Promise<void>` to delete a file (not a directory)
- `async list(path: string): Promise<DiskListingObject[]>` 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`

Expand Down
5 changes: 3 additions & 2 deletions src/drivers/s3/S3Disk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.');
Expand Down
16 changes: 15 additions & 1 deletion src/lib/Disk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand Down
17 changes: 17 additions & 0 deletions src/lib/DiskManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');
});
85 changes: 56 additions & 29 deletions src/lib/DiskManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -43,20 +52,20 @@ 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'
? this.resolveDiskConfig(
this.config[name] as string,
maxLookup - 1,
)
: (this.config[name] as DiskConfig);
: { name, config: this.config[name] as DiskConfig };
}
return null;
};
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions src/lib/fs/FSDisk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down

0 comments on commit 3845374

Please sign in to comment.