Skip to content

Commit cd56636

Browse files
committed
feat(json-api-nestjs-microorm): Adapter for microorm
Move adapter for microorm as separate package
1 parent f25d319 commit cd56636

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+6216
-0
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"extends": ["../../../.eslintrc.base.json"],
3+
"ignorePatterns": ["!**/*"],
4+
"overrides": [
5+
{
6+
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7+
"rules": {}
8+
},
9+
{
10+
"files": ["*.ts", "*.tsx"],
11+
"rules": {}
12+
},
13+
{
14+
"files": ["*.js", "*.jsx"],
15+
"rules": {}
16+
},
17+
{
18+
"files": ["*.json"],
19+
"parser": "jsonc-eslint-parser",
20+
"rules": {
21+
"@nx/dependency-checks": [
22+
"error",
23+
{
24+
"ignoredFiles": ["{projectRoot}/eslint.config.{js,cjs,mjs}"]
25+
}
26+
]
27+
}
28+
}
29+
]
30+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# json-api-nestjs-microorm
2+
3+
This library was generated with [Nx](https://nx.dev).
4+
5+
## Building
6+
7+
Run `nx build json-api-nestjs-microorm` to build the library.
8+
9+
## Running unit tests
10+
11+
Run `nx test json-api-nestjs-microorm` to execute the unit tests via [Jest](https://jestjs.io).
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export default {
2+
displayName: 'json-api-nestjs-microorm',
3+
preset: '../../../jest.preset.js',
4+
testEnvironment: 'node',
5+
transform: {
6+
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
7+
},
8+
moduleFileExtensions: ['ts', 'js', 'html'],
9+
coverageDirectory: '../../../coverage/libs/json-api/json-api-nestjs-microorm',
10+
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "@klerick/json-api-nestjs-microorm",
3+
"version": "0.0.1",
4+
"type": "commonjs",
5+
"main": "./src/index.js",
6+
"types": "./src/index.d.ts",
7+
"dependencies": {
8+
"tslib": "^2.3.0"
9+
}
10+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"name": "json-api-nestjs-microorm",
3+
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
4+
"sourceRoot": "libs/json-api/json-api-nestjs-microorm/src",
5+
"projectType": "library",
6+
"release": {
7+
"version": {
8+
"generatorOptions": {
9+
"packageRoot": "dist/{projectRoot}",
10+
"currentVersionResolver": "git-tag",
11+
"fallbackCurrentVersionResolver": "disk"
12+
}
13+
}
14+
},
15+
"tags": ["type:lib", "lib:json-api-nestjs", "lib:json-api-nestjs-microorm", "type:publish"],
16+
"targets": {
17+
"build": {
18+
"dependsOn": [
19+
{
20+
"projects": ["json-api-nestjs"],
21+
"target": "build",
22+
"params": "ignore"
23+
}
24+
],
25+
"executor": "@nx/js:tsc",
26+
"outputs": ["{options.outputPath}"],
27+
"options": {
28+
"outputPath": "dist/libs/json-api/json-api-nestjs-microorm",
29+
"tsConfig": "libs/json-api/json-api-nestjs-microorm/tsconfig.lib.json",
30+
"packageJson": "libs/json-api/json-api-nestjs-microorm/package.json",
31+
"main": "libs/json-api/json-api-nestjs-microorm/src/index.ts",
32+
"assets": ["libs/json-api/json-api-nestjs-microorm/*.md"]
33+
}
34+
},
35+
"nx-release-publish": {
36+
"options": {
37+
"packageRoot": "dist/{projectRoot}"
38+
}
39+
}
40+
},
41+
"implicitDependencies": ["json-api-nestjs"]
42+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './lib/micro-orm-json-api.module';
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export const ENTITY_METADATA_TOKEN = Symbol('ENTITY_METADATA_TOKEN');
2+
export const DEFAULT_ARRAY_TYPE = ['ArrayType', 'EnumArrayType'];
3+
export const CURRENT_DATA_SOURCE_TOKEN = Symbol('CURRENT_DATA_SOURCE_TOKEN');
4+
export const CURRENT_ENTITY_REPOSITORY = Symbol('CURRENT_ENTITY_REPOSITORY');
5+
export const CURRENT_ENTITY_MANAGER_TOKEN = Symbol(
6+
'CURRENT_ENTITY_MANAGER_TOKEN'
7+
);
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
import { FactoryProvider } from '@nestjs/common';
2+
import {
3+
EntityManager,
4+
MikroORM,
5+
EntityRepository,
6+
MetadataStorage,
7+
EntityClass,
8+
} from '@mikro-orm/core';
9+
import { kebabCase } from 'change-case-commonjs';
10+
import { getMikroORMToken } from '@mikro-orm/nestjs';
11+
12+
import {
13+
CheckRelationName,
14+
CHECK_RELATION_NAME,
15+
EntityParam,
16+
RunInTransaction,
17+
PrepareParams,
18+
RUN_IN_TRANSACTION_FUNCTION,
19+
ORM_SERVICE,
20+
MODULE_OPTIONS_TOKEN,
21+
ENTITY_PARAM_MAP,
22+
FIND_ONE_ROW_ENTITY,
23+
FindOneRowEntity,
24+
} from '@klerick/json-api-nestjs';
25+
import { getEntityName } from '@klerick/json-api-nestjs-shared';
26+
27+
import {
28+
getProps,
29+
getRelation,
30+
getPropsType,
31+
getPropsNullable,
32+
getPrimaryColumnName,
33+
getPrimaryColumnType,
34+
getRelationProperty,
35+
getArrayType,
36+
} from '../orm-helper';
37+
38+
import {
39+
ENTITY_METADATA_TOKEN,
40+
CURRENT_DATA_SOURCE_TOKEN,
41+
CURRENT_ENTITY_MANAGER_TOKEN,
42+
CURRENT_ENTITY_REPOSITORY,
43+
} from '../constants';
44+
import { MicroOrmService } from '../service';
45+
import { MicroOrmParam } from '../type';
46+
import { MicroOrmUtilService } from '../service/micro-orm-util.service';
47+
48+
export function CurrentMicroOrmProvider(
49+
connectionName?: string
50+
): FactoryProvider<MikroORM> {
51+
return {
52+
provide: CURRENT_DATA_SOURCE_TOKEN,
53+
useFactory: (mikroORM: MikroORM) => {
54+
return mikroORM;
55+
},
56+
inject: [connectionName ? getMikroORMToken(connectionName) : MikroORM],
57+
};
58+
}
59+
60+
export function CurrentEntityManager(): FactoryProvider<EntityManager> {
61+
return {
62+
provide: CURRENT_ENTITY_MANAGER_TOKEN,
63+
useFactory: (mikroORM: MikroORM) => mikroORM.em,
64+
inject: [CURRENT_DATA_SOURCE_TOKEN],
65+
};
66+
}
67+
68+
export function CurrentEntityRepository<E extends object>(
69+
entity: E
70+
): FactoryProvider<EntityRepository<E>> {
71+
return {
72+
provide: CURRENT_ENTITY_REPOSITORY,
73+
useFactory: (entityManager: EntityManager) =>
74+
entityManager.getRepository<E>(entity as unknown as EntityClass<E>),
75+
inject: [CURRENT_ENTITY_MANAGER_TOKEN],
76+
};
77+
}
78+
79+
export function CurrentEntityMetadata(): FactoryProvider<MetadataStorage> {
80+
return {
81+
provide: ENTITY_METADATA_TOKEN,
82+
useFactory: (mikroORM: MikroORM) => mikroORM.getMetadata(),
83+
inject: [CURRENT_DATA_SOURCE_TOKEN],
84+
};
85+
}
86+
87+
export function CheckRelationNameFactory<
88+
E extends object,
89+
IdKey extends string = 'id'
90+
>(): FactoryProvider<CheckRelationName<E>> {
91+
return {
92+
provide: CHECK_RELATION_NAME,
93+
inject: [MicroOrmUtilService],
94+
useFactory(microOrmUtilService: MicroOrmUtilService<E, IdKey>) {
95+
return (entity, value) =>
96+
!!microOrmUtilService.relationsName.find((i: any) => i === value);
97+
},
98+
};
99+
}
100+
101+
export function EntityPropsMap<E extends object>(entities: EntityClass<E>[]) {
102+
return {
103+
provide: ENTITY_PARAM_MAP,
104+
inject: [ENTITY_METADATA_TOKEN, MODULE_OPTIONS_TOKEN],
105+
useFactory: (
106+
metadataStorage: MetadataStorage,
107+
config: PrepareParams<MicroOrmParam>
108+
) => {
109+
const mapProperty = new Map<EntityClass<E>, EntityParam<E>>();
110+
const arrayConfig = config.options.arrayType;
111+
for (const item of entities) {
112+
const metadata = metadataStorage.get<E>(item);
113+
const className = getEntityName(item);
114+
mapProperty.set(item, {
115+
props: getProps(metadata),
116+
propsType: getPropsType(metadata, arrayConfig),
117+
propsNullable: getPropsNullable(metadata),
118+
primaryColumnName: getPrimaryColumnName(metadata),
119+
primaryColumnType: getPrimaryColumnType(metadata),
120+
propsArrayType: getArrayType(metadata),
121+
typeName: kebabCase(className),
122+
className: className,
123+
relations: getRelation(metadata),
124+
relationProperty: getRelationProperty(metadata),
125+
});
126+
}
127+
return mapProperty;
128+
},
129+
};
130+
}
131+
132+
export function RunInTransactionFactory(): FactoryProvider<RunInTransaction> {
133+
return {
134+
provide: RUN_IN_TRANSACTION_FUNCTION,
135+
inject: [],
136+
useFactory() {
137+
return async (callback) => callback();
138+
},
139+
};
140+
}
141+
142+
export function OrmServiceFactory() {
143+
return {
144+
provide: ORM_SERVICE,
145+
useClass: MicroOrmService,
146+
};
147+
}
148+
export function FindOneRowEntityFactory<
149+
E extends object,
150+
IdKey extends string
151+
>(): FactoryProvider<FindOneRowEntity<E>> {
152+
return {
153+
provide: FIND_ONE_ROW_ENTITY,
154+
inject: [MicroOrmUtilService],
155+
useFactory(microOrmUtilService: MicroOrmUtilService<E, IdKey>) {
156+
return async (entity, value) => {
157+
return microOrmUtilService
158+
.queryBuilder(entity)
159+
.where({
160+
[microOrmUtilService.currentPrimaryColumn]: value,
161+
})
162+
.getSingleResult();
163+
};
164+
},
165+
};
166+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './micro-orm-json-api.module';
2+
export * from './type';
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { DynamicModule } from '@nestjs/common';
2+
import { MikroOrmModule } from '@mikro-orm/nestjs';
3+
import {
4+
PrepareParams,
5+
MODULE_OPTIONS_TOKEN,
6+
NestProvider,
7+
} from '@klerick/json-api-nestjs';
8+
import { MicroOrmParam } from './type';
9+
10+
import {
11+
CurrentEntityManager,
12+
CurrentEntityMetadata,
13+
CurrentEntityRepository,
14+
CurrentMicroOrmProvider,
15+
OrmServiceFactory,
16+
RunInTransactionFactory,
17+
EntityPropsMap,
18+
CheckRelationNameFactory,
19+
FindOneRowEntityFactory,
20+
} from './factory';
21+
import { MicroOrmUtilService } from './service/micro-orm-util.service';
22+
23+
export class MicroOrmJsonApiModule {
24+
static module = 'microOrm' as const;
25+
static forRoot(options: PrepareParams<MicroOrmParam>): DynamicModule {
26+
const optionProvider = {
27+
provide: MODULE_OPTIONS_TOKEN,
28+
useValue: options,
29+
};
30+
31+
const microOrmModule = MikroOrmModule.forFeature(
32+
options.entities,
33+
options.connectionName
34+
);
35+
36+
const currentProvider = [
37+
...(options.providers || []),
38+
optionProvider,
39+
CurrentMicroOrmProvider(options.connectionName),
40+
CurrentEntityManager(),
41+
CurrentEntityMetadata(),
42+
RunInTransactionFactory(),
43+
EntityPropsMap(options.entities),
44+
];
45+
46+
const currentImport = [
47+
microOrmModule,
48+
...((options.imports || []) as DynamicModule[]),
49+
];
50+
51+
return {
52+
module: MicroOrmJsonApiModule,
53+
imports: currentImport,
54+
providers: currentProvider,
55+
exports: [...currentProvider, ...currentImport],
56+
};
57+
}
58+
59+
static getUtilProviders(entity: object): NestProvider {
60+
return [
61+
CurrentEntityRepository(entity),
62+
CheckRelationNameFactory(),
63+
OrmServiceFactory(),
64+
MicroOrmUtilService,
65+
FindOneRowEntityFactory(),
66+
];
67+
}
68+
}

0 commit comments

Comments
 (0)