Skip to content

Commit

Permalink
chore: add quickstart example
Browse files Browse the repository at this point in the history
  • Loading branch information
hodfords-phuong-vo-be committed Sep 23, 2024
1 parent 6540adf commit 1481a59
Show file tree
Hide file tree
Showing 22 changed files with 2,023 additions and 646 deletions.
102 changes: 0 additions & 102 deletions .eslintrc.js

This file was deleted.

22 changes: 12 additions & 10 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ on:
branches:
- main
jobs:
lint:
uses: hodfords-solutions/actions/.github/workflows/lint.yaml@main
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '22.x'
registry-url: 'https://registry.npmjs.org'
- run: sh scripts/publish.sh
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
uses: hodfords-solutions/actions/.github/workflows/publish.yaml@main
with:
build_path: dist/lib
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
update-docs:
uses: hodfords-solutions/actions/.github/workflows/update-doc.yaml@main
needs: build
secrets:
DOC_SSH_PRIVATE_KEY: ${{ secrets.DOC_SSH_PRIVATE_KEY }}
12 changes: 0 additions & 12 deletions .prettierrc

This file was deleted.

6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,17 @@ export class YourService extends TransactionService {
##### your-controller.controller.ts

```typescript
import { DataSource } from 'typeorm';

@Controller()
export class SomeController {
constructor(
private readonly yourService: YourService,
private connection: Connection
private dataSource: DataSource
) {}

async method(payload: SomePayload): Promise<SomeResponse> {
return this.connection.transaction(async (entityManager) => {
return this.dataSource.transaction(async (entityManager) => {
return await this.yourService
.withTransaction(entityManager, { excluded: [CacheService] })
.theMethodWillUseTransaction(payload);
Expand Down
1 change: 1 addition & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require("@hodfords/nestjs-eslint-config");
60 changes: 32 additions & 28 deletions lib/services/transaction.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common';
import { PARAMTYPES_METADATA, SELF_DECLARED_DEPS_METADATA } from '@nestjs/common/constants';
import { ModuleRef } from '@nestjs/core';
import { isString } from 'lodash';
import { isFunction, isString } from 'lodash';
import { EntityManager, Repository } from 'typeorm';
import { ClassType } from '../types/class.type';
import { ForwardRef } from '../types/forward-ref.type';
Expand All @@ -16,7 +16,7 @@ export class TransactionService {
protected excluded: ExcludeType[] = [];

public withTransaction(manager: EntityManager, transactionOptions: TransactionOption = {}): this {
let cache: Map<string, any> = new Map();
const cache: Map<string, any> = new Map();
return this.findArgumentsForProvider(
this.constructor as ClassType<this>,
manager,
Expand All @@ -29,7 +29,7 @@ export class TransactionService {
);
}

private refId(param: ProviderParam) {
private refId(param: ProviderParam): string {
return `${(param as ClassType).name}-ref`;
}

Expand All @@ -39,17 +39,18 @@ export class TransactionService {
manager: EntityManager,
excluded: ExcludeType[],
cache: Map<string, any>
) {
let tmpParam = (param as ForwardRef).forwardRef();
tmpParam = this.getOverrideProvider(tmpParam);
): any {
const tmpParam: ClassType = this.getOverrideProvider((param as ForwardRef).forwardRef());
const id = this.refId(instanceHost);

if (cache.has(this.refId(tmpParam))) {
return cache.get(this.refId(tmpParam));
}
if (!cache.has(id)) {
cache.set(id, new (instanceHost as ClassType)());
}
return this.findArgumentsForProvider(tmpParam as ClassType, manager, excluded, cache);

return this.findArgumentsForProvider(tmpParam, manager, excluded, cache);
}

private getArgument(
Expand All @@ -71,33 +72,31 @@ export class TransactionService {
} else if ((param as ForwardRef).forwardRef) {
return this.resolveForwardRefArgument(param, instanceHost, manager, excluded, cache);
}
const isExcluded =
excluded.length > 0 &&
excluded.some((ex) => {
if (isString(ex)) {
return ex === id;
}
return (ex as ClassType).name === id;
});
const isExcluded = excluded.some((item) => {
const excludedId = isString(item) ? item : (item as ClassType).name;
return excludedId === id;
});

if (id === ModuleRef.name) {
return TransactionService.moduleRef;
}
if (isExcluded) {
/// Returns current instance of service, if it is excluded
return TransactionService.moduleRef.get(tmpParam, { strict: false });
}
let argument: Repository<any>;
if (cache.has(id)) {
return cache.get(id);
}

let argument: Repository<any>;
const canBeRepository = id.includes('Repository') || this.hasRepositoryProperties(param);
if (isString(tmpParam) || canBeRepository) {
argument = this.getRepositoryArgument(canBeRepository, tmpParam, manager);
} else {
tmpParam = this.getOverrideProvider(tmpParam);
argument = this.findArgumentsForProvider(tmpParam as ClassType, manager, excluded, cache);
}

cache.set(id, argument);
return argument;
}
Expand All @@ -110,42 +109,47 @@ export class TransactionService {
);
}

private getOverrideProvider(param: string | ClassType) {
private getOverrideProvider(param: string | ClassType): any {
return TransactionService.moduleRef.get(param, { strict: false }).constructor;
}

private getRepositoryArgument(canBeRepository: boolean, tmpParam: string | ClassType, manager: EntityManager) {
private getRepositoryArgument(
canBeRepository: boolean,
tmpParam: string | ClassType,
manager: EntityManager
): Repository<any> {
let dependency: Repository<any>;
let isCustomRepository = false;

try {
if (canBeRepository) {
tmpParam = isString(tmpParam)
? TransactionService.moduleRef.get(tmpParam, { strict: false })
: tmpParam;
const repository = TransactionService.moduleRef.get(tmpParam, { strict: false });
dependency = manager.withRepository(repository);
tmpParam =
isString(tmpParam) || isFunction(tmpParam)
? TransactionService.moduleRef.get(tmpParam, { strict: false })
: tmpParam;
dependency = manager.withRepository(tmpParam as any);
isCustomRepository = true;
}
} catch (error) {
} catch {
dependency = TransactionService.moduleRef.get(tmpParam, { strict: false });
}

const isRepository = (dependency instanceof Repository || canBeRepository) && !isCustomRepository;
if (isRepository) {
// If the dependency is a repository, make a new repository with the desired transaction manager.
const entity: any = dependency.metadata.target;
return manager.getRepository(entity);
} else {
// The dependency is not a repository, use it directly.
return dependency;
}

return dependency;
}

private findArgumentsForProvider(
constructor: ClassType,
manager: EntityManager,
excluded: ExcludeType[],
cache: Map<string, any>
) {
): any {
const args: any[] = [];
const keys = Reflect.getMetadataKeys(constructor);

Expand Down
3 changes: 1 addition & 2 deletions lib/transaction.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ExcludeType } from './types/exclude.type';

@Module({})
export class TransactionModule {
constructor(private moduleRef: ModuleRef) {
constructor(moduleRef: ModuleRef) {
TransactionService.moduleRef = moduleRef;
}

Expand All @@ -15,7 +15,6 @@ export class TransactionModule {
provide: EXCLUDED_OPTIONS,
useValue: excluded
};

return {
module: TransactionModule,
providers: [excludedProviders],
Expand Down
21 changes: 21 additions & 0 deletions nest-cli.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"collection": "@nestjs/schematics",
"sourceRoot": "samples/quickstart/src",
"projects": {
"nestjs-transaction": {
"type": "library",
"root": "lib",
"entryFile": "index",
"sourceRoot": "lib"
}
},
"compilerOptions": {
"webpack": false,
"assets": [
{
"include": "../lib/public/**",
"watchAssets": true
}
]
}
}
Loading

0 comments on commit 1481a59

Please sign in to comment.