Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
scripts-prepend-node-path=true
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ We believe that everyone who's working with NestJs and building some RESTful ser
- [**@nestjsx/crud**](https://www.npmjs.com/package/@nestjsx/crud) - core package which provides `@Crud()` decorator for endpoints generation, global configuration, validation, helper decorators ([docs](https://github.com/nestjsx/crud/wiki/Controllers#description))
- [**@nestjsx/crud-request**](https://www.npmjs.com/package/@nestjsx/crud-request) - request builder/parser package which provides `RequestQueryBuilder` class for a frontend usage and `RequestQueryParser` that is being used internally for handling and validating query/path params on a backend side ([docs](https://github.com/nestjsx/crud/wiki/Requests#frontend-usage))
- [**@nestjsx/crud-typeorm**](https://www.npmjs.com/package/@nestjsx/crud-typeorm) - TypeORM package which provides base `TypeOrmCrudService` with methods for CRUD database operations ([docs](https://github.com/nestjsx/crud/wiki/ServiceTypeorm))
- [**@nestjsx/crud-objection**](https://www.npmjs.com/package/@nestjsx/crud-objection) - Objection.js package which provides base `ObjectionCrudService` with methods for CRUD database operations ([docs](https://github.com/nestjsx/crud/wiki/ServiceObjection))

## Documentation

Expand Down
18 changes: 18 additions & 0 deletions integration/crud-objection/app.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Module } from '@nestjs/common';
import { CompaniesModule } from './companies/companies.module';
import { ProjectsModule } from './projects/projects.module';
import { UsersModule } from './users/users.module';
import { DatabaseModule } from './database.module';
import { APP_GUARD } from '@nestjs/core';
import { AuthGuard } from './auth.guard';

@Module({
imports: [DatabaseModule, CompaniesModule, ProjectsModule, UsersModule],
providers: [
{
provide: APP_GUARD,
useClass: AuthGuard,
},
],
})
export class AppModule {}
16 changes: 16 additions & 0 deletions integration/crud-objection/auth.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';

import { UsersService } from './users';
import { USER_REQUEST_KEY } from './constants';

@Injectable()
export class AuthGuard implements CanActivate {
constructor(private usersService: UsersService) {}

async canActivate(ctx: ExecutionContext): Promise<boolean> {
const req = ctx.switchToHttp().getRequest();
req[USER_REQUEST_KEY] = await this.usersService.modelClass.query().findById(1);

return true;
}
}
16 changes: 16 additions & 0 deletions integration/crud-objection/base.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Model } from 'objection';

export class BaseModel extends Model {
readonly id: number;

createdAt: Date;
updatedAt: Date;

$beforeUpdate() {
this.updatedAt = new Date();
}

$beforeInsert() {
this.createdAt = new Date();
}
}
48 changes: 48 additions & 0 deletions integration/crud-objection/companies/companies.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Controller } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { Crud } from '@nestjsx/crud';

import { Company } from './company.model';
import { CompaniesService } from './companies.service';
import { serialize } from './responses';

@Crud({
model: {
type: Company,
},
serialize,
routes: {
deleteOneBase: {
returnDeleted: false,
},
},
query: {
alwaysPaginate: false,
allow: ['name'],
join: {
users: {
alias: 'companyUsers',
exclude: ['email'],
eager: true,
},
'users.projects': {
eager: true,
alias: 'usersProjects',
allow: ['name'],
},
'users.projects.company': {
eager: true,
alias: 'usersProjectsCompany',
},
projects: {
eager: true,
select: false,
},
},
},
})
@ApiTags('companies')
@Controller('companies')
export class CompaniesController {
constructor(public service: CompaniesService) {}
}
10 changes: 10 additions & 0 deletions integration/crud-objection/companies/companies.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { CompaniesService } from './companies.service';
import { CompaniesController } from './companies.controller';

@Module({
providers: [CompaniesService],
exports: [CompaniesService],
controllers: [CompaniesController],
})
export class CompaniesModule {}
12 changes: 12 additions & 0 deletions integration/crud-objection/companies/companies.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Inject, Injectable } from '@nestjs/common';

import { Company } from './company.model';
import { ModelClass } from 'objection';
import { ObjectionCrudService } from '@nestjsx/crud-objection';

@Injectable()
export class CompaniesService extends ObjectionCrudService<Company> {
constructor(@Inject('Company') modelClass: ModelClass<Company>) {
super(modelClass);
}
}
58 changes: 58 additions & 0 deletions integration/crud-objection/companies/company.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import * as path from 'path';
import { IsNotEmpty, IsOptional, IsString, MaxLength } from 'class-validator';
import { CrudValidationGroups } from '@nestjsx/crud';

import { User } from '../users/user.model';
import { Project } from '../projects/project.model';
import { BaseModel } from '../base.model';
import { Model } from 'objection';
import { Type } from 'class-transformer';

const { CREATE, UPDATE } = CrudValidationGroups;

export class Company extends BaseModel {
static tableName = 'companies';

@IsOptional({ groups: [UPDATE] })
@IsNotEmpty({ groups: [CREATE] })
@IsString({ always: true })
@MaxLength(100, { always: true })
name: string;

@IsOptional({ groups: [UPDATE] })
@IsNotEmpty({ groups: [CREATE] })
@IsString({ groups: [CREATE, UPDATE] })
@MaxLength(100, { groups: [CREATE, UPDATE] })
domain: string;

@IsOptional({ always: true })
@IsString({ always: true })
description: string;

/**
* Relations
*/

@Type((t) => User)
users?: User[];
projects?: Project[];

static relationMappings = {
users: {
relation: Model.HasManyRelation,
modelClass: path.resolve(__dirname, '../users/user.model'),
join: {
from: 'companies.id',
to: 'users.companyId',
},
},
projects: {
relation: Model.HasManyRelation,
modelClass: path.resolve(__dirname, '../projects/project.model'),
join: {
from: 'companies.id',
to: 'projects.companyId',
},
},
};
}
2 changes: 2 additions & 0 deletions integration/crud-objection/companies/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './company.model';
export * from './companies.service';
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsString, MaxLength } from 'class-validator';

export class CreateCompanyDto {
@ApiProperty({ type: 'string' })
@IsString()
@MaxLength(100)
name: string;

@ApiProperty({ type: 'string' })
@IsString()
@MaxLength(100)
domain: string;

@ApiProperty({ type: 'string' })
@IsString()
@MaxLength(100)
description: string;
}
5 changes: 5 additions & 0 deletions integration/crud-objection/companies/requests/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { CreateCompanyDto } from './create-company.dto';

export const dto = {
create: CreateCompanyDto,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ApiProperty } from '@nestjs/swagger';
import { Exclude } from 'class-transformer';

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

@ApiProperty({ type: 'string' })
name: string;

@ApiProperty({ type: 'string' })
domain: string;

@ApiProperty({ type: 'string' })
description: string;

@Exclude()
createdAt: any;

@Exclude()
updatedAt: any;
}
6 changes: 6 additions & 0 deletions integration/crud-objection/companies/responses/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { SerializeOptions } from '@nestjsx/crud';
import { GetCompanyResponseDto } from './get-company-response.dto';

export const serialize: SerializeOptions = {
get: GetCompanyResponseDto,
};
1 change: 1 addition & 0 deletions integration/crud-objection/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const USER_REQUEST_KEY = 'user';
55 changes: 55 additions & 0 deletions integration/crud-objection/database.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Global, Module } from '@nestjs/common';
import * as Knex from 'knex';
import { knexSnakeCaseMappers, Model } from 'objection';
import { UserProfile } from './users-profiles';
import { Project, UserProject } from './projects';
import { Company } from './companies';
import { User } from './users';
import { KNEX_CONNECTION } from './injection-tokens';
import { Device } from './devices';
import { License, UserLicense } from './users-licenses';
import { Note } from './notes';

const models = [
User,
Company,
Project,
UserProfile,
UserProject,
Device,
License,
UserLicense,
Note,
];

const modelProviders = models.map((model) => {
return {
provide: model.name,
useValue: model,
};
});

const providers = [
...modelProviders,
{
provide: KNEX_CONNECTION,
useFactory: async () => {
const knex = Knex({
client: 'pg',
connection: 'postgres://root:root@127.0.0.1:5455/nestjsx_crud_objection',
debug: process.env.KNEX_DEBUG === 'true',
...knexSnakeCaseMappers(),
});

Model.knex(knex);
return knex;
},
},
];

@Global()
@Module({
providers: [...providers],
exports: [...providers],
})
export class DatabaseModule {}
18 changes: 18 additions & 0 deletions integration/crud-objection/devices/device.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { IsOptional, IsString, IsUUID } from 'class-validator';
import { Model } from 'objection';

export class Device extends Model {
static readonly tableName = 'devices';

static get idColumn() {
return ['deviceKey'];
}

@IsOptional({ always: true })
@IsUUID('4', { always: true })
deviceKey: string;

@IsOptional({ always: true })
@IsString({ always: true })
description?: string;
}
29 changes: 29 additions & 0 deletions integration/crud-objection/devices/devices.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Controller } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { Crud } from '@nestjsx/crud';

import { DevicesService } from './devices.service';
import { serialize } from './response';
import { Device } from './device.model';

@Crud({
model: { type: Device },
serialize,
params: {
deviceKey: {
field: 'deviceKey',
type: 'uuid',
primary: true,
},
},
routes: {
deleteOneBase: {
returnDeleted: true,
},
},
})
@ApiTags('devices')
@Controller('/devices')
export class DevicesController {
constructor(public service: DevicesService) {}
}
11 changes: 11 additions & 0 deletions integration/crud-objection/devices/devices.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';

import { DevicesService } from './devices.service';
import { DevicesController } from './devices.controller';

@Module({
providers: [DevicesService],
exports: [DevicesService],
controllers: [DevicesController],
})
export class DevicesModule {}
12 changes: 12 additions & 0 deletions integration/crud-objection/devices/devices.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Inject, Injectable } from '@nestjs/common';

import { Device } from './device.model';
import { ObjectionCrudService } from '@nestjsx/crud-objection';
import { ModelClass } from 'objection';

@Injectable()
export class DevicesService extends ObjectionCrudService<Device> {
constructor(@Inject('Device') modelClass: ModelClass<Device>) {
super(modelClass);
}
}
2 changes: 2 additions & 0 deletions integration/crud-objection/devices/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './device.model';
export * from './devices.service';
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ApiProperty } from '@nestjs/swagger';
import { Exclude } from 'class-transformer';

export class DeleteDeviceResponseDto {
@ApiProperty({ type: 'string' })
deviceKey: string;

@Exclude()
description?: string;
}
Loading