Skip to content

Commit

Permalink
feat: support selecting optional configs with selectConfig (Nikaple#82)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikaple authored Dec 27, 2021
1 parent 15ce245 commit 5852b52
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 8 deletions.
4 changes: 2 additions & 2 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ Issue Number: N/A

## Does this PR introduce a breaking change?

[ ] Yes
[ ] No
- [ ] Yes
- [ ] No

<!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. -->

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x, 12.x, 14.x]
node-version: [12.x, 14.x, 16.x]
steps:
- uses: actions/checkout@v2

Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ export class Config {
}
```

## Type casting on environment variables
## Transforming the raw configuration

Environment variables are always loaded as strings, but configuration schemas are not. In such case, you can transform the raw config with `normalize` function:

Expand Down Expand Up @@ -650,6 +650,8 @@ export const routeConfig = selectConfig(ConfigModule, RouteConfig);

That's it! You can use `rootConfig` and `routeConfig` anywhere in your app now!

> If target configuration model is marked with `@Optional()`, you should call `selectConfig` with `{ allowOptional: true }` to allow optional configuration.

```ts
// app.controller.ts
import { Controller, Get } from '@nestjs/common';
Expand Down
21 changes: 18 additions & 3 deletions lib/utils/select-config.util.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
import { DynamicModule, ValueProvider } from '@nestjs/common';
import { ClassConstructor } from 'class-transformer';

export const selectConfig = <T>(
export interface SelectConfigOptions {
/**
* when true, allow undefined config declared with `@IsOptional()`
*/
allowOptional?: boolean;
}

export const selectConfig = <T, Option extends SelectConfigOptions>(
module: DynamicModule,
Config: ClassConstructor<T>,
): T => {
options?: Option,
): Option extends { allowOptional: true } ? T | undefined : T => {
const providers = module.providers as ValueProvider<T>[];
const selectedConfig = (providers || []).filter(
({ provide }) => provide === Config,
)[0];
if (options?.allowOptional) {
return selectedConfig?.useValue;
}
if (!selectedConfig) {
throw new Error(`You can only select config which exists in providers`);
throw new Error(
'You can only select config which exists in providers. \
If the config being selected is marked as optional, \
please pass `allowOptional` in options argument.',
);
}
return selectedConfig.useValue;
};
16 changes: 15 additions & 1 deletion tests/e2e/select-config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('Local toml', () => {
expect(tableConfig.name).toBe('test');
});

it(`can only select existing config`, async () => {
it(`can only select existing config without 'allowOptional'`, async () => {
const module = AppModule.withRawModule();

expect(() => selectConfig(module, class {})).toThrowError(
Expand All @@ -26,4 +26,18 @@ describe('Local toml', () => {
'You can only select config which exists in providers',
);
});

it(`can select optional config with 'allowOptional'`, async () => {
const module = AppModule.withRawModule();

expect(
selectConfig(module, class {}, { allowOptional: true }),
).toBeUndefined();
expect(
selectConfig({ module: class {} }, class {}, { allowOptional: true }),
).toBeUndefined();

const config = selectConfig(module, Config, { allowOptional: true });
expect(config?.isAuthEnabled).toBe(true);
});
});

0 comments on commit 5852b52

Please sign in to comment.