@lenne.tech/nest-server 11.7.3 → 11.9.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/dist/config.env.js +3 -0
- package/dist/config.env.js.map +1 -1
- package/dist/core/common/interfaces/server-options.interface.d.ts +35 -0
- package/dist/core/modules/auth/guards/roles.guard.js +4 -3
- package/dist/core/modules/auth/guards/roles.guard.js.map +1 -1
- package/dist/core/modules/auth/services/core-auth.service.js +5 -4
- package/dist/core/modules/auth/services/core-auth.service.js.map +1 -1
- package/dist/core/modules/error-code/core-error-code.controller.d.ts +7 -0
- package/dist/core/modules/error-code/core-error-code.controller.js +45 -0
- package/dist/core/modules/error-code/core-error-code.controller.js.map +1 -0
- package/dist/core/modules/error-code/core-error-code.service.d.ts +16 -0
- package/dist/core/modules/error-code/core-error-code.service.js +65 -0
- package/dist/core/modules/error-code/core-error-code.service.js.map +1 -0
- package/dist/core/modules/error-code/error-code.module.d.ts +7 -0
- package/dist/core/modules/error-code/error-code.module.js +64 -0
- package/dist/core/modules/error-code/error-code.module.js.map +1 -0
- package/dist/core/modules/error-code/error-codes.d.ts +219 -0
- package/dist/core/modules/error-code/error-codes.js +204 -0
- package/dist/core/modules/error-code/error-codes.js.map +1 -0
- package/dist/core/modules/error-code/index.d.ts +5 -0
- package/dist/core/modules/error-code/index.js +22 -0
- package/dist/core/modules/error-code/index.js.map +1 -0
- package/dist/core/modules/error-code/interfaces/error-code.interfaces.d.ts +12 -0
- package/dist/core/modules/error-code/interfaces/error-code.interfaces.js +3 -0
- package/dist/core/modules/error-code/interfaces/error-code.interfaces.js.map +1 -0
- package/dist/core/modules/file/core-file.controller.d.ts +1 -0
- package/dist/core/modules/file/core-file.controller.js +22 -0
- package/dist/core/modules/file/core-file.controller.js.map +1 -1
- package/dist/core/modules/tus/core-tus.controller.d.ts +9 -0
- package/dist/core/modules/tus/core-tus.controller.js +85 -0
- package/dist/core/modules/tus/core-tus.controller.js.map +1 -0
- package/dist/core/modules/tus/core-tus.service.d.ts +30 -0
- package/dist/core/modules/tus/core-tus.service.js +284 -0
- package/dist/core/modules/tus/core-tus.service.js.map +1 -0
- package/dist/core/modules/tus/index.d.ts +4 -0
- package/dist/core/modules/tus/index.js +21 -0
- package/dist/core/modules/tus/index.js.map +1 -0
- package/dist/core/modules/tus/interfaces/tus-config.interface.d.ts +10 -0
- package/dist/core/modules/tus/interfaces/tus-config.interface.js +59 -0
- package/dist/core/modules/tus/interfaces/tus-config.interface.js.map +1 -0
- package/dist/core/modules/tus/tus.module.d.ts +21 -0
- package/dist/core/modules/tus/tus.module.js +99 -0
- package/dist/core/modules/tus/tus.module.js.map +1 -0
- package/dist/core.module.js +8 -0
- package/dist/core.module.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/server/modules/error-code/error-code.controller.d.ts +8 -0
- package/dist/server/modules/error-code/error-code.controller.js +55 -0
- package/dist/server/modules/error-code/error-code.controller.js.map +1 -0
- package/dist/server/modules/error-code/error-code.service.d.ts +4 -0
- package/dist/server/modules/error-code/error-code.service.js +27 -0
- package/dist/server/modules/error-code/error-code.service.js.map +1 -0
- package/dist/server/modules/error-code/error-codes.d.ts +45 -0
- package/dist/server/modules/error-code/error-codes.js +24 -0
- package/dist/server/modules/error-code/error-codes.js.map +1 -0
- package/dist/server/modules/error-code/index.d.ts +3 -0
- package/dist/server/modules/error-code/index.js +20 -0
- package/dist/server/modules/error-code/index.js.map +1 -0
- package/dist/server/modules/file/file.controller.d.ts +5 -7
- package/dist/server/modules/file/file.controller.js +3 -31
- package/dist/server/modules/file/file.controller.js.map +1 -1
- package/dist/server/server.module.js +10 -1
- package/dist/server/server.module.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +5 -2
- package/src/config.env.ts +4 -0
- package/src/core/common/interfaces/server-options.interface.ts +243 -0
- package/src/core/modules/auth/guards/roles.guard.ts +5 -4
- package/src/core/modules/auth/services/core-auth.service.ts +5 -4
- package/src/core/modules/error-code/INTEGRATION-CHECKLIST.md +288 -0
- package/src/core/modules/error-code/core-error-code.controller.ts +54 -0
- package/src/core/modules/error-code/core-error-code.service.ts +135 -0
- package/src/core/modules/error-code/error-code.module.ts +119 -0
- package/src/core/modules/error-code/error-codes.ts +405 -0
- package/src/core/modules/error-code/index.ts +14 -0
- package/src/core/modules/error-code/interfaces/error-code.interfaces.ts +99 -0
- package/src/core/modules/file/README.md +165 -0
- package/src/core/modules/file/core-file.controller.ts +27 -1
- package/src/core/modules/tus/INTEGRATION-CHECKLIST.md +176 -0
- package/src/core/modules/tus/README.md +439 -0
- package/src/core/modules/tus/core-tus.controller.ts +88 -0
- package/src/core/modules/tus/core-tus.service.ts +424 -0
- package/src/core/modules/tus/index.ts +5 -0
- package/src/core/modules/tus/interfaces/tus-config.interface.ts +107 -0
- package/src/core/modules/tus/tus.module.ts +187 -0
- package/src/core.module.ts +16 -0
- package/src/index.ts +12 -0
- package/src/server/modules/error-code/README.md +131 -0
- package/src/server/modules/error-code/error-code.controller.ts +91 -0
- package/src/server/modules/error-code/error-code.service.ts +42 -0
- package/src/server/modules/error-code/error-codes.ts +65 -0
- package/src/server/modules/error-code/index.ts +8 -0
- package/src/server/modules/file/file.controller.ts +14 -34
- package/src/server/server.module.ts +15 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/nest-server",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.9.0",
|
|
4
4
|
"description": "Modern, fast, powerful Node.js web framework in TypeScript based on Nest with a GraphQL API and a connection to MongoDB (or other databases).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"node",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"build:pack": "npm pack && echo 'use file:/ROOT_PATH_TO_TGZ_FILE to integrate the package'",
|
|
22
22
|
"build:dev": "npm run build && yalc push --private",
|
|
23
23
|
"docs": "npm run docs:ci && open http://127.0.0.1:8080/ && open ./public/index.html && compodoc -p tsconfig.json -s ",
|
|
24
|
-
"docs:bootstrap": "node extras/update-spectaql-version.mjs &&
|
|
24
|
+
"docs:bootstrap": "node extras/update-spectaql-version.mjs && node scripts/run-spectaql.mjs",
|
|
25
25
|
"docs:ci": "ts-node ./scripts/init-server.ts && npm run docs:bootstrap && compodoc -p tsconfig.json",
|
|
26
26
|
"format": "prettier --write 'src/**/*.ts'",
|
|
27
27
|
"format:staged": "pretty-quick --staged",
|
|
@@ -93,6 +93,8 @@
|
|
|
93
93
|
"@nestjs/swagger": "11.2.3",
|
|
94
94
|
"@nestjs/terminus": "11.0.0",
|
|
95
95
|
"@nestjs/websockets": "11.1.9",
|
|
96
|
+
"@tus/file-store": "2.0.0",
|
|
97
|
+
"@tus/server": "2.3.0",
|
|
96
98
|
"apollo-server-core": "3.13.0",
|
|
97
99
|
"bcrypt": "6.0.0",
|
|
98
100
|
"better-auth": "1.4.8-beta.4",
|
|
@@ -167,6 +169,7 @@
|
|
|
167
169
|
"ts-morph": "27.0.2",
|
|
168
170
|
"ts-node": "10.9.2",
|
|
169
171
|
"tsconfig-paths": "4.2.0",
|
|
172
|
+
"tus-js-client": "4.3.1",
|
|
170
173
|
"typescript": "5.9.3",
|
|
171
174
|
"unplugin-swc": "1.5.9",
|
|
172
175
|
"vite": "7.3.0",
|
package/src/config.env.ts
CHANGED
|
@@ -262,6 +262,10 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
262
262
|
verificationLink: 'http://localhost:4200/user/verification',
|
|
263
263
|
},
|
|
264
264
|
env: 'local',
|
|
265
|
+
// Disable auto-registration to allow Server ErrorCodeModule with SRV_* codes
|
|
266
|
+
errorCode: {
|
|
267
|
+
autoRegister: false,
|
|
268
|
+
},
|
|
265
269
|
execAfterInit: 'npm run docs:bootstrap',
|
|
266
270
|
filter: {
|
|
267
271
|
maxLimit: null,
|
|
@@ -589,6 +589,70 @@ export interface IBetterAuthUserField {
|
|
|
589
589
|
type: BetterAuthFieldType;
|
|
590
590
|
}
|
|
591
591
|
|
|
592
|
+
/**
|
|
593
|
+
* Interface for Error Code module configuration
|
|
594
|
+
*
|
|
595
|
+
* Controls how the ErrorCodeModule is registered and configured.
|
|
596
|
+
*
|
|
597
|
+
* @since 11.9.0
|
|
598
|
+
*/
|
|
599
|
+
export interface IErrorCode {
|
|
600
|
+
/**
|
|
601
|
+
* Additional error registry to merge with core LTNS_* errors
|
|
602
|
+
*
|
|
603
|
+
* Use this to add project-specific error codes with a custom prefix.
|
|
604
|
+
*
|
|
605
|
+
* @example
|
|
606
|
+
* ```typescript
|
|
607
|
+
* const ProjectErrors = {
|
|
608
|
+
* ORDER_NOT_FOUND: {
|
|
609
|
+
* code: 'PROJ_0001',
|
|
610
|
+
* message: 'Order not found',
|
|
611
|
+
* translations: { de: 'Bestellung nicht gefunden.', en: 'Order not found.' }
|
|
612
|
+
* }
|
|
613
|
+
* } as const satisfies IErrorRegistry;
|
|
614
|
+
*
|
|
615
|
+
* errorCode: {
|
|
616
|
+
* additionalErrorRegistry: ProjectErrors,
|
|
617
|
+
* }
|
|
618
|
+
* ```
|
|
619
|
+
*/
|
|
620
|
+
additionalErrorRegistry?: Record<
|
|
621
|
+
string,
|
|
622
|
+
{
|
|
623
|
+
code: string;
|
|
624
|
+
message: string;
|
|
625
|
+
translations: { [locale: string]: string; de: string; en: string };
|
|
626
|
+
}
|
|
627
|
+
>;
|
|
628
|
+
|
|
629
|
+
/**
|
|
630
|
+
* Automatically register the ErrorCodeModule in CoreModule
|
|
631
|
+
*
|
|
632
|
+
* Set to `false` to disable auto-registration and provide your own
|
|
633
|
+
* ErrorCodeModule with custom controller and/or service.
|
|
634
|
+
*
|
|
635
|
+
* @default true
|
|
636
|
+
*
|
|
637
|
+
* @example
|
|
638
|
+
* ```typescript
|
|
639
|
+
* // In config.env.ts - disable auto-registration
|
|
640
|
+
* errorCode: {
|
|
641
|
+
* autoRegister: false,
|
|
642
|
+
* }
|
|
643
|
+
*
|
|
644
|
+
* // In server.module.ts - import your custom module
|
|
645
|
+
* @Module({
|
|
646
|
+
* imports: [
|
|
647
|
+
* CoreModule.forRoot(...),
|
|
648
|
+
* ErrorCodeModule.forRoot(), // Your custom module
|
|
649
|
+
* ],
|
|
650
|
+
* })
|
|
651
|
+
* ```
|
|
652
|
+
*/
|
|
653
|
+
autoRegister?: boolean;
|
|
654
|
+
}
|
|
655
|
+
|
|
592
656
|
/**
|
|
593
657
|
* Interface for JWT configuration (main and refresh)
|
|
594
658
|
*/
|
|
@@ -766,6 +830,31 @@ export interface IServerOptions {
|
|
|
766
830
|
*/
|
|
767
831
|
env?: string;
|
|
768
832
|
|
|
833
|
+
/**
|
|
834
|
+
* Configuration for the error code module
|
|
835
|
+
*
|
|
836
|
+
* Controls how error codes and translations are handled.
|
|
837
|
+
*
|
|
838
|
+
* @since 11.9.0
|
|
839
|
+
*
|
|
840
|
+
* @example
|
|
841
|
+
* ```typescript
|
|
842
|
+
* // Default: auto-register with core errors only
|
|
843
|
+
* errorCode: undefined
|
|
844
|
+
*
|
|
845
|
+
* // Add project-specific error codes
|
|
846
|
+
* errorCode: {
|
|
847
|
+
* additionalErrorRegistry: ProjectErrors,
|
|
848
|
+
* }
|
|
849
|
+
*
|
|
850
|
+
* // Disable auto-registration to provide your own module
|
|
851
|
+
* errorCode: {
|
|
852
|
+
* autoRegister: false,
|
|
853
|
+
* }
|
|
854
|
+
* ```
|
|
855
|
+
*/
|
|
856
|
+
errorCode?: IErrorCode;
|
|
857
|
+
|
|
769
858
|
/**
|
|
770
859
|
* Exec a command after server is initialized
|
|
771
860
|
* e.g. 'npm run docs:bootstrap'
|
|
@@ -1132,4 +1221,158 @@ export interface IServerOptions {
|
|
|
1132
1221
|
*/
|
|
1133
1222
|
path?: string;
|
|
1134
1223
|
};
|
|
1224
|
+
|
|
1225
|
+
/**
|
|
1226
|
+
* TUS resumable upload configuration.
|
|
1227
|
+
*
|
|
1228
|
+
* Follows the "Enabled by Default" pattern - tus is automatically enabled
|
|
1229
|
+
* without any configuration. Set `tus: false` to explicitly disable.
|
|
1230
|
+
*
|
|
1231
|
+
* Accepts:
|
|
1232
|
+
* - `true` or `undefined`: Enable with defaults (enabled by default)
|
|
1233
|
+
* - `false`: Disable TUS uploads
|
|
1234
|
+
* - `{ ... }`: Enable with custom configuration
|
|
1235
|
+
*
|
|
1236
|
+
* @example
|
|
1237
|
+
* ```typescript
|
|
1238
|
+
* // Default: TUS enabled with all defaults (no config needed)
|
|
1239
|
+
*
|
|
1240
|
+
* // Disable TUS
|
|
1241
|
+
* tus: false,
|
|
1242
|
+
*
|
|
1243
|
+
* // Custom configuration
|
|
1244
|
+
* tus: {
|
|
1245
|
+
* maxSize: 100 * 1024 * 1024, // 100 MB
|
|
1246
|
+
* path: '/uploads',
|
|
1247
|
+
* },
|
|
1248
|
+
* ```
|
|
1249
|
+
*
|
|
1250
|
+
* @since 11.8.0
|
|
1251
|
+
*/
|
|
1252
|
+
tus?: boolean | ITusConfig;
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
/**
|
|
1256
|
+
* TUS Upload Configuration Interface
|
|
1257
|
+
*
|
|
1258
|
+
* Follows the "Enabled by Default" pattern - tus is automatically enabled
|
|
1259
|
+
* without any configuration. Set `tus: false` to explicitly disable.
|
|
1260
|
+
*/
|
|
1261
|
+
export interface ITusConfig {
|
|
1262
|
+
/**
|
|
1263
|
+
* Additional allowed HTTP headers for TUS requests (beyond @tus/server defaults).
|
|
1264
|
+
*
|
|
1265
|
+
* Note: @tus/server already includes all TUS protocol headers:
|
|
1266
|
+
* Authorization, Content-Type, Location, Tus-Extension, Tus-Max-Size,
|
|
1267
|
+
* Tus-Resumable, Tus-Version, Upload-Concat, Upload-Defer-Length,
|
|
1268
|
+
* Upload-Length, Upload-Metadata, Upload-Offset, X-HTTP-Method-Override,
|
|
1269
|
+
* X-Requested-With, X-Forwarded-Host, X-Forwarded-Proto, Forwarded
|
|
1270
|
+
*
|
|
1271
|
+
* Use this only for project-specific custom headers.
|
|
1272
|
+
*
|
|
1273
|
+
* @default [] (no additional headers needed)
|
|
1274
|
+
*/
|
|
1275
|
+
allowedHeaders?: string[];
|
|
1276
|
+
|
|
1277
|
+
/**
|
|
1278
|
+
* Allowed MIME types for uploads.
|
|
1279
|
+
* If undefined, all types are allowed.
|
|
1280
|
+
* @default undefined (all types allowed)
|
|
1281
|
+
*/
|
|
1282
|
+
allowedTypes?: string[];
|
|
1283
|
+
|
|
1284
|
+
/**
|
|
1285
|
+
* Checksum extension configuration.
|
|
1286
|
+
* Enables data integrity verification.
|
|
1287
|
+
* @default true
|
|
1288
|
+
*/
|
|
1289
|
+
checksum?: boolean;
|
|
1290
|
+
|
|
1291
|
+
/**
|
|
1292
|
+
* Concatenation extension configuration.
|
|
1293
|
+
* Allows parallel uploads that are merged.
|
|
1294
|
+
* @default true
|
|
1295
|
+
*/
|
|
1296
|
+
concatenation?: boolean;
|
|
1297
|
+
|
|
1298
|
+
/**
|
|
1299
|
+
* Creation extension configuration.
|
|
1300
|
+
* Allows creating new uploads via POST.
|
|
1301
|
+
* @default true
|
|
1302
|
+
*/
|
|
1303
|
+
creation?: boolean | ITusCreationConfig;
|
|
1304
|
+
|
|
1305
|
+
/**
|
|
1306
|
+
* Creation With Upload extension configuration.
|
|
1307
|
+
* Allows sending data in the initial POST request.
|
|
1308
|
+
* @default true
|
|
1309
|
+
*/
|
|
1310
|
+
creationWithUpload?: boolean;
|
|
1311
|
+
|
|
1312
|
+
/**
|
|
1313
|
+
* Whether tus uploads are enabled.
|
|
1314
|
+
* @default true (enabled by default)
|
|
1315
|
+
*/
|
|
1316
|
+
enabled?: boolean;
|
|
1317
|
+
|
|
1318
|
+
/**
|
|
1319
|
+
* Expiration extension configuration.
|
|
1320
|
+
* Automatically cleans up incomplete uploads.
|
|
1321
|
+
* @default { expiresIn: '24h' }
|
|
1322
|
+
*/
|
|
1323
|
+
expiration?: boolean | ITusExpirationConfig;
|
|
1324
|
+
|
|
1325
|
+
/**
|
|
1326
|
+
* Maximum upload size in bytes
|
|
1327
|
+
* @default 50 * 1024 * 1024 * 1024 (50 GB)
|
|
1328
|
+
*/
|
|
1329
|
+
maxSize?: number;
|
|
1330
|
+
|
|
1331
|
+
/**
|
|
1332
|
+
* Base path for tus endpoints
|
|
1333
|
+
* @default '/tus'
|
|
1334
|
+
*/
|
|
1335
|
+
path?: string;
|
|
1336
|
+
|
|
1337
|
+
/**
|
|
1338
|
+
* Termination extension configuration.
|
|
1339
|
+
* Allows deleting uploads via DELETE.
|
|
1340
|
+
* @default true
|
|
1341
|
+
*/
|
|
1342
|
+
termination?: boolean;
|
|
1343
|
+
|
|
1344
|
+
/**
|
|
1345
|
+
* Directory for temporary upload chunks.
|
|
1346
|
+
* @default 'uploads/tus'
|
|
1347
|
+
*/
|
|
1348
|
+
uploadDir?: string;
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
/**
|
|
1352
|
+
* TUS Creation extension configuration
|
|
1353
|
+
*/
|
|
1354
|
+
export interface ITusCreationConfig {
|
|
1355
|
+
/**
|
|
1356
|
+
* Whether creation is enabled
|
|
1357
|
+
* @default true
|
|
1358
|
+
*/
|
|
1359
|
+
enabled?: boolean;
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
/**
|
|
1363
|
+
* TUS Expiration extension configuration
|
|
1364
|
+
*/
|
|
1365
|
+
export interface ITusExpirationConfig {
|
|
1366
|
+
/**
|
|
1367
|
+
* Whether expiration is enabled
|
|
1368
|
+
* @default true
|
|
1369
|
+
*/
|
|
1370
|
+
enabled?: boolean;
|
|
1371
|
+
|
|
1372
|
+
/**
|
|
1373
|
+
* Time until incomplete uploads expire
|
|
1374
|
+
* Supports formats: '24h', '1d', '12h', etc.
|
|
1375
|
+
* @default '24h'
|
|
1376
|
+
*/
|
|
1377
|
+
expiresIn?: string;
|
|
1135
1378
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ExecutionContext, Injectable, Logger, Optional, UnauthorizedException } from '@nestjs/common';
|
|
1
|
+
import { ExecutionContext, ForbiddenException, Injectable, Logger, Optional, UnauthorizedException } from '@nestjs/common';
|
|
2
2
|
import { ModuleRef, Reflector } from '@nestjs/core';
|
|
3
3
|
import { GqlExecutionContext } from '@nestjs/graphql';
|
|
4
4
|
import { getConnectionToken } from '@nestjs/mongoose';
|
|
@@ -7,6 +7,7 @@ import { firstValueFrom, isObservable } from 'rxjs';
|
|
|
7
7
|
|
|
8
8
|
import { RoleEnum } from '../../../common/enums/role.enum';
|
|
9
9
|
import { BetterAuthService } from '../../better-auth/better-auth.service';
|
|
10
|
+
import { ErrorCode } from '../../error-code';
|
|
10
11
|
import { AuthGuardStrategy } from '../auth-guard-strategy.enum';
|
|
11
12
|
import { ExpiredTokenException } from '../exceptions/expired-token.exception';
|
|
12
13
|
import { InvalidTokenException } from '../exceptions/invalid-token.exception';
|
|
@@ -331,7 +332,7 @@ export class RolesGuard extends AuthGuard(AuthGuardStrategy.JWT) {
|
|
|
331
332
|
|
|
332
333
|
// Check if locked
|
|
333
334
|
if (roles && roles.includes(RoleEnum.S_NO_ONE)) {
|
|
334
|
-
throw new UnauthorizedException(
|
|
335
|
+
throw new UnauthorizedException(ErrorCode.UNAUTHORIZED);
|
|
335
336
|
}
|
|
336
337
|
|
|
337
338
|
// Check roles
|
|
@@ -354,11 +355,11 @@ export class RolesGuard extends AuthGuard(AuthGuardStrategy.JWT) {
|
|
|
354
355
|
if (info?.name === 'TokenExpiredError') {
|
|
355
356
|
throw new ExpiredTokenException();
|
|
356
357
|
}
|
|
357
|
-
throw new UnauthorizedException(
|
|
358
|
+
throw new UnauthorizedException(ErrorCode.UNAUTHORIZED);
|
|
358
359
|
}
|
|
359
360
|
|
|
360
361
|
// Requester is not authorized
|
|
361
|
-
throw new
|
|
362
|
+
throw new ForbiddenException(ErrorCode.ACCESS_DENIED);
|
|
362
363
|
}
|
|
363
364
|
|
|
364
365
|
// Everything is ok
|
|
@@ -17,6 +17,7 @@ import { ServiceOptions } from '../../../common/interfaces/service-options.inter
|
|
|
17
17
|
import { ConfigService } from '../../../common/services/config.service';
|
|
18
18
|
import { BetterAuthUserMapper } from '../../better-auth/better-auth-user.mapper';
|
|
19
19
|
import { BetterAuthService } from '../../better-auth/better-auth.service';
|
|
20
|
+
import { ErrorCode } from '../../error-code';
|
|
20
21
|
import { CoreAuthModel } from '../core-auth.model';
|
|
21
22
|
import { CoreAuthSignInInput } from '../inputs/core-auth-sign-in.input';
|
|
22
23
|
import { CoreAuthSignUpInput } from '../inputs/core-auth-sign-up.input';
|
|
@@ -83,13 +84,13 @@ export class CoreAuthService {
|
|
|
83
84
|
// Check authentication
|
|
84
85
|
const user = serviceOptions.currentUser;
|
|
85
86
|
if (!user || !tokenOrRefreshToken) {
|
|
86
|
-
throw new UnauthorizedException(
|
|
87
|
+
throw new UnauthorizedException(ErrorCode.INVALID_TOKEN);
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
// Check authorization
|
|
90
91
|
const deviceId = this.decodeJwt(tokenOrRefreshToken)?.deviceId;
|
|
91
92
|
if (!deviceId || !user.refreshTokens[deviceId]) {
|
|
92
|
-
throw new UnauthorizedException(
|
|
93
|
+
throw new UnauthorizedException(ErrorCode.INVALID_TOKEN);
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
// Logout from all devices
|
|
@@ -374,7 +375,7 @@ export class CoreAuthService {
|
|
|
374
375
|
if (currentRefreshToken) {
|
|
375
376
|
deviceId = this.decodeJwt(currentRefreshToken)?.deviceId;
|
|
376
377
|
if (!deviceId || !user.refreshTokens?.[deviceId]) {
|
|
377
|
-
throw new UnauthorizedException(
|
|
378
|
+
throw new UnauthorizedException(ErrorCode.INVALID_TOKEN);
|
|
378
379
|
}
|
|
379
380
|
if (!this.configService.getFastButReadOnly('jwt.refresh.renewal')) {
|
|
380
381
|
// Return currentToken
|
|
@@ -398,7 +399,7 @@ export class CoreAuthService {
|
|
|
398
399
|
// Set new token
|
|
399
400
|
const payload = this.decodeJwt(newRefreshToken);
|
|
400
401
|
if (!payload) {
|
|
401
|
-
throw new UnauthorizedException(
|
|
402
|
+
throw new UnauthorizedException(ErrorCode.INVALID_TOKEN);
|
|
402
403
|
}
|
|
403
404
|
if (!deviceId) {
|
|
404
405
|
deviceId = payload.deviceId;
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
# ErrorCode Integration Checklist
|
|
2
|
+
|
|
3
|
+
**For integrating custom error codes into projects using `@lenne.tech/nest-server`.**
|
|
4
|
+
|
|
5
|
+
> **Estimated time:** 5-10 minutes
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Choose Your Scenario
|
|
10
|
+
|
|
11
|
+
| Scenario | Use When | Configuration | Complexity |
|
|
12
|
+
|----------|----------|---------------|------------|
|
|
13
|
+
| **A. additionalErrorRegistry** | Simple error code addition | Config in `config.env.ts` | Minimal |
|
|
14
|
+
| **B. Custom Service** | Need custom locales or logic | Service inheritance | Low |
|
|
15
|
+
| **C. Custom Controller** | Need custom controller/routes | Service + Controller | Medium |
|
|
16
|
+
|
|
17
|
+
**Recommendation:** Start with **Scenario A**. Only use B or C if you need customization beyond adding error codes.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Reference Implementation
|
|
22
|
+
|
|
23
|
+
All files are available as reference in the package:
|
|
24
|
+
|
|
25
|
+
**Local (in your node_modules):**
|
|
26
|
+
```
|
|
27
|
+
node_modules/@lenne.tech/nest-server/src/server/modules/error-code/
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**GitHub:**
|
|
31
|
+
https://github.com/lenneTech/nest-server/tree/develop/src/server/modules/error-code
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Scenario A: additionalErrorRegistry (Simplest)
|
|
36
|
+
|
|
37
|
+
Use this when you just want to add project-specific error codes.
|
|
38
|
+
|
|
39
|
+
### 1. Define Error Codes
|
|
40
|
+
|
|
41
|
+
**Create:** `src/server/common/errors/project-errors.ts`
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { IErrorRegistry, mergeErrorCodes } from '@lenne.tech/nest-server';
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Project-specific error codes
|
|
48
|
+
*
|
|
49
|
+
* Format: PREFIX_XXXX (e.g., PROJ_0001, APP_0001)
|
|
50
|
+
* Use a unique prefix to avoid collisions with LTNS_* core errors.
|
|
51
|
+
*/
|
|
52
|
+
export const ProjectErrors = {
|
|
53
|
+
ORDER_NOT_FOUND: {
|
|
54
|
+
code: 'PROJ_0001',
|
|
55
|
+
message: 'Order not found',
|
|
56
|
+
translations: {
|
|
57
|
+
de: 'Bestellung mit ID {orderId} wurde nicht gefunden.',
|
|
58
|
+
en: 'Order with ID {orderId} was not found.',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
PAYMENT_FAILED: {
|
|
62
|
+
code: 'PROJ_0002',
|
|
63
|
+
message: 'Payment processing failed',
|
|
64
|
+
translations: {
|
|
65
|
+
de: 'Die Zahlung konnte nicht verarbeitet werden: {reason}',
|
|
66
|
+
en: 'Payment processing failed: {reason}',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
} as const satisfies IErrorRegistry;
|
|
70
|
+
|
|
71
|
+
// Merged error codes for type-safe factory functions
|
|
72
|
+
export const ErrorCode = mergeErrorCodes(ProjectErrors);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 2. Add to config.env.ts
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import { ProjectErrors } from './server/common/errors/project-errors';
|
|
79
|
+
|
|
80
|
+
const config = {
|
|
81
|
+
// ... other config ...
|
|
82
|
+
errorCode: {
|
|
83
|
+
additionalErrorRegistry: ProjectErrors,
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Done!** Your project errors are now available via `/api/i18n/errors/:locale`.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Scenario B: Custom Service (For Custom Locales)
|
|
93
|
+
|
|
94
|
+
Use this when you need:
|
|
95
|
+
- Additional locales (e.g., French, Spanish)
|
|
96
|
+
- Custom logic in the service
|
|
97
|
+
|
|
98
|
+
### 1. Define Error Codes
|
|
99
|
+
|
|
100
|
+
Same as Scenario A, Step 1.
|
|
101
|
+
|
|
102
|
+
### 2. Create Custom Service
|
|
103
|
+
|
|
104
|
+
**Create:** `src/server/modules/error-code/error-code.service.ts`
|
|
105
|
+
**Copy from:** `node_modules/@lenne.tech/nest-server/src/server/modules/error-code/error-code.service.ts`
|
|
106
|
+
|
|
107
|
+
**Optional customization - add locales:**
|
|
108
|
+
```typescript
|
|
109
|
+
@Injectable()
|
|
110
|
+
export class ErrorCodeService extends CoreErrorCodeService {
|
|
111
|
+
// Override to add more locales
|
|
112
|
+
protected override supportedLocales = ['de', 'en', 'fr', 'es'] as const;
|
|
113
|
+
|
|
114
|
+
constructor() {
|
|
115
|
+
super();
|
|
116
|
+
this.registerErrorRegistry(ProjectErrors);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 3. Disable Auto-Registration
|
|
122
|
+
|
|
123
|
+
**Update:** `src/config.env.ts`
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
const config = {
|
|
127
|
+
// ... other config ...
|
|
128
|
+
errorCode: {
|
|
129
|
+
autoRegister: false, // Required! Prevents CoreModule from registering its own
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**WHY is `autoRegister: false` required?**
|
|
135
|
+
NestJS @Global() modules use "first wins" for provider registration. Without this, CoreModule's ErrorCodeModule loads first and your custom service is ignored.
|
|
136
|
+
|
|
137
|
+
### 4. Register in ServerModule
|
|
138
|
+
|
|
139
|
+
**Update:** `src/server/server.module.ts`
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
import { ErrorCodeModule as CoreErrorCodeModule } from '@lenne.tech/nest-server';
|
|
143
|
+
import { ErrorCodeService } from './modules/error-code/error-code.service';
|
|
144
|
+
|
|
145
|
+
@Module({
|
|
146
|
+
imports: [
|
|
147
|
+
CoreModule.forRoot(...),
|
|
148
|
+
// Register with custom service
|
|
149
|
+
CoreErrorCodeModule.forRoot({
|
|
150
|
+
service: ErrorCodeService,
|
|
151
|
+
}),
|
|
152
|
+
// ... other modules
|
|
153
|
+
],
|
|
154
|
+
})
|
|
155
|
+
export class ServerModule {}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Scenario C: Custom Controller (For Custom Routes)
|
|
161
|
+
|
|
162
|
+
Use this when you need:
|
|
163
|
+
- Custom controller endpoints (e.g., `/codes` listing)
|
|
164
|
+
- Different route paths
|
|
165
|
+
- Additional REST endpoints
|
|
166
|
+
|
|
167
|
+
**No custom module needed!** Use Core `ErrorCodeModule.forRoot()` with your custom controller and service.
|
|
168
|
+
|
|
169
|
+
### 1. Create Files
|
|
170
|
+
|
|
171
|
+
**Copy from:** `node_modules/@lenne.tech/nest-server/src/server/modules/error-code/`
|
|
172
|
+
|
|
173
|
+
Files needed:
|
|
174
|
+
- `error-codes.ts` - Your error definitions
|
|
175
|
+
- `error-code.service.ts` - Service extending CoreErrorCodeService
|
|
176
|
+
- `error-code.controller.ts` - Controller (**standalone**, not extending)
|
|
177
|
+
- `index.ts` - Exports
|
|
178
|
+
|
|
179
|
+
**No `error-code.module.ts` needed!**
|
|
180
|
+
|
|
181
|
+
### 2. Disable Auto-Registration
|
|
182
|
+
|
|
183
|
+
Same as Scenario B, Step 3.
|
|
184
|
+
|
|
185
|
+
### 3. Register via Core ErrorCodeModule
|
|
186
|
+
|
|
187
|
+
**Update:** `src/server/server.module.ts`
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
import { ErrorCodeModule } from '@lenne.tech/nest-server';
|
|
191
|
+
import { ErrorCodeController } from './modules/error-code/error-code.controller';
|
|
192
|
+
import { ErrorCodeService } from './modules/error-code/error-code.service';
|
|
193
|
+
|
|
194
|
+
@Module({
|
|
195
|
+
imports: [
|
|
196
|
+
CoreModule.forRoot(...),
|
|
197
|
+
// Use Core ErrorCodeModule with custom service and controller
|
|
198
|
+
ErrorCodeModule.forRoot({
|
|
199
|
+
controller: ErrorCodeController,
|
|
200
|
+
service: ErrorCodeService,
|
|
201
|
+
}),
|
|
202
|
+
// ... other modules
|
|
203
|
+
],
|
|
204
|
+
})
|
|
205
|
+
export class ServerModule {}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**WHY standalone controller instead of extending?**
|
|
209
|
+
NestJS registers routes from parent classes first, regardless of method order in child classes. This causes `:locale` to intercept `/codes`. A standalone controller ensures correct route order: static routes (`/codes`) first, then parameterized routes (`:locale`).
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Verification Checklist
|
|
214
|
+
|
|
215
|
+
After integration, verify:
|
|
216
|
+
|
|
217
|
+
- [ ] `npm run build` succeeds without errors
|
|
218
|
+
- [ ] `npm test` passes
|
|
219
|
+
- [ ] `GET /api/i18n/errors/de` returns your project error codes
|
|
220
|
+
- [ ] `GET /api/i18n/errors/en` returns English translations
|
|
221
|
+
- [ ] Error codes follow format `PREFIX_XXXX` (e.g., `PROJ_0001`)
|
|
222
|
+
- [ ] Translations include placeholders where needed (`{param}`)
|
|
223
|
+
|
|
224
|
+
### For Scenario C only:
|
|
225
|
+
- [ ] `GET /api/i18n/errors/codes` returns all error codes (if implemented)
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Common Mistakes
|
|
230
|
+
|
|
231
|
+
| Mistake | Symptom | Fix |
|
|
232
|
+
|---------|---------|-----|
|
|
233
|
+
| Forgot `autoRegister: false` | Project errors not appearing | Add `errorCode: { autoRegister: false }` to config |
|
|
234
|
+
| Wrong error code format | Validation errors | Use `PREFIX_XXXX` format (4 digits) |
|
|
235
|
+
| Missing translations | Runtime errors | Ensure all locales have translations |
|
|
236
|
+
| Controller extends CoreErrorCodeController | `/codes` returns 404 | Use standalone controller |
|
|
237
|
+
| Duplicate error codes | Unpredictable behavior | Ensure unique codes across all registries |
|
|
238
|
+
| Forgot to import module | No error translations | Import ErrorCodeModule in ServerModule |
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Using Error Codes in Code
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
import { ErrorCode, Errors } from '@lenne.tech/nest-server';
|
|
246
|
+
|
|
247
|
+
// Type-safe error code access
|
|
248
|
+
const code = ErrorCode.userNotFound; // Returns '#LTNS_0001: User not found'
|
|
249
|
+
|
|
250
|
+
// Factory functions with parameters
|
|
251
|
+
throw new BadRequestException(Errors.userNotFound({ email: 'test@example.com' }));
|
|
252
|
+
// Throws: '#LTNS_0001: User with email test@example.com was not found.'
|
|
253
|
+
|
|
254
|
+
// Project-specific errors (after registration)
|
|
255
|
+
import { ErrorCode as ProjectErrorCode } from './common/errors/project-errors';
|
|
256
|
+
|
|
257
|
+
const orderCode = ProjectErrorCode.ORDER_NOT_FOUND; // '#PROJ_0001: Order not found'
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## API Reference
|
|
263
|
+
|
|
264
|
+
### REST Endpoints
|
|
265
|
+
|
|
266
|
+
| Endpoint | Method | Description |
|
|
267
|
+
|----------|--------|-------------|
|
|
268
|
+
| `/api/i18n/errors/:locale` | GET | Get translations for locale (de, en, ...) |
|
|
269
|
+
| `/api/i18n/errors/codes` | GET | Get all error codes (Scenario C only) |
|
|
270
|
+
|
|
271
|
+
### Response Format (Nuxt i18n compatible)
|
|
272
|
+
|
|
273
|
+
```json
|
|
274
|
+
{
|
|
275
|
+
"errors": {
|
|
276
|
+
"LTNS_0001": "Benutzer mit E-Mail {email} wurde nicht gefunden.",
|
|
277
|
+
"PROJ_0001": "Bestellung mit ID {orderId} wurde nicht gefunden."
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## Detailed Documentation
|
|
285
|
+
|
|
286
|
+
For complete API reference and advanced topics:
|
|
287
|
+
- **Core Error Codes:** `node_modules/@lenne.tech/nest-server/src/core/modules/error-code/error-codes.ts`
|
|
288
|
+
- **Interfaces:** `node_modules/@lenne.tech/nest-server/src/core/modules/error-code/interfaces/error-code.interfaces.ts`
|