diff --git a/.prettierrc b/.prettierrc
index 41dcb96..988e56f 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,5 +1,6 @@
{
"trailingComma": "all",
"singleQuote": true,
- "arrowParens": "avoid"
+ "arrowParens": "avoid",
+ "printWidth": 80
}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..bac1591
--- /dev/null
+++ b/README.md
@@ -0,0 +1,68 @@
+
+
+
+
+
+ nestjs-storage is manage file Storage wrapping package flydrive
+
+
+
+
+
+
+
+## Installation
+
+```bash
+$ npm i --save @codebrew/nestjs-storage @slynova/flydrive
+
+# optional with s3 driver
+$ npm i --save @slynova/flydrive-s3
+
+# optional with gcs driver
+$ npm i --save @slynova/flydrive-gcs
+```
+
+## Example
+
+```typescript
+// app.module.ts
+import { Module } from '@nestjs/common'
+import { StorageModule, DriverType } from '@codebrew/nestjs-storage';
+
+@Module({
+ imports: [StorageModule.forRoot({
+ module: AppModule,
+ imports: [
+ StorageModule.forRoot({
+ default: 'local',
+ disks: {
+ local: {
+ driver: DriverType.LOCAL,
+ config: {
+ root: process.cwd(),
+ },
+ },
+ },
+ }),
+ ],
+ })]
+})
+export class AppModule {
+ constructor(private storage: StorageServic) {
+ this.storage.getDisk().put('test.txt', 'text content');
+ }
+}
+```
+
+## Support
+
+nestjs-storage is an MIT-licensed open source project. If this library is helpful, please click star to support it.
+
+## Stay in touch
+
+- Author - [David Kwon](https://github.com/tienne)
+
+## License
+
+nestjs-storage is MIT licensed.
diff --git a/lib/interfaces/index.ts b/lib/interfaces/index.ts
index 7125c79..7a92b83 100644
--- a/lib/interfaces/index.ts
+++ b/lib/interfaces/index.ts
@@ -1 +1,3 @@
export * from './Storage-module-options';
+export * from './storage-module-async-options';
+export * from './storage-options-factory';
diff --git a/lib/interfaces/storage-module-async-options.ts b/lib/interfaces/storage-module-async-options.ts
new file mode 100644
index 0000000..63b1f44
--- /dev/null
+++ b/lib/interfaces/storage-module-async-options.ts
@@ -0,0 +1,13 @@
+import { ModuleMetadata, Type } from '@nestjs/common';
+import { StorageModuleOptions } from './storage-module-options';
+import { StorageOptionsFactory } from './storage-options-factory';
+
+export interface StorageModuleAsyncOptions
+ extends Pick {
+ name?: string;
+ useFactory?: (
+ ...args: any[]
+ ) => Promise | StorageModuleOptions;
+ useClass?: Type;
+ inject?: any[];
+}
diff --git a/lib/interfaces/storage-module-options.ts b/lib/interfaces/storage-module-options.ts
index 14dd62d..eef10f0 100644
--- a/lib/interfaces/storage-module-options.ts
+++ b/lib/interfaces/storage-module-options.ts
@@ -1,13 +1,34 @@
import { StorageManagerConfig } from '@slynova/flydrive';
-import { DiskConfigType, DriverType } from '../types';
+import {
+ DiskConfigType,
+ DiskGCSConfigType,
+ DiskLocalConfigType,
+ DiskS3ConfigType,
+ DriverType,
+ DiskType,
+} from '../types';
export interface StorageModuleOptions extends StorageManagerConfig {
- isGlobal?: boolean;
default: string;
- disks: Record;
+ disks: Record;
}
export interface StorageDiskConfig {
driver: DriverType | string;
config: DiskConfigType;
}
+
+export interface AwsS3StorageDisk extends StorageDiskConfig {
+ driver: DriverType.S3 | 's3';
+ config: DiskS3ConfigType;
+}
+
+export interface LocalStorageDisk extends StorageDiskConfig {
+ driver: DriverType.LOCAL | 'local';
+ config: DiskLocalConfigType;
+}
+
+export interface GoogleGcsStorageDisk extends StorageDiskConfig {
+ driver: DriverType.GCS | 'gcs';
+ config: DiskGCSConfigType;
+}
diff --git a/lib/interfaces/storage-options-factory.ts b/lib/interfaces/storage-options-factory.ts
new file mode 100644
index 0000000..26c9096
--- /dev/null
+++ b/lib/interfaces/storage-options-factory.ts
@@ -0,0 +1,5 @@
+import { StorageModuleOptions } from './storage-module-options';
+
+export interface StorageOptionsFactory {
+ createStorageOptions(): Promise | StorageModuleOptions;
+}
diff --git a/lib/storage-core.module.ts b/lib/storage-core.module.ts
new file mode 100644
index 0000000..60f7fc8
--- /dev/null
+++ b/lib/storage-core.module.ts
@@ -0,0 +1,84 @@
+import {
+ DynamicModule,
+ Global,
+ Inject,
+ Module,
+ Provider,
+ Type,
+} from '@nestjs/common';
+import { StorageService } from './storage.service';
+
+import { STORAGE_MODULE_OPTIONS } from './storage.constants';
+import { StorageModuleOptions, StorageOptionsFactory } from './interfaces';
+import { ModuleRef } from '@nestjs/core';
+import { StorageModuleAsyncOptions } from './interfaces/storage-module-async-options';
+@Global()
+@Module({})
+export class StorageCoreModule {
+ constructor(
+ @Inject(STORAGE_MODULE_OPTIONS)
+ private readonly options: StorageModuleOptions,
+ private readonly moduleRef: ModuleRef,
+ ) {}
+
+ static forRoot(options: StorageModuleOptions): DynamicModule {
+ const storageModuleOptions: Provider = {
+ provide: STORAGE_MODULE_OPTIONS,
+ useValue: options,
+ };
+
+ return {
+ module: StorageCoreModule,
+ providers: [storageModuleOptions, StorageService],
+ exports: [StorageService],
+ };
+ }
+
+ static forRootAsync(options: StorageModuleAsyncOptions): DynamicModule {
+ const asyncProviders = this.createAsyncProviders(options);
+
+ return {
+ module: StorageCoreModule,
+ imports: options.imports,
+ providers: [...asyncProviders, StorageService],
+ exports: [StorageService],
+ };
+ }
+
+ private static createAsyncProviders(
+ options: StorageModuleAsyncOptions,
+ ): Provider[] {
+ if (options.useFactory) {
+ return [this.createAsyncOptionsProvider(options)];
+ }
+ const useClass = options.useClass as Type;
+ return [
+ this.createAsyncOptionsProvider(options),
+ {
+ provide: useClass,
+ useClass,
+ },
+ ];
+ }
+
+ private static createAsyncOptionsProvider(
+ options: StorageModuleAsyncOptions,
+ ): Provider {
+ if (options.useFactory) {
+ return {
+ provide: STORAGE_MODULE_OPTIONS,
+ useFactory: options.useFactory,
+ inject: options.inject || [],
+ };
+ }
+
+ const inject = [options.useClass as Type];
+
+ return {
+ provide: STORAGE_MODULE_OPTIONS,
+ useFactory: async (optionsFactory: StorageOptionsFactory) =>
+ optionsFactory.createStorageOptions(),
+ inject,
+ };
+ }
+}
diff --git a/lib/storage.constants.ts b/lib/storage.constants.ts
index 79b6edf..d2af8ea 100644
--- a/lib/storage.constants.ts
+++ b/lib/storage.constants.ts
@@ -2,3 +2,4 @@
* Injection tokens
*/
export const STORAGE_TOKEN = 'STORAGE_TOKEN';
+export const STORAGE_MODULE_OPTIONS = 'STORAGE_MODULE_OPTIONS';
diff --git a/lib/storage.module.ts b/lib/storage.module.ts
index c894439..80f571c 100644
--- a/lib/storage.module.ts
+++ b/lib/storage.module.ts
@@ -1,25 +1,22 @@
-import { DynamicModule, FactoryProvider, Module } from '@nestjs/common';
-import { StorageService } from './storage.service';
+import { DynamicModule, Module } from '@nestjs/common';
-import { STORAGE_TOKEN } from './storage.constants';
import { StorageModuleOptions } from './interfaces';
+import { StorageCoreModule } from './storage-core.module';
+import { StorageModuleAsyncOptions } from './interfaces/storage-module-async-options';
-@Module({
- providers: [StorageService],
- exports: [StorageService],
-})
+@Module({})
export class StorageModule {
static forRoot(options: StorageModuleOptions): DynamicModule {
return {
module: StorageModule,
- global: options.isGlobal,
- providers: [
- {
- provide: STORAGE_TOKEN,
- useValue: options,
- },
- ],
- exports: [StorageService],
+ imports: [StorageCoreModule.forRoot(options)],
+ };
+ }
+
+ static forRootAsync(options: StorageModuleAsyncOptions): DynamicModule {
+ return {
+ module: StorageModule,
+ imports: [StorageCoreModule.forRootAsync(options)],
};
}
}
diff --git a/lib/storage.service.ts b/lib/storage.service.ts
index 48be82f..d4105e9 100644
--- a/lib/storage.service.ts
+++ b/lib/storage.service.ts
@@ -1,14 +1,16 @@
import { Inject, Injectable } from '@nestjs/common';
import { Storage, StorageManager } from '@slynova/flydrive';
-import { STORAGE_TOKEN } from './storage.constants';
+import { STORAGE_MODULE_OPTIONS } from './storage.constants';
import { StorageModuleOptions } from './interfaces';
@Injectable()
export class StorageService {
private storageManager: StorageManager;
- constructor(@Inject(STORAGE_TOKEN) private options: StorageModuleOptions) {
+ constructor(
+ @Inject(STORAGE_MODULE_OPTIONS) private options: StorageModuleOptions,
+ ) {
this.storageManager = new StorageManager(options);
}
diff --git a/lib/types/disk.type.ts b/lib/types/disk.type.ts
new file mode 100644
index 0000000..13ec8ac
--- /dev/null
+++ b/lib/types/disk.type.ts
@@ -0,0 +1,12 @@
+import {
+ AwsS3StorageDisk,
+ GoogleGcsStorageDisk,
+ LocalStorageDisk,
+ StorageDiskConfig,
+} from '../interfaces';
+
+export type DiskType =
+ | AwsS3StorageDisk
+ | LocalStorageDisk
+ | GoogleGcsStorageDisk
+ | StorageDiskConfig;
diff --git a/lib/types/index.ts b/lib/types/index.ts
index 94bb9a7..3ce638e 100644
--- a/lib/types/index.ts
+++ b/lib/types/index.ts
@@ -1,2 +1,3 @@
export * from './driver.type';
export * from './disk-config.type';
+export * from './disk.type';
diff --git a/package.json b/package.json
index b03da43..6e2f6b2 100644
--- a/package.json
+++ b/package.json
@@ -17,9 +17,7 @@
"prerelease": "npm run build",
"release": "release-it"
},
- "dependencies": {
- "@slynova/flydrive": "^1.0.2"
- },
+ "dependencies": {},
"devDependencies": {
"@commitlint/cli": "^9.1.1",
"@commitlint/config-angular": "^9.1.1",
@@ -27,6 +25,7 @@
"@nestjs/core": "^7.3.2",
"@nestjs/platform-express": "^7.3.2",
"@nestjs/testing": "^7.3.2",
+ "@slynova/flydrive": "^1.0.2",
"@slynova/flydrive-gcs": "^1.0.2",
"@slynova/flydrive-s3": "^1.0.2",
"@types/jest": "^26.0.5",
diff --git a/tests/e2e/local-driver-async.spec.ts b/tests/e2e/local-driver-async.spec.ts
new file mode 100644
index 0000000..d0f84ed
--- /dev/null
+++ b/tests/e2e/local-driver-async.spec.ts
@@ -0,0 +1,37 @@
+import { INestApplication } from '@nestjs/common';
+import { Test } from '@nestjs/testing';
+import { AsyncFactoryModule } from '../src/async-factory.module';
+import { StorageService } from '../../lib';
+
+describe('async local driver module', () => {
+ let app: INestApplication, storageService: StorageService;
+
+ const fileName = 'local_async_test.txt',
+ fileContent = 'hi async module local storage test';
+
+ beforeEach(async () => {
+ const moduleRef = await Test.createTestingModule({
+ imports: [AsyncFactoryModule],
+ }).compile();
+
+ app = moduleRef.createNestApplication();
+ await app.init();
+ });
+
+ it(`should load configuration with "async module local driver"`, async () => {
+ storageService = app.get(StorageService);
+ });
+
+ it(`async module put text`, async () => {
+ await storageService.getDisk().put(`tests/data/${fileName}`, fileContent);
+ });
+
+ it(`async module get text file`, async () => {
+ const res = await storageService.getDisk().get(`tests/data/${fileName}`);
+ expect(res.raw).toEqual(fileContent);
+ });
+
+ afterEach(async () => {
+ await app.close();
+ });
+});
diff --git a/tests/src/app.module.ts b/tests/src/app.module.ts
index 677acec..9700174 100644
--- a/tests/src/app.module.ts
+++ b/tests/src/app.module.ts
@@ -1,12 +1,8 @@
import { DynamicModule, Module } from '@nestjs/common';
-
import { DriverType, StorageModule } from '../../lib';
-import { StorageService } from '../../lib/storage.service';
@Module({})
export class AppModule {
- constructor(private readonly storageService: StorageService) {}
-
static withLocalStorage(): DynamicModule {
return {
module: AppModule,
diff --git a/tests/src/async-factory.module.ts b/tests/src/async-factory.module.ts
new file mode 100644
index 0000000..0806830
--- /dev/null
+++ b/tests/src/async-factory.module.ts
@@ -0,0 +1,21 @@
+import { Module } from '@nestjs/common';
+import { DriverType, StorageModule } from '../../lib';
+
+@Module({
+ imports: [
+ StorageModule.forRootAsync({
+ useFactory: () => ({
+ default: 'local',
+ disks: {
+ local: {
+ driver: DriverType.LOCAL,
+ config: {
+ root: process.cwd(),
+ },
+ },
+ },
+ }),
+ }),
+ ],
+})
+export class AsyncFactoryModule {}