Skip to content

Commit

Permalink
Merge 412238d into 77bb83a
Browse files Browse the repository at this point in the history
  • Loading branch information
klalex committed Dec 19, 2020
2 parents 77bb83a + 412238d commit 7227f56
Show file tree
Hide file tree
Showing 34 changed files with 561 additions and 280 deletions.
3 changes: 2 additions & 1 deletion integration/crud-typeorm/companies/companies.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { serialize } from './responses';

@Crud({
model: {
type: Company,
type: Company
},
serialize,
routes: {
Expand All @@ -18,6 +18,7 @@ import { serialize } from './responses';
},
query: {
alwaysPaginate: false,
softDelete: true,
allow: ['name'],
join: {
users: {
Expand Down
5 changes: 4 additions & 1 deletion integration/crud-typeorm/companies/company.entity.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CrudValidationGroups } from '@nestjsx/crud';
import { Entity, Column, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
import { Entity, Column, OneToMany, PrimaryGeneratedColumn, DeleteDateColumn } from 'typeorm';
import {
IsOptional,
IsString,
Expand Down Expand Up @@ -43,6 +43,9 @@ export class Company extends BaseEntity {
@Column({ type: 'text', nullable: true, default: null })
description: string;

@DeleteDateColumn({ nullable: true })
deletedAt?: Date;

/**
* Relations
*/
Expand Down
2 changes: 1 addition & 1 deletion integration/crud-typeorm/seeds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class Seeds1544303473346 implements MigrationInterface {
{ name: 'Name6', domain: 'Domain6' },
{ name: 'Name7', domain: 'Domain7' },
{ name: 'Name8', domain: 'Domain8' },
{ name: 'Name9', domain: 'Domain9' },
{ name: 'Name9', domain: 'Domain9', deletedAt: new Date() },
{ name: 'Name10', domain: 'Domain10' },
]);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Entity, Column, OneToOne } from 'typeorm';
import { Entity, Column, OneToOne, DeleteDateColumn } from 'typeorm';
import { IsOptional, IsString, MaxLength } from 'class-validator';

import { BaseEntity } from '../base-entity';
Expand All @@ -12,6 +12,9 @@ export class UserProfile extends BaseEntity {
@Column({ type: 'varchar', length: 32, nullable: true, default: null })
name: string;

@DeleteDateColumn({ nullable: true })
deletedAt?: Date;

/**
* Relations
*/
Expand Down
4 changes: 4 additions & 0 deletions integration/crud-typeorm/users/user.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
OneToMany,
ManyToOne,
ManyToMany,
DeleteDateColumn,
} from 'typeorm';
import {
IsOptional,
Expand Down Expand Up @@ -65,6 +66,9 @@ export class User extends BaseEntity {
@Column({ nullable: false })
companyId?: number;

@DeleteDateColumn({ nullable: true })
deletedAt?: Date;

/**
* Relations
*/
Expand Down
1 change: 1 addition & 0 deletions integration/crud-typeorm/users/users.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { UsersService } from './users.service';
},
},
query: {
softDelete: true,
join: {
company: {
exclude: ['description'],
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@
"peerDependencies": {},
"optionalDependencies": {},
"dependencies": {
"@nestjs/common": "7.0.3",
"@nestjs/core": "7.0.3",
"@nestjs/common": "^7.5.1",
"@nestjs/core": "^7.5.1",
"@nestjs/platform-express": "7.0.3",
"@nestjs/swagger": "4.4.0",
"@nestjs/testing": "7.0.3",
"@nestjs/typeorm": "7.0.0",
"@nestjs/typeorm": "^7.1.5",
"@nuxtjs/opencollective": "0.2.2",
"@types/jest": "24.0.18",
"@types/node": "12.7.5",
Expand All @@ -83,7 +83,7 @@
"npm-check": "5.9.0",
"nps": "5.9.8",
"nps-utils": "1.7.0",
"pg": "7.12.1",
"pg": "^8.4.2",
"pluralize": "^8.0.0",
"prettier": "1.18.2",
"pretty-quick": "1.11.1",
Expand All @@ -100,7 +100,7 @@
"tsconfig-paths": "3.9.0",
"tslint": "5.20.0",
"tslint-config-prettier": "1.18.0",
"typeorm": "0.2.19",
"typeorm": "0.2.29",
"typescript": "3.6.3",
"validate-commit-msg": "2.14.0"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ export interface CreateQueryParams {
offset?: number;
page?: number;
resetCache?: boolean;
includeDeleted?: number;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ export interface ParsedRequestParams {
offset: number;
page: number;
cache: number;
includeDeleted: number;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ export interface RequestQueryBuilderOptions {
offset?: string | string[];
page?: string | string[];
cache?: string | string[];
includeDeleted?: string | string[];
};
}
12 changes: 11 additions & 1 deletion packages/crud-request/src/request-query.builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export class RequestQueryBuilder {
offset: 'offset',
page: 'page',
cache: 'cache',
includeDeleted: 'include_deleted',
},
};
private paramNames: {
Expand Down Expand Up @@ -166,6 +167,11 @@ export class RequestQueryBuilder {
return this;
}

setIncludeDeleted(n: number): this {
this.setNumeric(n, 'includeDeleted');
return this;
}

cond(
f: QueryFilter | QueryFilterArr,
cond: 'filter' | 'or' | 'search' = 'search',
Expand Down Expand Up @@ -212,6 +218,7 @@ export class RequestQueryBuilder {
if (params.resetCache) {
this.resetCache();
}
this.setIncludeDeleted(params.includeDeleted);
return this;
}

Expand Down Expand Up @@ -241,7 +248,10 @@ export class RequestQueryBuilder {
}
}

private setNumeric(n: number, cond: 'limit' | 'offset' | 'page' | 'cache'): void {
private setNumeric(
n: number,
cond: 'limit' | 'offset' | 'page' | 'cache' | 'includeDeleted',
): void {
if (!isNil(n)) {
validateNumeric(n, cond);
this.queryObject[this.paramNames[cond]] = n;
Expand Down
9 changes: 7 additions & 2 deletions packages/crud-request/src/request-query.parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export class RequestQueryParser implements ParsedRequestParams {
public offset: number;
public page: number;
public cache: number;
public includeDeleted: number;

private _params: any;
private _query: any;
Expand Down Expand Up @@ -80,6 +81,7 @@ export class RequestQueryParser implements ParsedRequestParams {
offset: this.offset,
page: this.page,
cache: this.cache,
includeDeleted: this.includeDeleted,
};
}

Expand All @@ -91,7 +93,6 @@ export class RequestQueryParser implements ParsedRequestParams {
this._query = query;
this._paramNames = paramNames;
let searchData = this._query[this.getParamNames('search')[0]];

this.search = this.parseSearchQueryParam(searchData) as any;
if (isNil(this.search)) {
this.filter = this.parseQueryParam(
Expand Down Expand Up @@ -120,6 +121,10 @@ export class RequestQueryParser implements ParsedRequestParams {
'cache',
this.numericParser.bind(this, 'cache'),
)[0];
this.includeDeleted = this.parseQueryParam(
'includeDeleted',
this.numericParser.bind(this, 'includeDeleted'),
)[0];
}
}

Expand Down Expand Up @@ -311,7 +316,7 @@ export class RequestQueryParser implements ParsedRequestParams {
}

private numericParser(
num: 'limit' | 'offset' | 'page' | 'cache',
num: 'limit' | 'offset' | 'page' | 'cache' | 'includeDeleted',
data: string,
): number {
const val = this.parseValue(data);
Expand Down
2 changes: 1 addition & 1 deletion packages/crud-request/src/request-query.validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export function validateSort(sort: QuerySort): void {

export function validateNumeric(
val: number,
num: 'limit' | 'offset' | 'page' | 'cache' | string,
num: 'limit' | 'offset' | 'page' | 'cache' | 'include_deleted' | string,
): void {
if (!isNumber(val)) {
throw new RequestQueryException(`Invalid ${num}. Number expected`);
Expand Down
3 changes: 2 additions & 1 deletion packages/crud-request/test/request-query.builder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,9 +335,10 @@ describe('#request-query', () => {
.setPage(3)
.sortBy({ field: 'foo', order: 'DESC' })
.resetCache()
.setIncludeDeleted(1)
.query(false);
const expected =
'fields=foo,bar&filter[0]=is||notnull&or[0]=ok||ne||false&join[0]=voo||h,data&limit=1&offset=2&page=3&sort[0]=foo,DESC&cache=0';
'fields=foo,bar&filter[0]=is||notnull&or[0]=ok||ne||false&join[0]=voo||h,data&limit=1&offset=2&page=3&sort[0]=foo,DESC&cache=0&include_deleted=1';
expect(test).toBe(expected);
});
});
Expand Down
1 change: 1 addition & 0 deletions packages/crud-request/test/request-query.parser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ describe('#request-query', () => {
offset: undefined,
page: undefined,
cache: undefined,
includeDeleted: undefined,
};
const test = qp.getParsed();
expect(test).toMatchObject(expected);
Expand Down
39 changes: 34 additions & 5 deletions packages/crud-typeorm/src/typeorm-crud.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export class TypeOrmCrudService<T> extends CrudService<T> {
protected dbName: ConnectionOptions['type'];
protected entityColumns: string[];
protected entityPrimaryColumns: string[];
protected entityHasDeleteColumn: boolean = false;
protected entityColumnsHash: ObjectLiteral = {};
protected entityRelationsHash: Map<string, IAllowedRelation> = new Map();
protected sqlInjectionRegEx: RegExp[] = [
Expand Down Expand Up @@ -193,6 +194,16 @@ export class TypeOrmCrudService<T> extends CrudService<T> {
}
}

/**
* Recover one
* @param req
* @param dto
*/
public async recoverOne(req: CrudRequest): Promise<T> {
const found = await this.getOneOrFail(req, false, true);
return this.repo.recover(found);
}

/**
* Replace one
* @param req
Expand Down Expand Up @@ -240,8 +251,10 @@ export class TypeOrmCrudService<T> extends CrudService<T> {
const toReturn = returnDeleted
? plainToClass(this.entityType, { ...found })
: undefined;
const deleted = await this.repo.remove(found);

const deleted =
req.options.query.softDelete === true
? await this.repo.softRemove(found)
: await this.repo.remove(found);
return toReturn;
}

Expand All @@ -268,6 +281,7 @@ export class TypeOrmCrudService<T> extends CrudService<T> {
parsed: ParsedRequestParams,
options: CrudRequestOptions,
many = true,
withDeleted = false,
): Promise<SelectQueryBuilder<T>> {
// create query builder
const builder = this.repo.createQueryBuilder(this.alias);
Expand Down Expand Up @@ -307,6 +321,13 @@ export class TypeOrmCrudService<T> extends CrudService<T> {
}
}

// if soft deleted is enabled add where statement to filter deleted records
if (this.entityHasDeleteColumn && options.query.softDelete) {
if (parsed.includeDeleted === 1 || withDeleted) {
builder.withDeleted();
}
}

/* istanbul ignore else */
if (many) {
// set sort (order by)
Expand Down Expand Up @@ -376,19 +397,27 @@ export class TypeOrmCrudService<T> extends CrudService<T> {
this.entityPrimaryColumns = this.repo.metadata.columns
.filter((prop) => prop.isPrimary)
.map((prop) => prop.propertyName);
this.entityHasDeleteColumn =
this.repo.metadata.columns.filter((prop) => prop.isDeleteDate).length > 0;
}

protected async getOneOrFail(req: CrudRequest, shallow = false): Promise<T> {
protected async getOneOrFail(
req: CrudRequest,
shallow = false,
withDeleted = false,
): Promise<T> {
const { parsed, options } = req;
const builder = shallow
? this.repo.createQueryBuilder(this.alias)
: await this.createBuilder(parsed, options);
: await this.createBuilder(parsed, options, true, withDeleted);

if (shallow) {
this.setSearchCondition(builder, parsed.search);
}

const found = await builder.getOne();
const found = withDeleted
? await builder.withDeleted().getOne()
: await builder.getOne();

if (!found) {
this.throwNotFoundException(this.alias);
Expand Down

0 comments on commit 7227f56

Please sign in to comment.