{siteConfig.tagline}
19 |10 | Env-Parser is a simple and lightweight library for parsing environment variables in Node.js applications. Inspired by znv but simpler and lighter. 11 |
12 | 13 | ## Installation 🤖 14 | To begin using it, we first install the required dependencies. 15 | ``` 16 | npm install @hodfords/env-parser 17 | ``` 18 | 19 | ## Usage 🚀 20 | 21 | Create `.env` file, you can also pass it via environment variable without creating a file. 22 | 23 | ```env 24 | APP_PORT=3000 25 | REDIS_PORT=6379 26 | REDIS_HOST=localhost 27 | ALLOW_SEND_MAIL=true 28 | ``` 29 | 30 | Create env file like `env.ts` and import `parse` and `z` from `@hodfords/env-parser`. 31 | ```typescript 32 | import { parse, z } from '@hodfords/env-parser'; 33 | 34 | export const env = parse(process.env, { 35 | APP_PORT: z.number().min(1000).max(9999), 36 | REDIS: { 37 | PORT: z.number().default(6379), 38 | HOST: z.string().default('localhost') 39 | }, 40 | ALLOW_SEND_MAIL: z.boolean().default(true) 41 | }); 42 | ``` 43 | 44 | > Note: env-parser supports multiple parser levels, but we recommend using up to 2 levels to ensure easier code readability. 45 | 46 | 47 | More validation function here: [Zod Validation](https://zod.dev/?id=basic-usage) 48 | 49 | ## License 50 | This project is licensed under the MIT License 51 | -------------------------------------------------------------------------------- /pages/nestjs-testing/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | displayed_sidebar: docs 3 | title: "@hodfords/nestjs-testing" 4 | --- 5 | 8 | 9 |10 | Nestjs-Testing is a testing library for Nestjs applications. It provides a set of utilities to help you test your Nestjs application. 11 |
12 | 13 | ## Installation 🤖 14 | To begin using it, we first install the required dependencies. 15 | ``` 16 | npm install @hodfords/nestjs-testing 17 | ``` 18 | 19 | ## Configuration 🚀 20 | To easily customize the configuration, let's create an object that extends the `BaseTestHelper` class. This object will be used to configure the test environment. 21 | 22 | ```typescript 23 | export class TestHelper extends BaseTestHelper { 24 | getSupertestConfig(): SupertestConfig { 25 | return { 26 | isUseBearerAuth: true, 27 | authenticationHeader: 'Authorization' 28 | }; 29 | } 30 | 31 | getTestModuleBuilder(): TestingModuleBuilder { 32 | return Test.createTestingModule({ 33 | imports: [AppModule] 34 | }); 35 | } 36 | } 37 | ``` 38 | 39 | ## Usage 🚀 40 | 41 | Write your test cases using the `TestHelper` class. 42 | 43 | ```typescript 44 | describe('AppController (e2e)', () => { 45 | let testHelper = new TestHelper(); 46 | 47 | beforeAll(async () => { 48 | await testHelper.initialize(); 49 | }); 50 | 51 | it('Get index success', async () => { 52 | return testHelper.get('/').isOk().expect('Hello World!'); 53 | }); 54 | }); 55 | ``` 56 | 57 | ## License 58 | This project is licensed under the MIT License 59 | -------------------------------------------------------------------------------- /pages/nestjs-any-guard/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | displayed_sidebar: docs 3 | title: "@hodfords/nestjs-any-guard" 4 | --- 5 | 8 | 9 |10 | Nestjs-AnyGuard is a custom guard for NestJS that allows you to apply multiple guards to a single route. It will pass the request to the first guard that returns true, and if none of the guards return true, it will throw a ForbiddenException. 11 |
12 | 13 | ## Installation 🤖 14 | 15 | To begin using it, we first install the required dependencies. 16 | 17 | ``` 18 | npm install @hodfords/nestjs-any-guard 19 | ``` 20 | ## Usage 📖 21 | 22 | ### AnyGuard Decorator 23 | **AnyGuard** is a custom decorator that allows you to apply multiple guards to a single route. It will pass the request to the first guard that returns true, and if none of the guards return true, it will throw an ForbiddenException. 24 | ```typescript 25 | @Post('example') 26 | @AnyGuard(Guard1, Guard2, Guard3) 27 | async example(@Body() body: any) { 28 | return body; 29 | } 30 | ``` 31 | 32 | ### Custom Guards 33 | **FirstSuccessGuard** is a custom guard that checks if any of the provided guards return true. If any guard returns true, it allows the request to proceed; otherwise, it throws a ForbiddenException. 34 | 35 | ```typescript 36 | 37 | @Post('example') 38 | @UseGuards(FirstSuccessGuard(Guard1, Guard2, Guard3)) 39 | async example(@Body() body: any) { 40 | return body; 41 | } 42 | 43 | ``` 44 | 45 | **HasHeaderGuard** checks if a specific header is present in the request. If the header is present and its value is 'true', it allows the request to proceed. Otherwise, it denies access. 46 | It is useful when you use with API-Gateway 47 | 48 | ```typescript 49 | @Post('example') 50 | @UseGuards(HasHeaderGuard('permission-passed')) 51 | async example(@Body() body: any) { 52 | return body; 53 | } 54 | ``` 55 | 56 | ## Limitations 🚧 57 | You have to register the guards in your module providers, otherwise it will not work. 58 | 59 | 60 | ## License 61 | 62 | This project is licensed under the MIT License 63 | -------------------------------------------------------------------------------- /pages/vite-config-builder/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | displayed_sidebar: docs 3 | title: "@hodfords/vite-config-builder" 4 | --- 5 | # Hodfords Vite Config Builder 6 | 7 | 10 | 11 | ## Installation 🤖 12 | 13 | * Install [PNPM](https://pnpm.io/) latest version 14 | * Install Nodejs >= 20 ( Should be use [NVM](https://github.com/nvm-sh/nvm) for install NodeJS ) 15 | 16 | * With NPM: 17 | ``` 18 | npm install @hodfords/vite-config-builder --save 19 | ``` 20 | 21 | * with PNPM: 22 | ``` 23 | pnpm install @hodfords/vite-config-builder 24 | ``` 25 | 26 | ## Usage 🚀 27 | ```typescript 28 | import createViteConfig from '@hodfords/vite-config-builder'; 29 | 30 | export default createViteConfig({ 31 | isUsePWA: true, 32 | isUseGzip: true, 33 | defineEnv: ['API_URL', 'APP_URL'], 34 | aliasPath: ['components', 'containers', 'config', 'api'], 35 | autoImport: { 36 | config: { 37 | eslintrc: { 38 | enabled: true, 39 | }, 40 | dirs: ['src/shared'], 41 | dts: 'src/types/auto-imports.d.ts', 42 | }, 43 | libs: [ 44 | { 45 | from: 'antd', 46 | imports: [ 47 | 'CollapseProps', 48 | 'ButtonProps', 49 | ], 50 | type: true, 51 | }, 52 | '@ant-design/plots': [ 53 | ['Pie', 'PieChart'], 54 | ['Column', 'ColumnChart'], 55 | ], 56 | ], 57 | } 58 | }); 59 | ``` 60 | 61 | ## Options 62 | 63 | ### `isUsePWA` - This option enable Vite PWA. 64 | - Type: `boolean` 65 | - Required: `true` 66 | 67 | ### `isUseGzip` - This option enable Gzip. 68 | - Type: `boolean` 69 | - Required: `true` 70 | 71 | ### `defineEnv` - This option define list Environments. 72 | - Type: `Array(string)` 73 | - Required: `true` 74 | 75 | ### `aliasPath` - This option define alias path. 76 | - Type: `Array(string)` 77 | - Required: `true` 78 | 79 | ### `autoImport` - This option define auto import libraries for Components, Functions, Utils, Types... 80 | - Type: `Object(array)` 81 | - Required: `true` 82 | 83 | ## License 📝 84 | 85 | This project is licensed under the MIT License 86 | -------------------------------------------------------------------------------- /pages/reactjs-codelint-config/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | displayed_sidebar: docs 3 | title: "@hodfords/reactjs-codelint-config" 4 | --- 5 | # Hodfords ReactJS Codelint Config 6 | 7 | 10 | 11 |reactjs-codelint-config include eslint, stylelint, tslint configs help you to maintain the code quality of your project.
12 | 13 | ## Installation 🤖 14 | 15 | * Install [PNPM](https://pnpm.io/) latest version 16 | * Install Nodejs >= 20 ( Should be use [NVM](https://github.com/nvm-sh/nvm) for install NodeJS ) 17 | 18 | * With NPM: 19 | ``` 20 | npm install @hodfords/reactjs-codelint-config --save 21 | ``` 22 | 23 | * with PNPM: 24 | ``` 25 | pnpm install @hodfords/reactjs-codelint-config 26 | ``` 27 | 28 | ## Configuration 🚀 29 | 30 | * To activate eslint, create a `eslint.config.js` file in the root of your project and add the following configuration: 31 | 32 | ```typescript 33 | import { eslintConfig } from '@hodfords/reactjs-codelint-config'; 34 | 35 | export default eslintConfig; 36 | ``` 37 | 38 | * To activate stylelint, create a `.stylelintrc.js` file in the root of your project and add the following configuration: 39 | 40 | ```typescript 41 | import { stylelintConfig } from '@hodfords/reactjs-codelint-config'; 42 | 43 | export default stylelintConfig; 44 | ``` 45 | 46 | ## Usage 🚀 47 | Run the following command to lint your project: 48 | ``` 49 | npx eslint 50 | ``` 51 | 52 | ## Eslint Config Details 53 | This configuration extends the `@hodfords/reactjs-codelint-config` package. It includes the following plugins: 54 | - `@typescript-eslint/parser` 55 | - `eslint-plugin-prettier` 56 | - `eslint-plugin-react` 57 | - `eslint-plugin-react-hooks` 58 | - `@typescript-eslint/eslint-plugin` 59 | - `eslint-plugin-unused-imports` 60 | - `eslint-plugin-import` 61 | - `eslint-plugin-react-func` 62 | - `@tanstack/eslint-plugin-query` 63 | 64 | ## Stylelint Config Details 65 | This configuration extends the `@hodfords/reactjs-codelint-config` package. It includes the following plugins: 66 | - `postcss-styled-syntax` 67 | - `stylelint-config-standard`, 68 | - `stylelint-config-recommended` 69 | 70 | ## License 📝 71 | 72 | This project is licensed under the MIT License 73 | -------------------------------------------------------------------------------- /pages/nestjs-swagger-helper/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | displayed_sidebar: docs 3 | title: "@hodfords/nestjs-swagger-helper" 4 | --- 5 | 8 | 9 |nestjs-swagger-helper streamlines the integration of Swagger documentation in NestJS applications. It provides utilities and decorators to simplify the creation and management of API documentation, making it easier to keep your API specs up-to-date and accessible.
10 | 11 | ## Installation 🤖 12 | 13 | Install the `nestjs-swagger-helper` package with: 14 | 15 | ``` 16 | npm install @hodfords/nestjs-swagger-helper --save 17 | ``` 18 | 19 | Next, create a file named `swagger-helper.config.ts` and add the following code. Then, include it in your `app.module.ts` file: 20 | 21 | ```typescript 22 | // APP_PREFIX is optional, if your application doesn't have this one you can skip 23 | export const swaggerConfig = SwaggerHelperModule.forRoot(APP_PREFIX); 24 | ``` 25 | 26 | Import the `SwaggerHelper` and use it to initialize Swagger 27 | 28 | ```typescript 29 | import { SwaggerHelper } from '@hodfords/nestjs-swagger-helper'; 30 | 31 | type SwaggerInitialization = { 32 | app: NestExpressApplication; 33 | appEnv: string; 34 | path: string; 35 | title: string; 36 | description: string; 37 | version: string; 38 | disablePrivateDocument: boolean; 39 | }; 40 | 41 | buildSwagger() { 42 | new SwaggerHelper({ 43 | app: this.app, 44 | appEnv: env.APP_ENV, 45 | path: `${env.APP_PREFIX}/documents`, 46 | title: 'Document for usdol', 47 | description: 'The usdol API description', 48 | version: '1.0', 49 | disablePrivateDocument: env.APP_ENV === 'production', 50 | }).buildDocuments(); 51 | } 52 | ``` 53 | 54 | ## Usage 🚀 55 | 56 | ### Decorators 57 | 58 | The library provides two decorators you can use: 59 | 60 | - `@ApiPublic`: Marks APIs as public. 61 | - `@ApiSetValue`: Typically used for login/signin APIs to automatically add a JWT token to Swagger when the request is 62 | successful. 63 | - `@ApiPermissions`: Used to document the permissions required for accessing specific API endpoints. 64 | 65 | ## License 📝 66 | 67 | This project is licensed under the MIT License 68 | -------------------------------------------------------------------------------- /src/components/HomepageFeatures/index.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx'; 2 | import Heading from '@theme/Heading'; 3 | import styles from './styles.module.css'; 4 | 5 | type FeatureItem = { 6 | title: string; 7 | Svg: React.ComponentType{description}
51 |nestjs-cls-translation provides context-aware translations in NestJS applications using Context-Local Storage (CLS), making it easier to manage and access locale-specific data across different parts of your application.
10 | 11 | ## Installation 🤖 12 | 13 | Install the `nestjs-cls-translation` package with: 14 | 15 | ```bash 16 | npm install @hodfords/nestjs-cls-translation --save 17 | ``` 18 | 19 | You'll need to configure the translation module by adding it to your NestJS app's module setup. Here’s how you can configure it: 20 | 21 | ```typescript 22 | TranslationModule.forRoot({ 23 | fallbackLanguage: 'en', 24 | parser: I18nJsonParser, 25 | parserOptions: { 26 | path: path.join(env.ROOT_PATH, 'i18n/'), 27 | watch: true 28 | }, 29 | resolvers: [new HeaderResolver(['language'])] 30 | }); 31 | ``` 32 | 33 | ## Usage 🚀 34 | 35 | #### Translation Functions 36 | 37 | To translate a specific key, use the trans function, passing the key for the translation string you wish to fetch: 38 | 39 | ```typescript 40 | const translatedText = trans('error.an_error_occurred') 41 | ``` 42 | 43 | This will return the translated string based on the user's current language, or the fallback language if no specific translation exists for the user's language. 44 | 45 | #### Get Current Language 46 | 47 | To retrieve the language currently being used in the context of a request, use the `currentLanguage()` function: 48 | 49 | ```typescript 50 | const currentLang = currentLanguage() 51 | ``` 52 | 53 | #### Get Default Language 54 | 55 | If you need to access the application's default or fallback language (set in the module configuration), use the `defaultLanguage()` function: 56 | 57 | ```typescript 58 | const defaultLang = defaultLanguage() 59 | ``` 60 | 61 | #### Run with a Specific Language Context 62 | 63 | You may want to execute certain parts of your code in a specific language context. The runInLanguage() function allows you to run a block of code under a designated language context, overriding the current language: 64 | 65 | ```typescript 66 | await runInLanguage('en', () => {...}); 67 | ``` 68 | 69 | ## License 📝 70 | 71 | This project is licensed under the MIT License 72 | -------------------------------------------------------------------------------- /pages/nestjs-eslint-config/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | displayed_sidebar: docs 3 | title: "@hodfords/nestjs-eslint-config" 4 | --- 5 | 8 | 9 | # ESLINT DEFAULT CONFIGURATION 10 | Eslint default configuration for Nestjs project. It will help you to maintain the code quality of your project. 11 | 12 | ## Installation 🤖 13 | To begin using it, we first install the required dependencies. 14 | ``` 15 | npm install @hodfords/nestjs-eslint-config 16 | ``` 17 | 18 | ## Configuration 🚀 19 | To activate eslint, create a `eslint.config.js` file in the root of your project and add the following configuration: 20 | ```javascript 21 | module.exports = require('@hodfords/nestjs-eslint-config'); 22 | ``` 23 | 24 | ## Usage 🚀 25 | Run the following command to lint your project: 26 | ``` 27 | npx eslint 28 | ``` 29 | 30 | ## Eslint Config Details 31 | This configuration extends the `@hodfords/eslint-config` package. It includes the following plugins: 32 | - `@typescript-eslint/eslint-plugin` 33 | - `@typescript-eslint/parser` 34 | - `eslint-plugin-prettier/recommended` 35 | 36 | Custom rules are also included in this configuration. 37 | 38 | ### Prettier Config 39 | ```javascript 40 | { 41 | useTabs: false, 42 | tabWidth: 4, 43 | printWidth: 120, 44 | singleQuote: true, 45 | trailingComma: 'none' 46 | } 47 | ``` 48 | 49 | ### Typescript Config 50 | 51 | #### Naming Conventions 52 | - `@typescript-eslint/naming-convention` 53 | - `enumMember`: `UPPER_CASE` 54 | - `objectLiteralProperty`: `['camelCase', 'PascalCase', 'UPPER_CASE']` 55 | - `['class', 'interface', 'enum']`: `PascalCase` 56 | - `variable`: `['PascalCase', 'camelCase', 'UPPER_CASE']` 57 | - `function`: `['PascalCase', 'camelCase']` 58 | - `'parameter','variable','function', 'classProperty','typeProperty','parameterProperty','classMethod','objectLiteralMethod','typeMethod'`: `'camelCase'` 59 | 60 | #### Typescript Custom Rules 61 | ``` 62 | '@typescript-eslint/interface-name-prefix': 'off', 63 | '@typescript-eslint/no-empty-function': 'off', 64 | '@typescript-eslint/explicit-function-return-type': 'off', 65 | '@typescript-eslint/explicit-module-boundary-types': 'off', 66 | '@typescript-eslint/no-explicit-any': 'off', 67 | '@typescript-eslint/no-inferrable-types': 'off', 68 | '@typescript-eslint/no-unused-vars': ['error', { args: 'none' }] 69 | ``` 70 | 71 | ### Js Rules 72 | - `max-line-per-function`: `50` 73 | - `max-lines`: `400` 74 | - `prefer-const` 75 | - `lines-between-class-members` 76 | - `indent`: `off` 77 | 78 | ## License 79 | This project is licensed under the MIT License 80 | -------------------------------------------------------------------------------- /pages/nestjs-validation/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | displayed_sidebar: docs 3 | title: "@hodfords/nestjs-validation" 4 | --- 5 | 8 | 9 |nestjs-validation enhances validation in your NestJS projects by providing a customized ValidationPipe that returns custom error messages. This library simplifies error handling by offering localized and user-friendly responses
10 | 11 | ## Installation 🤖 12 | 13 | Install the `nestjs-validation` package with: 14 | 15 | ```bash 16 | npm install @hodfords/nestjs-validation --save 17 | ``` 18 | 19 | ## Usage 🚀 20 | 21 | First, create an instance of `ValidationPipe` with the desired configuration: 22 | 23 | ```typescript 24 | import { ValidationPipe } from '@hodfords/nestjs-validation'; 25 | import { ValidateException } from '@hodfords/nestjs-exception'; 26 | 27 | export const validateConfig = new ValidationPipe({ 28 | whitelist: true, 29 | stopAtFirstError: true, 30 | forbidUnknownValues: false, 31 | exceptionFactory: (errors): ValidateException => new ValidateException(errors) 32 | }); 33 | ``` 34 | 35 | Next, set the validation configuration globally in your bootstrap function: 36 | 37 | ```typescript 38 | async function bootstrap() { 39 | const app = await NestFactory.create(AppModule); 40 | app.useGlobalPipes(validateConfig); 41 | await app.listen(3000); 42 | } 43 | ``` 44 | 45 | ### Customize Validation Error 46 | 47 | The original error message provides basic information but lacks detail. With **nestjs-validation**, you can enhance these errors by adding meaningful context, such as the field’s property name, value, and target object. 48 | 49 | **Original Validation Error** 50 | 51 | ```javascript 52 | ValidationError { 53 | target: AppDto { stringValue: undefined }, 54 | value: undefined, 55 | property: 'stringValue', 56 | children: [], 57 | constraints: { isString: 'stringValue must be a string' } 58 | } 59 | ``` 60 | 61 | **Customized Validation Error** 62 | 63 | ```javascript 64 | ValidationError { 65 | target: AppDto { stringValue: undefined }, 66 | value: undefined, 67 | property: 'stringValue', 68 | children: [], 69 | constraints: { 70 | isString: { 71 | message: '$property must be a string', 72 | detail: { property: 'stringValue', target: 'AppDto', value: undefined } 73 | } 74 | } 75 | } 76 | ``` 77 | 78 | ### Exception 79 | 80 | When combined with [nestjs-exception](https://www.npmjs.com/package/@hodfords/nestjs-exception), errors are translated into localized messages: 81 | 82 | ```json 83 | { 84 | "message": "Validate Exception", 85 | "errors": { 86 | "stringValue": { 87 | "messages": ["String Value must be a string"] 88 | } 89 | } 90 | } 91 | ``` 92 | 93 | ## License 📝 94 | 95 | This project is licensed under the MIT License 96 | -------------------------------------------------------------------------------- /pages/nestjs-storage/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | displayed_sidebar: docs 3 | title: "@hodfords/nestjs-storage" 4 | --- 5 | 8 | 9 |10 | Nestjs-Storage provides a powerful filesystem abstraction. The Nestjs-Storage integration provides simple drivers for working with local filesystems, Amazon S3, Azure. Even better, it's amazingly simple to switch between these storage options between your local development machine and production server as the API remains the same for each system. 11 |
12 | 13 | ## Installation 🤖 14 | To begin using it, we first install the required dependencies. 15 | ``` 16 | npm install @hodfords/nestjs-storage 17 | ``` 18 | 19 | ## Configuration 🚀 20 | To activate storage, import the `StorageModule` into the root `AppModule` and run the `forRoot()` static method as shown below: 21 | 22 | Azure configuration: 23 | ```typescript 24 | import { Module } from '@nestjs/common'; 25 | import { StorageModule } from '@hodfords/nestjs-storage'; 26 | 27 | @Module({ 28 | imports: [ 29 | StorageModule.forRoot({ 30 | account: { 31 | name: env.AZURE.ACCOUNT_NAME, 32 | key: env.AZURE.ACCOUNT_KEY, 33 | containerName: env.AZURE.CONTAINER_NAME, 34 | expiredIn: env.AZURE.SAS_EXPIRED_IN 35 | }, 36 | disk: 'azure' 37 | }) 38 | ], 39 | }) 40 | export class AppModule {} 41 | ``` 42 | 43 | Aws S3 configuration: 44 | ```typescript 45 | import { Module } from '@nestjs/common'; 46 | import { StorageModule } from '@hodfords/nestjs-storage'; 47 | 48 | @Module({ 49 | imports: [ 50 | StorageModule.forRoot({ 51 | account: { 52 | name: env.AWS.API_KEY, 53 | key: env.AWS.API_SECRET, 54 | containerName: env.AWS.BUCKET, 55 | expiredIn: env.AZURE.SAS_EXPIRED_IN, 56 | region: env.AWS.REGION 57 | }, 58 | disk: 's3' 59 | }) 60 | ], 61 | }) 62 | export class AppModule {} 63 | ``` 64 | 65 | ### Driver Prerequisites: 66 | - **Azure**: `npm install @azure/storage-blob` 67 | - **Aws S3**: `npm install @aws-sdk/client-s3 @aws-sdk/lib-storage @aws-sdk/s3-request-presigner` 68 | 69 | ## Usage 🚀 70 | 71 | Inject storage instance into your service or controller and use it as shown below: 72 | 73 | ```typescript 74 | import { StorageService } from "@hodfords/nestjs-storage"; 75 | 76 | @Injectable() 77 | export class AppService implements OnModuleInit { 78 | 79 | constructor(private storageService: StorageService) { 80 | } 81 | } 82 | ``` 83 | 84 | ### Delete file 85 | The delete method accepts a single filename 86 | 87 | ```typescript 88 | await this.storageService.deleteFile('path/to/file'); 89 | ``` 90 | 91 | This method may throw an exception if the file does not exist. You can ignore this exception by using the `deleteIfExists` method. 92 | 93 | ```typescript 94 | await this.storageService.deleteIfExists('path/to/file'); 95 | ``` 96 | 97 | ## License 98 | This project is licensed under the MIT License 99 | -------------------------------------------------------------------------------- /docusaurus.config.ts: -------------------------------------------------------------------------------- 1 | import { themes as prismThemes } from 'prism-react-renderer'; 2 | import type { Config } from '@docusaurus/types'; 3 | import type * as Preset from '@docusaurus/preset-classic'; 4 | import { pages } from './page'; 5 | 6 | const config: Config = { 7 | title: 'Hodfords OpenSource', 8 | tagline: 9 | 'At Hodfords, we believe in the power of open-source collaboration. This hub serves as the central place for developers, designers, and enthusiasts to explore, contribute, and utilize a growing collection of open-source libraries. ', 10 | favicon: 'img/favicon.ico', 11 | 12 | // Set the production url of your site here 13 | url: 'https://opensource.hodfords.uk', 14 | // Set the /nestjs-seeder streamlines the process of populating your NestJS application with mock data. It makes it easy to generate and manage seed data, ideal for testing and simulating API responses.
10 | 11 | ## Installation 🤖 12 | 13 | Install the `nestjs-seeder` package with: 14 | 15 | ``` 16 | npm install @hodfords/nestjs-seeder --save 17 | ``` 18 | 19 | ## Usage 🚀 20 | 21 | To seed fake user data into your database, follow these 6 steps: 22 | 23 | #### 1. Define the Factory 24 | 25 | First, create a factory for UserEntity. This factory will generate fake data for user records. 26 | 27 | ##### user.factory.ts 28 | 29 | ```typescript 30 | import { define } from '@hodfords/nestjs-seeder'; 31 | 32 | interface SeedUserOptions { 33 | countryId: string; 34 | } 35 | 36 | class UserEntity { 37 | name: string; 38 | age: string; 39 | countryId: string; 40 | createdAt: Date; 41 | } 42 | 43 | define(UserEntity, (options: SeedUserOptions) => { 44 | const user = new UserEntity(); 45 | 46 | user.name = faker.name.title(); 47 | user.age = faker.datatype.number(100); 48 | user.createdAt = faker.date.future(); 49 | 50 | return plainToClassFromExist(user, options || {}); 51 | }); 52 | ``` 53 | 54 | #### 2. Create the BaseSeeder 55 | 56 | Create a base seeder class that will be used to configure and run your seeding logic. 57 | 58 | ##### base.seeder.ts 59 | 60 | ```typescript 61 | import { Test } from '@nestjs/testing'; 62 | import { AppModule } from '~app.module'; 63 | import { databaseConfig } from '~config/database.config'; 64 | import { BaseSeeder as AbstractSeeder } from '@hodfords/nestjs-seeder'; 65 | 66 | export abstract class BaseSeeder extends AbstractSeeder { 67 | createModule() { 68 | return Test.createTestingModule({ 69 | imports: [AppModule, databaseConfig] 70 | }).compile(); 71 | } 72 | 73 | abstract run(): Promise10 | This repository contains a set of custom exception filters and exceptions designed for use in a NestJS application. It enhances error handling for HTTP-based and microservice-based (gRPC, Kafka) applications by providing more meaningful error responses and localization support. 11 | 12 |
13 | 14 | ## Installation 🤖 15 | 16 | To begin using it, we first install the required dependencies. 17 | 18 | ``` 19 | npm install @hodfords/nestjs-exception 20 | ``` 21 | 22 | ## Exception Classes 23 | 24 | > **Note**: These exception classes only function when used alongside the `HttpExceptionFilter` or one of its child classes (`GrpcExceptionFilter`, `KafkaExceptionFilter`, etc.). Be sure to apply the appropriate filter in your application. 25 | 26 | **1\. UuidException** 27 | 28 | This exception is used to handle invalid UUID formats in requests. It returns a 400 `BAD_REQUEST` status. 29 | 30 | Parameters: 31 | 32 | - `field`: The name of the field that contains the invalid UUID. This value is passed to indicate which field caused the exception. 33 | 34 | **2\. ValidateException** 35 | 36 | Handles specific validation errors related to a particular field. Returns a 422 `UNPROCESSABLE_ENTITY` status. 37 | 38 | Parameters: 39 | 40 | - `property`: The field name that caused the validation error. 41 | - `message`: The detailed message for the validation error. 42 | - `constraint`: The validation constraint that was violated (e.g., notNull). 43 | - `detail`: Additional information for the validation error, if applicable. 44 | 45 | ## Exception Filters 46 | 47 | - **HttpExceptionFilter**: Handles various types of HTTP exceptions with localization support. 48 | 49 | - **GrpcExceptionFilter**: Handles exceptions for gRPC microservices, formatting errors for gRPC clients. 50 | 51 | - **KafkaExceptionFilter**: Manages exceptions in Kafka microservices, formatting errors for Kafka messaging. 52 | 53 | - **ValidatorExceptionFilter**: Catches validation errors (`ValidateException`), supporting nested object validation and localization. 54 | 55 | **Note on Translation**: These filters, especially `HttpExceptionFilter` and `ValidatorExceptionFilter`, rely on a translation service to provide localized error messages. Ensure that your application has translation support enabled (e.g., using `@hodfords/nestjs-cls-translation`). The filters use translation keys defined in your language files to dynamically translate error messages based on the request's language. 56 | 57 | ## Example of usage 58 | 59 | To use the exception classes and filters in your NestJS application, follow these steps: 60 | 61 | #### 1\. **Applying the `HttpExceptionFilter`** 62 | 63 | **Global Application:** 64 | 65 | ```typescript 66 | import { HttpExceptionFilter } from '@hodfords/nestjs-exception'; 67 | import { NestFactory } from '@nestjs/core'; 68 | import { AppModule } from './app.module'; 69 | 70 | async function bootstrap() { 71 | const app = await NestFactory.create(AppModule); 72 | app.useGlobalFilters(new HttpExceptionFilter()); 73 | await app.listen(3000); 74 | } 75 | bootstrap(); 76 | ``` 77 | 78 | **Controller-Level Application:** 79 | 80 | ```typescript 81 | import { Controller, UseFilters } from '@nestjs/common'; 82 | import { HttpExceptionFilter } from 'hodfords/nestjs-exception'; 83 | 84 | @Controller('users') 85 | @UseFilters(HttpExceptionFilter) 86 | export class UserController {} 87 | ``` 88 | 89 | #### 2\. **Throwing a Custom Exception** 90 | 91 | ```typescript 92 | import { UuidException } from '@hodfords/nestjs-exception'; 93 | 94 | @Controller('users') 95 | export class UserController { 96 | @Get(':id') 97 | getUser(@Param('id') id: string) { 98 | if (!isValidUUID(id)) { 99 | throw new UuidException('id'); // Translation key: 'error.field_malformed' 100 | } 101 | return { id }; 102 | } 103 | } 104 | ``` 105 | 106 | ## License 107 | 108 | This project is licensed under the MIT License 109 | -------------------------------------------------------------------------------- /pages/nestjs-command/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | displayed_sidebar: docs 3 | title: "@hodfords/nestjs-command" 4 | --- 5 | 8 | 9 |nestjs-command simplifies creating and managing CLI commands in NestJS applications. It offers an easy way to define and execute commands, streamlining CLI integration and boosting productivity with minimal configuration.
10 | 11 | ## Installation 🤖 12 | 13 | Install the `nestjs-command` package with: 14 | 15 | ``` 16 | npm install @hodfords/nestjs-command --save 17 | ``` 18 | 19 | Set up in your codebase: 20 | 21 | - `src/config/command.config.ts` 22 | 23 | ```javascript 24 | import { CommandModule } from '@hodfords/nestjs-command'; 25 | 26 | export const commandConfig = CommandModule.register(); 27 | 28 | // export const = CommandModule.register(false) if typeorm is disabled 29 | ``` 30 | 31 | - `src/app.module.ts` 32 | 33 | ```javascript 34 | import { Module } from '@nestjs/common'; 35 | import { commandConfig } from '~config/command.config'; 36 | 37 | @Module({ 38 | imports: [commandConfig], 39 | controllers: [], 40 | providers: [] 41 | }) 42 | export class AppModule {} 43 | ``` 44 | 45 | - `src/cli.ts` 46 | 47 | ```javascript 48 | import { NestFactory } from '@nestjs/core'; 49 | import { CommandService } from '@hodfords/nestjs-command'; 50 | import { commandConfig } from '~config/command.config'; 51 | 52 | async function bootstrap() { 53 | const app = await NestFactory.createApplicationContext(AppModule); 54 | const commandService: CommandService = app.select(commandConfig).get(CommandService, { strict: true }); 55 | await commandService.exec(); 56 | await app.close(); 57 | } 58 | 59 | bootstrap(); 60 | ``` 61 | 62 | - `package.json` 63 | 64 | ```json 65 | "wz-command": "wz-command" 66 | ``` 67 | 68 | ## Usage 🚀 69 | 70 | Here’s how you can use them. For each type of component, you can use one of the two available command formats: with `npm run` or directly with `wz-command` 71 | 72 | ### Make a command 73 | 74 | ```bash 75 | npm run wz-command make-command10 | 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. 11 |
12 | 13 | ## Installation 🤖 14 | 15 | To begin using it, we first install the required dependencies. 16 | 17 | ``` 18 | npm install @hodfords/nestjs-response 19 | ``` 20 | 21 | ## Interceptor Setup 🚀 22 | 23 | - `Global Interceptor (Recommended):` 24 | 25 | 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. 26 | 27 | ```typescript 28 | import { APP_INTERCEPTOR } from '@nestjs/core'; 29 | import { ResponseInterceptor } from '@hodfords/nestjs-response'; 30 | 31 | @Module({ 32 | providers: [ 33 | { 34 | provide: APP_INTERCEPTOR, 35 | useClass: ResponseInterceptor 36 | } 37 | ] 38 | }) 39 | export class AppModule {} 40 | ``` 41 | 42 | - `Interceptor with Decorator:` 43 | 44 | 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. 45 | 46 | ```typescript 47 | import { Controller } from '@nestjs/common'; 48 | import { UseResponseInterceptor } from '@hodfords/nestjs-response'; 49 | 50 | @Controller() 51 | @UseResponseInterceptor() 52 | export class AppController {} 53 | ``` 54 | 55 | ## Usage 🚀 56 | 57 | `@ResponseModel()` 58 | 59 | Use the @ResponseModel decorator when an API return single response type. 60 | 61 | Parameter: 62 | 63 | - `responseClass`: The class that defines the response model. 64 | - `isArray` (optional): Set to `true` if the response is an array of `responseClass`. Defaults to `false`. 65 | - `isAllowEmpty` (optional): Set to true if the response can be empty. Defaults to `false`. 66 | 67 | Example of usage: 68 | 69 | ```typescript 70 | import { ResponseModel } from '@hodfords/nestjs-response'; 71 | import { Get } from '@nestjs/common'; 72 | import { IsNotEmpty, IsString } from 'class-validator'; 73 | 74 | class UserResponse { 75 | @IsNotEmpty() 76 | @IsString() 77 | name: string; 78 | } 79 | 80 | export class UserController { 81 | @Get() 82 | @ResponseModel(UserResponse, true) 83 | getAllUser() { 84 | return [{ name: 'John' }]; 85 | } 86 | } 87 | ``` 88 | 89 | `@ResponseModels()` 90 | 91 | Use the @ResponseModels decorator when an API might return multiple response types. 92 | 93 | Parameter: 94 | 95 | - `...responseClasses`: A list of response classes or arrays of response classes. 96 | 97 | Example of usage: 98 | 99 | ```typescript 100 | import { ResponseModels } from '@hodfords/nestjs-response'; 101 | import { Controller, Get, Param } from '@nestjs/common'; 102 | import { UserResponse } from './responses/user.response'; 103 | import { UserPaginationResponse } from './responses/user-pagination.response'; 104 | 105 | @Controller() 106 | export class AppController { 107 | @Get('list-models/:type') 108 | @ResponseModels(Number, [Number], UserPaginationResponse, [UserResponse], undefined, null) 109 | getModels(@Param('type') type: string) { 110 | if (type == 'undefined') { 111 | return undefined; 112 | } 113 | if (type == 'pagination') { 114 | return { 115 | items: [{ name: 'John' }, { name: 'Daniel' }], 116 | total: 2, 117 | lastPage: 1, 118 | perPage: 10, 119 | currentPage: 1 120 | }; 121 | } 122 | if (type == 'multiple') { 123 | return [{ name: 'John' }, { name: 'Daniel' }]; 124 | } 125 | if (type == 'list-number') { 126 | return [123, 456]; 127 | } 128 | if (type == 'number') { 129 | return 456; 130 | } 131 | return null; 132 | } 133 | } 134 | 135 | ``` 136 | 137 | ### Exception Handling 138 | 139 | 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. 140 | 141 | Example Case: If a property is expected to be a string, but a number is returned, a validation error will occur. 142 | 143 | ```typescript 144 | import { ResponseModel } from '@hodfords/nestjs-response'; 145 | import { Get } from '@nestjs/common'; 146 | import { IsString } from 'class-validator'; 147 | 148 | class UserResponse { 149 | @IsString() 150 | name: string; 151 | } 152 | 153 | export class UserController { 154 | @Get() 155 | @ResponseModel(UserResponse) 156 | getUser() { 157 | return { name: 123 }; // Error: name must be a number ... 158 | } 159 | } 160 | 161 | ``` 162 | 163 | ## License 164 | 165 | This project is licensed under the MIT License 166 | -------------------------------------------------------------------------------- /pages/typeorm-migrations/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | displayed_sidebar: docs 3 | title: "@hodfords/typeorm-migrations" 4 | --- 5 | 8 | 9 | ## Installation 🤖 10 | 11 | Install the `typeorm-migrations` package with: 12 | 13 | ```bash 14 | npm install @hodfords/typeorm-migrations --save 15 | ``` 16 | 17 | ### Usage 18 | 19 | We develop a class that abstracts the typeorm migration, making it easier to understand. For the update command, let's 20 | use pure queries for the time being. 21 | 22 | ### Example 23 | 24 | ```typescript 25 | export class CreateUserTable1626749239046 extends BaseMigration { 26 | async run(queryRunner: QueryRunner) { 27 | await this.create('User', (table) => { 28 | table.primaryUuid('id'); 29 | table.string('email').index(); 30 | table.string('firstName').nullable(); 31 | table.string('lastName').nullable(); 32 | table.string('password').nullable(); 33 | table.integer('role'); 34 | table.string('language').length(10).default("'en'"); 35 | table.timestamp('lastLoginAt').nullable(); 36 | table.uuid('enterpriseId').nullable().index().foreign('Enterprise'); 37 | table.createdAt().index(); 38 | table.updatedAt(); 39 | table.deletedAt(); 40 | }); 41 | } 42 | 43 | async rollback(queryRunner: QueryRunner) { 44 | await this.drop('User'); 45 | } 46 | } 47 | ``` 48 | 49 | ### Table methods 50 | 51 | The Table class provides various methods for defining columns in a database schema 52 | 53 | ```typescript 54 | string(name: string, length?: number, options?: Partialnestjs-mailer simplifies integrating and managing email functionalities in NestJS applications, making email operations easier and more efficient.
10 | 11 | ## Installation 🤖 12 | 13 | Install the `nestjs-mailer` package with: 14 | 15 | ``` 16 | npm install @hodfords/nestjs-mailer --save 17 | ``` 18 | 19 | To configure the mailer module dynamically, use `forRoot` to define your email template renderers, transport settings, and default sender email. 20 | 21 | ```typescript 22 | export const mailConfig = MailerModule.forRoot({ 23 | renders: { 24 | adapters: [ 25 | new HbsAdapter({ 26 | templateFolder: path.join(env.ROOT_PATH, `mails/templates/${getEmailFolder()}`), 27 | defaultVariable: async () => getMailConfigurations() 28 | }), 29 | new TranslateAdapter((text: string, options: any) => trans(text, options)), 30 | new MjmlAdapter() 31 | ], 32 | transport: env.MAILER_URL, 33 | defaultFrom: env.CONTACT_MAIL_ADDRESS 34 | }, 35 | ... 36 | }); 37 | ``` 38 | 39 | For more advanced use cases where additional services or repositories are required, you can register the module using `forRootAsync`. This allows injecting services, repositories, or even database connections for more complex setups 40 | 41 | ```typescript 42 | export const mailConfig = MailerModule.forRootAsync({ 43 | imports: [CoreModule], 44 | inject: [Connection, StorageService], 45 | useFactory: (connection: Connection, storageService: StorageService) => { 46 | const settingRepo = connection.getCustomRepository(SettingRepository); 47 | const hbsAdapter = new HbsAdapter({ 48 | templateFolder: path.join(env.ROOT_PATH, `mails/templates/${getEmailFolder()}`), 49 | defaultVariable: async (mail: BaseMail) => { 50 | const variables = getMailConfigurations(); 51 | if (mail.isWhitelabeled) { 52 | const setting = await settingRepo.findOne({ tenant: mail.tenantId }); 53 | variables.logoUrl = await storageService.generateBlobUrl(setting.blobLogo); 54 | } 55 | return variables; 56 | } 57 | }); 58 | return { 59 | renders: { 60 | adapters: [ 61 | hbsAdapter, 62 | new TranslateAdapter((text: string, options: any) => trans(text, options)), 63 | new MjmlAdapter() 64 | ] 65 | }, 66 | transport: env.MAILER_URL, 67 | defaultFrom: env.CONTACT_MAIL_ADDRESS 68 | }; 69 | } 70 | }); 71 | ``` 72 | 73 | ## Usage 🚀 74 | 75 | ### Adapters 76 | 77 | Currently, nestjs-mailer supports the following adapters: 78 | 79 | - `HbsAdapter`: For rendering Handlebars templates with dynamic variables and templates. 80 | - `TranslateAdapter`: For handling multi-language support and translations. 81 | - `MjmlAdapter`: For generating responsive HTML emails using MJML templates. 82 | 83 | ### Defining an Email 84 | 85 | To define a custom email, extend the BaseMail class and specify the email subject, template path, and data. 86 | 87 | Here's an example of how to define a `WelcomeEmail`: 88 | 89 | ```typescript 90 | import { BaseMail } from '@hodfords/nestjs-mailer'; 91 | 92 | export class WelcomeMail extends BaseMail { 93 | constructor(private email: string) { 94 | super(); 95 | } 96 | 97 | get subject(): string { 98 | return 'Welcome to Hodfords!'; 99 | } 100 | 101 | get template(): string { 102 | return path.join(env.ROOT_PATH, 'welcome-mail.mail.hbs'); 103 | } 104 | 105 | data(): Recordnestjs-transaction makes managing database transactions in NestJS easy and straightforward. It provides simple tools to start, commit, and roll back transactions, helping you ensure that multiple database operations are completed successfully or not at all. With `nestjs-transaction`, you can handle complex transaction scenarios with ease, making your data handling more reliable and error-free.
10 | 11 | ## Installation 🤖 12 | 13 | Install the `nestjs-transaction` package with: 14 | 15 | ```ts 16 | npm install @hodfords/nestjs-transaction --save 17 | ``` 18 | 19 | ## Usage 🚀 20 | 21 | First, you need to import the `TransactionModule` into your `AppModule` and 22 | 23 | ```typescript 24 | import { Module } from '@nestjs/common'; 25 | import { TransactionModule } from '@hodfords/nestjs-transaction'; 26 | 27 | @Module({ 28 | imports: [ 29 | TransactionModule.forRoot({ 30 | autoUseMasterNodeForChangeRequest: true 31 | }), 32 | // other modules 33 | ], 34 | controllers: [], 35 | providers: [], 36 | }) 37 | export class AppModule {} 38 | ``` 39 | #### Optional Configuration 40 | You can configure the `TransactionModule` with the following options: 41 | - `autoUseMasterNodeForChangeRequest`: If set to `true`, the module will automatically use the master node for change requests (except GET). This is useful for ensuring that write operations are always directed to the correct database node. 42 | 43 | ### How to use 44 | 45 | #### Transactional 46 | 47 | You can use the `@Transactional` decorator to mark a method as transactional. This means that all database operations within this method and child methods will be executed within a transaction context. If any operation fails, the entire transaction will be rolled back, ensuring data integrity. 48 | 49 | In any service, you can use the `@Transactional` decorator to ensure that the method is executed within a transaction context: 50 | 51 | > **Note**: We suggest using the `@Transactional` decorator on Controller/Task/Cron jobs methods, as it will automatically handle the transaction lifecycle for you. However, you can also use it in services if needed. 52 | 53 | ```typescript 54 | @Transactional() 55 | async myTransactionalMethod() { 56 | await this.myRepository.save(myEntity); 57 | } 58 | ``` 59 | 60 | In controllers, you can also use the `@Transactional` decorator to ensure that the entire request is wrapped in a transaction: 61 | ```typescript 62 | 63 | import { Controller, Post } from '@nestjs/common'; 64 | import { Transactional } from '@hodfords/nestjs-transaction'; 65 | import { MyService } from './my.service'; 66 | 67 | @Controller('my') 68 | export class MyController { 69 | constructor(private myService: MyService) {} 70 | 71 | @Post('create') 72 | @Transactional() 73 | async create() { 74 | return this.myService.create(); 75 | } 76 | } 77 | ``` 78 | 79 | You also use the `@Transactional` decorator with options to control the transaction behavior, such as isolation level. For example: 80 | 81 | ```typescript 82 | @Transactional({ isolationLevel: 'SERIALIZABLE'}) 83 | async myTransactionalMethod() { 84 | // This method will run in a transaction with SERIALIZABLE isolation level 85 | await this.myRepository.save(myEntity); 86 | } 87 | ``` 88 | 89 | #### Replication 90 | You can use the `@UseMasterNode`/`@UseSlaveNode` decorator to ensure that a method is executed on the master/slave node. This is useful for write operations that need to be directed to the master/slave database node. 91 | 92 | ```typescript 93 | import { Controller, Post } from '@nestjs/common'; 94 | import { UseMasterNode } from '@hodfords/nestjs-transaction'; 95 | import { MyService } from './my.service'; 96 | 97 | @Controller('my') 98 | export class MyController { 99 | constructor(private myService: MyService) {} 100 | 101 | @Post('create') 102 | @UseMasterNode() 103 | async create() { 104 | return this.myService.create(); 105 | } 106 | } 107 | ``` 108 | 109 | #### Hooks 110 | 111 | You can use the `@RunAfterTransactionCommit` decorator to run a method after a transaction has been successfully committed. This is useful for performing actions that should only occur if the transaction was successful. 112 | 113 | ```typescript 114 | import { Injectable } from '@nestjs/common'; 115 | import { RunAfterTransactionCommit } from '@hodfords/nestjs-transaction'; 116 | import { PostRepository } from './post.repository'; 117 | 118 | @Injectable() 119 | export class MyService { 120 | 121 | constructor(private postRepo: PostRepository) { 122 | } 123 | 124 | @Transactional() 125 | async create() { 126 | // Perform some database operations 127 | await this.postRepo.createPost({ title: 'New Post', content: 'This is a new post.' }); 128 | await this.emitEvent(); 129 | } 130 | 131 | @RunAfterTransactionCommit() 132 | async emitEvent() { 133 | // This method will be called after the transaction is committed 134 | console.log('Transaction committed successfully!'); 135 | } 136 | } 137 | ``` 138 | 139 | You also use it with method `runAfterTransactionCommit` without the decorator: 140 | 141 | ```typescript 142 | 143 | this.postRepo.create(...); 144 | runAfterTransactionCommit(() => { 145 | // This code will run after the transaction is committed 146 | console.log('Transaction committed successfully!'); 147 | }); 148 | ``` 149 | ## License 📝 150 | 151 | This project is licensed under the MIT License 152 | -------------------------------------------------------------------------------- /pages/nestjs-api-gateway/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | displayed_sidebar: docs 3 | title: "@hodfords/nestjs-api-gateway" 4 | --- 5 | 8 | 9 | # API Gateway 10 | 11 | The API Gateway houses the source code and documentation for the API Gateway - a powerful and versatile solution for managing and deploying APIs within a distributed and microservices-oriented architecture. This repository serves as the central hub for collaboration, version control, and issue tracking related to the development and enhancement of the API Gateway. 12 | 13 | ## Key Features: 14 | 15 | - **Centralized API Management**: The API Gateway streamlines API management by providing a central entry point for client applications. It handles API requests, directs traffic to appropriate microservices, and offers additional functionalities to developers and administrators. 16 | 17 | - **Security and Authentication**: Security is paramount, and the API Gateway offers robust authentication and authorization mechanisms to protect APIs from unauthorized access. It supports various authentication protocols, including API keys, JWT. 18 | 19 | - **Rate Limiting and Throttling**: To prevent abuse and ensure fair usage, the API Gateway allows administrators to set rate limits and throttling rules. This helps maintain API performance and prevents any single client from overwhelming the system. 20 | 21 | - **Logging and Monitoring**: The API Gateway provides comprehensive logging and monitoring capabilities, allowing developers and administrators to gain insights into API usage, performance, and errors in real-time. 22 | 23 | - **WebSocket Support**: Beyond traditional RESTful APIs, the API Gateway supports WebSocket communication for real-time interactions and push notifications. 24 | 25 | - **Error Handling and Fault Tolerance**: The API Gateway is designed with robust error handling and fault tolerance mechanisms to ensure high availability and reliability. 26 | 27 | ## Usage 28 | 29 | #### Install 30 | ```shell 31 | npm install @hodfords/api-gateway 32 | ``` 33 | 34 | #### Configuration 35 | Import the `ApiGatewayModule` and use the `forRoot` method to configure the API Gateway. The `forRoot` method accepts an options object with the following properties: 36 | ```typescript 37 | @Module({ 38 | imports: [ 39 | RedisModule.forRoot({ 40 | config: { 41 | host: env.REDIS.HOST, 42 | port: env.REDIS.PORT, 43 | db: env.REDIS.DB 44 | } 45 | }), // Required 46 | ScheduleModule.forRoot(), // Required 47 | ApiGatewayModule.forRoot({ 48 | apiServices: env.API_SERVICES, 49 | openApiSecurityKeys: ['auth-user-id'], 50 | openApiSecurityApiKeys: ['x-api-key'], 51 | excludeHeaders: ['auth-user-id'], 52 | swaggerOptions: { 53 | showExtensions: false, 54 | }, 55 | throttler: { 56 | globalRateLimit: 60, 57 | isEnable: true, 58 | globalRateLimitTTL: 60 59 | } 60 | }) 61 | ], 62 | controllers: [], 63 | providers: [] 64 | }) 65 | export class AppModule {} 66 | ``` 67 | 68 | #### Custom Authentication Header 69 | You can handle the authentication header by creating a custom authentication handler. The `handle` method will be called before the request is processed. The `handle` method accepts the incoming request object and should return a boolean value indicating whether the request is authenticated. 70 | ```typescript 71 | @ProxyMiddleware() 72 | export class AuthenticationMiddleware implements ProxyMiddlewareHandler { 73 | async handle(routerDetail: RouterDetail, request: IncomingMessage, proxyRequest: ProxyRequest): Promisenestjs-validation enhances validation in your NestJS projects by providing a customized `ValidationPipe` that returns custom error messages. This library simplifies error handling by offering localized and user-friendly responses
10 | 11 | ## Installation 🤖 12 | 13 | Install the `typeorm-helper` package with: 14 | 15 | ```bash 16 | npm install @hodfords/typeorm-helper --save 17 | ``` 18 | 19 | ## Usage 🚀 20 | 21 | ### Defining custom repositories and entities 22 | 23 | When managing different entities, you can define custom repositories and entities. Below is an example for the Category entity and its corresponding repository. 24 | 25 | #### Entity 26 | 27 | The `Category` table in the database is modeled by the `CategoryEntity`, `typeorm` decorators should be used to define this entity. 28 | 29 | ```typescript 30 | import { BaseEntity } from '@hodfords/typeorm-helper'; 31 | import { Column, Entity, ManyToMany, JoinTable, PrimaryGeneratedColumn } from 'typeorm'; 32 | 33 | @Entity('Category') 34 | export class CategoryEntity extends BaseEntity { 35 | @PrimaryGeneratedColumn() 36 | id: number; 37 | 38 | @Column() 39 | name: string; 40 | 41 | @ManyToMany(() => PostEntity, (post) => post.categories) 42 | @JoinTable({ name: 'PostCategory' }) 43 | posts: PostEntity[]; 44 | } 45 | ``` 46 | 47 | #### Repository 48 | 49 | The `CategoryRepository` is a custom repository that handles all database operations related to the `CategoryEntity`. By using the `@CustomRepository` decorator and extending `BaseRepository`, you ensure that your repository has both common CRUD functionality and can be easily customized with entity-specific methods. 50 | 51 | ```typescript 52 | import { CustomRepository, BaseRepository } from '@hodfords/typeorm-helper'; 53 | 54 | @CustomRepository(CategoryEntity) 55 | export class CategoryRepository extends BaseRepository10 | nestjs-grpc-helper simplifies gRPC integration in NestJS, allowing seamless communication between services. It enables easy setup of gRPC clients and servers, and supports building SDK packages that any service can import and use, ensuring consistent API interaction across your microservices architecture. 11 |
12 | 13 | ## Installation 🤖 14 | 15 | Install the `nestjs-grpc-helper` package with: 16 | 17 | ```bash 18 | npm install @hodfords/nestjs-grpc-helper --save 19 | ``` 20 | 21 | Next, automatically generate the proto file and include it in main.ts before starting the application: 22 | 23 | ```typescript 24 | import { generateProtoService } from '@hodfords/nestjs-grpc-helper'; 25 | 26 | generateProtoService(camelCase(env.APP_NAME), env.ROOT_PATH + '/../'); 27 | ``` 28 | 29 | ## Usage 🚀 30 | 31 | ### Creating microservices 32 | 33 | Create microservices using the `@GrpcMicroservice` decorator, similar to how you would use a Controller. Ensure that the response adheres to the [nestjs-response](https://www.npmjs.com/package/@hodfords/nestjs-response) rules: 34 | 35 | ```typescript 36 | @GrpcMicroservice() 37 | export class UserMicroservice { 38 | constructor(private userService: UserService) {} 39 | 40 | @GrpcAction('Get user by id') 41 | @ResponseModel(UserResponse) 42 | findUserById(@GrpcValue() dto: GetUserByIdDto): Promise10 | Nestjs-Base-Decorator provides a collection of useful, ready-to-use custom decorators for NestJS, designed to enhance and simplify common functionality in your applications. These decorators will help you write cleaner and more maintainable code, reducing the need for repetitive boilerplate. 11 |
12 | 13 | ## Installation 🤖 14 | 15 | To begin using it, we first install the required dependencies. 16 | 17 | ``` 18 | npm install @hodfords/nestjs-base-decorator 19 | ``` 20 | 21 | ## Table of Contents 22 | 23 | - [Installation 🤖](#installation-) 24 | - [Table of Contents](#table-of-contents) 25 | - [Usage 🚀](#usage-) 26 | - [Param Decorators](#param-decorators) 27 | - [@EnumQuery()](#enumquery) 28 | - [@EnumsQuery()](#enumsquery) 29 | - [@Id()](#id) 30 | - [@Ids()](#ids) 31 | - [@Int()](#int) 32 | - [@Ints()](#ints) 33 | - [@Pagination()](#pagination) 34 | - [@QueryBoolean()](#queryboolean) 35 | - [@QueryStrings()](#querystrings) 36 | - [@RealIp()](#realip) 37 | - [@RequireToUploadFile()](#requiretouploadfile) 38 | - [@RequireToUploadFiles()](#requiretouploadfiles) 39 | - [@Sort()](#sort) 40 | - [@Sorts()](#sorts) 41 | - [@Timestamp()](#timestamp) 42 | - [@Timezone()](#timezone) 43 | - [@UserAgent()](#useragent) 44 | - [@Value()](#value) 45 | - [Validators](#validators) 46 | 47 | ## Usage 🚀 48 | 49 | ### Param Decorators 50 | 51 | #### @EnumQuery() 52 | 53 | Use the `EnumQuery` decorator when you expect a single enum value as a query parameter. This will validate the query parameter against a predefined enum and generate Swagger documentation for it. 54 | 55 | Parameters: 56 | 57 | - `options`: 58 | - `key`: The name of the query parameter (required). 59 | - `enum`: The enum to validate against (required). 60 | - `separator`: The delimiter for multiple values (optional, default: `,`). 61 | - `description`: A description for Swagger documentation (optional). 62 | - `nullable`: If true, the query parameter is allowed to be `null` (optional, default: `false`). 63 | - `singleValue`: Only used internally for `EnumQuery` to indicate a single value (you don't need to set this manually). 64 | 65 | Example for usage: 66 | 67 | ```typescript 68 | 69 | import { Controller, Get } from '@nestjs/common'; 70 | import { EnumQuery } from '@hodfords/nestjs-base-decorator'; 71 | 72 | enum StatusEnum { 73 | ACTIVE = 'active', 74 | INACTIVE = 'inactive', 75 | } 76 | 77 | @Controller() 78 | export class ItemController { 79 | @Get('items') 80 | getItemByStatus( 81 | @EnumQuery({ 82 | key: 'status', 83 | enum: StatusEnum, 84 | description: 'Status of the item', 85 | nullable: false, 86 | }) 87 | status: StatusEnum, 88 | ) { 89 | return status; 90 | } 91 | } 92 | 93 | /* 94 | Request: GET /items?status=active 95 | Response: active 96 | */ 97 | ``` 98 | 99 | #### @EnumsQuery() 100 | 101 | Use the `EnumsQuery` decorator when you expect multiple enum values as query parameters, separated by a custom delimiter (default is `,`). This will validate the query parameters against a predefined enum and generate Swagger documentation for them. 102 | 103 | Parameters: 104 | 105 | - `options`: 106 | 107 | - `key`: The name of the query parameter (required). 108 | - `enum`: The enum to validate against (required). 109 | - `separator`: The delimiter for multiple values (optional, default: `,`). 110 | - `description`: A description for Swagger documentation (optional). 111 | - `nullable`: If true, the query parameter is allowed to be `null` (optional, default: `false`). 112 | - `singleValue`: Only used internally for `EnumQuery` to indicate a single value (you don't need to set this manually). 113 | 114 | Example for usage: 115 | 116 | ```typescript 117 | import { Controller, Get } from '@nestjs/common'; 118 | import { EnumsQuery } from '@hodfords/nestjs-base-decorator'; 119 | 120 | enum CategoryEnum { 121 | ELECTRONICS = 'electronics', 122 | FASHION = 'fashion', 123 | BOOKS = 'books', 124 | } 125 | 126 | @Controller() 127 | export class ProductController { 128 | @Get('products') 129 | getProductsByCategories( 130 | @EnumsQuery({ 131 | key: 'categories', 132 | enum: CategoryEnum, 133 | description: 'Categories of the product', 134 | separator: ',', 135 | nullable: false, 136 | }) 137 | categories: CategoryEnum[], 138 | ) { 139 | return categories; 140 | } 141 | } 142 | 143 | /* 144 | Request: GET /products?categories=books,fashion 145 | Response: ["books", "fashion"] 146 | */ 147 | ``` 148 | 149 | #### @Id() 150 | 151 | Use the `Id` decorator to validate a single UUID, either from the route parameters or query parameters. If the provided value is not a valid UUID, it will throw a `UuidException` from the `@hodfords/nestjs-exception` package. 152 | 153 | Parameters: 154 | 155 | - `options` (`string` | `ParamOptions`): 156 | 157 | - `key`: The name of the parameter in the request (required). 158 | - `nullable`: If `true`, the parameter is allowed to be null (optional, default: `false`). 159 | 160 | Example for usage: 161 | 162 | ```typescript 163 | import { Controller, Get } from '@nestjs/common'; 164 | import { Id } from '@hodfords/nestjs-base-decorator'; 165 | 166 | @Controller('users') 167 | export class UserController { 168 | @Get(':id') 169 | getUserById(@Id('id') id: string) { 170 | return id; 171 | } 172 | } 173 | 174 | /* 175 | Request: GET users/8be26127-c0ed-4cad-bd45-7f40dcf53e89 176 | Response: 8be26127-c0ed-4cad-bd45-7f40dcf53e89 177 | */ 178 | ``` 179 | 180 | #### @Ids() 181 | 182 | Use the `Ids` decorator when you need to validate multiple UUIDs passed as a comma-separated list in the `query` parameters. If any value in the list is not a valid UUID, it throws a `UuidException` from the `@hodfords/nestjs-exception` package. 183 | 184 | Parameters: 185 | 186 | - `options` (`string` | `ParamOptions`): 187 | 188 | - `key`: The name of the parameter in the request (required). 189 | - `nullable`: If `true`, the parameter is allowed to be null (optional, default: `false`). 190 | 191 | Example for usage: 192 | 193 | ```typescript 194 | import { Controller, Get } from '@nestjs/common'; 195 | import { Ids } from '@hodfords/nestjs-base-decorator'; 196 | 197 | @Controller('users') 198 | export class UserController { 199 | @Get() 200 | getUsersByIds(@Ids('ids') ids: string[]) { 201 | return ids; 202 | } 203 | } 204 | 205 | /* 206 | Request: GET users?ids=8be26127-c0ed-4cad-bd45-7f40dcf53e89,1b3a0d50-2695-49e7-9498-c4cb1cada6e9 207 | Response: ["8be26127-c0ed-4cad-bd45-7f40dcf53e89","1b3a0d50-2695-49e7-9498-c4cb1cada6e9"] 208 | */ 209 | ``` 210 | 211 | #### @Int() 212 | 213 | The `Int` decorator is used to validate a single integer, either from route parameters or query parameters. 214 | 215 | Parameters: `key` (default: `'id'`) 216 | 217 | Example for usage: 218 | 219 | ```typescript 220 | import { Controller, Get } from '@nestjs/common'; 221 | import { Int } from '@hodfords/nestjs-base-decorator'; 222 | 223 | @Controller('users') 224 | export class UserController { 225 | @Get(':id') 226 | getUserById(@Int('id') id: number) { 227 | return id; 228 | } 229 | } 230 | 231 | /* 232 | Request: GET /users/123 233 | Response: 123 234 | */ 235 | ``` 236 | 237 | #### @Ints() 238 | 239 | The `Ints` decorator is used to validate multiple integers passed as a comma-separated list in query parameters. 240 | 241 | Parameters: `key` (default: `'ids'`) 242 | 243 | Example for usage: 244 | 245 | ```typescript 246 | import { Controller, Get } from '@nestjs/common'; 247 | import { Ints } from '@hodfords/nestjs-base-decorator'; 248 | 249 | @Controller('users') 250 | export class UserController { 251 | @Get() 252 | getUsersByIds(@Ints('ids') ids: number[]) { 253 | return ids; 254 | } 255 | } 256 | 257 | /* 258 | Request: GET /users?ids=123,456 259 | Response: [123,456] 260 | */ 261 | ``` 262 | 263 | #### @Pagination() 264 | 265 | The `Pagination` decorator is used to handle pagination logic by extracting the `page` and `perPage` parameters from the query string of an incoming request. The decorator also includes automatic Swagger documentation using `nestjs/swagger`. 266 | 267 | Parameters: 268 | 269 | - `paginationParams`: 270 | - `page`: The current page number (optional, default: 1). 271 | - `perPage`: The number of items per page (optional, default: 10, max: 1000). 272 | 273 | Example for usage: 274 | 275 | ```typescript 276 | import { Controller, Get } from '@nestjs/common'; 277 | import { Pagination, PaginationParams } from '@hodfords/nestjs-base-decorator'; 278 | 279 | @Controller('users') 280 | export class UserController { 281 | @Get() 282 | getUsers( 283 | @Pagination() pagination: PaginationParams 284 | ) { 285 | return `Page: ${pagination.page}, Per Page: ${pagination.perPage}`; 286 | } 287 | } 288 | 289 | /* 290 | Request: GET /users?page=1&perPage=10 291 | Response: Page: 1, Per Page: 10 292 | */ 293 | ``` 294 | 295 | #### @QueryBoolean() 296 | 297 | The `QueryBoolean` decorator allows you to extract and validate boolean values from the query parameters in a NestJS route. It checks if the query parameter is `'true'` and returns `true`, otherwise it returns `false`. 298 | 299 | Parameters: `key`, `options` (`ApiQueryOptions`) 300 | 301 | Example for usage: 302 | 303 | ```typescript 304 | import { Controller, Get } from '@nestjs/common'; 305 | import { QueryBoolean } from '@hodfords/nestjs-base-decorator'; 306 | 307 | @Controller('users') 308 | export class UsersController { 309 | @Get() 310 | getUsers(@QueryBoolean('isActive') isActive: boolean) { 311 | return isActive; 312 | } 313 | } 314 | 315 | /* 316 | Request: GET /users?isActive=true 317 | Response: true 318 | 319 | Request: GET /users?isActive=123 320 | Response: false 321 | */ 322 | ``` 323 | 324 | #### @QueryStrings() 325 | 326 | The `QueryStrings` decorator extracts query parameters from HTTP requests, parses them as comma-separated strings, and ensures uniqueness by eliminating duplicates. Additionally, it integrates with `@nestjs/swagger` to automatically document the query parameters in the Swagger UI. 327 | 328 | Parameters: `key`, `options` (`ApiQueryOptions`) 329 | 330 | Example for usage: 331 | 332 | ```typescript 333 | import { Controller, Get } from '@nestjs/common'; 334 | import { QueryStrings } from '@hodfords/nestjs-base-decorator'; 335 | 336 | @Controller() 337 | export class AppController { 338 | constructor() {} 339 | 340 | @Get() 341 | findTags(@QueryStrings('tags') tags: string[]): string[] { 342 | return tags; 343 | } 344 | } 345 | 346 | /* 347 | Request: GET ?tags=name,age 348 | Response: ["name, "age"] 349 | */ 350 | ``` 351 | 352 | #### @RealIp() 353 | 354 | The `RealIp` decorator is a custom NestJS decorator that retrieves the client's real IP address from an incoming HTTP request. It leverages the `@supercharge/request-ip` library to accurately identify the IP address, even if the client is behind a proxy or using a load balancer. 355 | 356 | Example for usage: 357 | 358 | ```typescript 359 | import { Controller, Get } from '@nestjs/common'; 360 | import { RealIp } from '@hodfords/nestjs-base-decorator'; 361 | 362 | @Controller('users') 363 | export class UserController { 364 | 365 | @Get('ip') 366 | getClientIp(@RealIp() ip: string): string { 367 | return `Client IP: ${ip}`; 368 | } 369 | } 370 | 371 | /* 372 | Request: GET /ip 373 | Response: "Client IP": "203.0.113.195" 374 | */ 375 | ``` 376 | 377 | #### @RequireToUploadFile() 378 | 379 | The `RequireToUploadFile` decorator is a custom NestJS decorator that simplifies file upload handling for single and multiple file uploads. It leverages NestJS `Interceptors` and custom interceptors to validate file uploads. The decorator allows developers to specify file upload configurations like file size limits, allowed MIME types, and custom storage engines. 380 | 381 | Parameters: 382 | 383 | - `fieldName`: Specifies the form field name used to upload the file(s). 384 | - `options`: An object that configures the file upload behavior. It includes: 385 | - `fileSize`: Maximum file size (in bytes) for the upload. Default is set to `10 * 1024 * 1024`. 386 | - `allowedMimeTypes`: Array of allowed MIME types for the uploaded files. Default is `['image/png', 387 | 'image/jpeg', 388 | 'image/jpg', 389 | 'image/svg+xml', 390 | 'image/bmp', 391 | 'image/heic', 392 | 'image/heif', 393 | 'application/pdf', 394 | 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 395 | 'application/vnd.ms-excel']`. 396 | - `maxCount`: Maximum number of files that can be uploaded in a single request. 397 | - `storageEngine`: Custom storage engine for handling uploaded files (e.g., disk storage or cloud storage). 398 | 399 | Example for usage: 400 | 401 | ```typescript 402 | import { Controller, Post, UploadedFiles } from '@nestjs/common'; 403 | import { RequireToUploadFile } from '@hodfords/nestjs-base-decorator'; 404 | 405 | @Controller('files') 406 | export class FileController { 407 | @Post('upload') 408 | @RequireToUploadFile({ fieldName: 'file' }) 409 | uploadFile(@UploadedFiles() file: Express.Multer.File[]) { 410 | return file; 411 | } 412 | } 413 | ``` 414 | 415 | If you want only upload with one file and present it as a object, you can follow below: 416 | 417 | ```typescript 418 | import { Controller, Post, UploadedFile } from '@nestjs/common'; 419 | import { RequireToUploadFile } from '@hodfords/nestjs-base-decorator'; 420 | 421 | @Controller('files') 422 | export class FileController { 423 | @Post('upload') 424 | @RequireToUploadFile({ fieldName: 'file', options: { maxCount: 1 } }) 425 | uploadFile(@UploadedFile() file: Express.Multer.File) { 426 | return file; 427 | } 428 | } 429 | ``` 430 | 431 | #### @RequireToUploadFiles() 432 | 433 | The `RequireToUploadFiles` decorator simplifies the process of uploading multiple files with different field names in NestJS. It uses the `FileFieldsInterceptor` from `@nestjs/platform-express` to manage multiple file uploads from distinct form fields and allows customization through file upload options. The decorator integrates with custom interceptors for additional validation and handling of the uploaded files. 434 | 435 | Parameters: 436 | 437 | - `fieldNames`: 438 | - `name`: The name of the form field. 439 | - `maxCount`: (Optional) Maximum number of files allowed for this field. If not provided, defaults to the global `maxCount` value. 440 | - `options`: 441 | - `fileSize`: Maximum file size (in bytes). 442 | - `allowedMimeTypes`: Array of allowed MIME types for uploaded files. 443 | - `maxCount`: Default maximum number of files allowed per field. 444 | - `storageEngine`: Custom storage engine to handle file uploads. 445 | 446 | Example for usage: 447 | 448 | ```typescript 449 | import { Controller, Post, UploadedFile } from '@nestjs/common'; 450 | import { RequireToUploadFile } from '@hodfords/nestjs-base-decorator'; 451 | 452 | @Controller('files') 453 | export class FileController { 454 | @Post('upload') 455 | @RequireToUploadFiles({ 456 | fieldNames: [ 457 | { name: 'profile', maxCount: 1 }, 458 | { name: 'documents', maxCount: 5 } 459 | ] 460 | }) 461 | uploadUserFiles(@UploadedFiles() files: { profile: Express.Multer.File[]; documents: Express.Multer.File[] }) { 462 | return files; 463 | } 464 | } 465 | ``` 466 | 467 | #### @Sort() 468 | 469 | The `Sort` decorator simplifies handling sorting parameters in NestJS controllers. It defines two query parameters, `sortField` and `sortDirection`, allowing API clients to specify how to sort data in their requests. The decorator integrates with Swagger for automatic API documentation and validates the sorting fields and directions against predefined sets of allowed values. 470 | 471 | Parameters: 472 | 473 | - `sortParams`: 474 | - `allowedFields`: An array of allowed fields for sorting (e.g., `['name', 'createdAt']`). 475 | - `default`: An object with default sorting parameters: 476 | - `sortField`: The default field to sort by. 477 | - `sortDirection`: The default sorting direction (`ASC` or `DESC`). 478 | 479 | Example for usage: 480 | 481 | ```typescript 482 | import { Controller, Get, Query } from '@nestjs/common'; 483 | import { Sort, SortParams } from '@hodfords/nestjs-base-decorator'; 484 | 485 | @Controller('users') 486 | export class UserController { 487 | 488 | @Get() 489 | getUsers(@Sort({ allowedFields: ['name', 'createdAt'], default: { sortField: 'createdAt', sortDirection: 'DESC' } }) query: SortParams) { 490 | const { sortField, sortDirection } = query; 491 | return `Sorted by ${sortField} in ${sortDirection} order`; 492 | } 493 | } 494 | 495 | /* 496 | Request: GET ?sortField=createdAt&sortDirection=DESC 497 | Response: Sorted by createdAt in DESC order 498 | */ 499 | ``` 500 | 501 | #### @Sorts() 502 | 503 | The `Sorts` decorator provides an elegant solution for handling multiple sorting fields in NestJS controllers. It allows clients to specify multiple fields and their respective sort directions. The decorator automatically generates Swagger documentation for these parameters and ensures proper validation of both fields and directions. 504 | 505 | Parameters: 506 | 507 | - `sortParams`: 508 | - `allowedFields`: An array of allowed fields for sorting (e.g., `['name', 'createdAt']`). 509 | - `default`: An object with default sorting parameters: 510 | - `sortField`: The default field to sort by. 511 | - `sortDirection`: The default sorting direction (`ASC` or `DESC`). 512 | 513 | Example for usage: 514 | 515 | ```typescript 516 | import { Controller, Get, Query } from '@nestjs/common'; 517 | import { Sorts, SortMultipleParams } from '@hodfords/nestjs-base-decorator'; 518 | 519 | @Controller('users') 520 | export class UserController { 521 | 522 | @Get() 523 | getUsers( 524 | @Sorts({ allowedFields: ['name', 'createdAt'], default: { sortField: 'createdAt', sortDirection: 'DESC' } }) 525 | query: SortMultipleParams[] 526 | ) { 527 | return query; 528 | } 529 | } 530 | 531 | /* 532 | Request: GET ?sortFields=createdAt,name:DESC 533 | Response: [ 534 | { 535 | "field": "createdAt", 536 | "direction": "ASC" 537 | }, 538 | { 539 | "field": "name", 540 | "direction": "DESC" 541 | } 542 | ] 543 | */ 544 | ``` 545 | 546 | #### @Timestamp() 547 | 548 | The `Timestamp` decorator is used to extract and validate a timestamp from the request parameters or query in a NestJS controller. It ensures the timestamp is valid and handles optional or nullable parameters. 549 | 550 | Parameters: 551 | 552 | - `options`: 553 | - `key`: The name of the parameter to extract (required). 554 | - `nullable`: Indicates if the timestamp can be nullable (optional, default: `false`). 555 | 556 | Example for usage: 557 | 558 | ```typescript 559 | import { Controller, Get, Query } from '@nestjs/common'; 560 | import { Timestamp } from '@hodfords/nestjs-base-decorator'; 561 | 562 | @Controller('events') 563 | export class EventController { 564 | 565 | @Get() 566 | getEvents(@Timestamp('timestamp') timestamp: number) { 567 | return timestamp; 568 | } 569 | } 570 | 571 | /* 572 | Request: GET /events?timestamp=1581739337 573 | Response: 1581739337 574 | */ 575 | ``` 576 | 577 | #### @Timezone() 578 | 579 | The `Timezone` decorator is designed to validate and extract a timezone string from request parameters or query in a NestJS controller. It leverages the `dayjs` library along with the `timezone` and `utc` plugins to ensure that the provided timezone is valid. 580 | 581 | Parameters: 582 | 583 | - `options`: 584 | - `key`: The name of the parameter to extract (required). 585 | - `nullable`: Indicates if the timestamp can be nullable (optional, default: `false`). 586 | 587 | Example for usage: 588 | 589 | ```typescript 590 | import { Controller, Get, Query } from '@nestjs/common'; 591 | import { Timezone } from '@hodfords/nestjs-base-decorator'; 592 | 593 | @Controller('events') 594 | export class EventController { 595 | 596 | @Get() 597 | getEvents(@Timezone('timezone') timezone: string) { 598 | return timezone; 599 | } 600 | } 601 | 602 | /* 603 | Request: GET ?timezone=America/New_York 604 | Response: America/New_York 605 | */ 606 | ``` 607 | 608 | #### @UserAgent() 609 | 610 | The `UserAgent` decorator is a simple utility that extracts the `User-Agent` header from incoming requests in a NestJS application. This header typically contains information about the client's browser, operating system, and device. 611 | 612 | Example for usage: 613 | 614 | ```typescript 615 | import { Controller, Get, Query } from '@nestjs/common'; 616 | import { UserAgent } from '@hodfords/nestjs-base-decorator'; 617 | 618 | @Controller('users') 619 | export class UserController { 620 | 621 | @Get('user-agent') 622 | getUserAgent(@UserAgent() userAgent: string) { 623 | return userAgent; 624 | } 625 | } 626 | ``` 627 | 628 | #### @Value() 629 | 630 | The `Value` decorator is used to extract the `value` property from the payload of a microservice request in NestJS. It is a wrapper around the `Payload` decorator provided by `@nestjs/microservices`, allowing you to directly access the `value` property in microservice message handlers. 631 | 632 | Example for usage: 633 | 634 | ```typescript 635 | import { Controller } from '@nestjs/common'; 636 | import { EventPattern } from '@nestjs/microservices'; 637 | import { Value } from '@hodfords/nestjs-base-decorator'; 638 | 639 | @Controller() 640 | export class MathController { 641 | 642 | @EventPattern('math.add') 643 | handleAddition(@Value() value: number) { 644 | return `Value received: ${value}`; 645 | } 646 | } 647 | 648 | ``` 649 | 650 | ### Validators 651 | 652 | #### @ExistIds() 653 | 654 | The `@ExistIds()` decorator is used to validate whether all provided IDs exist in a specified database table column. It uses `TypeORM` to query the table and check if the given values match the records in the database. 655 | 656 | Parameters: 657 | 658 | - `table`: The `Entity` class (which extends `BaseEntity`) represents the database table where the validation will be performed. 659 | - `allowEmpty`: A boolean to allow empty arrays as valid input (optional, default: `false`). 660 | - `validationOptions`: `ValidationOptions` from `class-validator` to configure custom messages and options. 661 | 662 | Example for usage: 663 | 664 | ```typescript 665 | import { ExistIds } from '@hodfords/nestjs-base-decorator'; 666 | import { Entity } from 'typeorm'; 667 | import { BaseEntity } from '@hodfords/typeorm-helper'; 668 | 669 | @Entity() 670 | export class UserEntity extends BaseEntity { 671 | @PrimaryGeneratedColumn('uuid') 672 | id: string; 673 | } 674 | 675 | class UserRequestDto { 676 | @ExistIds(UserEntity) 677 | userIds: string[]; 678 | } 679 | ``` 680 | 681 | #### @Exists() 682 | 683 | The `@Exists()` decorator is used to validate if a specific value exists in a column of a database table. It supports case-insensitive searches and custom query conditions to allow more flexible validations. 684 | 685 | Parameters: 686 | 687 | - `table`: The `Entity` class (which extends `BaseEntity`) represents the database table where the validation will be performed. 688 | - `column`: The column name in the database to check the existence of the value. 689 | - `caseInsensitive`: A boolean to enable case-insensitive comparison (option, default: `false`). 690 | - `customs`: An array of custom conditions that apply additional filters to the query (optional). 691 | - `validationOptions`: `ValidationOptions` from `class-validator` to configure custom messages and options (optional). 692 | 693 | ```typescript 694 | import { Exists } from '@hodfords/nestjs-base-decorator'; 695 | import { Entity } from 'typeorm'; 696 | import { IsEmail } from 'class-validator'; 697 | import { BaseEntity } from '@hodfords/typeorm-helper'; 698 | 699 | @Entity() 700 | export class UserEntity extends BaseEntity { 701 | @Column() 702 | email: string; 703 | } 704 | 705 | class UserRequestDto { 706 | @Exists(UserEntity, 'email') 707 | @IsEmail() 708 | email: string; 709 | } 710 | ``` 711 | 712 | ## License 713 | 714 | This project is licensed under the MIT License 715 | --------------------------------------------------------------------------------