Skip to content
Merged
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
24 changes: 12 additions & 12 deletions .github/workflows/Release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,18 @@ jobs:
- name: Test
run: |
npx nx run-many --target=test --all --code-coverage --coverage --reporters=default --reporters=default --coverageReporters=cobertura,html,json
SUMMARY=$(node ./tools/utils/merge-codecoverage/index.js | grep "All files" | awk '{print $4}')
echo "COVERAGE=$(echo ${SUMMARY})" >> $GITHUB_ENV
- name: Cretae Badge
uses: schneegans/dynamic-badges-action@v1.0.0
with:
auth: ${{ secrets.GIST_SECRET }}
gistID: ${{ secrets.GIST_ID }}
filename: coverage-json-api.json
label: Test Coverage
message: ${{ env.COVERAGE }}
color: green
namedLogo: jest
# SUMMARY=$(node ./tools/utils/merge-codecoverage/index.js | grep "All files" | awk '{print $4}')
# echo "COVERAGE=$(echo ${SUMMARY})" >> $GITHUB_ENV
# - name: Cretae Badge
# uses: schneegans/dynamic-badges-action@v1.0.0
# with:
# auth: ${{ secrets.GIST_SECRET }}
# gistID: ${{ secrets.GIST_ID }}
# filename: coverage-json-api.json
# label: Test Coverage
# message: ${{ env.COVERAGE }}
# color: green
# namedLogo: jest
- name: Deploy
run: npx nx affected --target=deploy --base=$BEFORE_SHA

11 changes: 4 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,17 @@
</p>

<p align="center">
Json API plugin for
Json API plugins for
<a href="http://nestjs.com/" target="blank">NestJS</a>
framework
</p>
<p>
Tools to implement JSON API, such as, end point, query params, body params, validation and transformation response.
</p>

## Description

<p>
This plugin works upon TypeOrm library, which is used as the main database abstraction layer tool. The module automatically generates an API according to JSON API specification from the database structure (TypeORM entities). It supports features such as requests validation based on database fields types, request filtering, endpoints extending, data relations control and much more. Our module significantly reduces the development time of REST services by removing the need to negotiate the mechanism of client-server interaction and implementing automatic API generation without the need to write any code.
</p>

- *[json-api-nestjs](https://github.com/klerick/nestjs-json-api/tree/master/libs/json-api-nestjs)* - plugin for create CRUD overs JSON API
- *json-api-nestjs-sdk* - tool for client, call api over *json-api-nestjs*(coming soon...)
- *kson-api-nestjs-acl* - tool for acl over *json-api-nestjs*(coming soon...)
## Installation

```bash
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ParseUUIDPipe } from '@nestjs/common';
import { BookList } from 'database';
import { JsonApi } from 'json-api-nestjs';

@JsonApi(BookList, {
pipeForId: ParseUUIDPipe,
})
export class ExtendBookListController {}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Get, Param, Inject } from '@nestjs/common';

import { HttpService } from '@nestjs/axios';
import { Users } from 'database';
import {
JsonApi,
Expand All @@ -10,6 +10,7 @@ import {
QueryParams,
} from 'json-api-nestjs';
import { ExampleService } from '../../service/example/example.service';
import { map } from 'rxjs';

@JsonApi(Users, {
allowMethod: excludeMethod(['deleteRelationship']),
Expand All @@ -18,6 +19,7 @@ import { ExampleService } from '../../service/example/example.service';
export class ExtendUserController extends JsonBaseController<Users> {
@InjectService() public service: JsonApiService<Users>;
@Inject(ExampleService) protected exampleService: ExampleService;
@Inject(HttpService) protected httpService: HttpService;

public override getAll(query: QueryParams<Users>) {
return this.service.getAll({ query });
Expand All @@ -27,4 +29,11 @@ export class ExtendUserController extends JsonBaseController<Users> {
testOne(@Param('id') id: string): string {
return this.exampleService.testMethode(id);
}

@Get('test-http')
testHttp() {
return this.httpService
.get('http://localhost:3333/api/v1/book-list')
.pipe(map((r) => r.data));
}
}
9 changes: 6 additions & 3 deletions apps/example/src/app/resources/resources.module.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { Module } from '@nestjs/common';
import { JsonApiModule } from 'json-api-nestjs';
import { Users, Addresses, Comments, Roles } from 'database';
import { HttpModule } from '@nestjs/axios';
import { Users, Addresses, Comments, Roles, BookList } from 'database';

import { ExtendUserController } from './controllers/extend-user/extend-user.controller';
import { ExtendBookListController } from './controllers/extend-book-list/extend-book-list.controller';
import { ExampleService } from './service/example/example.service';

@Module({
imports: [
JsonApiModule.forRoot({
entities: [Users, Addresses, Comments, Roles],
controllers: [ExtendUserController],
entities: [Users, Addresses, Comments, Roles, BookList],
controllers: [ExtendUserController, ExtendBookListController],
providers: [ExampleService],
imports: [HttpModule],
options: {
debug: true,
maxExecutionTime: 3000,
Expand Down
4 changes: 2 additions & 2 deletions libs/database/src/lib/config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { TypeOrmModuleOptions } from '@nestjs/typeorm';

import { config as ormConfig } from './config-cli';
import { Roles, Comments, Users, Addresses } from './entities';
import { Roles, Comments, Users, Addresses, BookList } from './entities';

export const config: TypeOrmModuleOptions = {
...ormConfig,
...{
entities: [Roles, Comments, Users, Addresses],
entities: [Roles, Comments, Users, Addresses, BookList],
},
};
38 changes: 38 additions & 0 deletions libs/database/src/lib/entities/book-list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {
Column,
Entity,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
import { IsEmpty, IsNotEmpty } from 'class-validator';

@Entity('book_list')
export class BookList {
@PrimaryGeneratedColumn()
public id: string;

@IsNotEmpty()
@Column({
type: 'text',
nullable: false,
})
public text: string;

@IsEmpty()
@Column({
name: 'created_at',
type: 'timestamp',
nullable: true,
default: 'CURRENT_TIMESTAMP',
})
public createdAt: Date;

@IsEmpty()
@UpdateDateColumn({
name: 'updated_at',
type: 'timestamp',
nullable: true,
default: 'CURRENT_TIMESTAMP',
})
public updatedAt: Date;
}
1 change: 1 addition & 0 deletions libs/database/src/lib/entities/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './roles';
export * from './users';
export * from './comments';
export * from './users-have-roles';
export * from './book-list';
52 changes: 52 additions & 0 deletions libs/database/src/lib/migrations/1665469071344-CreateBookTable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {
MigrationInterface,
QueryRunner,
Table,
TableColumn,
TableForeignKey,
} from 'typeorm';

export class CreateCommentsTable1665469071344 implements MigrationInterface {
protected readonly tableName = 'book_list';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
CREATE EXTENSION IF NOT EXISTS "uuid-ossp"
`);
await queryRunner.createTable(
new Table({
name: this.tableName,
columns: [
new TableColumn({
name: 'id',
type: 'uuid',
isGenerated: true,
isPrimary: true,
unsigned: true,
generationStrategy: 'uuid',
}),
new TableColumn({
name: 'text',
type: 'text',
isNullable: false,
}),
new TableColumn({
name: 'created_at',
type: 'timestamp',
isNullable: true,
default: 'CURRENT_TIMESTAMP',
}),
new TableColumn({
name: 'updated_at',
type: 'timestamp',
isNullable: true,
default: 'CURRENT_TIMESTAMP',
}),
],
})
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropTable(this.tableName);
}
}
5 changes: 4 additions & 1 deletion libs/json-api-nestjs/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
****strong text****
# json-api-nestjs

This plugin works upon TypeOrm library, which is used as the main database abstraction layer tool. The module automatically generates an API according to JSON API specification from the database structure (TypeORM entities). It supports features such as requests validation based on database fields types, request filtering, endpoints extending, data relations control and much more. Our module significantly reduces the development time of REST services by removing the need to negotiate the mechanism of client-server interaction and implementing automatic API generation without the need to write any code.

## Installation

```bash
Expand Down Expand Up @@ -47,9 +48,11 @@ export interface ModuleOptions {
controllers?: NestController[]; // List of controller, if you need extend default present
connectionName?: string; // Type orm connection name: "default" is default name
providers?: NestProvider[]; // List of addition provider for useing in custom controller
imports?: NestImport[]; // List of addition module for useing in custom controller
options?: {
requiredSelectField?: boolean; // Need list of select field in get endpoint, try is default
debug?: boolean; // Debug info in result object
pipeForId?: Type<PipeTransform> // Nestjs pipe for validate id params, by default ParseIntPipe
};
}
```
Expand Down
15 changes: 8 additions & 7 deletions libs/json-api-nestjs/src/lib/config/bindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
queryTransformSchemaMixin,
bodyRelationshipPipeMixin,
bodyRelationshipPatchPipeMixin,
idPipeMixin,
} from '../mixin/pipes';

import { PARAMS_RELATION_NAME, PARAMS_RESOURCE_ID } from '../constants';
Expand Down Expand Up @@ -49,7 +50,7 @@ const Bindings: BindingsConfig = {
{
property: PARAMS_RESOURCE_ID,
decorator: Param,
mixins: [() => ParseIntPipe],
mixins: [idPipeMixin],
},
{
decorator: Query,
Expand All @@ -71,7 +72,7 @@ const Bindings: BindingsConfig = {
{
property: PARAMS_RESOURCE_ID,
decorator: Param,
mixins: [() => ParseIntPipe],
mixins: [idPipeMixin],
},
],
},
Expand All @@ -96,7 +97,7 @@ const Bindings: BindingsConfig = {
{
property: PARAMS_RESOURCE_ID,
decorator: Param,
mixins: [() => ParseIntPipe],
mixins: [idPipeMixin],
},
{
decorator: Body,
Expand All @@ -113,7 +114,7 @@ const Bindings: BindingsConfig = {
{
property: PARAMS_RESOURCE_ID,
decorator: Param,
mixins: [() => ParseIntPipe],
mixins: [idPipeMixin],
},
{
property: PARAMS_RELATION_NAME,
Expand All @@ -131,7 +132,7 @@ const Bindings: BindingsConfig = {
{
property: PARAMS_RESOURCE_ID,
decorator: Param,
mixins: [() => ParseIntPipe],
mixins: [idPipeMixin],
},
{
property: PARAMS_RELATION_NAME,
Expand All @@ -153,7 +154,7 @@ const Bindings: BindingsConfig = {
{
property: PARAMS_RESOURCE_ID,
decorator: Param,
mixins: [() => ParseIntPipe],
mixins: [idPipeMixin],
},
{
property: PARAMS_RELATION_NAME,
Expand All @@ -175,7 +176,7 @@ const Bindings: BindingsConfig = {
{
property: PARAMS_RESOURCE_ID,
decorator: Param,
mixins: [() => ParseIntPipe],
mixins: [idPipeMixin],
},
{
property: PARAMS_RELATION_NAME,
Expand Down
2 changes: 2 additions & 0 deletions libs/json-api-nestjs/src/lib/constants/defaults.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ParseIntPipe } from '@nestjs/common';
import { ConfigParam } from '../types';

export const DEFAULT_QUERY_PAGE = 1;
Expand All @@ -8,4 +9,5 @@ export const ConfigParamDefault: ConfigParam = {
debug: true,
maxExecutionTime: 5000,
requiredSelectField: true,
pipeForId: ParseIntPipe,
};
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@
"type": "string"
},
"id": {
"type": "string",
"pattern": "^\\d+$",
"description": "Use string should be as number string"
"type": "string"
}
},
"required": ["type", "id"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@
"type": "string"
},
"id": {
"type": "string",
"pattern": "^\\d+$",
"description": "Use string should be as number string"
"type": "string"
}
},
"required": ["type", "id"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,18 @@ export function inputBodyPatchSchema(
schemaName,
arrayPropsConfig
);
const patternObject: Record<string, string> = {};
if (
Reflect.getMetadata('design:type', entity['prototype'], 'id') === Number
) {
patternObject.pattern = '^\\d+$';
patternObject.description = 'Use string should be as number string';
}
json.properties.data.properties = {
...{
id: {
type: 'string',
pattern: '^\\d+$',
description: 'Use string should be as number string',
...patternObject,
},
},
...json.properties.data.properties,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,15 @@ export function inputBodyPostSchema(
...relDataType.properties.data.properties,
type: {
...relDataType.properties.data.properties.type,
enum: [
camelToKebab(getEntityName(arrayPropsConfig.relationType[item])),
],
...(arrayPropsConfig.relationType[item]
? {
enum: [
camelToKebab(
getEntityName(arrayPropsConfig.relationType[item])
),
],
}
: {}),
},
},
};
Expand Down
Loading