first commit

This commit is contained in:
Bastian Wagner
2026-07-31 21:02:47 +02:00
commit 6bea4f766a
512 changed files with 64459 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
import { instanceToPlain } from 'class-transformer';
import { AfterLoad, BaseEntity } from 'typeorm';
export class EntityHelper extends BaseEntity {
__entity?: string;
@AfterLoad()
setEntityName() {
this.__entity = this.constructor.name;
}
toJSON() {
return instanceToPlain(this);
}
}

View File

@@ -0,0 +1,11 @@
import { IPaginationOptions } from './types/pagination-options';
export const infinityPagination = <T>(
data: T[],
options: IPaginationOptions,
) => {
return {
data,
hasNextPage: data.length === options.limit,
};
};

View File

@@ -0,0 +1,7 @@
export declare type DeepPartial<T> = {
[P in keyof T]?: T[P] extends Array<infer U>
? Array<DeepPartial<U>>
: T[P] extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: DeepPartial<T[P]> | T[P];
};

View File

@@ -0,0 +1,3 @@
import { FindOptionsWhere } from 'typeorm';
export type EntityCondition<T> = FindOptionsWhere<T>;

View File

@@ -0,0 +1,5 @@
import { EntityCondition } from './entity-condition.type';
export type FindOptions<T> = {
where: EntityCondition<T>[] | EntityCondition<T>;
};

View File

@@ -0,0 +1,4 @@
export interface IPaginationOptions {
page: number;
limit: number;
}

View File

@@ -0,0 +1,30 @@
import {
HttpException,
HttpStatus,
ValidationError,
ValidationPipeOptions,
} from '@nestjs/common';
const validationOptions: ValidationPipeOptions = {
transform: true,
whitelist: true,
errorHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY,
exceptionFactory: (errors: ValidationError[]) =>
new HttpException(
{
status: HttpStatus.UNPROCESSABLE_ENTITY,
errors: errors.reduce(
(accumulator, currentValue) => ({
...accumulator,
[currentValue.property]: Object.values(
currentValue.constraints,
).join(', '),
}),
{},
),
},
HttpStatus.UNPROCESSABLE_ENTITY,
),
};
export default validationOptions;

View File

@@ -0,0 +1,32 @@
import {
ValidatorConstraint,
ValidatorConstraintInterface,
} from 'class-validator';
import { DataSource } from 'typeorm';
import { InjectDataSource } from '@nestjs/typeorm';
import { ValidationArguments } from 'class-validator/types/validation/ValidationArguments';
import { Injectable } from '@nestjs/common';
@Injectable()
@ValidatorConstraint({ name: 'IsExist', async: true })
export class IsExist implements ValidatorConstraintInterface {
constructor(
@InjectDataSource()
private dataSource: DataSource,
) {}
async validate(value: string, validationArguments: ValidationArguments) {
const repository = validationArguments.constraints[0];
const pathToProperty = validationArguments.constraints[1];
const entity: unknown = await this.dataSource
.getRepository(repository)
.findOne({
where: {
[pathToProperty ? pathToProperty : validationArguments.property]:
pathToProperty ? value?.[pathToProperty] : value,
},
});
return Boolean(entity);
}
}

View File

@@ -0,0 +1,39 @@
import {
ValidatorConstraint,
ValidatorConstraintInterface,
} from 'class-validator';
import { DataSource } from 'typeorm';
import { ValidationArguments } from 'class-validator/types/validation/ValidationArguments';
import { Injectable } from '@nestjs/common';
import { InjectDataSource } from '@nestjs/typeorm';
type ValidationEntity =
| {
id?: number | string;
}
| undefined;
@Injectable()
@ValidatorConstraint({ name: 'IsNotExist', async: true })
export class IsNotExist implements ValidatorConstraintInterface {
constructor(
@InjectDataSource()
private dataSource: DataSource,
) {}
async validate(value: string, validationArguments: ValidationArguments) {
const repository = validationArguments.constraints[0] as string;
const currentValue = validationArguments.object as ValidationEntity;
const entity = (await this.dataSource.getRepository(repository).findOne({
where: {
[validationArguments.property]: value,
},
})) as ValidationEntity;
if (entity?.id === currentValue?.id) {
return true;
}
return !entity;
}
}