nestjs-backend-common 0.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/.github/README.md +9 -0
- package/.github/workflows/publish.yml +46 -0
- package/.prettierignore +8 -0
- package/.prettierrc +27 -0
- package/dist/src/correlation-id/correlation-id.constant.js +6 -0
- package/dist/src/correlation-id/correlation-id.constant.js.map +1 -0
- package/dist/src/correlation-id/correlation-id.interceptor.js +58 -0
- package/dist/src/correlation-id/correlation-id.interceptor.js.map +1 -0
- package/dist/src/correlation-id/correlation-id.module.js +37 -0
- package/dist/src/correlation-id/correlation-id.module.js.map +1 -0
- package/dist/src/correlation-id/correlation-id.service.js +28 -0
- package/dist/src/correlation-id/correlation-id.service.js.map +1 -0
- package/dist/src/correlation-id/correlation-id.type.js +3 -0
- package/dist/src/correlation-id/correlation-id.type.js.map +1 -0
- package/dist/src/correlation-id/index.js +21 -0
- package/dist/src/correlation-id/index.js.map +1 -0
- package/dist/src/index.js +19 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/types/index.js +3 -0
- package/dist/src/types/index.js.map +1 -0
- package/eslint.config.mjs +99 -0
- package/package.json +50 -0
- package/src/correlation-id/correlation-id.constant.ts +2 -0
- package/src/correlation-id/correlation-id.interceptor.ts +71 -0
- package/src/correlation-id/correlation-id.module.ts +26 -0
- package/src/correlation-id/correlation-id.service.ts +18 -0
- package/src/correlation-id/correlation-id.type.ts +7 -0
- package/src/correlation-id/index.ts +4 -0
- package/src/index.ts +2 -0
- package/src/types/index.ts +3 -0
- package/tsconfig.build.json +10 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# NestJS Backend Common
|
|
2
|
+
|
|
3
|
+
All the utility functions and common modules I usually use in my NestJS applications will be published and maintained here.
|
|
4
|
+
|
|
5
|
+
## [Increase Version](https://docs.npmjs.com/cli/v8/commands/npm-version)
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm version patch --no-git-tag-version
|
|
9
|
+
```
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: Publish The Library
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
# https://stackoverflow.com/a/72183279/8784518
|
|
10
|
+
id-token: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build:
|
|
14
|
+
runs-on: ubuntu-24.04
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout
|
|
17
|
+
uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Check the current published version
|
|
20
|
+
run: |
|
|
21
|
+
LAST_PUBLISHED_VERSION=$(npm view nestjs-backend-common version 2> /dev/null || echo "")
|
|
22
|
+
PACKAGE_VERSION=$(cat package.json | grep version | head -1 | awk -F: '{ print $2 }' | sed 's/[",]//g')
|
|
23
|
+
if [[ $LAST_PUBLISHED_VERSION == $PACKAGE_VERSION ]]; then
|
|
24
|
+
echo "Version is published already, if you need to publish a new version please increase the version in package.json"
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
- uses: pnpm/action-setup@v4
|
|
28
|
+
name: Install pnpm
|
|
29
|
+
with:
|
|
30
|
+
version: 10
|
|
31
|
+
run_install: false
|
|
32
|
+
|
|
33
|
+
- name: Install Node.js
|
|
34
|
+
uses: actions/setup-node@v4
|
|
35
|
+
with:
|
|
36
|
+
node-version: 22
|
|
37
|
+
cache: "pnpm"
|
|
38
|
+
registry-url: "https://registry.npmjs.org/"
|
|
39
|
+
|
|
40
|
+
- name: Install Dependencies
|
|
41
|
+
run: pnpm install --frozen-lockfile
|
|
42
|
+
|
|
43
|
+
- name: Publish Package on npm 📦
|
|
44
|
+
run: pnpm publish --provenance --access public --no-git-checks
|
|
45
|
+
env:
|
|
46
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/.prettierignore
ADDED
package/.prettierrc
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"arrowParens": "always",
|
|
3
|
+
"useTabs": false,
|
|
4
|
+
"bracketSpacing": true,
|
|
5
|
+
"endOfLine": "lf",
|
|
6
|
+
"printWidth": 70,
|
|
7
|
+
"quoteProps": "consistent",
|
|
8
|
+
"tabWidth": 2,
|
|
9
|
+
"trailingComma": "all",
|
|
10
|
+
"semi": true,
|
|
11
|
+
"singleQuote": true,
|
|
12
|
+
"overrides": [
|
|
13
|
+
{
|
|
14
|
+
"files": ["*.yml", "*.yaml"],
|
|
15
|
+
"options": {
|
|
16
|
+
"singleQuote": false,
|
|
17
|
+
"tabWidth": 2
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"files": "*.md",
|
|
22
|
+
"options": {
|
|
23
|
+
"tabWidth": 2
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CORRELATION_ID_CLS_KEY = exports.CORRELATION_ID_HEADER_NAME = void 0;
|
|
4
|
+
exports.CORRELATION_ID_HEADER_NAME = 'correlation-id';
|
|
5
|
+
exports.CORRELATION_ID_CLS_KEY = 'CORRELATION_ID_CLS_KEY';
|
|
6
|
+
//# sourceMappingURL=correlation-id.constant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"correlation-id.constant.js","sourceRoot":"","sources":["../../../src/correlation-id/correlation-id.constant.ts"],"names":[],"mappings":";;;AAAa,QAAA,0BAA0B,GAAG,gBAAgB,CAAC;AAC9C,QAAA,sBAAsB,GAAG,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var CorrelationIdInterceptor_1;
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.CorrelationIdInterceptor = void 0;
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
const graphql_1 = require("@nestjs/graphql");
|
|
13
|
+
const crypto_1 = require("crypto");
|
|
14
|
+
const correlation_id_constant_1 = require("./correlation-id.constant");
|
|
15
|
+
let CorrelationIdInterceptor = CorrelationIdInterceptor_1 = class CorrelationIdInterceptor {
|
|
16
|
+
clsService;
|
|
17
|
+
logger = new common_1.Logger(CorrelationIdInterceptor_1.name);
|
|
18
|
+
constructor(clsService) {
|
|
19
|
+
this.clsService = clsService;
|
|
20
|
+
}
|
|
21
|
+
intercept(executionContext, next) {
|
|
22
|
+
let correlationId;
|
|
23
|
+
switch (executionContext.getType()) {
|
|
24
|
+
case 'http': {
|
|
25
|
+
const request = executionContext
|
|
26
|
+
.switchToHttp()
|
|
27
|
+
.getRequest();
|
|
28
|
+
const correlationIdValue = Array.isArray(request.headers[correlation_id_constant_1.CORRELATION_ID_HEADER_NAME])
|
|
29
|
+
? request.headers[correlation_id_constant_1.CORRELATION_ID_HEADER_NAME][0]
|
|
30
|
+
: request.headers[correlation_id_constant_1.CORRELATION_ID_HEADER_NAME];
|
|
31
|
+
correlationId = correlationIdValue ?? (0, crypto_1.randomUUID)();
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
case 'graphql': {
|
|
35
|
+
const ctx = graphql_1.GqlExecutionContext.create(executionContext);
|
|
36
|
+
const req = ctx.getContext().req;
|
|
37
|
+
correlationId = req.headers[correlation_id_constant_1.CORRELATION_ID_HEADER_NAME];
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
case 'rpc': {
|
|
41
|
+
const { correlationId: correlationIdValue } = executionContext
|
|
42
|
+
.switchToRpc()
|
|
43
|
+
.getContext();
|
|
44
|
+
correlationId = correlationIdValue ?? (0, crypto_1.randomUUID)();
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
default:
|
|
48
|
+
throw new Error('Unimplemented request type');
|
|
49
|
+
}
|
|
50
|
+
this.clsService.set(correlation_id_constant_1.CORRELATION_ID_CLS_KEY, correlationId);
|
|
51
|
+
return next.handle();
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
exports.CorrelationIdInterceptor = CorrelationIdInterceptor;
|
|
55
|
+
exports.CorrelationIdInterceptor = CorrelationIdInterceptor = CorrelationIdInterceptor_1 = __decorate([
|
|
56
|
+
(0, common_1.Injectable)()
|
|
57
|
+
], CorrelationIdInterceptor);
|
|
58
|
+
//# sourceMappingURL=correlation-id.interceptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"correlation-id.interceptor.js","sourceRoot":"","sources":["../../../src/correlation-id/correlation-id.interceptor.ts"],"names":[],"mappings":";;;;;;;;;;AAEA,2CAMwB;AACxB,6CAAsD;AACtD,mCAAoC;AAIpC,uEAGmC;AAG5B,IAAM,wBAAwB,gCAA9B,MAAM,wBAAwB;IAGN;IAFrB,MAAM,GAAG,IAAI,eAAM,CAAC,0BAAwB,CAAC,IAAI,CAAC,CAAC;IAE3D,YAA6B,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;IAAG,CAAC;IAEvD,SAAS,CAAC,gBAAkC,EAAE,IAAiB;QAC7D,IAAI,aAAqB,CAAC;QAE1B,QAAQ,gBAAgB,CAAC,OAAO,EAA0B,EAAE,CAAC;YAC3D,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,MAAM,OAAO,GAAY,gBAAgB;qBACtC,YAAY,EAAE;qBACd,UAAU,EAAE,CAAC;gBAChB,MAAM,kBAAkB,GAAG,KAAK,CAAC,OAAO,CACtC,OAAO,CAAC,OAAO,CAAC,oDAA0B,CAAC,CAC5C;oBACC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,oDAA0B,CAAC,CAAC,CAAC,CAAC;oBAChD,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,oDAA0B,CAAC,CAAC;gBAEhD,aAAa,GAAG,kBAAkB,IAAI,IAAA,mBAAU,GAAE,CAAC;gBAEnD,MAAM;YACR,CAAC;YACD,KAAK,SAAS,CAAC,CAAC,CAAC;gBACf,MAAM,GAAG,GAAG,6BAAmB,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;gBACzD,MAAM,GAAG,GAAY,GAAG,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC;gBAE1C,aAAa,GAAG,GAAG,CAAC,OAAO,CACzB,oDAA0B,CACjB,CAAC;gBAEZ,MAAM;YACR,CAAC;YACD,KAAK,KAAK,CAAC,CAAC,CAAC;gBACX,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,GAAG,gBAAgB;qBAC3D,WAAW,EAAE;qBACb,UAAU,EAA8B,CAAC;gBAE5C,aAAa,GAAG,kBAAkB,IAAI,IAAA,mBAAU,GAAE,CAAC;gBAEnD,MAAM;YACR,CAAC;YACD;gBACE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAClD,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,gDAAsB,EAAE,aAAa,CAAC,CAAC;QAE3D,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;IACvB,CAAC;CACF,CAAA;AAlDY,4DAAwB;mCAAxB,wBAAwB;IADpC,IAAA,mBAAU,GAAE;GACA,wBAAwB,CAkDpC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var CorrelationIdModule_1;
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.CorrelationIdModule = void 0;
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
const core_1 = require("@nestjs/core");
|
|
13
|
+
const nestjs_cls_1 = require("nestjs-cls");
|
|
14
|
+
const correlation_id_interceptor_1 = require("./correlation-id.interceptor");
|
|
15
|
+
const correlation_id_service_1 = require("./correlation-id.service");
|
|
16
|
+
let CorrelationIdModule = CorrelationIdModule_1 = class CorrelationIdModule {
|
|
17
|
+
forRoot(options) {
|
|
18
|
+
return {
|
|
19
|
+
global: options?.isGlobal ?? false,
|
|
20
|
+
module: CorrelationIdModule_1,
|
|
21
|
+
imports: [nestjs_cls_1.ClsModule],
|
|
22
|
+
providers: [
|
|
23
|
+
{
|
|
24
|
+
provide: core_1.APP_INTERCEPTOR,
|
|
25
|
+
useClass: correlation_id_interceptor_1.CorrelationIdInterceptor,
|
|
26
|
+
},
|
|
27
|
+
correlation_id_service_1.CorrelationIdService,
|
|
28
|
+
],
|
|
29
|
+
exports: [correlation_id_service_1.CorrelationIdService],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
exports.CorrelationIdModule = CorrelationIdModule;
|
|
34
|
+
exports.CorrelationIdModule = CorrelationIdModule = CorrelationIdModule_1 = __decorate([
|
|
35
|
+
(0, common_1.Module)({})
|
|
36
|
+
], CorrelationIdModule);
|
|
37
|
+
//# sourceMappingURL=correlation-id.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"correlation-id.module.js","sourceRoot":"","sources":["../../../src/correlation-id/correlation-id.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAuD;AACvD,uCAA+C;AAC/C,2CAAuC;AAEvC,6EAAwE;AACxE,qEAAgE;AAIzD,IAAM,mBAAmB,2BAAzB,MAAM,mBAAmB;IAC9B,OAAO,CAAC,OAAoC;QAC1C,OAAO;YACL,MAAM,EAAE,OAAO,EAAE,QAAQ,IAAI,KAAK;YAClC,MAAM,EAAE,qBAAmB;YAC3B,OAAO,EAAE,CAAC,sBAAS,CAAC;YACpB,SAAS,EAAE;gBACT;oBACE,OAAO,EAAE,sBAAe;oBACxB,QAAQ,EAAE,qDAAwB;iBACnC;gBACD,6CAAoB;aACrB;YACD,OAAO,EAAE,CAAC,6CAAoB,CAAC;SAChC,CAAC;IACJ,CAAC;CACF,CAAA;AAhBY,kDAAmB;8BAAnB,mBAAmB;IAD/B,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,mBAAmB,CAgB/B"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var CorrelationIdService_1;
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.CorrelationIdService = void 0;
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
const crypto_1 = require("crypto");
|
|
13
|
+
const correlation_id_constant_1 = require("./correlation-id.constant");
|
|
14
|
+
let CorrelationIdService = CorrelationIdService_1 = class CorrelationIdService {
|
|
15
|
+
clsService;
|
|
16
|
+
logger = new common_1.Logger(CorrelationIdService_1.name);
|
|
17
|
+
constructor(clsService) {
|
|
18
|
+
this.clsService = clsService;
|
|
19
|
+
}
|
|
20
|
+
get correlationId() {
|
|
21
|
+
return (this.clsService.get(correlation_id_constant_1.CORRELATION_ID_CLS_KEY) ?? (0, crypto_1.randomUUID)());
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
exports.CorrelationIdService = CorrelationIdService;
|
|
25
|
+
exports.CorrelationIdService = CorrelationIdService = CorrelationIdService_1 = __decorate([
|
|
26
|
+
(0, common_1.Injectable)()
|
|
27
|
+
], CorrelationIdService);
|
|
28
|
+
//# sourceMappingURL=correlation-id.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"correlation-id.service.js","sourceRoot":"","sources":["../../../src/correlation-id/correlation-id.service.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAoD;AACpD,mCAAoC;AAGpC,uEAAmE;AAG5D,IAAM,oBAAoB,4BAA1B,MAAM,oBAAoB;IAGF;IAFZ,MAAM,GAAG,IAAI,eAAM,CAAC,sBAAoB,CAAC,IAAI,CAAC,CAAC;IAEhE,YAA6B,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;IAAG,CAAC;IAEvD,IAAI,aAAa;QACf,OAAO,CACL,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,gDAAsB,CAAC,IAAI,IAAA,mBAAU,GAAE,CAC5D,CAAC;IACJ,CAAC;CACF,CAAA;AAVY,oDAAoB;+BAApB,oBAAoB;IADhC,IAAA,mBAAU,GAAE;GACA,oBAAoB,CAUhC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"correlation-id.type.js","sourceRoot":"","sources":["../../../src/correlation-id/correlation-id.type.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./correlation-id.constant"), exports);
|
|
18
|
+
__exportStar(require("./correlation-id.module"), exports);
|
|
19
|
+
__exportStar(require("./correlation-id.service"), exports);
|
|
20
|
+
__exportStar(require("./correlation-id.type"), exports);
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/correlation-id/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4DAA0C;AAC1C,0DAAwC;AACxC,2DAAyC;AACzC,wDAAsC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./correlation-id"), exports);
|
|
18
|
+
__exportStar(require("./types"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mDAAiC;AACjC,0CAAwB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import eslint from '@eslint/js';
|
|
4
|
+
import perfectionist from 'eslint-plugin-perfectionist';
|
|
5
|
+
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
|
|
6
|
+
import globals from 'globals';
|
|
7
|
+
import { dirname } from 'path';
|
|
8
|
+
import tseslint from 'typescript-eslint';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = dirname(__filename);
|
|
13
|
+
|
|
14
|
+
export default tseslint.config(
|
|
15
|
+
{
|
|
16
|
+
ignores: ['eslint.config.mjs', '**/dist'],
|
|
17
|
+
},
|
|
18
|
+
eslint.configs.recommended,
|
|
19
|
+
...tseslint.configs.recommendedTypeChecked,
|
|
20
|
+
eslintPluginPrettierRecommended,
|
|
21
|
+
{
|
|
22
|
+
languageOptions: {
|
|
23
|
+
globals: {
|
|
24
|
+
...globals.node,
|
|
25
|
+
...globals.jest,
|
|
26
|
+
},
|
|
27
|
+
ecmaVersion: 5,
|
|
28
|
+
sourceType: 'module',
|
|
29
|
+
parserOptions: {
|
|
30
|
+
projectService: true,
|
|
31
|
+
tsconfigRootDir: __dirname,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
rules: {
|
|
37
|
+
'@typescript-eslint/no-explicit-any': 'error',
|
|
38
|
+
'@typescript-eslint/no-floating-promises': 'warn',
|
|
39
|
+
'@typescript-eslint/no-unsafe-argument': 'warn',
|
|
40
|
+
'@typescript-eslint/no-unsafe-assignment': 'off',
|
|
41
|
+
'@typescript-eslint/no-unsafe-member-access': 'off',
|
|
42
|
+
'@typescript-eslint/no-unsafe-call': 'off',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
files: ['**/*.config.ts', '**/*.spec.ts', '**/*.e2e-spec.ts'],
|
|
47
|
+
rules: {
|
|
48
|
+
'@typescript-eslint/naming-convention': [
|
|
49
|
+
'error',
|
|
50
|
+
{
|
|
51
|
+
selector: 'typeParameter',
|
|
52
|
+
format: ['PascalCase'],
|
|
53
|
+
|
|
54
|
+
custom: {
|
|
55
|
+
regex: '^T[A-Z][a-zA-Z]+$',
|
|
56
|
+
match: true,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
'@typescript-eslint/no-unused-vars': [
|
|
61
|
+
'error',
|
|
62
|
+
{
|
|
63
|
+
argsIgnorePattern: '^_',
|
|
64
|
+
varsIgnorePattern: '^_',
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
'@typescript-eslint/no-namespace': 'off',
|
|
68
|
+
'@typescript-eslint/no-empty-interface': 'off',
|
|
69
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
70
|
+
'@typescript-eslint/no-unsafe-argument': 'off',
|
|
71
|
+
'@typescript-eslint/no-empty-object-type': 'off',
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
plugins: {
|
|
76
|
+
perfectionist,
|
|
77
|
+
},
|
|
78
|
+
rules: {
|
|
79
|
+
'@typescript-eslint/no-unused-vars': [
|
|
80
|
+
'warn',
|
|
81
|
+
{
|
|
82
|
+
argsIgnorePattern: '^_[^_].*$|^_$',
|
|
83
|
+
varsIgnorePattern: '^_[^_].*$|^_$',
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
'perfectionist/sort-named-imports': 'error',
|
|
87
|
+
'perfectionist/sort-exports': 'error',
|
|
88
|
+
'perfectionist/sort-imports': 'error',
|
|
89
|
+
'perfectionist/sort-named-exports': 'error',
|
|
90
|
+
'perfectionist/sort-enums': 'error',
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
ignores: ['*decorator.ts', '*.spec.ts'],
|
|
95
|
+
rules: {
|
|
96
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
);
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nestjs-backend-common",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"main": "dist/index",
|
|
5
|
+
"types": "dist/index",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+ssh://git@github.com/kasir-barati/nestjs-backend-common.git"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"npm",
|
|
12
|
+
"common",
|
|
13
|
+
"nestjs",
|
|
14
|
+
"nodejs",
|
|
15
|
+
"javascript",
|
|
16
|
+
"typescript"
|
|
17
|
+
],
|
|
18
|
+
"author": "kasir-barati",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/kasir-barati/nestjs-backend-common/issues"
|
|
22
|
+
},
|
|
23
|
+
"homepage": "https://github.com/kasir-barati/nestjs-backend-common#readme",
|
|
24
|
+
"description": "All the utility functions and common modules I usually use in my NestJS applications will be published and maintained here.",
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@nestjs/common": "^11.0.20",
|
|
27
|
+
"@nestjs/core": "^11.0.20",
|
|
28
|
+
"@nestjs/graphql": "^13.1.0",
|
|
29
|
+
"nestjs-cls": "^5.4.3"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@eslint/js": "^9.25.0",
|
|
33
|
+
"@types/express": "^5.0.1",
|
|
34
|
+
"@types/node": "^22.14.1",
|
|
35
|
+
"eslint-config-prettier": "^10.1.2",
|
|
36
|
+
"eslint-plugin-perfectionist": "^4.11.0",
|
|
37
|
+
"eslint-plugin-prettier": "^5.2.6",
|
|
38
|
+
"globals": "^16.0.0",
|
|
39
|
+
"prettier": "^3.5.3",
|
|
40
|
+
"typescript": "^5.8.3",
|
|
41
|
+
"typescript-eslint": "^8.30.1"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"test": "jest",
|
|
45
|
+
"build": "rm -rf dist && tsc",
|
|
46
|
+
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\"",
|
|
47
|
+
"lint:fix": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
|
48
|
+
"prepublish": "npm run build"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Request } from 'express';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
CallHandler,
|
|
5
|
+
ExecutionContext,
|
|
6
|
+
Injectable,
|
|
7
|
+
Logger,
|
|
8
|
+
NestInterceptor,
|
|
9
|
+
} from '@nestjs/common';
|
|
10
|
+
import { GqlExecutionContext } from '@nestjs/graphql';
|
|
11
|
+
import { randomUUID } from 'crypto';
|
|
12
|
+
import { ClsService } from 'nestjs-cls';
|
|
13
|
+
|
|
14
|
+
import { CommonExecutionContext } from '../types';
|
|
15
|
+
import {
|
|
16
|
+
CORRELATION_ID_CLS_KEY,
|
|
17
|
+
CORRELATION_ID_HEADER_NAME,
|
|
18
|
+
} from './correlation-id.constant';
|
|
19
|
+
|
|
20
|
+
@Injectable()
|
|
21
|
+
export class CorrelationIdInterceptor implements NestInterceptor {
|
|
22
|
+
private logger = new Logger(CorrelationIdInterceptor.name);
|
|
23
|
+
|
|
24
|
+
constructor(private readonly clsService: ClsService) {}
|
|
25
|
+
|
|
26
|
+
intercept(executionContext: ExecutionContext, next: CallHandler) {
|
|
27
|
+
let correlationId: string;
|
|
28
|
+
|
|
29
|
+
switch (executionContext.getType<CommonExecutionContext>()) {
|
|
30
|
+
case 'http': {
|
|
31
|
+
const request: Request = executionContext
|
|
32
|
+
.switchToHttp()
|
|
33
|
+
.getRequest();
|
|
34
|
+
const correlationIdValue = Array.isArray(
|
|
35
|
+
request.headers[CORRELATION_ID_HEADER_NAME],
|
|
36
|
+
)
|
|
37
|
+
? request.headers[CORRELATION_ID_HEADER_NAME][0]
|
|
38
|
+
: request.headers[CORRELATION_ID_HEADER_NAME];
|
|
39
|
+
|
|
40
|
+
correlationId = correlationIdValue ?? randomUUID();
|
|
41
|
+
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
case 'graphql': {
|
|
45
|
+
const ctx = GqlExecutionContext.create(executionContext);
|
|
46
|
+
const req: Request = ctx.getContext().req;
|
|
47
|
+
|
|
48
|
+
correlationId = req.headers[
|
|
49
|
+
CORRELATION_ID_HEADER_NAME
|
|
50
|
+
] as string;
|
|
51
|
+
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case 'rpc': {
|
|
55
|
+
const { correlationId: correlationIdValue } = executionContext
|
|
56
|
+
.switchToRpc()
|
|
57
|
+
.getContext<{ correlationId?: string }>();
|
|
58
|
+
|
|
59
|
+
correlationId = correlationIdValue ?? randomUUID();
|
|
60
|
+
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
default:
|
|
64
|
+
throw new Error('Unimplemented request type');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
this.clsService.set(CORRELATION_ID_CLS_KEY, correlationId);
|
|
68
|
+
|
|
69
|
+
return next.handle();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { DynamicModule, Module } from '@nestjs/common';
|
|
2
|
+
import { APP_INTERCEPTOR } from '@nestjs/core';
|
|
3
|
+
import { ClsModule } from 'nestjs-cls';
|
|
4
|
+
|
|
5
|
+
import { CorrelationIdInterceptor } from './correlation-id.interceptor';
|
|
6
|
+
import { CorrelationIdService } from './correlation-id.service';
|
|
7
|
+
import { CorrelationIdModuleOptions } from './correlation-id.type';
|
|
8
|
+
|
|
9
|
+
@Module({})
|
|
10
|
+
export class CorrelationIdModule {
|
|
11
|
+
forRoot(options?: CorrelationIdModuleOptions): DynamicModule {
|
|
12
|
+
return {
|
|
13
|
+
global: options?.isGlobal ?? false,
|
|
14
|
+
module: CorrelationIdModule,
|
|
15
|
+
imports: [ClsModule],
|
|
16
|
+
providers: [
|
|
17
|
+
{
|
|
18
|
+
provide: APP_INTERCEPTOR,
|
|
19
|
+
useClass: CorrelationIdInterceptor,
|
|
20
|
+
},
|
|
21
|
+
CorrelationIdService,
|
|
22
|
+
],
|
|
23
|
+
exports: [CorrelationIdService],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Injectable, Logger } from '@nestjs/common';
|
|
2
|
+
import { randomUUID } from 'crypto';
|
|
3
|
+
import { ClsService } from 'nestjs-cls';
|
|
4
|
+
|
|
5
|
+
import { CORRELATION_ID_CLS_KEY } from './correlation-id.constant';
|
|
6
|
+
|
|
7
|
+
@Injectable()
|
|
8
|
+
export class CorrelationIdService {
|
|
9
|
+
private readonly logger = new Logger(CorrelationIdService.name);
|
|
10
|
+
|
|
11
|
+
constructor(private readonly clsService: ClsService) {}
|
|
12
|
+
|
|
13
|
+
get correlationId(): string {
|
|
14
|
+
return (
|
|
15
|
+
this.clsService.get(CORRELATION_ID_CLS_KEY) ?? randomUUID()
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
}
|
package/src/index.ts
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2024",
|
|
4
|
+
"experimentalDecorators": true,
|
|
5
|
+
"module": "NodeNext",
|
|
6
|
+
"rootDir": "./",
|
|
7
|
+
"outDir": "./dist",
|
|
8
|
+
"moduleResolution": "nodenext",
|
|
9
|
+
"sourceMap": true,
|
|
10
|
+
"removeComments": false,
|
|
11
|
+
"newLine": "crlf",
|
|
12
|
+
"esModuleInterop": true,
|
|
13
|
+
"forceConsistentCasingInFileNames": true,
|
|
14
|
+
"strict": true,
|
|
15
|
+
"strictPropertyInitialization": false,
|
|
16
|
+
"skipLibCheck": true
|
|
17
|
+
}
|
|
18
|
+
}
|