Skip to content

Commit 4696f51

Browse files
committed
feat(json-api-nestjs): Microro orm
Create orm methode, create general transform service, use this service for swagger and zod
1 parent 18f4a0c commit 4696f51

File tree

46 files changed

+1058
-781
lines changed

Some content is hidden

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

46 files changed

+1058
-781
lines changed

apps/json-api-server/src/app/resources/controllers/entity-orm.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ import { BookList as tBookList } from '@nestjs-json-api/typeorm-database';
55
import { BookList as mkBookList } from '@nestjs-json-api/microorm-database';
66

77
const Users = process.env['ORM_TYPE'] === 'typeorm' ? tUsers : mkUsers;
8-
const BookList = process.env['ORM_TYPE'] === 'typeorm' ? tBookList : tBookList;
8+
const BookList = process.env['ORM_TYPE'] === 'typeorm' ? tBookList : mkBookList;
99

1010
export { Users, BookList };

apps/json-api-server/src/app/resources/controllers/extend-book-list/extend-book-list.controller.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { ParseUUIDPipe } from '@nestjs/common';
22
import { BookList } from '../entity-orm';
33
import { JsonApi, JsonBaseController } from '@klerick/json-api-nestjs';
44

5-
@JsonApi(BookList as typeof BookList, {
5+
@JsonApi(BookList as any, {
66
pipeForId: ParseUUIDPipe,
77
overrideRoute: 'override-book-list',
88
allowMethod: ['getOne', 'postOne', 'deleteOne'],

libs/json-api/json-api-nestjs-shared/src/lib/types/response-body.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
TypeOfArray,
66
ValueOf,
77
} from '.';
8+
import { Collection } from '@mikro-orm/core';
89

910
export type PageProps = {
1011
totalItems: number;
@@ -30,8 +31,14 @@ export type Attributes<D> = {
3031
[P in EntityProps<D>]?: D[P] extends EntityField ? D[P] : TypeOfArray<D[P]>;
3132
};
3233

34+
export type DataResult<E, S = string> = E extends unknown[]
35+
? MainData<S>[]
36+
: E extends Collection<any>
37+
? MainData<S>[]
38+
: MainData<S> | null;
39+
3340
export type Data<E, S = string> = {
34-
data?: E extends unknown[] ? MainData<S>[] : MainData<S> | null;
41+
data?: DataResult<E, S>;
3542
};
3643

3744
export type Relationships<T> = {

libs/json-api/json-api-nestjs-shared/src/lib/types/utils-string.type.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { Collection } from '@mikro-orm/core';
2+
13
export type KebabCase<S> = S extends `${infer C}${infer T}`
24
? KebabCase<T> extends infer U
35
? U extends string
@@ -15,6 +17,10 @@ export type KebabToCamelCase<S extends string> =
1517
? `${Capitalize<T>}${Capitalize<KebabToCamelCase<U>>}`
1618
: S;
1719

18-
export type TypeOfArray<T> = T extends (infer U)[] ? U : T;
20+
export type TypeOfArray<T> = T extends (infer U)[]
21+
? U
22+
: T extends Collection<infer U>
23+
? U
24+
: T;
1925

2026
export type ValueOf<T> = T[keyof T];

libs/json-api/json-api-nestjs/src/lib/constants/di.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,5 @@ export const ZOD_PATCH_RELATIONSHIP_SCHEMA = Symbol(
2828
);
2929
export const CURRENT_DATA_SOURCE_TOKEN = Symbol('CURRENT_DATA_SOURCE_TOKEN');
3030
export const CURRENT_ENTITY_REPOSITORY = Symbol('CURRENT_ENTITY_REPOSITORY');
31+
32+
export const ENTITY_MAP_PROPS = Symbol('ENTITY_MAP_PROPS');

libs/json-api/json-api-nestjs/src/lib/mock-utils/index.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,33 @@ import { DataType, IMemoryDb, newDb } from 'pg-mem';
22
import { readFileSync } from 'fs';
33
import { join } from 'path';
44
import { v4 } from 'uuid';
5+
// @ts-ignore
6+
import type { PGlite } from '@electric-sql/pglite';
7+
8+
export async function createAndPullSchemaBasePgLite(): Promise<PGlite> {
9+
const db = await Promise.all([
10+
import('@electric-sql/pglite'),
11+
// @ts-ignore
12+
import('@electric-sql/pglite/contrib/uuid_ossp'),
13+
]).then(
14+
([{ PGlite }, { uuid_ossp }]) =>
15+
new PGlite({
16+
extensions: { uuid_ossp },
17+
database: 'pgLite',
18+
username: 'postgres',
19+
})
20+
);
21+
22+
// await db.exec(
23+
// 'CREATE SCHEMA IF NOT EXISTS public; SET search_path TO public;'
24+
// );
25+
26+
// const dump = readFileSync(join(__dirname, 'db-for-test'), {
27+
// encoding: 'utf8',
28+
// });
29+
// await db.exec(dump);
30+
return db;
31+
}
532

633
export function createAndPullSchemaBase(): IMemoryDb {
734
const dump = readFileSync(join(__dirname, 'db-for-test'), {

libs/json-api/json-api-nestjs/src/lib/mock-utils/microrom/entities/notes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { Users, IUsers } from './index';
88
export class Notes {
99
@PrimaryKey({
1010
type: 'uuid',
11-
defaultRaw: 'uuid_generate_v4()',
11+
defaultRaw: 'gen_random_uuid()',
1212
})
1313
public id!: string;
1414

libs/json-api/json-api-nestjs/src/lib/mock-utils/microrom/index.ts

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import { DynamicModule } from '@nestjs/common';
2+
import { Test, TestingModule } from '@nestjs/testing';
23
import { MikroOrmModule } from '@mikro-orm/nestjs';
3-
import { MikroORM } from '@mikro-orm/core';
4+
import { EntityManager, MikroORM } from '@mikro-orm/core';
45
import { PostgreSqlDriver } from '@mikro-orm/postgresql';
6+
import { SqlHighlighter } from '@mikro-orm/sql-highlighter';
7+
import { QueryField } from '@klerick/json-api-nestjs-shared';
58

69
import { IMemoryDb } from 'pg-mem';
710

@@ -13,20 +16,54 @@ import {
1316
UserGroups,
1417
Users,
1518
} from './entities';
19+
import { ObjectLiteral } from '../../types';
20+
import { Query } from '../../modules/mixin/zod';
21+
22+
import {
23+
CurrentEntityManager,
24+
CurrentEntityMetadata,
25+
CurrentEntityRepository,
26+
CurrentMicroOrmProvider,
27+
OrmServiceFactory,
28+
EntityPropsMap,
29+
} from '../../modules/micro-orm/factory';
30+
import { MicroOrmUtilService } from '../../modules/micro-orm/service/micro-orm-util.service';
31+
import { CURRENT_ENTITY, GLOBAL_MODULE_OPTIONS_TOKEN } from '../../constants';
1632

1733
export * from './entities';
1834
export * from './utils';
1935

2036
export const entities = [Users, UserGroups, Roles, Comments, Addresses, Notes];
2137

38+
import { sharedConnect, initMikroOrm, pullAllData } from './utils';
39+
import { DEFAULT_ARRAY_TYPE } from '../../modules/micro-orm/constants';
40+
import { JsonApiTransformerService } from '../../modules/mixin/service/json-api-transformer.service';
41+
42+
export function mockDbPgLiteTestModule(dbName = `test_db_${Date.now()}`) {
43+
const mikroORM = {
44+
provide: MikroORM,
45+
useFactory: async () => {
46+
const knexInst = await sharedConnect();
47+
return initMikroOrm(knexInst, dbName);
48+
},
49+
};
50+
return {
51+
module: MikroOrmModule,
52+
providers: [mikroORM],
53+
exports: [mikroORM],
54+
};
55+
}
56+
2257
export function mockDBTestModule(db: IMemoryDb): DynamicModule {
2358
const mikroORM = {
2459
provide: MikroORM,
2560
useFactory: () =>
2661
db.adapters.createMikroOrm({
62+
highlighter: new SqlHighlighter(),
2763
entities: [Users, UserGroups, Roles, Comments, Addresses, Notes],
2864
driver: PostgreSqlDriver,
2965
allowGlobalContext: true,
66+
debug: ['query', 'query-params'],
3067
}),
3168
};
3269
return {
@@ -35,3 +72,81 @@ export function mockDBTestModule(db: IMemoryDb): DynamicModule {
3572
exports: [mikroORM],
3673
};
3774
}
75+
const readOnlyDbName = `readonly_db_${Date.now()}`;
76+
77+
export function dbRandomName(readOnly = false) {
78+
if (readOnly) {
79+
return readOnlyDbName;
80+
}
81+
return `test_db_${Date.now()}`;
82+
}
83+
84+
export async function pullData(em: EntityManager, count = 1) {
85+
for (let i = 0; i < count; i++) {
86+
await pullAllData(em);
87+
}
88+
}
89+
90+
export function getModuleForPgLite<E extends ObjectLiteral>(
91+
entity: E,
92+
dbName = `test_db_${Date.now()}`
93+
): Promise<TestingModule> {
94+
return Test.createTestingModule({
95+
imports: [mockDbPgLiteTestModule(dbName)],
96+
providers: [
97+
CurrentMicroOrmProvider(),
98+
CurrentEntityManager(),
99+
CurrentEntityMetadata(),
100+
CurrentEntityRepository(entity),
101+
MicroOrmUtilService,
102+
{
103+
provide: CURRENT_ENTITY,
104+
useValue: entity,
105+
},
106+
OrmServiceFactory(),
107+
EntityPropsMap(entities as any),
108+
{
109+
provide: GLOBAL_MODULE_OPTIONS_TOKEN,
110+
useValue: { options: { arrayType: DEFAULT_ARRAY_TYPE } },
111+
},
112+
JsonApiTransformerService,
113+
],
114+
}).compile();
115+
}
116+
117+
export function getModuleFor<E extends ObjectLiteral>(
118+
db: IMemoryDb,
119+
entity: E
120+
): Promise<TestingModule> {
121+
return Test.createTestingModule({
122+
imports: [mockDBTestModule(db)],
123+
providers: [
124+
CurrentMicroOrmProvider(),
125+
CurrentEntityManager(),
126+
CurrentEntityMetadata(),
127+
CurrentEntityRepository(entity),
128+
MicroOrmUtilService,
129+
{
130+
provide: CURRENT_ENTITY,
131+
useValue: entity,
132+
},
133+
OrmServiceFactory(),
134+
],
135+
}).compile();
136+
}
137+
138+
export function getDefaultQuery<R extends ObjectLiteral>(): Query<R> {
139+
return {
140+
[QueryField.filter]: {
141+
relation: null,
142+
target: null,
143+
},
144+
[QueryField.fields]: null,
145+
[QueryField.include]: null,
146+
[QueryField.sort]: null,
147+
[QueryField.page]: {
148+
size: 1,
149+
number: 1,
150+
},
151+
} satisfies Query<R>;
152+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from './provider-entities';
22
export * from './pull-data';
3+
export * from './init-db';

libs/json-api/json-api-nestjs/src/lib/mock-utils/microrom/utils/pull-data.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export async function pullNote() {
3838
export async function pullRole() {
3939
const role = new Roles();
4040
role.key = faker.string.alphanumeric(5);
41-
role.name = faker.string.alphanumeric(5);
41+
role.name = faker.word.words();
4242
return role;
4343
}
4444

@@ -104,6 +104,7 @@ export async function pullAllData(em: EntityManager) {
104104

105105
managerUser.addresses = address2;
106106
managerUser.userGroup = userGroup3;
107+
managerUser.roles.add(role1, role2);
107108

108109
await em.persistAndFlush([
109110
user,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy