Skip to content

Commit

Permalink
Merge 501368d into 2fae216
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelyali committed May 8, 2020
2 parents 2fae216 + 501368d commit 3d5e73a
Show file tree
Hide file tree
Showing 20 changed files with 160 additions and 17 deletions.
2 changes: 2 additions & 0 deletions integration/crud-typeorm/app.module.ts
Expand Up @@ -8,6 +8,7 @@ import { CompaniesModule } from './companies/companies.module';
import { ProjectsModule } from './projects/projects.module';
import { UsersModule } from './users/users.module';
import { DevicesModule } from './devices/devices.module';
import { NotesModule } from './notes/notes.module';

@Module({
imports: [
Expand All @@ -16,6 +17,7 @@ import { DevicesModule } from './devices/devices.module';
ProjectsModule,
UsersModule,
DevicesModule,
NotesModule,
],
providers: [
{
Expand Down
4 changes: 1 addition & 3 deletions integration/crud-typeorm/companies/companies.controller.ts
Expand Up @@ -4,14 +4,12 @@ import { Crud } from '@nestjsx/crud';

import { Company } from './company.entity';
import { CompaniesService } from './companies.service';
import { dto } from './dto';
import { serialize } from './response';
import { serialize } from './responses';

@Crud({
model: {
type: Company,
},
// dto,
serialize,
routes: {
deleteOneBase: {
Expand Down
2 changes: 1 addition & 1 deletion integration/crud-typeorm/companies/companies.service.ts
@@ -1,6 +1,6 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { TypeOrmCrudService } from '../../../packages/crud-typeorm/src/typeorm-crud.service';
import { TypeOrmCrudService } from '@nestjsx/crud-typeorm';

import { Company } from './company.entity';

Expand Down
2 changes: 2 additions & 0 deletions integration/crud-typeorm/notes/index.ts
@@ -0,0 +1,2 @@
export * from './note.entity';
export * from './notes.service';
10 changes: 10 additions & 0 deletions integration/crud-typeorm/notes/note.entity.ts
@@ -0,0 +1,10 @@
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity('notes')
export class Note {
@PrimaryGeneratedColumn()
id: number;

@Column({ name: 'revision_id', nullable: false })
revisionId: number;
}
22 changes: 22 additions & 0 deletions integration/crud-typeorm/notes/notes.controller.ts
@@ -0,0 +1,22 @@
import { Controller } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { Crud } from '@nestjsx/crud';

import { Note } from './note.entity';
import { NotesService } from './notes.service';
import { dto } from './requests';
import { serialize } from './responses';

@Crud({
model: { type: Note },
dto,
serialize,
query: {
alwaysPaginate: true,
},
})
@ApiTags('notes')
@Controller('/notes')
export class NotesController {
constructor(public service: NotesService) {}
}
14 changes: 14 additions & 0 deletions integration/crud-typeorm/notes/notes.module.ts
@@ -0,0 +1,14 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';

import { Note } from './note.entity';
import { NotesService } from './notes.service';
import { NotesController } from './notes.controller';

@Module({
imports: [TypeOrmModule.forFeature([Note])],
providers: [NotesService],
exports: [NotesService],
controllers: [NotesController],
})
export class NotesModule {}
12 changes: 12 additions & 0 deletions integration/crud-typeorm/notes/notes.service.ts
@@ -0,0 +1,12 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { TypeOrmCrudService } from '../../../packages/crud-typeorm/src';

import { Note } from './note.entity';

@Injectable()
export class NotesService extends TypeOrmCrudService<Note> {
constructor(@InjectRepository(Note) repo) {
super(repo);
}
}
8 changes: 8 additions & 0 deletions integration/crud-typeorm/notes/requests/create-note.dto.ts
@@ -0,0 +1,8 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNumber } from 'class-validator';

export class CreateNoteDto {
@ApiProperty({ type: 'number' })
@IsNumber()
revisionId: string;
}
5 changes: 5 additions & 0 deletions integration/crud-typeorm/notes/requests/index.ts
@@ -0,0 +1,5 @@
import { CreateNoteDto } from './create-note.dto';

export const dto = {
create: CreateNoteDto,
};
12 changes: 12 additions & 0 deletions integration/crud-typeorm/notes/responses/get-note-response.dto.ts
@@ -0,0 +1,12 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNumber } from 'class-validator';

export class GetNoteResponseDto {
@ApiProperty({ type: 'number' })
@IsNumber()
id: string;

@ApiProperty({ type: 'number' })
@IsNumber()
revisionId: string;
}
5 changes: 5 additions & 0 deletions integration/crud-typeorm/notes/responses/index.ts
@@ -0,0 +1,5 @@
import { GetNoteResponseDto } from './get-note-response.dto';

export const serialize = {
get: GetNoteResponseDto,
};
33 changes: 24 additions & 9 deletions integration/crud-typeorm/seeds.ts
@@ -1,16 +1,20 @@
import { plainToClass } from 'class-transformer';
import { MigrationInterface, Repository, QueryRunner } from 'typeorm';
import { ClassType } from 'class-transformer/ClassTransformer';
import { Company } from './companies';
import { Project, UserProject } from './projects';
import { Name, User } from './users';
import { License, UserLicense } from './users-licenses';
import { UserProfile } from './users-profiles';
import { Note } from './notes';

export class Seeds1544303473346 implements MigrationInterface {
private save<T>(repo: Repository<T>, type: any, data: Partial<T>[]): Promise<T[]> {
private save<T>(repo: Repository<T>, data: Partial<T>[]): Promise<T[]> {
return repo.save(
data.map((partial: Partial<T>) =>
plainToClass<any, any>(type, partial, { ignoreDecorators: true }),
plainToClass<any, any>(repo.target as ClassType<T>, partial, {
ignoreDecorators: true,
}),
),
);
}
Expand All @@ -25,9 +29,10 @@ export class Seeds1544303473346 implements MigrationInterface {
const licensesRepo = connection.getRepository(License);
const usersLincesesRepo = connection.getRepository(UserLicense);
const usersProjectsRepo = connection.getRepository(UserProject);
const notesRepo = connection.getRepository(Note);

// companies
await this.save(companiesRepo, Company, [
await this.save(companiesRepo, [
{ name: 'Name1', domain: 'Domain1' },
{ name: 'Name2', domain: 'Domain2' },
{ name: 'Name3', domain: 'Domain3' },
Expand All @@ -41,7 +46,7 @@ export class Seeds1544303473346 implements MigrationInterface {
]);

// projects
await this.save(projectsRepo, Project, [
await this.save(projectsRepo, [
{ name: 'Project1', description: 'description1', isActive: true, companyId: 1 },
{ name: 'Project2', description: 'description2', isActive: true, companyId: 1 },
{ name: 'Project3', description: 'description3', isActive: true, companyId: 2 },
Expand All @@ -65,7 +70,7 @@ export class Seeds1544303473346 implements MigrationInterface {
]);

// user-profiles
await this.save(usersProfilesRepo, UserProfile, [
await this.save(usersProfilesRepo, [
{ name: 'User1' },
{ name: 'User2' },
{ name: 'User3' },
Expand All @@ -91,7 +96,7 @@ export class Seeds1544303473346 implements MigrationInterface {
// users
const name: Name = { first: null, last: null };
const name1: Name = { first: 'firstname1', last: 'lastname1' };
await this.save(usersRepo, User, [
await this.save(usersRepo, [
{ email: '1@email.com', isActive: true, companyId: 1, profileId: 1, name: name1 },
{ email: '2@email.com', isActive: true, companyId: 1, profileId: 2, name },
{ email: '3@email.com', isActive: true, companyId: 1, profileId: 3, name },
Expand All @@ -116,7 +121,7 @@ export class Seeds1544303473346 implements MigrationInterface {
]);

// licenses
await this.save(licensesRepo, License, [
await this.save(licensesRepo, [
{ name: 'License1' },
{ name: 'License2' },
{ name: 'License3' },
Expand All @@ -125,20 +130,30 @@ export class Seeds1544303473346 implements MigrationInterface {
]);

// user-licenses
await this.save(usersLincesesRepo, UserLicense, [
await this.save(usersLincesesRepo, [
{ userId: 1, licenseId: 1, yearsActive: 3 },
{ userId: 1, licenseId: 2, yearsActive: 5 },
{ userId: 1, licenseId: 4, yearsActive: 7 },
{ userId: 2, licenseId: 5, yearsActive: 1 },
]);

// user-projects
await this.save(usersProjectsRepo, UserProject, [
await this.save(usersProjectsRepo, [
{ projectId: 1, userId: 1, review: 'User project 1 1' },
{ projectId: 1, userId: 2, review: 'User project 1 2' },
{ projectId: 2, userId: 2, review: 'User project 2 2' },
{ projectId: 3, userId: 3, review: 'User project 3 3' },
]);

// notes
await this.save(notesRepo, [
{ revisionId: 1 },
{ revisionId: 1 },
{ revisionId: 2 },
{ revisionId: 2 },
{ revisionId: 3 },
{ revisionId: 3 },
]);
}

public async down(queryRunner: QueryRunner): Promise<any> {}
Expand Down
10 changes: 7 additions & 3 deletions packages/crud-typeorm/src/typeorm-crud.service.ts
Expand Up @@ -361,10 +361,10 @@ export class TypeOrmCrudService<T> extends CrudService<T> {
this.entityColumns = this.repo.metadata.columns.map((prop) => {
// In case column is an embedded, use the propertyPath to get complete path
if (prop.embeddedMetadata) {
this.entityColumnsHash[prop.propertyPath] = true;
this.entityColumnsHash[prop.propertyPath] = prop.databasePath;
return prop.propertyPath;
}
this.entityColumnsHash[prop.propertyName] = true;
this.entityColumnsHash[prop.propertyName] = prop.databasePath;
return prop.propertyName;
});
this.entityPrimaryColumns = this.repo.metadata.columns
Expand Down Expand Up @@ -838,7 +838,11 @@ export class TypeOrmCrudService<T> extends CrudService<T> {
if (sort) {
return `${this.alias}.${field}`;
}
return `${i}${this.alias}${i}.${i}${field}${i}`;

const dbColName =
this.entityColumnsHash[field] !== field ? this.entityColumnsHash[field] : field;

return `${i}${this.alias}${i}.${i}${dbColName}${i}`;
case 2:
return field;
default:
Expand Down
12 changes: 12 additions & 0 deletions packages/crud-typeorm/test/__fixture__/notes.service.ts
@@ -0,0 +1,12 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';

import { TypeOrmCrudService } from '../../../crud-typeorm/src/typeorm-crud.service';
import { Note } from '../../../../integration/crud-typeorm/notes';

@Injectable()
export class NotesService extends TypeOrmCrudService<Note> {
constructor(@InjectRepository(Note) repo) {
super(repo);
}
}
24 changes: 23 additions & 1 deletion packages/crud-typeorm/test/b.query-params.spec.ts
Expand Up @@ -11,11 +11,13 @@ import { withCache } from '../../../integration/crud-typeorm/orm.config';
import { Project } from '../../../integration/crud-typeorm/projects';
import { User } from '../../../integration/crud-typeorm/users';
import { UserProfile } from '../../../integration/crud-typeorm/users-profiles';
import { Note } from '../../../integration/crud-typeorm/notes';
import { HttpExceptionFilter } from '../../../integration/shared/https-exception.filter';
import { Crud } from '../../crud/src/decorators';
import { CompaniesService } from './__fixture__/companies.service';
import { ProjectsService } from './__fixture__/projects.service';
import { UsersService, UsersService2 } from './__fixture__/users.service';
import { NotesService } from './__fixture__/notes.service';

// tslint:disable:max-classes-per-file
describe('#crud-typeorm', () => {
Expand Down Expand Up @@ -153,11 +155,19 @@ describe('#crud-typeorm', () => {
constructor(public service: UsersService2) {}
}

@Crud({
model: { type: Note },
})
@Controller('notes')
class NotesController {
constructor(public service: NotesService) {}
}

beforeAll(async () => {
const fixture = await Test.createTestingModule({
imports: [
TypeOrmModule.forRoot({ ...withCache, logging: false }),
TypeOrmModule.forFeature([Company, Project, User, UserProfile]),
TypeOrmModule.forFeature([Company, Project, User, UserProfile, Note]),
],
controllers: [
CompaniesController,
Expand All @@ -168,13 +178,15 @@ describe('#crud-typeorm', () => {
UsersController,
UsersController2,
UsersController3,
NotesController,
],
providers: [
{ provide: APP_FILTER, useClass: HttpExceptionFilter },
CompaniesService,
UsersService,
UsersService2,
ProjectsService,
NotesService,
],
}).compile();

Expand Down Expand Up @@ -852,6 +864,16 @@ describe('#crud-typeorm', () => {
.expect(200);
expect(res.body).toBeArrayOfSize(7);
});
it('should search by display column name, but use dbName in sql query', async () => {
const query = qb.search({ revisionId: 2 }).query();
const res = await request(server)
.get('/notes')
.query(query)
.expect(200);
expect(res.body).toBeArrayOfSize(2);
expect(res.body[0].revisionId).toBe(2);
expect(res.body[1].revisionId).toBe(2);
});
});

describe('#update', () => {
Expand Down

0 comments on commit 3d5e73a

Please sign in to comment.