@vn.chemgio/nestjs-utilities 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -0
- package/dist/cache/README.md +91 -0
- package/dist/cache/index.d.ts +10 -0
- package/dist/cache/index.js +75 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/queue/README.md +82 -0
- package/dist/queue/index.d.ts +14 -0
- package/dist/queue/index.js +17 -0
- package/dist/queue/index.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/dist/typeorm/README.md +100 -0
- package/dist/typeorm/index.d.ts +11 -0
- package/dist/typeorm/index.js +53 -0
- package/dist/typeorm/index.js.map +1 -0
- package/package.json +156 -0
- package/src/cache/README.md +91 -0
- package/src/queue/README.md +82 -0
- package/src/typeorm/README.md +100 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# @vn.chemgio/nestjs-utilities/typeorm
|
|
2
|
+
|
|
3
|
+
TypeORM configuration helpers for cloud databases (RDS PostgreSQL / MySQL).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @vn.chemgio/nestjs-utilities @nestjs/typeorm @nestjs/config
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
The following environment variables must be declared in your `.env` file (or provided to `ConfigModule.forRoot()`):
|
|
14
|
+
|
|
15
|
+
| Variable | Required | Default |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| `DB_HOST` | No | `localhost` |
|
|
18
|
+
| `DB_PORT` | No | `5432` (PG) / `3306` (MySQL) |
|
|
19
|
+
| `DB_USERNAME` | Yes | — |
|
|
20
|
+
| `DB_PASSWORD` | Yes | — |
|
|
21
|
+
| `DB_DATABASE` | No | `postgres` / `mysql` |
|
|
22
|
+
| `DB_SYNCHRONIZE` | No | `false` |
|
|
23
|
+
| `DB_LOGGING` | No | `false` |
|
|
24
|
+
| `DB_SSL_REJECT_UNAUTHORIZED` | No | `false` |
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
// app.module.ts
|
|
30
|
+
import { Module } from '@nestjs/common'
|
|
31
|
+
import { ConfigModule, ConfigService } from '@nestjs/config'
|
|
32
|
+
import { TypeOrmModule } from '@nestjs/typeorm'
|
|
33
|
+
import { configTypeOrmRDSPostgres } from '@vn.chemgio/nestjs-utilities/typeorm'
|
|
34
|
+
|
|
35
|
+
@Module({
|
|
36
|
+
imports: [
|
|
37
|
+
ConfigModule.forRoot(),
|
|
38
|
+
TypeOrmModule.forRootAsync({
|
|
39
|
+
inject: [ConfigService],
|
|
40
|
+
useFactory: (config: ConfigService) =>
|
|
41
|
+
configTypeOrmRDSPostgres(config, {
|
|
42
|
+
poolSize: 20,
|
|
43
|
+
schema: 'public',
|
|
44
|
+
}),
|
|
45
|
+
}),
|
|
46
|
+
],
|
|
47
|
+
})
|
|
48
|
+
export class AppModule {}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Environment variables
|
|
52
|
+
|
|
53
|
+
| Variable | Default | Type | Description |
|
|
54
|
+
|---|---|---|---|
|
|
55
|
+
| `DB_HOST` | `localhost` | `string` | Database host |
|
|
56
|
+
| `DB_PORT` | `5432` (PG) / `3306` (MySQL) | `number` | Connection port |
|
|
57
|
+
| `DB_USERNAME` | — | `string` | Database username |
|
|
58
|
+
| `DB_PASSWORD` | — | `string` | Database password |
|
|
59
|
+
| `DB_DATABASE` | `postgres` / `mysql` | `string` | Database name |
|
|
60
|
+
| `DB_SYNCHRONIZE` | `false` | `boolean` | Auto-sync schema (dev only) |
|
|
61
|
+
| `DB_LOGGING` | `false` | `boolean` | Enable query logging |
|
|
62
|
+
| `DB_SSL_REJECT_UNAUTHORIZED` | `false` | `boolean` | Reject unauthorized SSL certs |
|
|
63
|
+
|
|
64
|
+
## TypeOrmConfigOptions
|
|
65
|
+
|
|
66
|
+
| Option | Default | Description |
|
|
67
|
+
|---|---|---|
|
|
68
|
+
| `schema` | — | PostgreSQL schema (e.g. `public`) |
|
|
69
|
+
| `poolSize` | `20` (PG) / `10` (MySQL) | Maximum connections in pool |
|
|
70
|
+
| `idleTimeoutMs` | `30000` (PG) / `10000` (MySQL) | Max idle time before closing |
|
|
71
|
+
| `connectionTimeoutMs` | `10000` (PG) / `5000` (MySQL) | Connection timeout |
|
|
72
|
+
| `statementTimeoutMs` | `30000` (PG) | Query timeout |
|
|
73
|
+
|
|
74
|
+
## SSL — why both `ssl` and `extra.ssl`?
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
ssl: { rejectUnauthorized: false },
|
|
78
|
+
extra: {
|
|
79
|
+
ssl: { rejectUnauthorized: false },
|
|
80
|
+
// ...
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
- **`ssl`** — tells TypeORM to configure the driver (`pg` / `mysql2`) with TLS
|
|
85
|
+
- **`extra.ssl`** — passes SSL config directly to the underlying driver pool
|
|
86
|
+
|
|
87
|
+
Cloud databases (AWS RDS, Google Cloud SQL, etc.) often use self-signed certificates, requiring `rejectUnauthorized: false` to trust them.
|
|
88
|
+
|
|
89
|
+
## Sample .env
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
DB_HOST=database-1.xxxxxx.us-east-1.rds.amazonaws.com
|
|
93
|
+
DB_PORT=5432
|
|
94
|
+
DB_USERNAME=postgres
|
|
95
|
+
DB_PASSWORD=my-secret-pw
|
|
96
|
+
DB_DATABASE=mydb
|
|
97
|
+
DB_SYNCHRONIZE=false
|
|
98
|
+
DB_LOGGING=true
|
|
99
|
+
DB_SSL_REJECT_UNAUTHORIZED=false
|
|
100
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ConfigService } from '@nestjs/config';
|
|
2
|
+
import type { TypeOrmModuleOptions } from '@nestjs/typeorm';
|
|
3
|
+
export interface TypeOrmConfigOptions {
|
|
4
|
+
schema?: string;
|
|
5
|
+
poolSize?: number;
|
|
6
|
+
idleTimeoutMs?: number;
|
|
7
|
+
connectionTimeoutMs?: number;
|
|
8
|
+
statementTimeoutMs?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function configTypeOrmRDSPostgres(configService: ConfigService, options?: TypeOrmConfigOptions): TypeOrmModuleOptions;
|
|
11
|
+
export declare function configTypeOrmMySQL(configService: ConfigService, options?: TypeOrmConfigOptions): TypeOrmModuleOptions;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.configTypeOrmRDSPostgres = configTypeOrmRDSPostgres;
|
|
4
|
+
exports.configTypeOrmMySQL = configTypeOrmMySQL;
|
|
5
|
+
function configTypeOrmRDSPostgres(configService, options) {
|
|
6
|
+
const rejectUnauthorized = configService.get('DB_SSL_REJECT_UNAUTHORIZED', false);
|
|
7
|
+
return {
|
|
8
|
+
type: 'postgres',
|
|
9
|
+
host: configService.get('DB_HOST', 'localhost'),
|
|
10
|
+
port: configService.get('DB_PORT', 5432),
|
|
11
|
+
username: configService.get('DB_USERNAME'),
|
|
12
|
+
password: configService.get('DB_PASSWORD'),
|
|
13
|
+
database: configService.get('DB_DATABASE', 'postgres'),
|
|
14
|
+
synchronize: configService.get('DB_SYNCHRONIZE', false),
|
|
15
|
+
logging: configService.get('DB_LOGGING', false) ? 'all' : false,
|
|
16
|
+
ssl: { rejectUnauthorized },
|
|
17
|
+
extra: {
|
|
18
|
+
ssl: { rejectUnauthorized },
|
|
19
|
+
max: options?.poolSize ?? 20,
|
|
20
|
+
idleTimeoutMillis: options?.idleTimeoutMs ?? 30000,
|
|
21
|
+
connectionTimeoutMillis: options?.connectionTimeoutMs ?? 10000,
|
|
22
|
+
statement_timeout: options?.statementTimeoutMs ?? 30000,
|
|
23
|
+
...(options?.schema ? { schema: options.schema } : {}),
|
|
24
|
+
},
|
|
25
|
+
autoLoadEntities: true,
|
|
26
|
+
retryAttempts: 10,
|
|
27
|
+
retryDelay: 3000,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function configTypeOrmMySQL(configService, options) {
|
|
31
|
+
const rejectUnauthorized = configService.get('DB_SSL_REJECT_UNAUTHORIZED', false);
|
|
32
|
+
return {
|
|
33
|
+
type: 'mysql',
|
|
34
|
+
host: configService.get('DB_HOST', 'localhost'),
|
|
35
|
+
port: configService.get('DB_PORT', 3306),
|
|
36
|
+
username: configService.get('DB_USERNAME'),
|
|
37
|
+
password: configService.get('DB_PASSWORD'),
|
|
38
|
+
database: configService.get('DB_DATABASE', 'mysql'),
|
|
39
|
+
synchronize: configService.get('DB_SYNCHRONIZE', false),
|
|
40
|
+
logging: configService.get('DB_LOGGING', false) ? 'all' : false,
|
|
41
|
+
ssl: { rejectUnauthorized },
|
|
42
|
+
extra: {
|
|
43
|
+
ssl: { rejectUnauthorized },
|
|
44
|
+
max: options?.poolSize ?? 10,
|
|
45
|
+
idleTimeoutMillis: options?.idleTimeoutMs ?? 10000,
|
|
46
|
+
connectionTimeoutMillis: options?.connectionTimeoutMs ?? 5000,
|
|
47
|
+
},
|
|
48
|
+
autoLoadEntities: true,
|
|
49
|
+
retryAttempts: 10,
|
|
50
|
+
retryDelay: 3000,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/typeorm/index.ts"],"names":[],"mappings":";;AAWA,4DA8BC;AAED,gDA4BC;AA5DD,SAAgB,wBAAwB,CACtC,aAA4B,EAC5B,OAA8B;IAE9B,MAAM,kBAAkB,GAAG,aAAa,CAAC,GAAG,CAC1C,4BAA4B,EAC5B,KAAK,CACN,CAAC;IACF,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,aAAa,CAAC,GAAG,CAAS,SAAS,EAAE,WAAW,CAAC;QACvD,IAAI,EAAE,aAAa,CAAC,GAAG,CAAS,SAAS,EAAE,IAAI,CAAC;QAChD,QAAQ,EAAE,aAAa,CAAC,GAAG,CAAqB,aAAa,CAAC;QAC9D,QAAQ,EAAE,aAAa,CAAC,GAAG,CAAqB,aAAa,CAAC;QAC9D,QAAQ,EAAE,aAAa,CAAC,GAAG,CAAS,aAAa,EAAE,UAAU,CAAC;QAC9D,WAAW,EAAE,aAAa,CAAC,GAAG,CAAU,gBAAgB,EAAE,KAAK,CAAC;QAChE,OAAO,EAAE,aAAa,CAAC,GAAG,CAAU,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;QACxE,GAAG,EAAE,EAAE,kBAAkB,EAAE;QAC3B,KAAK,EAAE;YACL,GAAG,EAAE,EAAE,kBAAkB,EAAE;YAC3B,GAAG,EAAE,OAAO,EAAE,QAAQ,IAAI,EAAE;YAC5B,iBAAiB,EAAE,OAAO,EAAE,aAAa,IAAI,KAAK;YAClD,uBAAuB,EAAE,OAAO,EAAE,mBAAmB,IAAI,KAAK;YAC9D,iBAAiB,EAAE,OAAO,EAAE,kBAAkB,IAAI,KAAK;YACvD,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACvD;QACD,gBAAgB,EAAE,IAAI;QACtB,aAAa,EAAE,EAAE;QACjB,UAAU,EAAE,IAAI;KACjB,CAAC;AACJ,CAAC;AAED,SAAgB,kBAAkB,CAChC,aAA4B,EAC5B,OAA8B;IAE9B,MAAM,kBAAkB,GAAG,aAAa,CAAC,GAAG,CAC1C,4BAA4B,EAC5B,KAAK,CACN,CAAC;IACF,OAAO;QACL,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,aAAa,CAAC,GAAG,CAAS,SAAS,EAAE,WAAW,CAAC;QACvD,IAAI,EAAE,aAAa,CAAC,GAAG,CAAS,SAAS,EAAE,IAAI,CAAC;QAChD,QAAQ,EAAE,aAAa,CAAC,GAAG,CAAqB,aAAa,CAAC;QAC9D,QAAQ,EAAE,aAAa,CAAC,GAAG,CAAqB,aAAa,CAAC;QAC9D,QAAQ,EAAE,aAAa,CAAC,GAAG,CAAS,aAAa,EAAE,OAAO,CAAC;QAC3D,WAAW,EAAE,aAAa,CAAC,GAAG,CAAU,gBAAgB,EAAE,KAAK,CAAC;QAChE,OAAO,EAAE,aAAa,CAAC,GAAG,CAAU,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;QACxE,GAAG,EAAE,EAAE,kBAAkB,EAAE;QAC3B,KAAK,EAAE;YACL,GAAG,EAAE,EAAE,kBAAkB,EAAE;YAC3B,GAAG,EAAE,OAAO,EAAE,QAAQ,IAAI,EAAE;YAC5B,iBAAiB,EAAE,OAAO,EAAE,aAAa,IAAI,KAAK;YAClD,uBAAuB,EAAE,OAAO,EAAE,mBAAmB,IAAI,IAAI;SAC9D;QACD,gBAAgB,EAAE,IAAI;QACtB,aAAa,EAAE,EAAE;QACjB,UAAU,EAAE,IAAI;KACjB,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vn.chemgio/nestjs-utilities",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "NestJS utilities collection - modular packages for common NestJS integrations",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Wind Blade",
|
|
7
|
+
"url": "https://github.com/Vn-ChemGio"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/Vn-ChemGio/nestjs-utilities.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/Vn-ChemGio/nestjs-utilities/issues"
|
|
15
|
+
},
|
|
16
|
+
"homepage": "https://github.com/Vn-ChemGio/nestjs-utilities#readme",
|
|
17
|
+
"private": false,
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"import": "./dist/index.js",
|
|
23
|
+
"require": "./dist/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./typeorm": {
|
|
26
|
+
"types": "./dist/typeorm/index.d.ts",
|
|
27
|
+
"import": "./dist/typeorm/index.js",
|
|
28
|
+
"require": "./dist/typeorm/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./cache": {
|
|
31
|
+
"types": "./dist/cache/index.d.ts",
|
|
32
|
+
"import": "./dist/cache/index.js",
|
|
33
|
+
"require": "./dist/cache/index.js"
|
|
34
|
+
},
|
|
35
|
+
"./queue": {
|
|
36
|
+
"types": "./dist/queue/index.d.ts",
|
|
37
|
+
"import": "./dist/queue/index.js",
|
|
38
|
+
"require": "./dist/queue/index.js"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"typesVersions": {
|
|
42
|
+
"*": {
|
|
43
|
+
"typeorm": [
|
|
44
|
+
"./dist/typeorm/index.d.ts"
|
|
45
|
+
],
|
|
46
|
+
"cache": [
|
|
47
|
+
"./dist/cache/index.d.ts"
|
|
48
|
+
],
|
|
49
|
+
"queue": [
|
|
50
|
+
"./dist/queue/index.d.ts"
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"main": "./dist/index.js",
|
|
55
|
+
"types": "./dist/index.d.ts",
|
|
56
|
+
"publishConfig": {
|
|
57
|
+
"access": "public"
|
|
58
|
+
},
|
|
59
|
+
"files": [
|
|
60
|
+
"dist",
|
|
61
|
+
"README.md",
|
|
62
|
+
"src/typeorm/README.md",
|
|
63
|
+
"src/cache/README.md",
|
|
64
|
+
"src/queue/README.md"
|
|
65
|
+
],
|
|
66
|
+
"scripts": {
|
|
67
|
+
"build": "tsc -p tsconfig.build.json && node -e \"require('fs').copyFileSync('src/typeorm/README.md','dist/typeorm/README.md');require('fs').copyFileSync('src/cache/README.md','dist/cache/README.md');require('fs').copyFileSync('src/queue/README.md','dist/queue/README.md')\"",
|
|
68
|
+
"clean": "rimraf dist",
|
|
69
|
+
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
70
|
+
"lint": "eslint \"{src,test}/**/*.ts\" --fix",
|
|
71
|
+
"test": "jest",
|
|
72
|
+
"test:watch": "jest --watch",
|
|
73
|
+
"test:cov": "jest --coverage",
|
|
74
|
+
"prepublishOnly": "npm run build",
|
|
75
|
+
"prepack": "npm run build"
|
|
76
|
+
},
|
|
77
|
+
"peerDependencies": {
|
|
78
|
+
"@keyv/redis": "^5.1.6",
|
|
79
|
+
"@keyv/valkey": "^1.0.11",
|
|
80
|
+
"@nestjs/common": "^11.0.1",
|
|
81
|
+
"@nestjs/config": "^4.0.4",
|
|
82
|
+
"@nestjs/core": "^11.0.1",
|
|
83
|
+
"@nestjs/typeorm": "^11.0.1",
|
|
84
|
+
"rxjs": "^7.8.1",
|
|
85
|
+
"@nestjs/bullmq": "^11.0.0",
|
|
86
|
+
"bullmq": "^5.44.0"
|
|
87
|
+
},
|
|
88
|
+
"peerDependenciesMeta": {
|
|
89
|
+
"@nestjs/typeorm": {
|
|
90
|
+
"optional": true
|
|
91
|
+
},
|
|
92
|
+
"@nestjs/config": {
|
|
93
|
+
"optional": true
|
|
94
|
+
},
|
|
95
|
+
"@keyv/valkey": {
|
|
96
|
+
"optional": true
|
|
97
|
+
},
|
|
98
|
+
"@keyv/redis": {
|
|
99
|
+
"optional": true
|
|
100
|
+
},
|
|
101
|
+
"@nestjs/bullmq": {
|
|
102
|
+
"optional": true
|
|
103
|
+
},
|
|
104
|
+
"bullmq": {
|
|
105
|
+
"optional": true
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
"dependencies": {
|
|
109
|
+
"cacheable": "^2.3.5",
|
|
110
|
+
"keyv": "^5.6.0",
|
|
111
|
+
"reflect-metadata": "^0.2.2"
|
|
112
|
+
},
|
|
113
|
+
"devDependencies": {
|
|
114
|
+
"@eslint/eslintrc": "^3.2.0",
|
|
115
|
+
"@eslint/js": "^9.18.0",
|
|
116
|
+
"@keyv/redis": "^5.1.6",
|
|
117
|
+
"@keyv/valkey": "^1.0.11",
|
|
118
|
+
"@nestjs/common": "^11.0.1",
|
|
119
|
+
"@nestjs/config": "^4.0.4",
|
|
120
|
+
"@nestjs/core": "^11.0.1",
|
|
121
|
+
"@nestjs/testing": "^11.0.1",
|
|
122
|
+
"@nestjs/typeorm": "^11.0.1",
|
|
123
|
+
"@nestjs/bullmq": "^11.0.0",
|
|
124
|
+
"bullmq": "^5.44.0",
|
|
125
|
+
"@types/jest": "^30.0.0",
|
|
126
|
+
"@types/node": "^24.0.0",
|
|
127
|
+
"eslint": "^9.18.0",
|
|
128
|
+
"eslint-config-prettier": "^10.0.1",
|
|
129
|
+
"eslint-plugin-prettier": "^5.2.2",
|
|
130
|
+
"globals": "^17.0.0",
|
|
131
|
+
"jest": "^30.0.0",
|
|
132
|
+
"prettier": "^3.4.2",
|
|
133
|
+
"rimraf": "^6.0.1",
|
|
134
|
+
"rxjs": "^7.8.1",
|
|
135
|
+
"ts-jest": "^29.2.5",
|
|
136
|
+
"typescript": "^5.7.3",
|
|
137
|
+
"typescript-eslint": "^8.20.0"
|
|
138
|
+
},
|
|
139
|
+
"jest": {
|
|
140
|
+
"moduleFileExtensions": [
|
|
141
|
+
"js",
|
|
142
|
+
"json",
|
|
143
|
+
"ts"
|
|
144
|
+
],
|
|
145
|
+
"rootDir": "src",
|
|
146
|
+
"testRegex": ".*\\.spec\\.ts$",
|
|
147
|
+
"transform": {
|
|
148
|
+
"^.+\\.(t|j)s$": "ts-jest"
|
|
149
|
+
},
|
|
150
|
+
"collectCoverageFrom": [
|
|
151
|
+
"**/*.(t|j)s"
|
|
152
|
+
],
|
|
153
|
+
"coverageDirectory": "../coverage",
|
|
154
|
+
"testEnvironment": "node"
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# @vn.chemgio/nestjs-utilities/cache
|
|
2
|
+
|
|
3
|
+
A global NestJS cache module using [Keyv](https://keyv.org/) + [Cacheable](https://github.com/jaredwray/cacheable) with Valkey or Redis backend.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @vn.chemgio/nestjs-utilities keyv cacheable
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Depending on your store:
|
|
12
|
+
|
|
13
|
+
- **Valkey**: `npm install @keyv/valkey`
|
|
14
|
+
- **Redis**: `npm install @keyv/redis`
|
|
15
|
+
|
|
16
|
+
## Quick start
|
|
17
|
+
|
|
18
|
+
### Valkey (reads `VALKEY_URL` from env)
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
// app.module.ts
|
|
22
|
+
import { CacheModule } from '@vn.chemgio/nestjs-utilities/cache'
|
|
23
|
+
|
|
24
|
+
@Module({
|
|
25
|
+
imports: [
|
|
26
|
+
CacheModule.forRoot({ store: 'valkey' }),
|
|
27
|
+
// Requires VALKEY_URL in your .env:
|
|
28
|
+
// VALKEY_URL=valkey://localhost:6379
|
|
29
|
+
],
|
|
30
|
+
})
|
|
31
|
+
export class AppModule {}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Redis (reads `REDIS_URL` from env)
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
CacheModule.forRoot({ store: 'redis' })
|
|
38
|
+
// Requires REDIS_URL in .env:
|
|
39
|
+
// REDIS_URL=redis://localhost:6379
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Direct URL (no env vars needed)
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
CacheModule.forRoot({
|
|
46
|
+
store: 'valkey',
|
|
47
|
+
url: 'valkey://user:pass@host:6379',
|
|
48
|
+
})
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Usage in a service
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { Inject } from '@nestjs/common'
|
|
55
|
+
import { CACHE_MANAGER } from '@vn.chemgio/nestjs-utilities/cache'
|
|
56
|
+
import { Cacheable } from 'cacheable'
|
|
57
|
+
|
|
58
|
+
@Injectable()
|
|
59
|
+
export class MyService {
|
|
60
|
+
constructor(
|
|
61
|
+
@Inject(CACHE_MANAGER) private readonly cache: Cacheable,
|
|
62
|
+
) {}
|
|
63
|
+
|
|
64
|
+
async getData(key: string) {
|
|
65
|
+
return this.cache.get(key)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async setData(key: string, value: unknown, ttl?: number) {
|
|
69
|
+
await this.cache.set(key, value, ttl)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## CacheModuleOptions
|
|
75
|
+
|
|
76
|
+
| Option | Default | Description |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| `store` | `'valkey'` | Backend store: `'valkey'` or `'redis'` |
|
|
79
|
+
| `namespace` | `'{default}'` | Cache namespace prefix |
|
|
80
|
+
| `url` | — | Connection URL. If omitted, reads `VALKEY_URL` or `REDIS_URL` from env |
|
|
81
|
+
|
|
82
|
+
## How it works
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
Cacheable → Keyv → KeyvValkey / KeyvRedis → Valkey / Redis
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- `KeyvValkey` / `KeyvRedis` connects to the backend
|
|
89
|
+
- `Keyv` wraps it with a uniform API
|
|
90
|
+
- `Cacheable` adds TTL, namespace, and caching logic
|
|
91
|
+
- The module is `@Global()`, so `CACHE_MANAGER` is available everywhere
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# @vn.chemgio/nestjs-utilities/queue
|
|
2
|
+
|
|
3
|
+
RDS-style config factory for [BullMQ](https://bullmq.io) (via `@nestjs/bullmq`).
|
|
4
|
+
|
|
5
|
+
Works with either Valkey (`VALKEY_URL`) or Redis (`REDIS_URL`) environment variables.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @vn.chemgio/nestjs-utilities @nestjs/bullmq bullmq
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { BullModule } from '@nestjs/bullmq';
|
|
17
|
+
import { configBullMQ } from '@vn.chemgio/nestjs-utilities/queue';
|
|
18
|
+
|
|
19
|
+
@Module({
|
|
20
|
+
imports: [
|
|
21
|
+
BullModule.forRootAsync({
|
|
22
|
+
useFactory: configBullMQ,
|
|
23
|
+
inject: [ConfigService],
|
|
24
|
+
}),
|
|
25
|
+
BullModule.registerQueue({ name: 'email' }),
|
|
26
|
+
],
|
|
27
|
+
})
|
|
28
|
+
export class AppModule {}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Valkey (reads `VALKEY_URL` from env)
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
BullModule.forRootAsync({
|
|
35
|
+
// Requires VALKEY_URL in .env:
|
|
36
|
+
// VALKEY_URL=valkey://localhost:6379
|
|
37
|
+
useFactory: configBullMQ,
|
|
38
|
+
inject: [ConfigService],
|
|
39
|
+
})
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Redis (reads `REDIS_URL` from env)
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
BullModule.forRootAsync({
|
|
46
|
+
useFactory: (config: ConfigService) =>
|
|
47
|
+
configBullMQ(config, { store: 'redis' }),
|
|
48
|
+
inject: [ConfigService],
|
|
49
|
+
})
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### With custom prefix and default job options
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
BullModule.forRootAsync({
|
|
56
|
+
useFactory: (config: ConfigService) =>
|
|
57
|
+
configBullMQ(config, {
|
|
58
|
+
prefix: '{myapp}',
|
|
59
|
+
defaultJobOptions: { attempts: 3, removeOnComplete: 100 },
|
|
60
|
+
}),
|
|
61
|
+
inject: [ConfigService],
|
|
62
|
+
})
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Direct URL (no env vars)
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
BullModule.forRootAsync({
|
|
69
|
+
useFactory: () => ({
|
|
70
|
+
connection: { url: 'redis://user:pass@host:6379' },
|
|
71
|
+
prefix: '{default}',
|
|
72
|
+
}),
|
|
73
|
+
})
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## QueueModuleOptions
|
|
77
|
+
|
|
78
|
+
| Option | Default | Description |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| `store` | `'valkey'` | Backend store: `'valkey'` or `'redis'` |
|
|
81
|
+
| `prefix` | `'{default}'` | BullMQ key prefix |
|
|
82
|
+
| `defaultJobOptions` | — | Default job options for all queues (e.g. `{ attempts: 3 }`) |
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# @vn.chemgio/nestjs-utilities/typeorm
|
|
2
|
+
|
|
3
|
+
TypeORM configuration helpers for cloud databases (RDS PostgreSQL / MySQL).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @vn.chemgio/nestjs-utilities @nestjs/typeorm @nestjs/config
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
The following environment variables must be declared in your `.env` file (or provided to `ConfigModule.forRoot()`):
|
|
14
|
+
|
|
15
|
+
| Variable | Required | Default |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| `DB_HOST` | No | `localhost` |
|
|
18
|
+
| `DB_PORT` | No | `5432` (PG) / `3306` (MySQL) |
|
|
19
|
+
| `DB_USERNAME` | Yes | — |
|
|
20
|
+
| `DB_PASSWORD` | Yes | — |
|
|
21
|
+
| `DB_DATABASE` | No | `postgres` / `mysql` |
|
|
22
|
+
| `DB_SYNCHRONIZE` | No | `false` |
|
|
23
|
+
| `DB_LOGGING` | No | `false` |
|
|
24
|
+
| `DB_SSL_REJECT_UNAUTHORIZED` | No | `false` |
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
// app.module.ts
|
|
30
|
+
import { Module } from '@nestjs/common'
|
|
31
|
+
import { ConfigModule, ConfigService } from '@nestjs/config'
|
|
32
|
+
import { TypeOrmModule } from '@nestjs/typeorm'
|
|
33
|
+
import { configTypeOrmRDSPostgres } from '@vn.chemgio/nestjs-utilities/typeorm'
|
|
34
|
+
|
|
35
|
+
@Module({
|
|
36
|
+
imports: [
|
|
37
|
+
ConfigModule.forRoot(),
|
|
38
|
+
TypeOrmModule.forRootAsync({
|
|
39
|
+
inject: [ConfigService],
|
|
40
|
+
useFactory: (config: ConfigService) =>
|
|
41
|
+
configTypeOrmRDSPostgres(config, {
|
|
42
|
+
poolSize: 20,
|
|
43
|
+
schema: 'public',
|
|
44
|
+
}),
|
|
45
|
+
}),
|
|
46
|
+
],
|
|
47
|
+
})
|
|
48
|
+
export class AppModule {}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Environment variables
|
|
52
|
+
|
|
53
|
+
| Variable | Default | Type | Description |
|
|
54
|
+
|---|---|---|---|
|
|
55
|
+
| `DB_HOST` | `localhost` | `string` | Database host |
|
|
56
|
+
| `DB_PORT` | `5432` (PG) / `3306` (MySQL) | `number` | Connection port |
|
|
57
|
+
| `DB_USERNAME` | — | `string` | Database username |
|
|
58
|
+
| `DB_PASSWORD` | — | `string` | Database password |
|
|
59
|
+
| `DB_DATABASE` | `postgres` / `mysql` | `string` | Database name |
|
|
60
|
+
| `DB_SYNCHRONIZE` | `false` | `boolean` | Auto-sync schema (dev only) |
|
|
61
|
+
| `DB_LOGGING` | `false` | `boolean` | Enable query logging |
|
|
62
|
+
| `DB_SSL_REJECT_UNAUTHORIZED` | `false` | `boolean` | Reject unauthorized SSL certs |
|
|
63
|
+
|
|
64
|
+
## TypeOrmConfigOptions
|
|
65
|
+
|
|
66
|
+
| Option | Default | Description |
|
|
67
|
+
|---|---|---|
|
|
68
|
+
| `schema` | — | PostgreSQL schema (e.g. `public`) |
|
|
69
|
+
| `poolSize` | `20` (PG) / `10` (MySQL) | Maximum connections in pool |
|
|
70
|
+
| `idleTimeoutMs` | `30000` (PG) / `10000` (MySQL) | Max idle time before closing |
|
|
71
|
+
| `connectionTimeoutMs` | `10000` (PG) / `5000` (MySQL) | Connection timeout |
|
|
72
|
+
| `statementTimeoutMs` | `30000` (PG) | Query timeout |
|
|
73
|
+
|
|
74
|
+
## SSL — why both `ssl` and `extra.ssl`?
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
ssl: { rejectUnauthorized: false },
|
|
78
|
+
extra: {
|
|
79
|
+
ssl: { rejectUnauthorized: false },
|
|
80
|
+
// ...
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
- **`ssl`** — tells TypeORM to configure the driver (`pg` / `mysql2`) with TLS
|
|
85
|
+
- **`extra.ssl`** — passes SSL config directly to the underlying driver pool
|
|
86
|
+
|
|
87
|
+
Cloud databases (AWS RDS, Google Cloud SQL, etc.) often use self-signed certificates, requiring `rejectUnauthorized: false` to trust them.
|
|
88
|
+
|
|
89
|
+
## Sample .env
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
DB_HOST=database-1.xxxxxx.us-east-1.rds.amazonaws.com
|
|
93
|
+
DB_PORT=5432
|
|
94
|
+
DB_USERNAME=postgres
|
|
95
|
+
DB_PASSWORD=my-secret-pw
|
|
96
|
+
DB_DATABASE=mydb
|
|
97
|
+
DB_SYNCHRONIZE=false
|
|
98
|
+
DB_LOGGING=true
|
|
99
|
+
DB_SSL_REJECT_UNAUTHORIZED=false
|
|
100
|
+
```
|