wip: example typeorm

This commit is contained in:
Supan Adit Pratama 2024-11-10 11:05:35 +07:00
parent 291e656757
commit 3450fd026a
13 changed files with 146 additions and 52 deletions

View File

@ -1 +0,0 @@
export * from './pagination.entity';

View File

@ -1,13 +0,0 @@
export interface IPaginationEntity<T> {
// Data related
data: T[];
totalData: number;
// Page related
totalPage: number;
currentPage: number;
lastPage: number;
perPage: number;
nextPage: number | null;
previousPage: number | null;
}

View File

@ -1,8 +1,6 @@
export * from './constants'; export * from './constants';
export * from './dto'; export * from './dto';
export * from './entities';
export * from './executors'; export * from './executors';
export * from './interfaces'; export * from './interfaces';
export * from './processes'; export * from './processes';
export * from './skeleton-crud.controller'; export * from './skeleton-crud.controller';

View File

@ -1,8 +1,13 @@
import { EntityTarget, FindOptionsWhere, ObjectLiteral } from "typeorm"; import { EntityTarget, ObjectLiteral } from 'typeorm';
export interface TypeORMModuleOptions<T extends ObjectLiteral> { export interface TypeORMModuleOptions<T extends ObjectLiteral> {
entity: EntityTarget<T>; entity: EntityTarget<T>;
processCreate?;
processDelete?;
processList?;
processPagination?;
processRead?;
processUpdate?;
synchronize?: boolean; synchronize?: boolean;
entities: string[]; entities?: string[];
uniqueWhereClause: FindOptionsWhere<T>;
} }

View File

@ -9,6 +9,6 @@ export class TypeORMDeleteProcess<T>
public identityKey: string = 'id'; public identityKey: string = 'id';
async process() { async process() {
this.result = await this.service.getRepository().delete(this.uniqueWhereClause); this.result = await this.service.getRepository().delete(this.identityData);
} }
} }

View File

@ -6,8 +6,6 @@ export class TypeORMReadProcess<T> extends TypeORMProcess<T> implements ReadProc
public identityKey: string = 'id'; public identityKey: string = 'id';
async process() { async process() {
this.result = await this.service.getRepository().findOne({ this.result = await this.service.getRepository().findOne(this.identityData);
where: this.uniqueWhereClause,
});
} }
} }

View File

@ -1,16 +1,10 @@
import { DefaultProcess } from '@aditama-labs/nest-autocrud/skeleton'; import { DefaultProcess } from '@aditama-labs/nest-autocrud/skeleton';
import { Inject, Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { TypeORMService } from '../typeorm.service'; import { TypeORMService } from '../typeorm.service';
import { TYPEORM_WHERE_CLAUSE } from '../constants';
import { FindOptionsWhere } from 'typeorm';
@Injectable() @Injectable()
export class TypeORMProcess<T> extends DefaultProcess { export class TypeORMProcess<T> extends DefaultProcess {
constructor( constructor(public service: TypeORMService<T>) {
public service: TypeORMService<T>,
@Inject(TYPEORM_WHERE_CLAUSE)
public uniqueWhereClause: FindOptionsWhere<T>,
) {
super(); super();
} }
} }

View File

@ -12,6 +12,6 @@ export class TypeORMUpdateProcess<T>
async process() { async process() {
this.result = await this.service this.result = await this.service
.getRepository() .getRepository()
.update(this.uniqueWhereClause, this.payload); .update(this.identityData, this.payload);
} }
} }

View File

@ -1,12 +1,25 @@
import { DynamicModule, Module } from '@nestjs/common'; import { DynamicModule, Module } from '@nestjs/common';
import { DataSource, ObjectLiteral } from 'typeorm'; import { DataSource, ObjectLiteral } from 'typeorm';
import { import { TYPEORM_DATASOURCE, TYPEORM_REPOSITORY } from './constants';
TYPEORM_DATASOURCE,
TYPEORM_REPOSITORY,
TYPEORM_WHERE_CLAUSE,
} from './constants';
import { TypeORMModuleOptions } from './interfaces'; import { TypeORMModuleOptions } from './interfaces';
import { TypeORMService } from './typeorm.service'; import { TypeORMService } from './typeorm.service';
import {
CREATE_PROCESS,
DELETE_PROCESS,
LIST_PROCESS,
PAGINATION_PROCESS,
READ_PROCESS,
UPDATE_PROCESS,
} from '@aditama-labs/nest-autocrud/skeleton';
import {
TypeORMCreateProcess,
TypeORMDeleteProcess,
TypeORMListProcess,
TypeORMPaginationProcess,
TypeORMReadProcess,
TypeORMUpdateProcess,
} from './processes';
import { TypeOrmModule } from '@nestjs/typeorm';
const getDatabaseCredential = ( const getDatabaseCredential = (
synchronize?: boolean, synchronize?: boolean,
@ -19,8 +32,9 @@ const getDatabaseCredential = (
entityList = entities; entityList = entities;
} }
let protocol; const defaultProtocol = url.protocol.substring(0, url.protocol.length - 1);
switch (url.protocol) { let protocol = defaultProtocol;
switch (defaultProtocol) {
case 'postgresql': case 'postgresql':
protocol = 'postgres'; protocol = 'postgres';
break; break;
@ -49,6 +63,27 @@ const getDatabaseCredential = (
@Module({}) @Module({})
export class TypeORMModule { export class TypeORMModule {
private static autoPresetProvider(providers, option, key, preset) {
if (option) {
providers = [
...providers,
{
provide: key,
useClass: option,
},
];
} else {
providers = [
...providers,
{
provide: key,
useClass: preset,
},
];
}
return providers;
}
static forRoot<T extends ObjectLiteral>( static forRoot<T extends ObjectLiteral>(
options: TypeORMModuleOptions<T>, options: TypeORMModuleOptions<T>,
): DynamicModule { ): DynamicModule {
@ -65,22 +100,69 @@ export class TypeORMModule {
}, },
{ {
provide: TYPEORM_REPOSITORY, provide: TYPEORM_REPOSITORY,
useFactory: (dataSource: DataSource) => useFactory: (dataSource: DataSource) => {
dataSource.getRepository(options.entity), return dataSource.getRepository(options.entity);
},
inject: [TYPEORM_DATASOURCE], inject: [TYPEORM_DATASOURCE],
}, },
]; ];
providers = TypeORMModule.autoPresetProvider(
providers,
options.processCreate,
CREATE_PROCESS,
TypeORMCreateProcess,
);
providers = TypeORMModule.autoPresetProvider(
providers,
options.processDelete,
DELETE_PROCESS,
TypeORMDeleteProcess,
);
providers = TypeORMModule.autoPresetProvider(
providers,
options.processList,
LIST_PROCESS,
TypeORMListProcess,
);
providers = TypeORMModule.autoPresetProvider(
providers,
options.processPagination,
PAGINATION_PROCESS,
TypeORMPaginationProcess,
);
providers = TypeORMModule.autoPresetProvider(
providers,
options.processRead,
READ_PROCESS,
TypeORMReadProcess,
);
providers = TypeORMModule.autoPresetProvider(
providers,
options.processUpdate,
UPDATE_PROCESS,
TypeORMUpdateProcess,
);
return { return {
module: TypeORMModule, module: TypeORMModule,
providers: [ providers: [...providers],
...providers, exports: [
{ TYPEORM_DATASOURCE,
provide: TYPEORM_WHERE_CLAUSE, TYPEORM_REPOSITORY,
useValue: options.uniqueWhereClause, // List of Process
}, CREATE_PROCESS,
DELETE_PROCESS,
LIST_PROCESS,
PAGINATION_PROCESS,
READ_PROCESS,
UPDATE_PROCESS,
], ],
exports: providers,
}; };
} }
} }

View File

@ -1,12 +1,10 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { CustomModule } from './example/prisma/custom/custom.module'; import { CustomModule } from './example/prisma/custom/custom.module';
import { SimpleModule } from './example/prisma/simple/simple.module'; import { SimpleModule } from './example/prisma/simple/simple.module';
import { SimpleTypeORMModule } from './example/typeorm/simple.module';
@Module({ @Module({
imports: [ imports: [SimpleTypeORMModule],
SimpleModule,
CustomModule,
],
controllers: [], controllers: [],
providers: [], providers: [],
}) })

View File

@ -0,0 +1,13 @@
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity('account')
export class UserEntity {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ type: String })
username: string;
@Column({ type: String })
name: string;
}

View File

@ -0,0 +1,5 @@
import { SkeletonCRUDController } from '@aditama-labs/nest-autocrud/skeleton';
import { Controller } from '@nestjs/common';
@Controller('example/simple/typeorm')
export class SimpleTypeORMController extends SkeletonCRUDController {}

View File

@ -0,0 +1,15 @@
import { TypeORMModule } from '@aditama-labs/nest-autocrud/typeorm';
import { Module } from '@nestjs/common';
import { SimpleTypeORMController } from './simple.controller';
import { UserEntity } from './entities/user.entity';
@Module({
imports: [
TypeORMModule.forRoot<UserEntity>({
entity: UserEntity,
}),
],
controllers: [SimpleTypeORMController],
providers: [],
})
export class SimpleTypeORMModule {}