Skip to content

Commit

Permalink
feat(nestjs): add nestjs integration package
Browse files Browse the repository at this point in the history
  • Loading branch information
nartc committed Jan 2, 2021
1 parent c9bf760 commit db550c3
Show file tree
Hide file tree
Showing 28 changed files with 297 additions and 34 deletions.
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ module.exports = {
'<rootDir>/packages/classes',
'<rootDir>/packages/integration-test',
'<rootDir>/packages/pojos',
'<rootDir>/packages/nestjs',
],
};
3 changes: 3 additions & 0 deletions nx.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
},
"pojos": {
"tags": []
},
"nestjs": {
"tags": []
}
},
"workspaceLayout": {
Expand Down
35 changes: 35 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
],
"dependencies": {},
"devDependencies": {
"@nestjs/common": "7.6.5",
"@nrwl/cli": "11.0.20",
"@nrwl/eslint-plugin-nx": "11.0.20",
"@nrwl/jest": "11.0.20",
Expand Down
7 changes: 2 additions & 5 deletions packages/classes/src/lib/classes.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { createInitialMapping } from '@automapper/core';
import type {
Dictionary,
ErrorHandler,
Mapping,
MapPlugin,
MapPluginInitializer,
} from '@automapper/types';
import { MappingClassId } from '@automapper/types';
import 'reflect-metadata';
Expand All @@ -21,9 +20,7 @@ import { instantiate, isClass } from './utils';
*
* @param {ErrorHandler} errorHandler
*/
export const classes = (
errorHandler: ErrorHandler
): MapPlugin<Constructible> => {
export const classes: MapPluginInitializer<Constructible> = (errorHandler) => {
// Initialize all the storages
const metadataStorage = new ClassMetadataStorage();
const mappingStorage = new ClassMappingStorage();
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/lib/create-mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function createMapper<TKey = unknown>({
name,
pluginInitializer,
namingConventions,
errorHandle: customErrorHandler,
errorHandler: customErrorHandler,
}: CreateMapperOptions<TKey>): Mapper<TKey> {
// default errorHandler to console.error
const errorHandler = customErrorHandler || { handle: console.error };
Expand Down
2 changes: 1 addition & 1 deletion packages/integration-test/src/lib/setup.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function setup(
name,
pluginInitializer,
namingConventions,
errorHandle: { handle: spiedErrorHandle },
errorHandler: { handle: spiedErrorHandle },
});

afterEach(() => {
Expand Down
1 change: 1 addition & 0 deletions packages/nestjs/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "extends": "../../.eslintrc.json", "ignorePatterns": ["!**/*"], "rules": {} }
7 changes: 7 additions & 0 deletions packages/nestjs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# nestjs

This library was generated with [Nx](https://nx.dev).

## Running unit tests

Run `nx test nestjs` to execute the unit tests via [Jest](https://jestjs.io).
15 changes: 15 additions & 0 deletions packages/nestjs/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module.exports = {
displayName: 'nestjs',
preset: '../../jest.preset.js',
globals: {
'ts-jest': {
tsConfig: '<rootDir>/tsconfig.spec.json',
},
},
testEnvironment: 'node',
transform: {
'^.+\\.[tj]sx?$': 'ts-jest',
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
coverageDirectory: '../../coverage/packages/nestjs',
};
8 changes: 8 additions & 0 deletions packages/nestjs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "@automapper/nestjs",
"version": "0.0.1",
"peerDependencies": {
"@nestjs/common": "^7.0.0",
"@nestjs/core": "^7.0.0"
}
}
4 changes: 4 additions & 0 deletions packages/nestjs/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './lib/automapper.module';
export * from './lib/interfaces';
export * from './lib/di';
export * from './lib/abstracts';
12 changes: 12 additions & 0 deletions packages/nestjs/src/lib/abstracts/automapper-profile.abstract.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { Mapper, MappingProfile } from '@automapper/types';

export abstract class AutomapperProfile {
protected mapper: Mapper;

protected constructor(mapper: Mapper) {
this.mapper = mapper;
this.mapper.addProfile(this.mapProfile());
}

abstract mapProfile(): MappingProfile;
}
1 change: 1 addition & 0 deletions packages/nestjs/src/lib/abstracts/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './automapper-profile.abstract';
19 changes: 19 additions & 0 deletions packages/nestjs/src/lib/automapper.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { DynamicModule, Global, Logger, Module } from '@nestjs/common';
import type { AutomapperModuleOptions } from './interfaces';
import { createAutomapperProviders } from './utils';

@Global()
@Module({})
export class AutomapperModule {
private static readonly logger = new Logger(AutomapperModule.name);

static forRoot(forRootOptions: AutomapperModuleOptions): DynamicModule {
const providers = createAutomapperProviders(forRootOptions, this.logger);

return {
module: AutomapperModule,
providers,
exports: providers,
};
}
}
5 changes: 5 additions & 0 deletions packages/nestjs/src/lib/di/get-mapper-token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const DEFAULT_MAPPER_TOKEN = 'automapper:nestjs:default';

export function getMapperToken(name?: string) {
return name ? `automapper:nestjs:${name}` : DEFAULT_MAPPER_TOKEN;
}
1 change: 1 addition & 0 deletions packages/nestjs/src/lib/di/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './get-mapper-token';
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type {
CreateMapperOptions,
ErrorHandler,
NamingConvention,
} from '@automapper/types';

export interface AutomapperModuleOptions {
options: CreateMapperOptions[];
globalErrorHandler?: ErrorHandler;
globalNamingConventions?: {
source: NamingConvention;
destination: NamingConvention;
};
singular?: boolean;
}
1 change: 1 addition & 0 deletions packages/nestjs/src/lib/interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './automapper-module-options.interface';
60 changes: 60 additions & 0 deletions packages/nestjs/src/lib/utils/create-automapper-providers.util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { createMapper } from '@automapper/core';
import type { Provider } from '@nestjs/common';
import { Logger } from '@nestjs/common';
import { getMapperToken } from '../di';
import type { AutomapperModuleOptions } from '../interfaces';

export function createAutomapperProviders(
forRootOptions: AutomapperModuleOptions,
logger: Logger
): Provider[] {
const {
options,
globalErrorHandler,
globalNamingConventions,
singular = false,
} = forRootOptions;

if (singular) {
if (options.length > 1) {
const error =
'singular cannot be set to true when you have more than one plugin';
logger.error(error);
throw new Error(error);
}

const [
{ name, namingConventions, errorHandler, pluginInitializer },
] = options;
const mapper = createMapper({
name,
pluginInitializer,
errorHandler: errorHandler ||
globalErrorHandler || { handle: logger.error },
namingConventions: namingConventions || globalNamingConventions,
});

return [
{
provide: getMapperToken(),
useValue: mapper,
},
];
}

return options.map(
({ name, errorHandler, namingConventions, pluginInitializer }) => {
const mapper = createMapper({
name,
pluginInitializer,
errorHandler: errorHandler ||
globalErrorHandler || { handle: logger.error },
namingConventions: namingConventions || globalNamingConventions,
});
return {
provide: getMapperToken(mapper.name),
useValue: mapper,
};
}
);
}
1 change: 1 addition & 0 deletions packages/nestjs/src/lib/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './create-automapper-providers.util'
13 changes: 13 additions & 0 deletions packages/nestjs/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}
12 changes: 12 additions & 0 deletions packages/nestjs/tsconfig.lib.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"outDir": "../../dist/out-tsc",
"declaration": true,
"types": ["node"],
"target": "es6"
},
"exclude": ["**/*.spec.ts"],
"include": ["**/*.ts"]
}
15 changes: 15 additions & 0 deletions packages/nestjs/tsconfig.spec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": [
"**/*.spec.ts",
"**/*.spec.tsx",
"**/*.spec.js",
"**/*.spec.jsx",
"**/*.d.ts"
]
}
6 changes: 3 additions & 3 deletions packages/types/src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type {
Mapping,
NamingConvention,
} from './core';
import type { MapPlugin } from './plugin';
import type { MapPluginInitializer } from './plugin';
import type { Dictionary } from './utils';

export interface MapOptions<
Expand Down Expand Up @@ -32,6 +32,6 @@ export interface CreateMapperOptions<TKey = unknown> {
source: NamingConvention;
destination: NamingConvention;
};
pluginInitializer: (errorHandler: ErrorHandler) => MapPlugin<TKey>;
errorHandle?: ErrorHandler;
pluginInitializer: MapPluginInitializer<TKey>;
errorHandler?: ErrorHandler;
}
12 changes: 11 additions & 1 deletion packages/types/src/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import type { Mapping } from './core';
import type { ErrorHandler, Mapping } from './core';
import type { CreateMapOptions } from './options';
import type { Dictionary } from './utils';

/**
* How a plugin should provide
*/
export interface MapPlugin<TKey = unknown> {
/**
* Instruction on how a plugin should initialize a mapping for a pair of Source <> Destination
Expand Down Expand Up @@ -48,3 +51,10 @@ export interface MapPlugin<TKey = unknown> {
*/
dispose?(): void;
}

/**
* Plugin initializer
*/
export interface MapPluginInitializer<TKey = unknown> {
(errorHandler: ErrorHandler): MapPlugin<TKey>;
}
Loading

0 comments on commit db550c3

Please sign in to comment.