Skip to content

Commit

Permalink
Merge pull request #5 from vahidvdn/feature/support-useClass-and-useE…
Browse files Browse the repository at this point in the history
…xisting

Feature/support use class and use existing
  • Loading branch information
vahidvdn authored Jun 26, 2021
2 parents ac81d2e + 44283d5 commit e811bf5
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 15 deletions.
20 changes: 19 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1 +1,19 @@
RELEASE 1.0.0
## RELEASE 1.1.0
### Feature
* Add full support for useClass and useExisting
* Add more docs
### Bug Fixes
* Fix minor bugs

## RELEASE 1.0.5
### Feature
* Update package.json
* Add more docs
### Bug Fixes
* Fix minor bugs

## RELEASE 1.0.1
### Feature
* Initial support for About currency conversion module for nestjs
### Bug Fixes
* Fix minor bugs
8 changes: 6 additions & 2 deletions example/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,19 @@ const rates = {

@Module({
imports: [
ConfigModule.forRoot(),
// CashifyModule.forRoot({base: 'EUR', rates}),
CashifyModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
base: configService.get<string>('BASE'), rates
}),
inject: [ConfigService]
})
}),
// CashifyModule.forRootAsync({
// useClass: CashifyConfigService,
// import: [ConfigModule],
// extraProviders: [ConfigService],
// })
],
controllers: [AppController],
providers: [AppService],
Expand Down
20 changes: 20 additions & 0 deletions example/src/cashify-config.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { CashifyOptionsFactory } from 'nestjs-cashify';

@Injectable()
export class CashifyConfigService implements CashifyOptionsFactory {
constructor(private configService: ConfigService) {}

createCashifyOptions() {
const rates = {
GBP: 0.92,
EUR: 1.00,
USD: 1.12
};
return {
base: this.configService.get<string>('BASE'),
rates
};
}
}
11 changes: 9 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nestjs-cashify",
"version": "1.0.5",
"version": "1.1.0",
"description": "Currency conversion module for nest",
"author": "Vahid Najafi <vahid.vdn@gmail.com>",
"license": "MIT",
Expand All @@ -22,7 +22,14 @@
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"keywords": [
"nestjs"
"nestjs",
"nodejs",
"cashify",
"nestjs-cashify",
"currency-exchange",
"conversion",
"money",
"exchange-rates"
],
"publishConfig": {
"access": "public"
Expand Down
82 changes: 72 additions & 10 deletions src/cashify.module.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
import { DynamicModule, Module } from '@nestjs/common';
import { DynamicModule, Module, Provider } from '@nestjs/common';
import { Cashify } from 'cashify';
import { CASHIFY, CashifyService, CASHIFY_OPTIONS } from './';
import { CashifyOptionsFactory } from './interfaces/cashify-module.interface';

@Module({})
export class CashifyModule {

/**
* @param options a simple configuration object
* @returns DynamicModule object
*/
public static forRoot(options): DynamicModule {

/**
* To have access to the Cashify's instance by CASHIFY token injection
* The reason we export it too, is that we can have direct access in consumer module,
* so if there is a new method added in future for core module by it's author,
* consumer module can have access to it
*/
const CashifyProvider = {
provide: CASHIFY,
useValue: new Cashify(options),
Expand All @@ -18,13 +31,19 @@ export class CashifyModule {
]
}
}

/**
* @param optionsAsync this is not a simple object of main options
* this is an async configuration with useFactory passed from consumer module
* @returns DynamicModule object
*/
public static forRootAsync(optionsAsync): DynamicModule {
const CashifyOptionProvider = {
provide: CASHIFY_OPTIONS,
useFactory: optionsAsync.useFactory,
inject: optionsAsync.inject || []
};
const CashifyProvider = {

/**
* This is our main provider that is accessible within the service
* The same one in forRoot method (but resolve the options in an async way)
*/
const CashifyProvider = {
provide: CASHIFY,
useFactory: (options) => new Cashify(options),
inject: [CASHIFY_OPTIONS],
Expand All @@ -35,10 +54,53 @@ export class CashifyModule {
imports: optionsAsync.imports,
exports: [CashifyService, CashifyProvider],
providers: [
...this.createAsyncProviders(optionsAsync),
CashifyProvider,
CashifyOptionProvider,
CashifyService
]
CashifyService,
...(optionsAsync.extraProviders || []),
],
}
}

private static createAsyncProviders(options): Provider[] {
if (options.useExisting || options.useFactory) {
return [this.createAsyncOptionsProvider(options)];
}
return [
this.createAsyncOptionsProvider(options),
{
provide: options.useClass,
useClass: options.useClass,
},
];
}

private static createAsyncOptionsProvider(optionsAsync): Provider {

/**
* This is going to be a factory provider and import in the list of providers
* This provider make the options value available in CashifyProvider. Since it's a provider,
* it can be injected in CashifyProvider
*/
if (optionsAsync.useFactory) {
return {
provide: CASHIFY_OPTIONS,
useFactory: optionsAsync.useFactory,
inject: optionsAsync.inject || []
};
}

/**
* In consumer module, if we use useClass, the give class may have some dependencies,
* like ConfigService (and it's module). But they are not available in this module's context.
* So, we have an 'imports' object and extraProviders in forRootAsync method.
* Then we can dynamically add them from consumer module. See example in example folder.
*/
return {
provide: CASHIFY_OPTIONS,
useFactory: async (optionsFactory: CashifyOptionsFactory) =>
optionsFactory.createCashifyOptions(),
inject: [optionsAsync.useExisting || optionsAsync.useClass],
};
}
}
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
export * from './cashify.const';
export * from './cashify.module';
export * from './cashify.service';
export * from './interfaces';

11 changes: 11 additions & 0 deletions src/interfaces/cashify-module.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Interface describing a `CashifyOptionsFactory`. Providers supplying configuration
* options for the Cashify module must implement this interface.
*
* @see [Async configuration](https://docs.nestjs.com/techniques/caching#async-configuration)
*
* @publicApi
*/
export interface CashifyOptionsFactory {
createCashifyOptions();
}
1 change: 1 addition & 0 deletions src/interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './cashify-module.interface';

0 comments on commit e811bf5

Please sign in to comment.