Skip to content

Commit

Permalink
feat: suport nestjs v9
Browse files Browse the repository at this point in the history
  • Loading branch information
huy-tq-hodfords authored and hodfords-quangnv-be committed Nov 29, 2024
0 parents commit 9da65d0
Show file tree
Hide file tree
Showing 37 changed files with 16,626 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .auto-changelog
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"output": "CHANGELOG.md",
"template": "keepachangelog",
"unreleased": true,
"ignoreCommitPattern": "^(?!(feat|fix|\\[feat\\]|\\[fix\\]))(.*)$",
"commitLimit": false,
"commitUrl": "https://github.com/hodfords-solutions/nestjs-storage/commit/{id}"
}
39 changes: 39 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
root: true,
env: {
node: true,
jest: true,
},
ignorePatterns: ['.eslintrc.js'],
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'prettier/prettier': [
'error',
{
singleQuote: true,
printWidth: 120,
proseWrap: "always",
tabWidth: 4,
useTabs: false,
trailingComma: "none",
bracketSpacing: true,
bracketSameLine: false,
semi: true,
endOfLine: "auto"
}
],
},
};
20 changes: 20 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Publish Package to npmjs
on:
push:
branches:
- main
- feat/support-nestjs-9
jobs:
lint:
uses: hodfords-solutions/actions/.github/workflows/lint.yaml@main
build:
uses: hodfords-solutions/actions/.github/workflows/publish.yaml@main
with:
build_path: dist/lib
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
update-docs:
uses: hodfords-solutions/actions/.github/workflows/update-doc.yaml@main
needs: build
secrets:
DOC_SSH_PRIVATE_KEY: ${{ secrets.DOC_SSH_PRIVATE_KEY }}
35 changes: 35 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# compiled output
/dist
/node_modules

# Logs
logs
*.log
npm-debug.log*
pnpm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# OS
.DS_Store

# Tests
/coverage
/.nyc_output

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
4 changes: 4 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx --no-install lint-staged
3 changes: 3 additions & 0 deletions .lintstagedrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"libs/**/*.ts": ["prettier --write"]
}
3 changes: 3 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}
registry=https://registry.npmjs.org/
always-auth=true
12 changes: 12 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"singleQuote": true,
"printWidth": 120,
"proseWrap": "always",
"tabWidth": 4,
"useTabs": false,
"trailingComma": "none",
"bracketSpacing": true,
"bracketSameLine": false,
"semi": true,
"endOfLine": "auto"
}
8 changes: 8 additions & 0 deletions .trunk/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*out
*logs
*actions
*notifications
*tools
plugins
user_trunk.yaml
user.yaml
10 changes: 10 additions & 0 deletions .trunk/configs/.markdownlint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Autoformatter friendly markdownlint config (all formatting rules disabled)
default: true
blank_lines: false
bullet: false
html: false
indentation: false
line_length: false
spaces: false
url: false
whitespace: false
7 changes: 7 additions & 0 deletions .trunk/configs/.shellcheckrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
enable=all
source-path=SCRIPTDIR
disable=SC2154

# If you're having issues with shellcheck following source, disable the errors via:
# disable=SC1090
# disable=SC1091
10 changes: 10 additions & 0 deletions .trunk/configs/.yamllint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
rules:
quoted-strings:
required: only-when-needed
extra-allowed: ['{|}']
empty-values:
forbid-in-block-mappings: true
forbid-in-flow-mappings: true
key-duplicates: {}
octal-values:
forbid-implicit-octal: true
38 changes: 38 additions & 0 deletions .trunk/trunk.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# This file controls the behavior of Trunk: https://docs.trunk.io/cli
# To learn more about the format of this file, see https://docs.trunk.io/reference/trunk-yaml
version: 0.1
cli:
version: 1.17.2
# Trunk provides extensibility via plugins. (https://docs.trunk.io/plugins)
plugins:
sources:
- id: trunk
ref: v1.3.0
uri: https://github.com/trunk-io/plugins
# Many linters and tools depend on runtimes - configure them here. (https://docs.trunk.io/runtimes)
runtimes:
enabled:
- [email protected]
- [email protected]
- [email protected]
# This is the section where you manage your linters. (https://docs.trunk.io/check/configuration)
lint:
enabled:
- [email protected]
- [email protected]
- git-diff-check
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
actions:
disabled:
- trunk-announce
- trunk-check-pre-push
- trunk-fmt-pre-commit
enabled:
- trunk-upgrade-available
161 changes: 161 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
<p align="center">
<a href="http://opensource.hodfords.uk" target="blank"><img src="https://opensource.hodfords.uk/img/logo.svg" width="320" alt="Nest Logo" /></a>
</p>

<p align="center">
Nestjs-Response is a simple yet powerful library for managing API responses in a NestJS application. It provides decorators to handle response models, allowing easy integration with Swagger for API documentation and validation.
</p>

## Installation 🤖

To begin using it, we first install the required dependencies.

```
npm install @hodfords/nestjs-response
```

## Interceptor Setup 🚀

- `Global Interceptor (Recommended):`

Global interceptors are applied across the entire application. To set up a global interceptor, you can register it in the providers array in your module.

```typescript
import { APP_INTERCEPTOR } from '@nestjs/core';
import { ResponseInterceptor } from '@hodfords/nestjs-response';

@Module({
providers: [
{
provide: APP_INTERCEPTOR,
useClass: ResponseInterceptor
}
]
})
export class AppModule {}
```

- `Interceptor with Decorator:`

For microservices or specific scenarios, use the @UseInterceptors decorator to apply interceptors at the controller or method level. However, it's generally recommended to use global interceptors.

```typescript
import { Controller } from '@nestjs/common';
import { UseResponseInterceptor } from '@hodfords/nestjs-response';

@Controller()
@UseResponseInterceptor()
export class AppController {}
```

## Usage 🚀

`@ResponseModel()`

Use the @ResponseModel decorator when an API return single response type.

Parameter:

- `responseClass`: The class that defines the response model.
- `isArray` (optional): Set to `true` if the response is an array of `responseClass`. Defaults to `false`.
- `isAllowEmpty` (optional): Set to true if the response can be empty. Defaults to `false`.

Example of usage:

```typescript
import { ResponseModel } from '@hodfords/nestjs-response';
import { Get } from '@nestjs/common';
import { IsNotEmpty, IsString } from 'class-validator';

class UserResponse {
@IsNotEmpty()
@IsString()
name: string;
}

export class UserController {
@Get()
@ResponseModel(UserResponse, true)
getAllUser() {
return [{ name: 'John' }];
}
}
```

`@ResponseModels()`

Use the @ResponseModels decorator when an API might return multiple response types.

Parameter:

- `...responseClasses`: A list of response classes or arrays of response classes.

Example of usage:

```typescript
import { ResponseModels } from '@hodfords/nestjs-response';
import { Controller, Get, Param } from '@nestjs/common';
import { UserResponse } from './responses/user.response';
import { UserPaginationResponse } from './responses/user-pagination.response';

@Controller()
export class AppController {
@Get('list-models/:type')
@ResponseModels(Number, [Number], UserPaginationResponse, [UserResponse], undefined, null)
getModels(@Param('type') type: string) {
if (type == 'undefined') {
return undefined;
}
if (type == 'pagination') {
return {
items: [{ name: 'John' }, { name: 'Daniel' }],
total: 2,
lastPage: 1,
perPage: 10,
currentPage: 1
};
}
if (type == 'multiple') {
return [{ name: 'John' }, { name: 'Daniel' }];
}
if (type == 'list-number') {
return [123, 456];
}
if (type == 'number') {
return 456;
}
return null;
}
}

```

### Exception Handling

When the response data does not match the expected model, a validation exception will be raised. This ensures that the API returns data conforming to the defined structure.

Example Case: If a property is expected to be a string, but a number is returned, a validation error will occur.

```typescript
import { ResponseModel } from '@hodfords/nestjs-response';
import { Get } from '@nestjs/common';
import { IsString } from 'class-validator';

class UserResponse {
@IsString()
name: string;
}

export class UserController {
@Get()
@ResponseModel(UserResponse)
getUser() {
return { name: 123 }; // Error: name must be a number ...
}
}

```

## License

This project is licensed under the MIT License
2 changes: 2 additions & 0 deletions libs/constants/metadata.constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const RESPONSE_METADATA_KEY = 'response:class';
export const RESPONSE_METADATA_KEYS = 'response:classes';
1 change: 1 addition & 0 deletions libs/constants/native-class-response-names.constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const NativeClassResponseNamesConstant = ['Boolean', 'String', 'Number'];
Loading

0 comments on commit 9da65d0

Please sign in to comment.