{"_id":"@camcima/nestjs-rfc9457","_rev":"10-4ffe737a5d15f4f281e83e9e22ce6e6e","name":"@camcima/nestjs-rfc9457","dist-tags":{"latest":"0.7.0"},"versions":{"0.0.2":{"name":"@camcima/nestjs-rfc9457","version":"0.0.2","keywords":["nestjs","rfc9457","rfc7807","problem-details","error-handling","api"],"author":{"name":"Carlos Cima"},"license":"MIT","_id":"@camcima/nestjs-rfc9457@0.0.2","maintainers":[{"name":"camcima","email":"camcima@hotmail.com"}],"homepage":"https://github.com/camcima/nestjs-rfc9457#readme","bugs":{"url":"https://github.com/camcima/nestjs-rfc9457/issues"},"dist":{"shasum":"b9962a77695b409f7870699bd66f06d97caf100c","tarball":"https://registry.npmjs.org/@camcima/nestjs-rfc9457/-/nestjs-rfc9457-0.0.2.tgz","fileCount":33,"integrity":"sha512-uv4Xz7JS3pQb2kMNfmthGE8DECOlwWWzKjF/gLblDglwdwnZuE8C8lyd0vG13Zpt6hs1DJULMpfzZvmw9d1D1w==","signatures":[{"sig":"MEUCIQDbHa3anwNzu1pJzOtwevebAcTgaY1HHmfixokcCZBMhAIgYsPKPXtedjWry3LwexjEyn3Vrq9sKbyObnRJ0f+qA50=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":65323},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18"},"gitHead":"eff00dc3fdb0879eccf3ac9b74262900bb37a648","scripts":{"lint":"eslint 'src/**/*.ts' 'test/**/*.ts'","test":"jest","build":"tsc -p tsconfig.build.json","format":"prettier --check 'src/**/*.ts' 'test/**/*.ts'","release":"release-it","test:cov":"jest --coverage","test:e2e":"jest --testPathPattern=test/e2e","test:unit":"jest --testPathPattern=test/unit","format:fix":"prettier --write 'src/**/*.ts' 'test/**/*.ts'","prepublishOnly":"npm run build"},"_npmUser":{"name":"camcima","email":"camcima@hotmail.com"},"repository":{"url":"git+https://github.com/camcima/nestjs-rfc9457.git","type":"git"},"_npmVersion":"11.6.3","description":"NestJS library for RFC 9457 Problem Details responses","directories":{},"_nodeVersion":"22.16.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0","rxjs":"^7.0.0","eslint":"^8.0.0","fastify":"^4.0.0","ts-jest":"^29.0.0","ts-node":"^10.9.2","lefthook":"^1.0.0","prettier":"^3.0.0","supertest":"^7.0.0","release-it":"^18.0.0","typescript":"^5.0.0","@types/jest":"^29.0.0","@nestjs/core":"^10.0.0","@nestjs/common":"^10.0.0","@commitlint/cli":"^19.0.0","@nestjs/testing":"^10.0.0","class-validator":"^0.14.0","@types/supertest":"^6.0.0","reflect-metadata":"^0.2.0","class-transformer":"^0.5.0","eslint-config-prettier":"^9.0.0","eslint-plugin-prettier":"^5.0.0","@nestjs/platform-express":"^10.0.0","@nestjs/platform-fastify":"^10.0.0","@typescript-eslint/parser":"^7.0.0","@commitlint/config-conventional":"^19.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"peerDependencies":{"@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0","class-validator":"^0.14.0","reflect-metadata":"^0.1.13 || ^0.2.0"},"peerDependenciesMeta":{"class-validator":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nestjs-rfc9457_0.0.2_1775468760617_0.9865841237520636","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"@camcima/nestjs-rfc9457","version":"0.1.0","keywords":["nestjs","rfc9457","rfc7807","problem-details","error-handling","api"],"author":{"name":"Carlos Cima"},"license":"MIT","_id":"@camcima/nestjs-rfc9457@0.1.0","maintainers":[{"name":"camcima","email":"camcima@hotmail.com"}],"homepage":"https://github.com/camcima/nestjs-rfc9457#readme","bugs":{"url":"https://github.com/camcima/nestjs-rfc9457/issues"},"dist":{"shasum":"c71e56603c459f2da352b1df2b36af1f2f035852","tarball":"https://registry.npmjs.org/@camcima/nestjs-rfc9457/-/nestjs-rfc9457-0.1.0.tgz","fileCount":33,"integrity":"sha512-yyviYb6Q+NdKoh8e4cr6mR0pfNriYkeP4wF66HSXQIvQkMCvmu1qCVHN3qaRgfFod8oFjJBlRyZSXMKOSrec1Q==","signatures":[{"sig":"MEQCICxwC1ZmNK9G9rJrNCcIXASe57276vdTs4qS75KH5QutAiAsiMfyYDm0UW86+GZmjKs1uMkhQxBQvn5YKFVZ8FZRFQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":67682},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18"},"gitHead":"50ba5206adb561287070daa9ff79601e32b70f9c","scripts":{"lint":"eslint 'src/**/*.ts' 'test/**/*.ts'","test":"jest","build":"tsc -p tsconfig.build.json","format":"prettier --check 'src/**/*.ts' 'test/**/*.ts'","release":"release-it","test:cov":"jest --coverage","test:e2e":"jest --testPathPattern=test/e2e","test:unit":"jest --testPathPattern=test/unit","audit:deps":"npm audit --omit=dev","format:fix":"prettier --write 'src/**/*.ts' 'test/**/*.ts'","audit:secrets":"gitleaks git --no-banner --redact -v","prepublishOnly":"npm run build"},"_npmUser":{"name":"camcima","email":"camcima@hotmail.com"},"repository":{"url":"git+https://github.com/camcima/nestjs-rfc9457.git","type":"git"},"_npmVersion":"11.6.3","description":"NestJS library for RFC 9457 Problem Details responses","directories":{},"_nodeVersion":"22.16.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^30.3.0","rxjs":"^7.0.0","eslint":"^8.0.0","fastify":"^4.0.0","ts-jest":"^29.0.0","ts-node":"^10.9.2","lefthook":"^1.0.0","prettier":"^3.0.0","supertest":"^7.0.0","release-it":"^18.0.0","typescript":"^6.0.2","@types/jest":"^30.0.0","@types/node":"^22.19.17","@nestjs/core":"^11.1.18","@nestjs/common":"^11.1.18","@commitlint/cli":"^20.5.0","@nestjs/testing":"^11.1.18","class-validator":"^0.14.0","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.0","class-transformer":"^0.5.0","eslint-config-prettier":"^9.0.0","eslint-plugin-prettier":"^5.0.0","@nestjs/platform-express":"^11.1.18","@nestjs/platform-fastify":"^11.1.18","@typescript-eslint/parser":"^7.0.0","@commitlint/config-conventional":"^20.5.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"peerDependencies":{"@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0","class-validator":"^0.14.0","reflect-metadata":"^0.1.13 || ^0.2.0"},"peerDependenciesMeta":{"class-validator":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nestjs-rfc9457_0.1.0_1775487464666_0.35404119609349505","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@camcima/nestjs-rfc9457","version":"0.2.0","keywords":["nestjs","rfc9457","rfc7807","problem-details","error-handling","api"],"author":{"name":"Carlos Cima"},"license":"MIT","_id":"@camcima/nestjs-rfc9457@0.2.0","maintainers":[{"name":"camcima","email":"camcima@hotmail.com"}],"homepage":"https://github.com/camcima/nestjs-rfc9457#readme","bugs":{"url":"https://github.com/camcima/nestjs-rfc9457/issues"},"dist":{"shasum":"e43baaa9f4f58a061b5d1a13807b6baee80e9ef1","tarball":"https://registry.npmjs.org/@camcima/nestjs-rfc9457/-/nestjs-rfc9457-0.2.0.tgz","fileCount":42,"integrity":"sha512-nePXQoZefKcHnmPF9yl2ki9MnVdNGa4HmCfCrWZx3x/sF5VCd+VHzUc/j10P7Y8N9rGWrHCoZFat3ZLEmDXpKg==","signatures":[{"sig":"MEYCIQDbtd+229QDHN4Zpse4taGHn1SRtU5DyT439C+K2uImJwIhAJed1sFIiWCyWQVfhazmiAbJVGEYn2mnU4ipPoaKTLDw","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":86026},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./swagger":{"types":"./dist/swagger/index.d.ts","default":"./dist/swagger/index.js"}},"gitHead":"677c6d2de5568afaf548d04fa9629b19c0d9fe16","scripts":{"lint":"eslint 'src/**/*.ts' 'test/**/*.ts'","test":"jest","build":"tsc -p tsconfig.build.json","format":"prettier --check 'src/**/*.ts' 'test/**/*.ts'","release":"release-it","test:cov":"jest --coverage","test:e2e":"jest --testPathPattern=test/e2e","test:unit":"jest --testPathPattern=test/unit","audit:deps":"npm audit --omit=dev","format:fix":"prettier --write 'src/**/*.ts' 'test/**/*.ts'","audit:secrets":"gitleaks git --no-banner --redact -v","prepublishOnly":"npm run build"},"_npmUser":{"name":"camcima","email":"camcima@hotmail.com"},"repository":{"url":"git+https://github.com/camcima/nestjs-rfc9457.git","type":"git"},"_npmVersion":"11.6.3","description":"NestJS library for RFC 9457 Problem Details responses","directories":{},"_nodeVersion":"22.16.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^30.3.0","rxjs":"^7.0.0","eslint":"^8.0.0","fastify":"^4.0.0","ts-jest":"^29.0.0","ts-node":"^10.9.2","lefthook":"^1.0.0","prettier":"^3.0.0","supertest":"^7.0.0","release-it":"^18.0.0","typescript":"^6.0.2","@types/jest":"^30.0.0","@types/node":"^22.19.17","@nestjs/core":"^11.1.18","@nestjs/common":"^11.1.18","@commitlint/cli":"^20.5.0","@nestjs/swagger":"^11.1.18","@nestjs/testing":"^11.1.18","class-validator":"^0.14.0","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.0","class-transformer":"^0.5.0","eslint-config-prettier":"^9.0.0","eslint-plugin-prettier":"^5.0.0","@nestjs/platform-express":"^11.1.18","@nestjs/platform-fastify":"^11.1.18","@typescript-eslint/parser":"^7.0.0","@commitlint/config-conventional":"^20.5.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"peerDependencies":{"@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0","@nestjs/swagger":"^7.0.0 || ^8.0.0 || ^11.0.0","class-validator":"^0.14.0","reflect-metadata":"^0.1.13 || ^0.2.0"},"peerDependenciesMeta":{"@nestjs/swagger":{"optional":true},"class-validator":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nestjs-rfc9457_0.2.0_1775495327631_0.03892776806901832","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@camcima/nestjs-rfc9457","version":"0.3.0","keywords":["nestjs","rfc9457","rfc7807","problem-details","error-handling","api"],"author":{"name":"Carlos Cima"},"license":"MIT","_id":"@camcima/nestjs-rfc9457@0.3.0","maintainers":[{"name":"camcima","email":"camcima@hotmail.com"}],"homepage":"https://github.com/camcima/nestjs-rfc9457#readme","bugs":{"url":"https://github.com/camcima/nestjs-rfc9457/issues"},"dist":{"shasum":"88119f39606f71d5e4ed1f9404b256f08a75aa8d","tarball":"https://registry.npmjs.org/@camcima/nestjs-rfc9457/-/nestjs-rfc9457-0.3.0.tgz","fileCount":42,"integrity":"sha512-Ewbgml0Z+bi/ucbSKRn/6FFrvHxAyGbxiaeNswO36b6KMqPVV0dV+EXPDsVoOkDpS2aTBFQ0+A6MI6XJF9S6JA==","signatures":[{"sig":"MEUCIQCJFtpDFRM8d4MxH5rtfTt1Ur3Mvo/wnLfXUAc6qwn6CgIgRAOXTzofpvEXtgpzzkQrhtJXDu4Bl8MmZVa3TiCnRMw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":89370},"main":"dist/index.js","pnpm":{"overrides":{"fastify@<5.8.5":">=5.8.5","lodash@<4.18.0":">=4.18.0","undici@<6.24.0":">=6.24.0","basic-ftp@<5.3.0":">=5.3.0","path-to-regexp@<8.4.0":">=8.4.0"}},"types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./swagger":{"types":"./dist/swagger/index.d.ts","default":"./dist/swagger/index.js"}},"gitHead":"8c9db466b009e9e440fa8c456fb30e7c1af02c5a","scripts":{"lint":"eslint 'src/**/*.ts' 'test/**/*.ts'","test":"jest","build":"tsc -p tsconfig.build.json","format":"prettier --check 'src/**/*.ts' 'test/**/*.ts'","release":"release-it","test:cov":"jest --coverage","test:e2e":"jest --testPathPattern=test/e2e","test:unit":"jest --testPathPattern=test/unit","audit:deps":"pnpm audit --prod","format:fix":"prettier --write 'src/**/*.ts' 'test/**/*.ts'","audit:secrets":"gitleaks git --no-banner --redact -v","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"camcima","email":"camcima@hotmail.com"},"repository":{"url":"git+https://github.com/camcima/nestjs-rfc9457.git","type":"git"},"_npmVersion":"11.6.3","description":"NestJS library for RFC 9457 Problem Details responses","directories":{},"_nodeVersion":"22.16.0","_hasShrinkwrap":false,"packageManager":"pnpm@9.15.0","devDependencies":{"jest":"^30.3.0","rxjs":"^7.0.0","eslint":"^8.0.0","ts-jest":"^29.0.0","ts-node":"^10.9.2","lefthook":"^1.0.0","prettier":"^3.8.3","supertest":"^7.0.0","release-it":"^18.0.0","typescript":"^6.0.2","@types/jest":"^30.0.0","@types/node":"^25.6.0","@nestjs/core":"^11.1.19","@nestjs/common":"^11.1.19","@commitlint/cli":"^20.5.0","@nestjs/swagger":"^11.2.7","@nestjs/testing":"^11.1.19","class-validator":"^0.14.0","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.0","class-transformer":"^0.5.0","eslint-config-prettier":"^9.0.0","eslint-plugin-prettier":"^5.0.0","@nestjs/platform-express":"^11.1.19","@nestjs/platform-fastify":"^11.1.19","@typescript-eslint/parser":"^7.0.0","@commitlint/config-conventional":"^20.5.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"peerDependencies":{"@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0","@nestjs/swagger":"^7.0.0 || ^8.0.0 || ^11.0.0","class-validator":"^0.14.0","reflect-metadata":"^0.1.13 || ^0.2.0"},"peerDependenciesMeta":{"@nestjs/swagger":{"optional":true},"class-validator":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nestjs-rfc9457_0.3.0_1776974150714_0.5724388252013974","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"name":"@camcima/nestjs-rfc9457","version":"0.3.1","keywords":["nestjs","rfc9457","rfc7807","problem-details","error-handling","api"],"author":{"name":"Carlos Cima"},"license":"MIT","_id":"@camcima/nestjs-rfc9457@0.3.1","maintainers":[{"name":"camcima","email":"camcima@hotmail.com"}],"homepage":"https://github.com/camcima/nestjs-rfc9457#readme","bugs":{"url":"https://github.com/camcima/nestjs-rfc9457/issues"},"dist":{"shasum":"2f6124702a808bcb99f8bcfd9155250573bfc8cb","tarball":"https://registry.npmjs.org/@camcima/nestjs-rfc9457/-/nestjs-rfc9457-0.3.1.tgz","fileCount":42,"integrity":"sha512-Ygu3R+4AHidzUFk2vlkVBoyNfCKU9PGJvSuOnd73aPi8zoS4waTp6tbiBqha/3ltDld1nncjlUCHCSeliw2DVQ==","signatures":[{"sig":"MEUCIDFVM5UTQHx/o7GSIukeEc0ePgfKuQ2QPHUifCJpjBGBAiEA3vI5k348XwVyX/K4CPLq90DmH0tDxsRpztzZzTBRYo4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":91061},"main":"dist/index.js","pnpm":{"overrides":{"fastify@<5.8.5":">=5.8.5","lodash@<4.18.0":">=4.18.0","undici@<6.24.0":">=6.24.0","basic-ftp@<5.3.0":">=5.3.0","path-to-regexp@<8.4.0":">=8.4.0"}},"types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./swagger":{"types":"./dist/swagger/index.d.ts","default":"./dist/swagger/index.js"}},"gitHead":"5eb35e4a6d18e3761d4014be57831b7e48f3688b","scripts":{"lint":"eslint 'src/**/*.ts' 'test/**/*.ts'","test":"jest","build":"tsc -p tsconfig.build.json","format":"prettier --check 'src/**/*.ts' 'test/**/*.ts'","release":"release-it","test:cov":"jest --coverage","test:e2e":"jest --testPathPatterns=test/e2e","test:unit":"jest --testPathPatterns=test/unit","audit:deps":"pnpm audit --prod","format:fix":"prettier --write 'src/**/*.ts' 'test/**/*.ts'","audit:secrets":"gitleaks git --no-banner --redact -v","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"camcima","email":"camcima@hotmail.com"},"repository":{"url":"git+https://github.com/camcima/nestjs-rfc9457.git","type":"git"},"_npmVersion":"10.9.7","description":"NestJS library for RFC 9457 Problem Details responses","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"packageManager":"pnpm@9.15.0","devDependencies":{"jest":"^30.3.0","rxjs":"^7.0.0","eslint":"^10.2.1","globals":"^17.5.0","ts-jest":"^29.0.0","ts-node":"^10.9.2","lefthook":"^1.0.0","prettier":"^3.8.3","supertest":"^7.0.0","release-it":"^20.0.1","typescript":"^6.0.2","@types/jest":"^30.0.0","@types/node":"^25.6.0","@nestjs/core":"^11.1.19","@nestjs/common":"^11.1.19","@commitlint/cli":"^20.5.0","@nestjs/swagger":"^11.2.7","@nestjs/testing":"^11.1.19","class-validator":"^0.14.0","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.0","class-transformer":"^0.5.0","typescript-eslint":"^8.59.1","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.0.0","@nestjs/platform-express":"^11.1.19","@nestjs/platform-fastify":"^11.1.19","@commitlint/config-conventional":"^20.5.0"},"peerDependencies":{"@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0","@nestjs/swagger":"^7.0.0 || ^8.0.0 || ^11.0.0","class-validator":"^0.14.0","reflect-metadata":"^0.1.13 || ^0.2.0"},"peerDependenciesMeta":{"@nestjs/swagger":{"optional":true},"class-validator":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nestjs-rfc9457_0.3.1_1777556942730_0.33704413750685536","host":"s3://npm-registry-packages-npm-production"}},"0.3.2":{"name":"@camcima/nestjs-rfc9457","version":"0.3.2","keywords":["nestjs","rfc9457","rfc7807","problem-details","error-handling","api"],"author":{"name":"Carlos Cima"},"license":"MIT","_id":"@camcima/nestjs-rfc9457@0.3.2","maintainers":[{"name":"camcima","email":"camcima@hotmail.com"}],"homepage":"https://github.com/camcima/nestjs-rfc9457#readme","bugs":{"url":"https://github.com/camcima/nestjs-rfc9457/issues"},"dist":{"shasum":"a1b3db3601bc3c645a3bc3fb8411c41003765f07","tarball":"https://registry.npmjs.org/@camcima/nestjs-rfc9457/-/nestjs-rfc9457-0.3.2.tgz","fileCount":42,"integrity":"sha512-1b6t0RYTAc6B6DK2qJTCE0/225YcM+YqhQrE6Zd+rOkMQdwhZKcBrTlzCSU6T75ESzXuH6BYDVGg0BfKP+o1/Q==","signatures":[{"sig":"MEUCICPsX21VjWJPRyf+84d//WctK6a7QfTZWJGVBky4pDkhAiEA20iboo2xNHOpideg3kLpahXLqE0jqaIAimgJ2aiX+rQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":91131},"main":"dist/index.js","pnpm":{"overrides":{"qs@6.15.1":"6.15.2","fastify@<5.8.5":">=5.8.5","lodash@<4.18.0":">=4.18.0","undici@<6.24.0":">=6.24.0","basic-ftp@<5.3.0":">=5.3.0","brace-expansion@5.0.5":"5.0.6","path-to-regexp@<8.4.0":">=8.4.0"}},"types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./swagger":{"types":"./dist/swagger/index.d.ts","default":"./dist/swagger/index.js"}},"gitHead":"cf70d7f7a9ba52975783243ce2915138fab25add","scripts":{"lint":"eslint 'src/**/*.ts' 'test/**/*.ts'","test":"jest","build":"tsc -p tsconfig.build.json","format":"prettier --check 'src/**/*.ts' 'test/**/*.ts'","release":"release-it","test:cov":"jest --coverage","test:e2e":"jest --testPathPatterns=test/e2e","test:unit":"jest --testPathPatterns=test/unit","audit:deps":"pnpm audit --prod","format:fix":"prettier --write 'src/**/*.ts' 'test/**/*.ts'","audit:secrets":"gitleaks git --no-banner --redact -v","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"camcima","email":"camcima@hotmail.com"},"repository":{"url":"git+https://github.com/camcima/nestjs-rfc9457.git","type":"git"},"_npmVersion":"10.9.7","description":"NestJS library for RFC 9457 Problem Details responses","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"packageManager":"pnpm@9.15.0","devDependencies":{"jest":"^30.4.2","rxjs":"^7.8.2","eslint":"^10.4.1","globals":"^17.6.0","ts-jest":"^29.4.11","ts-node":"^10.9.2","lefthook":"^2.1.9","prettier":"^3.8.3","supertest":"^7.2.2","release-it":"^20.2.0","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^25.9.1","@nestjs/core":"^11.1.24","@nestjs/common":"^11.1.24","@commitlint/cli":"^21.0.2","@nestjs/swagger":"^11.4.4","@nestjs/testing":"^11.1.24","class-validator":"^0.14.4","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","class-transformer":"^0.5.1","typescript-eslint":"^8.60.0","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@nestjs/platform-express":"^11.1.24","@nestjs/platform-fastify":"^11.1.24","@commitlint/config-conventional":"^21.0.2"},"peerDependencies":{"@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0","@nestjs/swagger":"^7.0.0 || ^8.0.0 || ^11.0.0","class-validator":"^0.14.0","reflect-metadata":"^0.1.13 || ^0.2.0"},"peerDependenciesMeta":{"@nestjs/swagger":{"optional":true},"class-validator":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nestjs-rfc9457_0.3.2_1780178376543_0.7443664467836466","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@camcima/nestjs-rfc9457","version":"0.4.0","keywords":["nestjs","rfc9457","rfc7807","problem-details","error-handling","api"],"author":{"name":"Carlos Cima"},"license":"MIT","_id":"@camcima/nestjs-rfc9457@0.4.0","maintainers":[{"name":"camcima","email":"camcima@hotmail.com"}],"homepage":"https://github.com/camcima/nestjs-rfc9457#readme","bugs":{"url":"https://github.com/camcima/nestjs-rfc9457/issues"},"dist":{"shasum":"213fbefa198e185b51bfe42cf7fe19c6d2088731","tarball":"https://registry.npmjs.org/@camcima/nestjs-rfc9457/-/nestjs-rfc9457-0.4.0.tgz","fileCount":42,"integrity":"sha512-foSqYB9sD5ah1PXOrjAQUwXvLZWMYNzvsTkHm+HGuE1cqrJvtnzkKolgs/z+cdKP7ekHSzxcRSfG3S89OEfuaw==","signatures":[{"sig":"MEQCIEwF71NRt6nVPGbEJiY+Zy3pKwUsQsziZdVCp3xlEVqJAiBatAM8aob/nURoDueUFXxXB3aZbEDDLep+P+KrT5ONkg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":97436},"main":"dist/index.js","pnpm":{"overrides":{"qs@6.15.1":"6.15.2","fastify@<5.8.5":">=5.8.5","lodash@<4.18.0":">=4.18.0","undici@<6.24.0":">=6.24.0","basic-ftp@<5.3.0":">=5.3.0","brace-expansion@5.0.5":"5.0.6","path-to-regexp@<8.4.0":">=8.4.0"}},"types":"dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./swagger":{"types":"./dist/swagger/index.d.ts","default":"./dist/swagger/index.js"}},"gitHead":"9e293843934311e554a242a207f7b11c3ea6e15d","scripts":{"lint":"eslint 'src/**/*.ts' 'test/**/*.ts'","test":"jest","build":"tsc -p tsconfig.build.json","format":"prettier --check 'src/**/*.ts' 'test/**/*.ts'","release":"release-it","test:cov":"jest --coverage","test:e2e":"jest --testPathPatterns=test/e2e","test:unit":"jest --testPathPatterns=test/unit","audit:deps":"pnpm audit --prod","format:fix":"prettier --write 'src/**/*.ts' 'test/**/*.ts'","audit:secrets":"gitleaks git --no-banner --redact -v","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"camcima","email":"camcima@hotmail.com"},"repository":{"url":"git+https://github.com/camcima/nestjs-rfc9457.git","type":"git"},"_npmVersion":"10.9.7","description":"NestJS library for RFC 9457 Problem Details responses","directories":{},"sideEffects":false,"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"packageManager":"pnpm@9.15.0","devDependencies":{"jest":"^30.4.2","rxjs":"^7.8.2","eslint":"^10.4.1","globals":"^17.6.0","ts-jest":"^29.4.11","ts-node":"^10.9.2","lefthook":"^2.1.9","prettier":"^3.8.4","supertest":"^7.2.2","release-it":"^20.2.0","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^25.9.3","@nestjs/core":"^11.1.26","@nestjs/common":"^11.1.26","@commitlint/cli":"^21.0.2","@nestjs/swagger":"^11.4.4","@nestjs/testing":"^11.1.26","class-validator":"^0.15.1","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","class-transformer":"^0.5.1","typescript-eslint":"^8.61.0","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@nestjs/platform-express":"^11.1.26","@nestjs/platform-fastify":"^11.1.26","@commitlint/config-conventional":"^21.0.2"},"peerDependencies":{"@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0","@nestjs/swagger":"^7.0.0 || ^8.0.0 || ^11.0.0","class-validator":"^0.14.0 || ^0.15.0","reflect-metadata":"^0.1.13 || ^0.2.0"},"peerDependenciesMeta":{"@nestjs/swagger":{"optional":true},"class-validator":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nestjs-rfc9457_0.4.0_1782203307447_0.36183541614858417","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@camcima/nestjs-rfc9457","version":"0.5.0","keywords":["nestjs","rfc9457","rfc7807","problem-details","error-handling","api"],"author":{"name":"Carlos Cima"},"license":"MIT","_id":"@camcima/nestjs-rfc9457@0.5.0","maintainers":[{"name":"camcima","email":"camcima@hotmail.com"}],"homepage":"https://github.com/camcima/nestjs-rfc9457#readme","bugs":{"url":"https://github.com/camcima/nestjs-rfc9457/issues"},"dist":{"shasum":"175ad7fc0ef2794e7b72aa64177c8fe6b3aae868","tarball":"https://registry.npmjs.org/@camcima/nestjs-rfc9457/-/nestjs-rfc9457-0.5.0.tgz","fileCount":43,"integrity":"sha512-6xv04l4yWy7BdZM2EpokdmUGpznH4HezyQRRT9erf2bcgM3eqAmC66Dt9adkGNjxm3Qj43Mr/7KBuHAPbOGJ+g==","signatures":[{"sig":"MEUCIQCSA1rguU49ZolKKKFW50kx8bWvf1smTo+PjY+O+1WMQQIgPFUov4DEN+ufYXWSn93DOlAdLAQWWBj3hbG5B+1cD1I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":384401},"main":"dist/index.js","pnpm":{"overrides":{"qs@6.15.1":"6.15.2","multer@<2.2.0":"^2.2.0","fastify@<5.8.5":">=5.8.5","js-yaml@<4.2.0":"^4.2.0","lodash@<4.18.0":">=4.18.0","undici@<7.28.0":"^7.28.0","basic-ftp@<5.3.0":">=5.3.0","form-data@<4.0.6":"^4.0.6","@babel/core@<7.29.6":"^7.29.6","brace-expansion@5.0.5":"5.0.6","path-to-regexp@<8.4.0":">=8.4.0"}},"types":"dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./swagger":{"types":"./dist/swagger/index.d.ts","default":"./dist/swagger/index.js"}},"gitHead":"f86d0258cea3d879923df711d09effe4d0070f10","scripts":{"lint":"eslint 'src/**/*.ts' 'test/**/*.ts'","test":"vitest run","build":"tsc -p tsconfig.build.json","format":"prettier --check 'src/**/*.ts' 'test/**/*.ts'","release":"release-it","test:cov":"vitest run --coverage","test:e2e":"vitest run test/e2e","test:unit":"vitest run test/unit","audit:deps":"pnpm audit --prod","format:fix":"prettier --write 'src/**/*.ts' 'test/**/*.ts'","test:watch":"vitest","audit:secrets":"gitleaks git --no-banner --redact -v","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"camcima","email":"camcima@hotmail.com"},"repository":{"url":"git+https://github.com/camcima/nestjs-rfc9457.git","type":"git"},"_npmVersion":"10.9.7","description":"NestJS library for RFC 9457 Problem Details responses","directories":{},"sideEffects":false,"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"packageManager":"pnpm@9.15.0","devDependencies":{"rxjs":"^7.8.2","eslint":"^10.5.0","vitest":"^4.1.9","globals":"^17.7.0","ts-node":"^10.9.2","lefthook":"^2.1.9","prettier":"^3.8.4","@swc/core":"^1.15.43","supertest":"^7.2.2","release-it":"^20.2.0","typescript":"^6.0.3","@types/node":"^26.0.0","@nestjs/core":"^11.1.27","unplugin-swc":"^1.5.9","@nestjs/common":"^11.1.27","@commitlint/cli":"^21.0.2","@nestjs/swagger":"^11.4.4","@nestjs/testing":"^11.1.27","class-validator":"^0.15.1","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","class-transformer":"^0.5.1","typescript-eslint":"^8.62.0","@vitest/coverage-v8":"^4.1.9","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@nestjs/platform-express":"^11.1.27","@nestjs/platform-fastify":"^11.1.27","@commitlint/config-conventional":"^21.0.2"},"peerDependencies":{"@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0","@nestjs/swagger":"^7.0.0 || ^8.0.0 || ^11.0.0","class-validator":"^0.14.0 || ^0.15.0","reflect-metadata":"^0.1.13 || ^0.2.0"},"peerDependenciesMeta":{"@nestjs/swagger":{"optional":true},"class-validator":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nestjs-rfc9457_0.5.0_1783646235066_0.31347064693149873","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"@camcima/nestjs-rfc9457","version":"0.6.0","keywords":["nestjs","rfc9457","rfc7807","problem-details","error-handling","api"],"author":{"name":"Carlos Cima"},"license":"MIT","_id":"@camcima/nestjs-rfc9457@0.6.0","maintainers":[{"name":"camcima","email":"camcima@hotmail.com"}],"homepage":"https://github.com/camcima/nestjs-rfc9457#readme","bugs":{"url":"https://github.com/camcima/nestjs-rfc9457/issues"},"dist":{"shasum":"4123df9e9c02750de296055a71d08fb2efda06db","tarball":"https://registry.npmjs.org/@camcima/nestjs-rfc9457/-/nestjs-rfc9457-0.6.0.tgz","fileCount":73,"integrity":"sha512-nhcObJmPaHCu4oQSAPxa8YgPkC3NgmIKIKJ27omeGXbhstYBBqpavIeBl+ipyA5nDehiobQeLIcE+k9vrc/Few==","signatures":[{"sig":"MEUCIQC/be2iyKWCXfwmgOa/Xpe89PjuN4FZwqjCbyrpdR6MmgIgJElJ2aCxo0/Lownu8PrZDeFzQmnVIMbYzSH05qceLSo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":227486},"main":"dist/index.js","pnpm":{"overrides":{"qs@6.15.1":"6.15.2","find-my-way":"^9.7.0","js-yaml@5.2.1":"5.2.2","multer@<2.2.0":"^2.2.0","fastify@<5.8.5":">=5.8.5","js-yaml@<4.3.1":"^4.3.1","lodash@<4.18.0":">=4.18.0","nanoid@<3.3.18":"^3.3.18","undici@<7.29.0":"^7.29.0","fast-uri@<3.1.5":"^3.1.5","basic-ftp@<5.3.0":">=5.3.0","form-data@<4.0.6":"^4.0.6","@babel/core@<7.29.6":"^7.29.6","brace-expansion@5.0.5":"5.0.6","path-to-regexp@<8.4.0":">=8.4.0"}},"types":"dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./swagger":{"types":"./dist/swagger/index.d.ts","default":"./dist/swagger/index.js"}},"gitHead":"eecd032a8b12459ccdef0aa44db49c54f97d09be","scripts":{"lint":"eslint 'src/**/*.ts' 'test/**/*.ts'","test":"vitest run","build":"tsc -p tsconfig.build.json","format":"prettier --check 'src/**/*.ts' 'test/**/*.ts'","release":"release-it","test:cov":"vitest run --coverage","test:e2e":"vitest run test/e2e","test:unit":"vitest run test/unit","audit:deps":"pnpm audit --prod","format:fix":"prettier --write 'src/**/*.ts' 'test/**/*.ts'","test:watch":"vitest","audit:secrets":"gitleaks git --no-banner --redact -v","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"camcima","email":"camcima@hotmail.com"},"repository":{"url":"git+https://github.com/camcima/nestjs-rfc9457.git","type":"git"},"_npmVersion":"10.9.7","description":"NestJS library for RFC 9457 Problem Details responses","directories":{},"sideEffects":false,"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"packageManager":"pnpm@9.15.0","devDependencies":{"rxjs":"^7.8.2","eslint":"^10.6.0","vitest":"^4.1.9","globals":"^17.7.0","ts-node":"^10.9.2","lefthook":"^2.1.9","prettier":"^3.9.4","@swc/core":"^1.15.43","supertest":"^7.2.2","release-it":"^20.2.1","typescript":"^6.0.3","@types/node":"^26.1.0","@nestjs/core":"^11.1.27","unplugin-swc":"^1.5.9","@nestjs/common":"^11.1.27","@commitlint/cli":"^21.2.0","@nestjs/swagger":"^11.4.5","@nestjs/testing":"^11.1.27","class-validator":"^0.15.1","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","class-transformer":"^0.5.1","typescript-eslint":"^8.63.0","@vitest/coverage-v8":"^4.1.9","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@nestjs/platform-express":"^11.1.27","@nestjs/platform-fastify":"^11.1.27","@commitlint/config-conventional":"^21.2.0"},"peerDependencies":{"@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0","@nestjs/swagger":"^7.0.0 || ^8.0.0 || ^11.0.0","class-validator":"^0.14.0 || ^0.15.0","reflect-metadata":"^0.1.13 || ^0.2.0"},"peerDependenciesMeta":{"@nestjs/swagger":{"optional":true},"class-validator":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nestjs-rfc9457_0.6.0_1787135417942_0.008148056439597262","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"_id":"@camcima/nestjs-rfc9457@0.7.0","bugs":{"url":"https://github.com/camcima/nestjs-rfc9457/issues"},"dist":{"shasum":"577110165b32ea86ef46b674d48ffbdd197dbc1c","tarball":"https://registry.npmjs.org/@camcima/nestjs-rfc9457/-/nestjs-rfc9457-0.7.0.tgz","fileCount":74,"integrity":"sha512-Bdi7n+1I/+PmDHmNcGql2QGDZVgEweNyH8GmkFekvvBFvfl/YQDgrcZLoWdKaAVXPyFfp+O/RQJVH7Pakkpg/Q==","signatures":[{"sig":"MEYCIQCEYiW543nDlJ7e9xT7Uwkzat+QrwuDMRVbgAblNZGMKAIhAPOZ/jP0b4DhreHLys+uSJkzc6EUij2QRH/ybA7d5VLJ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCAo5/lB6dGCrpwTTI55/gwnE9eT4AoNjVMUxIOhwXhVwIgZ4x4Bfo89L51OW1L/PLiG+C9FKmvz68tbQUYJabzEVg="}],"unpackedSize":245724},"main":"dist/index.js","name":"@camcima/nestjs-rfc9457","pnpm":{"overrides":{"qs@<6.16.0":"^6.16.0","find-my-way":"^9.7.0","js-yaml@5.2.1":"5.2.2","multer@<2.3.0":"^2.3.0","js-yaml@<4.3.1":"^4.3.1","lodash@<4.18.0":">=4.18.0","nanoid@<3.3.18":"^3.3.18","undici@<7.29.0":"^7.29.0","fast-uri@<3.1.5":"^3.1.5","fastify@<5.12.1":">=5.12.1","basic-ftp@<5.3.0":">=5.3.0","form-data@<4.0.6":"^4.0.6","@babel/core@<7.29.6":"^7.29.6","brace-expansion@5.0.5":"5.0.6","path-to-regexp@<8.4.0":">=8.4.0"}},"types":"dist/index.d.ts","author":{"name":"Carlos Cima"},"engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./swagger":{"types":"./dist/swagger/index.d.ts","default":"./dist/swagger/index.js"}},"gitHead":"1bbfaf96a705e1662385c6bbc1f178bed8adb2e3","license":"MIT","scripts":{"lint":"eslint 'src/**/*.ts' 'test/**/*.ts'","test":"vitest run","build":"tsc -p tsconfig.build.json","format":"prettier --check 'src/**/*.ts' 'test/**/*.ts'","release":"release-it","test:cov":"vitest run --coverage","test:e2e":"vitest run test/e2e","test:unit":"vitest run test/unit","audit:deps":"pnpm audit --prod","format:fix":"prettier --write 'src/**/*.ts' 'test/**/*.ts'","test:watch":"vitest","audit:secrets":"gitleaks git --no-banner --redact -v","prepublishOnly":"pnpm run build"},"version":"0.7.0","_npmUser":{"name":"camcima","email":"camcima@hotmail.com"},"homepage":"https://github.com/camcima/nestjs-rfc9457#readme","keywords":["nestjs","rfc9457","rfc7807","problem-details","error-handling","api"],"repository":{"url":"git+https://github.com/camcima/nestjs-rfc9457.git","type":"git"},"_npmVersion":"10.9.7","description":"NestJS library for RFC 9457 Problem Details responses","directories":{},"maintainers":[{"name":"camcima","email":"camcima@hotmail.com"}],"sideEffects":false,"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"packageManager":"pnpm@9.15.0","devDependencies":{"rxjs":"^7.8.2","eslint":"^10.6.0","vitest":"^4.1.9","globals":"^17.7.0","ts-node":"^10.9.2","lefthook":"^2.1.9","prettier":"^3.9.4","@swc/core":"^1.15.43","supertest":"^7.2.2","release-it":"^21.0.2","typescript":"^6.0.3","@types/node":"^26.1.0","@nestjs/core":"^12.0.1","unplugin-swc":"^1.5.9","@nestjs/common":"^12.0.1","@commitlint/cli":"^21.2.0","@nestjs/swagger":"^12.0.1","@nestjs/testing":"^12.0.1","class-validator":"^0.15.1","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","class-transformer":"^0.5.1","typescript-eslint":"^8.63.0","@vitest/coverage-v8":"^4.1.9","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.6","@nestjs/platform-express":"^12.0.1","@nestjs/platform-fastify":"^12.0.1","@commitlint/config-conventional":"^21.2.0","@release-it/conventional-changelog":"^12.0.0"},"peerDependencies":{"@nestjs/core":"^10.0.0 || ^11.0.0 || ^12.0.0","@nestjs/common":"^10.0.0 || ^11.0.0 || ^12.0.0","@nestjs/swagger":"^7.0.0 || ^8.0.0 || ^11.0.0 || ^12.0.0","class-validator":"^0.14.0 || ^0.15.0","reflect-metadata":"^0.1.13 || ^0.2.0"},"peerDependenciesMeta":{"@nestjs/swagger":{"optional":true},"class-validator":{"optional":true}},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/nestjs-rfc9457_0.7.0_1790514014560_0.9766158013518746"}}},"time":{"created":"2026-04-06T09:46:00.489Z","modified":"2026-09-27T13:00:14.811Z","0.0.2":"2026-04-06T09:46:00.779Z","0.1.0":"2026-04-06T14:57:44.871Z","0.2.0":"2026-04-06T17:08:47.781Z","0.3.0":"2026-04-23T19:55:50.879Z","0.3.1":"2026-04-30T13:49:02.904Z","0.3.2":"2026-05-30T21:59:36.679Z","0.4.0":"2026-06-23T08:28:27.572Z","0.5.0":"2026-07-10T01:17:15.219Z","0.6.0":"2026-08-19T10:30:18.091Z","0.7.0":"2026-09-27T13:00:14.640Z"},"bugs":{"url":"https://github.com/camcima/nestjs-rfc9457/issues"},"author":{"name":"Carlos Cima"},"license":"MIT","homepage":"https://github.com/camcima/nestjs-rfc9457#readme","keywords":["nestjs","rfc9457","rfc7807","problem-details","error-handling","api"],"repository":{"url":"git+https://github.com/camcima/nestjs-rfc9457.git","type":"git"},"description":"NestJS library for RFC 9457 Problem Details responses","maintainers":[{"name":"camcima","email":"camcima@hotmail.com"}],"readme":"<div align=\"center\">\n\n<picture>\n  <img alt=\"nestjs-rfc9457\" src=\"assets/logo.svg\" width=\"580\">\n</picture>\n\n<br>\n\n[![CI](https://github.com/camcima/nestjs-rfc9457/actions/workflows/ci.yml/badge.svg)](https://github.com/camcima/nestjs-rfc9457/actions/workflows/ci.yml)\n[![CodeQL](https://github.com/camcima/nestjs-rfc9457/actions/workflows/codeql.yml/badge.svg)](https://github.com/camcima/nestjs-rfc9457/actions/workflows/codeql.yml)\n[![codecov](https://codecov.io/gh/camcima/nestjs-rfc9457/graph/badge.svg)](https://codecov.io/gh/camcima/nestjs-rfc9457)\n[![npm version](https://img.shields.io/npm/v/@camcima/nestjs-rfc9457)](https://www.npmjs.com/package/@camcima/nestjs-rfc9457)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![TypeScript](https://img.shields.io/badge/TypeScript-6-blue.svg)](https://www.typescriptlang.org/)\n[![Node.js](https://img.shields.io/badge/Node.js-20%20%7C%2022%20%7C%2024-green.svg)](https://nodejs.org/)\n\n</div>\n\nNestJS library for [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) Problem Details HTTP error responses.\n\n## Table of Contents\n\n- [What is RFC 9457?](#what-is-rfc-9457)\n- [Features](#features)\n- [Installation](#installation)\n- [Coding Agent Skill](#coding-agent-skill)\n- [Quick Start](#quick-start)\n- [Configuration](#configuration)\n- [Async Configuration](#async-configuration)\n- [Custom Exception Types](#custom-exception-types)\n- [Validation Integration](#validation-integration)\n- [Swagger / OpenAPI Integration](#swagger--openapi-integration)\n- [Advanced Usage](#advanced-usage)\n- [API Reference](#api-reference)\n- [Example Responses](#example-responses)\n- [Examples](#examples)\n- [Security](#security)\n- [Contributing](#contributing)\n- [License](#license)\n\n## What is RFC 9457?\n\n[RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) (July 2023) defines a standard JSON format for HTTP API error responses, using the `application/problem+json` media type. It supersedes RFC 7807 and gives APIs a consistent, machine-readable way to communicate errors.\n\nA Problem Details response looks like this:\n\n```json\n{\n  \"type\": \"https://api.example.com/problems/not-found\",\n  \"title\": \"Not Found\",\n  \"status\": 404,\n  \"detail\": \"User 42 not found\",\n  \"instance\": \"/api/users/42\"\n}\n```\n\nThe five standard members are:\n\n| Member     | Description                                            |\n| ---------- | ------------------------------------------------------ |\n| `type`     | URI identifying the problem type                       |\n| `title`    | Short human-readable summary of the problem type       |\n| `status`   | HTTP status code (advisory)                            |\n| `detail`   | Human-readable explanation of this specific occurrence |\n| `instance` | URI identifying this specific occurrence               |\n\nExtension members (arbitrary key-value pairs) are allowed for problem-type-specific data.\n\n---\n\n## Features\n\n- Zero-config drop-in: import the module once in `AppModule` and all HTTP exceptions become RFC 9457 responses\n- Automatic `ValidationPipe` integration — flat string-array errors work out of the box (Tier 1)\n- Enhanced structured validation errors with `property`, `constraints`, and nested `children` (Tier 2)\n- `@ProblemType()` class decorator for custom exception types with full prototype-chain inheritance\n- `ProblemDetailException` for one-off problems carrying extension members and status-specific response headers\n- Configurable `type` URI generation with `typeBaseUri` and automatic kebab-case slug derivation\n- Four `instance` strategies: `'request-uri'`, `'uuid'`, `'none'`, or a custom callback\n- Optional catch-all mode for non-`HttpException` throwables (produces 500 Problem Details)\n- Custom `exceptionMapper` callback for full control over any exception\n- `responseHeaders` callback for status companions such as `Retry-After` and `WWW-Authenticate`\n- Default `error`-level logging of unhandled exceptions when `catchAllExceptions: true` (override via `onUnhandled` callback)\n- `ProblemDetailsFactory` is injectable — use it directly in GraphQL, microservices, or custom filters\n- Optional `@nestjs/swagger` integration: `ProblemDetailDto` and `ValidationProblemDetailDto` for OpenAPI documentation, plus a `applyProblemDetailResponses()` helper that auto-applies `@ApiResponse` decorators to all controllers under `application/problem+json`\n- Works with both Express and Fastify adapters\n- Zero runtime dependencies; `class-validator` and `@nestjs/swagger` are optional peer dependencies\n\n---\n\n## Installation\n\n```bash\nnpm install @camcima/nestjs-rfc9457\n```\n\n```bash\nyarn add @camcima/nestjs-rfc9457\n```\n\n```bash\npnpm add @camcima/nestjs-rfc9457\n```\n\n### Peer dependencies\n\n| Package            | Version                                        | Required                               |\n| ------------------ | ---------------------------------------------- | -------------------------------------- |\n| `@nestjs/common`   | `^10.0.0 \\|\\| ^11.0.0 \\|\\| ^12.0.0`            | Yes                                    |\n| `@nestjs/core`     | `^10.0.0 \\|\\| ^11.0.0 \\|\\| ^12.0.0`            | Yes                                    |\n| `reflect-metadata` | `^0.1.13 \\|\\| ^0.2.0`                          | Yes                                    |\n| `class-validator`  | `^0.14.0 \\|\\| ^0.15.0`                         | No (optional, for Tier 2 validation)   |\n| `@nestjs/swagger`  | `^7.0.0 \\|\\| ^8.0.0 \\|\\| ^11.0.0 \\|\\| ^12.0.0` | No (optional, for OpenAPI integration) |\n\n> **Note:** `reflect-metadata` must be imported once at your application's entry point. NestJS's standard bootstrap already does this, so no extra setup is needed in a typical app — the library relies on it for `@ProblemType()` decorator metadata.\n\n---\n\n## Coding Agent Skill\n\nThis repository ships an [agent skill](./skills/configure-nestjs-rfc9457/SKILL.md) that teaches AI coding agents (Claude Code, Cursor, Cline, Copilot, and others) how to install and wire `@camcima/nestjs-rfc9457` into a NestJS project. It covers module registration, Tier 1/Tier 2 validation, Swagger integration, custom exception types via `@ProblemType()`, and async configuration with `ConfigService`.\n\n### Install via the [Vercel skills CLI](https://github.com/vercel-labs/skills)\n\nFrom the root of the NestJS project where you want the agent to use the skill:\n\n```bash\nnpx skills add camcima/nestjs-rfc9457\n```\n\nThe CLI auto-detects your agent (Claude Code, Cursor, Cline, etc.) and installs the skill into the right location. After installation, ask your agent something like _\"set up RFC 9457 problem details in this project\"_ — the skill activates automatically and the agent will follow it to install the package, register `Rfc9457Module`, and apply any optional integrations you ask for.\n\nTo list installed skills: `npx skills list`. To remove: `npx skills remove configure-nestjs-rfc9457`.\n\n### Manual install\n\nIf you don't use the Vercel CLI, copy the skill folder directly into your agent's skill directory. Common locations:\n\n| Agent         | Path                                       |\n| ------------- | ------------------------------------------ |\n| Claude Code   | `.claude/skills/configure-nestjs-rfc9457/` |\n| Cursor        | `.cursor/skills/configure-nestjs-rfc9457/` |\n| Generic / SDK | `.agents/skills/configure-nestjs-rfc9457/` |\n\nThe skill is a single self-contained `SKILL.md` — no scripts or assets are required.\n\n---\n\n## Quick Start\n\nImport `Rfc9457Module` once in your root `AppModule`. Because the module is **global**, you do not need to import it in any other module — the exception filter applies everywhere in your application automatically. Do not call `forRoot()` in more than one module: each call registers another global exception filter.\n\n```typescript\n// app.module.ts\nimport { Module } from '@nestjs/common';\nimport { Rfc9457Module } from '@camcima/nestjs-rfc9457';\n\n@Module({\n  imports: [Rfc9457Module.forRoot()],\n})\nexport class AppModule {}\n```\n\nThat is all the configuration you need. Every `HttpException` thrown anywhere in your application will now produce an RFC 9457 response.\n\n### Before and after\n\n**Before** (standard NestJS `NotFoundException`):\n\n```json\n{\n  \"statusCode\": 404,\n  \"message\": \"User 42 not found\",\n  \"error\": \"Not Found\"\n}\n```\n\n**After** (with `@camcima/nestjs-rfc9457`):\n\n```json\n{\n  \"type\": \"about:blank\",\n  \"title\": \"Not Found\",\n  \"status\": 404,\n  \"detail\": \"User 42 not found\"\n}\n```\n\nThe response `Content-Type` is set to `application/problem+json` as required by the RFC.\n\n> **Hybrid applications (WebSockets / microservices):** the filter only handles HTTP contexts. For non-HTTP transports it rethrows the exception untouched so it never corrupts the transport with an HTTP reply — but the rethrow does **not** re-enter Nest's default WS/RPC handlers. If your app uses gateways or microservice listeners, bind transport-scoped exception filters for those contexts.\n\n> **Committed responses:** if an exception is thrown after the response has already been committed (headers sent — e.g. mid-stream), the filter cannot safely write a Problem Details body over it. It logs the exception and ends the response instead of attempting a second write, mirroring `BaseExceptionFilter`'s own behavior.\n\n---\n\n## Configuration\n\n`Rfc9457Module.forRoot()` accepts an optional `Rfc9457ModuleOptions` object.\n\n```typescript\nRfc9457Module.forRoot({\n  typeBaseUri: 'https://api.example.com/problems',\n  instanceStrategy: 'request-uri',\n  catchAllExceptions: true,\n  exceptionMapper: (exception, request) => {\n    /* ... */\n  },\n  validationExceptionMapper: (messages, request) => {\n    /* ... */\n  },\n  responseHeaders: (problem, exception, request) => {\n    /* ... */\n  },\n});\n```\n\n### `typeBaseUri`\n\n**Type**: `string` | **Default**: `undefined`\n\nWhen set, the library generates `type` URIs by combining the base URI with a kebab-case slug derived from the HTTP status phrase. When omitted, `type` defaults to `\"about:blank\"` (per RFC 9457 §4.2).\n\n```typescript\nRfc9457Module.forRoot({\n  typeBaseUri: 'https://api.example.com/problems',\n});\n```\n\nA `NotFoundException` (404) becomes:\n\n```json\n{\n  \"type\": \"https://api.example.com/problems/not-found\",\n  \"title\": \"Not Found\",\n  \"status\": 404\n}\n```\n\nSlug derivation uses the HTTP status phrase from Node's built-in `http.STATUS_CODES`:\n\n- `\"Not Found\"` → `not-found`\n- `\"Internal Server Error\"` → `internal-server-error`\n- `\"Unprocessable Entity\"` → `unprocessable-entity`\n\n> **`about:blank` and `title` (RFC 9457 §4.2.1):** when `type` resolves to `\"about:blank\"`, the RFC says `title` **SHOULD** be the generic HTTP status phrase for that status code. The library fills in that phrase automatically whenever a resolution step (an `HttpException`, `@ProblemType()`, or a mapper) does not itself supply a `title` — but it never rewrites an explicit `title` your `exceptionMapper` or `@ProblemType()` metadata sets. If you set a domain-specific `title` without also setting `type`, the response pairs that title with `\"about:blank\"`; set a domain-specific `type` URI alongside it (or configure `typeBaseUri`) to keep the two consistent.\n\n### `instanceStrategy`\n\n**Type**: `'request-uri' | 'uuid' | 'none' | ((request, exception) => string | undefined)` | **Default**: `'none'`\n\nControls how the `instance` field is populated.\n\n**`'none'`** — `instance` is omitted from the response (default):\n\n```typescript\nRfc9457Module.forRoot({ instanceStrategy: 'none' });\n```\n\n**`'request-uri'`** — uses the request URL path:\n\n```typescript\nRfc9457Module.forRoot({ instanceStrategy: 'request-uri' });\n// instance: \"/api/users/42\"\n```\n\nThe query string is stripped before the path is used as `instance`, so query\nparameters (which often carry tokens or PII) are never echoed into the response\nbody. If you need the full URL including the query string, use a custom callback\nthat returns `request.url`.\n\nExpress's `originalUrl` is preferred when present. Inside a mounted router\nExpress rewrites `req.url` relative to the mount point, so a handler mounted at\n`/api` would otherwise report `instance: \"/users/42\"` for a request the client\nsent to `/api/users/42`. Fastify does not define `originalUrl` and its `url` is\nalready the full path, so nothing changes there.\n\n**`'uuid'`** — generates a `urn:uuid:<v4>` per occurrence:\n\n```typescript\nRfc9457Module.forRoot({ instanceStrategy: 'uuid' });\n// instance: \"urn:uuid:a8098c1a-f86e-11da-bd1a-00112444be1e\"\n```\n\n**Custom callback** — full control, receives the request and the original exception:\n\n```typescript\nRfc9457Module.forRoot({\n  instanceStrategy: (request, exception) => {\n    return `https://errors.example.com/log?path=${request.url}`;\n  },\n});\n```\n\nReturn `undefined` from a custom callback to omit `instance` for that occurrence.\n\nThe `request` parameter implements `Rfc9457Request`:\n\n```typescript\ninterface Rfc9457Request {\n  url: string;\n  method: string;\n  originalUrl?: string;\n}\n```\n\nBoth Express's `Request` and Fastify's `FastifyRequest` are structurally\nassignable to this interface, so you can pass them directly. To read\nadapter-specific fields inside a callback, narrow to the concrete request type:\n\n```typescript\ninstanceStrategy: (request) => {\n  const req = request as unknown as import('express').Request;\n  return `https://errors.example.com/log?id=${req.headers['x-request-id']}`;\n};\n```\n\n### `catchAllExceptions`\n\n**Type**: `boolean` | **Default**: `false`\n\nWhen `false` (default), exceptions that are not `HttpException` instances are passed to NestJS's default error handling via `super.catch()`. When `true`, any throwable — including plain `Error` objects and non-HTTP exceptions — is caught and produces a generic 500 Problem Details response. Internal error information is never exposed in the response body.\n\nErrors raised by the HTTP adapter itself keep their own status (e.g. a 413 for an oversized body), matching NestJS's default handling. Two kinds are recognized by their `statusCode` plus a marker: errors built by the [`http-errors`](https://www.npmjs.com/package/http-errors) package, which Express's body parser throws, carry a boolean `expose`; Fastify's own errors carry an `FST_` code. The message becomes `detail` only for client errors (for `http-errors`, only when `expose` is `true`). Other errors that merely carry a `statusCode` still produce a 500.\n\n```typescript\nRfc9457Module.forRoot({ catchAllExceptions: true });\n```\n\n**Observability:** when this branch fires (a non-`HttpException` reaches the filter and no `exceptionMapper` claims it), the library logs the exception at `error` level via NestJS's built-in `Logger` (context `Rfc9457ExceptionFilter`) before sending the generic 500. This keeps unexpected throwables visible in server logs even though the response body is intentionally bland. To redirect or replace this logging, use the [`onUnhandled`](#onunhandled) callback described below.\n\n### `suppress5xxDetail`\n\n**Type**: `boolean` | **Default**: `false`\n\nWhen `true`, the `detail` member is stripped from every problem response with a 5xx status, regardless of its source — an `HttpException` message, an `exceptionMapper` result, or `@ProblemType()` metadata. This is intentionally blunt: it is an opt-in production-hardening switch guaranteeing that no internal error text reaches clients on a server error, rather than a fine-grained per-field filter.\n\n```typescript\nRfc9457Module.forRoot({ suppress5xxDetail: true });\n```\n\nDefault is `false` to match NestJS semantics, where an explicit `HttpException` message is client-facing by design. 4xx responses are never affected.\n\n### `exceptionMapper`\n\n**Type**: `(exception: unknown, request: Rfc9457Request) => ProblemDetail | null`\n\nA callback that runs first in the resolution chain. Return a `ProblemDetail` object to take full control of the response, or `null` to fall through to the next resolution step (`@ProblemType()` metadata, then validation handling, then default mapping).\n\n```typescript\nRfc9457Module.forRoot({\n  exceptionMapper: (exception, request) => {\n    if (exception instanceof DatabaseException) {\n      return {\n        type: 'https://api.example.com/problems/database-error',\n        title: 'Database Error',\n        status: 503,\n        detail: 'A temporary database error occurred',\n      };\n    }\n    return null; // fall through to default handling\n  },\n});\n```\n\nIf the returned `ProblemDetail` omits `status`, the factory falls back to `exception.getStatus()` (if it is an `HttpException`) or `500`.\n\n### Status invariants\n\n**Every problem response this library emits carries a 400–599 status.** This is library policy, not an RFC requirement: RFC 9457 allows problem details with any HTTP status code, but notes that they \"most naturally fit the semantics of 4xx and 5xx responses\" ([§1](https://www.rfc-editor.org/rfc/rfc9457.html#section-1)). Two rules enforce the policy:\n\n1. A `status` supplied by `exceptionMapper`, `@ProblemType()` metadata, or `ProblemDetailException` must be an integer in 400–599. A value outside the range is ignored — the library logs a warning and falls back to `exception.getStatus()` (for an `HttpException`) or `500`.\n2. An `HttpException` whose own status is outside 400–599 (e.g. `new HttpException('moved', 302)`) is **not** rendered as a problem document at all. The filter hands it back to NestJS, which sends its standard response at the requested status. A redirect or success response is not a problem to report, and silently rewriting a deliberate redirect into a 500 would be worse.\n\nAn `exceptionMapper` still takes precedence: if it claims such an exception and returns a valid error status, that problem response is sent normally.\n\nIf you call `ProblemDetailsFactory` directly, rule 2 does not apply — the factory must return something, so a non-error status is clamped to `500` and a warning is logged. Prefer letting the filter make the delegation decision.\n\n### `onUnhandled`\n\n**Type**: `(exception: unknown, request: Rfc9457Request, problem: Readonly<ProblemDetail>) => void` | **Default**: built-in `Logger.error(...)` (context `Rfc9457ExceptionFilter`)\n\nCalled when a non-`HttpException` reaches the catch-all branch (i.e. `catchAllExceptions: true` AND the `exceptionMapper` returned `null`). Use this to send unhandled exceptions to a structured sink (Sentry, Datadog, a custom pino child logger) or to suppress the default log entirely.\n\n```typescript\nRfc9457Module.forRoot({\n  catchAllExceptions: true,\n  instanceStrategy: 'uuid',\n  onUnhandled: (exception, request, problem) => {\n    // Route to Sentry, Datadog, etc.\n    sentry.captureException(exception, {\n      tags: { method: request.method, url: request.url },\n      // `problem.instance` is the identifier the client sees. Recording it\n      // here is what lets a support ticket quoting that URN be traced back\n      // to this stack trace.\n      extra: { instance: problem.instance },\n    });\n  },\n});\n```\n\nThe third parameter is the fully resolved problem body that is about to be sent. It is typed `Readonly` because the response is serialized from the same object as soon as the callback returns: mutating it (through a cast, or through a nested extension value the shallow `Readonly` does not cover) changes what the client receives, which is not what this hook is for.\n\n**The filter still sends the generic 500 Problem Details response after invoking `onUnhandled`.** This callback exists purely for observability — it never changes the HTTP response.\n\nWhen `onUnhandled` is **not** provided, the library calls `Logger.error(...)` with either the exception's `stack` string or a `{ exception }` structured context (for non-`Error` values). When an `instance` was generated for the occurrence, it is appended to the log message (`… [instance: urn:uuid:…]`) so the default logging is correlatable too. The log context is `Rfc9457ExceptionFilter` so it can be filtered or silenced via NestJS's logger configuration.\n\n### `responseHeaders`\n\n**Type**: `(problem: Readonly<ProblemDetail>, exception: unknown, request: Rfc9457Request) => Record<string, string> | undefined` | **Default**: `undefined`\n\nSupplies transport response headers that accompany a problem response. Some statuses are only fully specified by a header: `Retry-After` on 429 and 503, `WWW-Authenticate` on 401. Those belong in the header block, not the body, and this is the channel for them.\n\n```typescript\nRfc9457Module.forRoot({\n  responseHeaders: (problem) => {\n    if (problem.status === 401) return { 'WWW-Authenticate': 'Bearer realm=\"api\"' };\n    if (problem.status === 429 && typeof problem.retryAfterSeconds === 'number') {\n      return { 'Retry-After': String(problem.retryAfterSeconds) };\n    }\n    return undefined;\n  },\n});\n```\n\nCalled once per problem response with the resolved body, the originating exception, and the request. Return `undefined` to add nothing.\n\n`Content-Type` is reserved: it is written after these headers and always ends up `application/problem+json`. A throw inside the callback is contained like every other callback — it is logged and the response goes out without the extra headers. Each header name and value, whether from this callback or from a `ProblemDetailException`, is checked with Node's own header validation first; an invalid entry (e.g. a value containing a newline) is dropped and logged by name, and the rest of the response is sent unchanged.\n\nFor a header that belongs to one specific occurrence rather than to a global policy, pass it at the throw site instead — see [`ProblemDetailException`](#problemdetailexception-one-off-problems-with-extension-members). Throw-site headers are applied first, and this callback is merged over them, so a global policy can override a throw-site value.\n\n### `validationStatuses`\n\n**Type**: `number[]` | **Default**: `[400]`\n\nThe HTTP status codes at which `ValidationPipe` default output is treated as a Tier 1 validation error. Set this when you configure `ValidationPipe({ errorHttpStatusCode })`:\n\n```typescript\n// main.ts\napp.useGlobalPipes(new ValidationPipe({ errorHttpStatusCode: 422 }));\n\n// app.module.ts\nRfc9457Module.forRoot({ validationStatuses: [400, 422] });\n```\n\nDetection is an explicit allow-list because the validation response shape is indistinguishable from business `HttpException`s constructed with a message array — NestJS sets the `error` field to the status phrase in both cases (e.g. `new ConflictException(['order already shipped'])` produces `{ message: [...], error: 'Conflict' }`). Declare only statuses your application reserves for validation; business exceptions at other statuses are never misclassified. At undeclared statuses, validation messages are still preserved by joining them into `detail`.\n\n### `validationExceptionMapper`\n\n**Type**: `(messages: string[], request: Rfc9457Request, status: number) => ProblemDetail`\n\nOverrides the default Tier 1 validation error response. Receives the flat string array from the exception's `getResponse().message`, the request, and the HTTP status the exception carried (one of `validationStatuses`). Only applies to Tier 1 (flat string) validation errors — Tier 2 structured errors from `Rfc9457ValidationException` bypass this callback.\n\n```typescript\nRfc9457Module.forRoot({\n  validationExceptionMapper: (messages, request, status) => ({\n    type: 'https://api.example.com/problems/validation-error',\n    title: 'Validation Error',\n    status, // echo the detected status — do not hard-code it\n    detail: 'One or more fields failed validation',\n    violations: messages,\n  }),\n});\n```\n\n### Callback failure policy\n\nThe error path is total: a failure inside any user-supplied callback never\nreplaces the problem-details response.\n\n- `exceptionMapper` throws → the failure is logged (context\n  `Rfc9457ExceptionFilter` when the mapper runs in the filter,\n  `ProblemDetailsFactory` when it runs in the factory) and resolution\n  continues down the standard chain (decorator → validation →\n  HttpException → fallback).\n- `validationExceptionMapper` throws → logged (context\n  `ProblemDetailsFactory`); the response falls back to the default Tier 1\n  validation body (`status`, status-phrase `title`,\n  `detail: \"Request validation failed\"`, and the `errors` array) — it does\n  not re-enter the resolution chain.\n- `instanceStrategy` throws → logged; the `instance` member is omitted.\n- `onUnhandled` throws → logged together with the original exception; the\n  generic 500 problem response is still sent.\n- `responseHeaders` throws → logged; the response is sent without the\n  callback's headers.\n- A header entry is invalid (from `responseHeaders` or a\n  `ProblemDetailException`) → that entry is dropped and logged by name, never\n  by value; the remaining headers and the problem response are sent.\n\nCallback errors are never included in the response body.\n\n`exceptionMapper`, `validationExceptionMapper`, and `instanceStrategy` are\nsynchronous contracts — their return types don't admit a `Promise`, so an\n`async` callback is rejected at compile time. `onUnhandled` returns `void`,\nwhich means an `async` callback type-checks; the filter handles that case\ntoo: if the callback returns a thenable, its rejection is caught, logged\ntogether with the original exception, and never surfaces as an unhandled\nrejection. The generic 500 response is sent synchronously either way —\nthe library does not await the callback.\n\n---\n\n## Async Configuration\n\nUse `Rfc9457Module.forRootAsync()` to inject configuration from a service such as `ConfigService`.\n\n### `useFactory`\n\n```typescript\nimport { Module } from '@nestjs/common';\nimport { ConfigModule, ConfigService } from '@nestjs/config';\nimport { Rfc9457Module } from '@camcima/nestjs-rfc9457';\n\n@Module({\n  imports: [\n    ConfigModule.forRoot(),\n    Rfc9457Module.forRootAsync({\n      imports: [ConfigModule],\n      inject: [ConfigService],\n      useFactory: (config: ConfigService) => ({\n        typeBaseUri: config.get<string>('PROBLEM_TYPE_BASE_URI'),\n        instanceStrategy: 'uuid',\n        catchAllExceptions: config.get<boolean>('CATCH_ALL_EXCEPTIONS', false),\n      }),\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n### `useClass`\n\nImplement the `Rfc9457OptionsFactory` interface:\n\n```typescript\nimport { Injectable } from '@nestjs/common';\nimport { Rfc9457OptionsFactory, Rfc9457ModuleOptions } from '@camcima/nestjs-rfc9457';\n\n@Injectable()\nexport class Rfc9457ConfigService implements Rfc9457OptionsFactory {\n  createRfc9457Options(): Rfc9457ModuleOptions {\n    return {\n      typeBaseUri: 'https://api.example.com/problems',\n      instanceStrategy: 'uuid',\n    };\n  }\n}\n```\n\n```typescript\nRfc9457Module.forRootAsync({\n  useClass: Rfc9457ConfigService,\n});\n```\n\n### `useExisting`\n\nReuse an existing provider that implements `Rfc9457OptionsFactory`:\n\n```typescript\nRfc9457Module.forRootAsync({\n  imports: [SharedConfigModule],\n  useExisting: SharedConfigService,\n});\n```\n\n---\n\n## Custom Exception Types\n\nUse the `@ProblemType()` decorator to attach RFC 9457 problem type metadata to your exception classes. The decorator stores a **template** with type identity fields (`type`, `title`, `status`). Occurrence-specific fields (`detail`, `instance`) are always resolved at runtime by the factory from the exception message and the configured instance strategy.\n\n```typescript\nimport { HttpException } from '@nestjs/common';\nimport { ProblemType } from '@camcima/nestjs-rfc9457';\n\n@ProblemType({\n  type: 'https://api.example.com/problems/insufficient-funds',\n  title: 'Insufficient Funds',\n  status: 422,\n})\nexport class InsufficientFundsException extends HttpException {\n  constructor(\n    public readonly balance: number,\n    public readonly required: number,\n  ) {\n    super(`Balance ${balance} is less than required ${required}`, 422);\n  }\n}\n```\n\nWhen this exception is thrown, the response is:\n\n```json\n{\n  \"type\": \"https://api.example.com/problems/insufficient-funds\",\n  \"title\": \"Insufficient Funds\",\n  \"status\": 422,\n  \"detail\": \"Balance 50 is less than required 100\"\n}\n```\n\nThe decorator accepts a `ProblemTypeMetadata` object:\n\n```typescript\ninterface ProblemTypeMetadata {\n  type?: string; // URI for the problem type\n  title?: string; // Short human-readable summary\n  status?: number; // HTTP status code\n}\n```\n\nAll three fields are optional. If `status` is omitted, the factory uses `exception.getStatus()` for `HttpException` subclasses or falls back to `500` in catch-all mode. If `type` is omitted and `typeBaseUri` is configured, the slug for the status code is used.\n\n### Inheritance\n\nMetadata lookup walks the prototype chain, so child classes automatically inherit their parent's `@ProblemType()` metadata:\n\n```typescript\n// Parent defines the problem type\n@ProblemType({\n  type: 'https://api.example.com/problems/payment-error',\n  title: 'Payment Error',\n  status: 402,\n})\nexport class PaymentException extends HttpException {\n  constructor(message: string) {\n    super(message, 402);\n  }\n}\n\n// Child inherits parent's @ProblemType() metadata\nexport class CardDeclinedException extends PaymentException {\n  constructor() {\n    super('Card was declined');\n  }\n}\n```\n\nA child class can **fully override** the parent's metadata by applying its own `@ProblemType()` decorator. There is no merging — the child's decorator replaces the parent's entirely.\n\n```typescript\n@ProblemType({\n  type: 'https://api.example.com/problems/card-declined',\n  title: 'Card Declined',\n  status: 402,\n})\nexport class CardDeclinedException extends PaymentException {\n  constructor() {\n    super('Card was declined');\n  }\n}\n```\n\n`@ProblemType()` can also decorate plain `Error` subclasses (not extending `HttpException`), but these are only handled by the factory when `catchAllExceptions: true` is set. Because that combination silently produces NestJS's default error body instead of your problem type, the filter logs a warning (once per exception class) naming the class and how to fix it, rather than leaving you to wonder why the decorator had no effect.\n\n### `ProblemDetailException`: one-off problems with extension members\n\n`@ProblemType()` describes a **reusable problem type**. When you need a **one-off problem** — particularly one carrying occurrence-specific extension members — throw a `ProblemDetailException` instead. It takes a complete problem document and passes every member through to the response body:\n\n```typescript\nimport { ProblemDetailException } from '@camcima/nestjs-rfc9457';\n\nthrow new ProblemDetailException({\n  type: 'https://api.example.com/problems/insufficient-funds',\n  title: 'Insufficient Funds',\n  status: 402,\n  detail: 'Your balance is too low to cover this transfer.',\n  balance: 30,\n  cost: 50,\n});\n```\n\n```json\n{\n  \"type\": \"https://api.example.com/problems/insufficient-funds\",\n  \"title\": \"Insufficient Funds\",\n  \"status\": 402,\n  \"detail\": \"Your balance is too low to cover this transfer.\",\n  \"balance\": 30,\n  \"cost\": 50\n}\n```\n\n`status` is required and must be an error status (400–599); anything else throws a `RangeError` at construction. Normalization still applies: a bare `type` slug is expanded against `typeBaseUri`, a missing `title` is filled from the status phrase, and the configured instance strategy runs.\n\n**Why this exists.** A plain `HttpException` cannot carry extension members. Given `new HttpException({ message: 'Balance too low', balance: 30 }, 402)`, NestJS's response object is read for its `message` only — `balance` is dropped. Since extension members are the whole point of RFC 9457's extensibility, this class is the supported way to emit them from a throw site.\n\n**Combined with `@ProblemType()`.** Decorate a subclass to declare the reusable identity once, then supply per-occurrence data at each throw. Instance members win per-member:\n\n```typescript\n@ProblemType({\n  type: 'https://api.example.com/problems/payment-error',\n  title: 'Payment Error',\n  status: 402,\n})\nexport class PaymentProblem extends ProblemDetailException {}\n\nthrow new PaymentProblem({ status: 409, detail: 'Already settled', settledAt });\n// type and title come from the decorator; status, detail and settledAt from the throw\n```\n\n**Response headers.** Pass headers for this occurrence as the second argument:\n\n```typescript\nthrow new ProblemDetailException(\n  { status: 429, title: 'Too Many Requests', retryAfterSeconds: 60 },\n  { headers: { 'Retry-After': '60' } },\n);\n```\n\nPrecedence is unchanged: a global [`exceptionMapper`](#exceptionmapper) that claims the exception still wins, and [`suppress5xxDetail`](#suppress5xxdetail) still strips `detail` from a 5xx (extension members are left alone).\n\n---\n\n## Validation Integration\n\n### Tier 1 — Automatic (zero config)\n\nWhen NestJS's `ValidationPipe` rejects a request, it throws a `BadRequestException` whose response contains a `message` array of strings. The library detects this automatically and produces a structured validation error response with no configuration required.\n\n```typescript\n// main.ts — standard ValidationPipe setup, nothing extra needed\napp.useGlobalPipes(new ValidationPipe());\n```\n\nResponse:\n\n```json\n{\n  \"type\": \"about:blank\",\n  \"title\": \"Bad Request\",\n  \"status\": 400,\n  \"detail\": \"Request validation failed\",\n  \"errors\": [\"email must be an email\", \"age must not be less than 0\"]\n}\n```\n\nTo customize the Tier 1 response, use the `validationExceptionMapper` option described in the [Configuration](#configuration) section.\n\n**Custom status codes.** If you configure `ValidationPipe({ errorHttpStatusCode: 422 })` (or any other 4xx), declare that status in the [`validationStatuses`](#validationstatuses) module option (`validationStatuses: [400, 422]`) and the library produces the same structured validation response at that status, with the matching `title` (e.g. `Unprocessable Entity`). Without the declaration, the messages are still preserved — joined into `detail` — but the `errors` array is not emitted. Detection is an explicit opt-in per status because the validation output shape is indistinguishable from business exceptions constructed with message arrays.\n\n### Tier 2 — Enhanced structured errors (opt-in)\n\nFor rich, structured validation output with `property`, `constraints`, and nested `children` arrays, use the `createRfc9457ValidationPipeExceptionFactory` helper.\n\n**Step 1** — Install `class-validator` if you have not already:\n\n```bash\nnpm install class-validator class-transformer\n```\n\n**Step 2** — Use the factory as the `ValidationPipe` exception factory:\n\n```typescript\n// main.ts\nimport { ValidationPipe } from '@nestjs/common';\nimport { createRfc9457ValidationPipeExceptionFactory } from '@camcima/nestjs-rfc9457';\n\napp.useGlobalPipes(\n  new ValidationPipe({\n    exceptionFactory: createRfc9457ValidationPipeExceptionFactory(),\n  }),\n);\n```\n\nResponse for a DTO with nested validation:\n\n```json\n{\n  \"type\": \"about:blank\",\n  \"title\": \"Bad Request\",\n  \"status\": 400,\n  \"detail\": \"Request validation failed\",\n  \"errors\": [\n    {\n      \"property\": \"email\",\n      \"constraints\": {\n        \"isEmail\": \"email must be an email\"\n      }\n    },\n    {\n      \"property\": \"address\",\n      \"children\": [\n        {\n          \"property\": \"zip\",\n          \"constraints\": {\n            \"isPostalCode\": \"zip must be a postal code\"\n          }\n        }\n      ]\n    }\n  ]\n}\n```\n\nNested validation errors are preserved as `children` arrays matching the `class-validator` `ValidationError` tree. They are **not** flattened to dotted paths (e.g., `\"address.zip\"`) — the original structure is preserved.\n\n**Custom status (e.g. 422).** To use a different status, configure both the pipe and the factory:\n\n```typescript\napp.useGlobalPipes(\n  new ValidationPipe({\n    errorHttpStatusCode: 422,\n    exceptionFactory: createRfc9457ValidationPipeExceptionFactory({ status: 422 }),\n  }),\n);\n```\n\n`createRfc9457ValidationPipeExceptionFactory` throws a `RangeError` if `status` is outside the 400–599 error range.\n\n> **Breaking change (vs earlier releases (<=0.4.x)):** `Rfc9457ValidationException` now extends `HttpException` rather than `BadRequestException`, so its status is configurable. Code that narrows on `instanceof BadRequestException` no longer matches; narrow on `Rfc9457ValidationException` (or `HttpException`) instead.\n\n---\n\n## Swagger / OpenAPI Integration\n\nThe library ships optional Swagger support under a separate import path so it does not require `@nestjs/swagger` as a mandatory dependency. Install `@nestjs/swagger` as usual if you have not already:\n\n```bash\nnpm install @nestjs/swagger\n```\n\nAll Swagger-related exports are imported from the `/swagger` subpath:\n\n```typescript\nimport {\n  ProblemDetailDto,\n  ValidationProblemDetailDto,\n  ValidationErrorDto,\n  applyProblemDetailResponses,\n} from '@camcima/nestjs-rfc9457/swagger';\n```\n\n### Auto-applying error schemas to all controllers\n\nThe `applyProblemDetailResponses()` helper uses NestJS's `DiscoveryService` to programmatically attach `@ApiResponse` decorators to every controller in your application. Responses are documented under `application/problem+json` as required by RFC 9457.\n\n**Step 1** — Import `DiscoveryModule` in your app module:\n\n```typescript\nimport { Module } from '@nestjs/common';\nimport { DiscoveryModule } from '@nestjs/core';\nimport { Rfc9457Module } from '@camcima/nestjs-rfc9457';\n\n@Module({\n  imports: [DiscoveryModule, Rfc9457Module.forRoot()],\n})\nexport class AppModule {}\n```\n\n**Step 2** — Call the helper inside the lazy document factory passed to `SwaggerModule.setup()`:\n\n```typescript\nimport { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';\nimport { applyProblemDetailResponses } from '@camcima/nestjs-rfc9457/swagger';\n\nconst config = new DocumentBuilder().setTitle('My API').build();\n\nSwaggerModule.setup('/api', app, () => {\n  applyProblemDetailResponses(app);\n  return SwaggerModule.createDocument(app, config);\n});\n```\n\nBy default, this documents `400` and `500` responses on every route using `ProblemDetailDto`. The generated OpenAPI spec will show `application/problem+json` as the response media type with the correct schema.\n\n**Idempotent by design.** `applyProblemDetailResponses` is safe to call more than once. For a given controller and status, only the first call's options are applied — later calls for that same pair are no-ops. This means lazy document factories that run repeatedly (hot reload, multiple `SwaggerModule.setup()` calls for separate specs, etc.) never duplicate `@ApiResponse` metadata, and you don't need to guard the call site with your own \"already applied\" bookkeeping.\n\n> **Calling it more than once.** Safe: for a given controller class and status,\n> the first call's options are applied and later calls are ignored, so lazy\n> document factories, hot reload, and multiple `SwaggerModule.setup()` calls do\n> not duplicate metadata.\n>\n> One consequence is worth knowing if you run **two applications in one\n> process** (an e2e suite, a monorepo harness) that **share controller\n> classes**: the first application to be documented decides the options for that\n> class, and a later call with different `validationStatuses` is ignored. This\n> is a constraint of `@nestjs/swagger` rather than a caching choice —\n> `@ApiResponse` stores its metadata on the class itself, so both applications\n> necessarily read the same annotations. Applying per application would not give\n> each its own view; it would append a second response object that\n> `@nestjs/swagger` merges into one entry with a doubled description. Give each\n> application its own controller classes if they must be documented differently.\n\n### Options\n\n`applyProblemDetailResponses` accepts an optional second argument:\n\n```typescript\ninterface ApplyProblemDetailResponsesOptions {\n  /** HTTP status codes to document. Default: [400, 500]. */\n  statuses?: number[];\n\n  /**\n   * Statuses that use ValidationProblemDetailDto (with the errors array)\n   * instead of the base ProblemDetailDto. Default: [].\n   */\n  validationStatuses?: number[];\n\n  /**\n   * Return false to skip a controller (e.g. health-check controllers).\n   * Default: include all controllers.\n   */\n  filter?: (controller: DiscoveredController) => boolean;\n}\n```\n\n#### Excluding controllers\n\nPass a `filter` to skip controllers you don't want documented with the default error responses — for example a health-check endpoint:\n\n```typescript\napplyProblemDetailResponses(app, {\n  filter: (controller) => controller.metatype?.name !== 'HealthController',\n});\n```\n\n#### Documenting additional statuses\n\n```typescript\napplyProblemDetailResponses(app, {\n  statuses: [400, 401, 403, 404, 500],\n});\n```\n\n#### Documenting Tier 2 structured validation errors\n\nIf you use `Rfc9457ValidationException` (Tier 2) for validation, you can tell the helper to use `ValidationProblemDetailDto` for specific statuses. This DTO includes the `errors` array of structured `ValidationErrorDto` objects:\n\n```typescript\napplyProblemDetailResponses(app, {\n  statuses: [400, 500],\n  validationStatuses: [400],\n});\n```\n\nThis documents 400 responses with the `ValidationProblemDetailDto` schema (which includes `errors: ValidationErrorDto[]`) and 500 responses with the base `ProblemDetailDto`.\n\n### Using DTOs manually for per-route documentation\n\nFor finer control, use the DTO classes directly with `@ApiResponse()` on individual routes:\n\n```typescript\nimport { ApiResponse } from '@nestjs/swagger';\nimport { ProblemDetailDto, ValidationProblemDetailDto } from '@camcima/nestjs-rfc9457/swagger';\n\n@Get(':id')\n@ApiResponse({\n  status: 404,\n  description: 'Not Found',\n  content: {\n    'application/problem+json': {\n      schema: { $ref: '#/components/schemas/ProblemDetailDto' },\n    },\n  },\n})\nfindOne(@Param('id') id: string) {\n  // ...\n}\n```\n\nOr more concisely using the `type` shorthand (documents as `application/json` instead of `application/problem+json`):\n\n```typescript\n@ApiResponse({ status: 404, type: ProblemDetailDto })\n```\n\n### Extending DTOs for custom extension members\n\nIf your API returns extension members (additional fields beyond the five standard RFC 9457 members), extend `ProblemDetailDto` to document them:\n\n```typescript\nimport { ApiProperty } from '@nestjs/swagger';\nimport { ProblemDetailDto } from '@camcima/nestjs-rfc9457/swagger';\n\nexport class InsufficientFundsProblemDto extends ProblemDetailDto {\n  @ApiProperty({ example: 50 })\n  balance!: number;\n\n  @ApiProperty({ example: 100 })\n  required!: number;\n}\n```\n\n### Available DTOs\n\n| DTO                          | Description                                                                          |\n| ---------------------------- | ------------------------------------------------------------------------------------ |\n| `ProblemDetailDto`           | The five standard RFC 9457 fields (`type`, `title`, `status`, `detail`, `instance`)  |\n| `ValidationProblemDetailDto` | Extends `ProblemDetailDto` with `errors: ValidationErrorDto[]` for Tier 2 validation |\n| `ValidationErrorDto`         | Structured validation error (`property?`, `constraints?`, `children?`)               |\n\n### Design note\n\nThe auto-apply helper uses `ProblemDetailDto` for all statuses by default. This is intentional: a single HTTP status (e.g. 400) can produce different response shapes at runtime — a plain problem detail for non-validation errors, `errors: string[]` for Tier 1 validation, or `errors: ValidationErrorDto[]` for Tier 2 validation. The base DTO is the common denominator that is always correct. Use `validationStatuses` to opt in to the more specific schema when your application uses Tier 2 validation exclusively.\n\n---\n\n## Advanced Usage\n\n### Using `ProblemDetailsFactory` directly\n\n`ProblemDetailsFactory` is an injectable service exported by `Rfc9457Module`. You can inject it into any provider to produce Problem Details responses in contexts outside the standard HTTP filter — for example, GraphQL error formatters or microservice exception handlers.\n\n```typescript\nimport { Injectable } from '@nestjs/common';\nimport { ProblemDetailsFactory, Rfc9457Request } from '@camcima/nestjs-rfc9457';\n\n@Injectable()\nexport class GraphQLErrorFormatter {\n  constructor(private readonly problemDetailsFactory: ProblemDetailsFactory) {}\n\n  format(exception: unknown, context: { path: string; method: string }) {\n    const request: Rfc9457Request = {\n      url: context.path,\n      method: context.method,\n    };\n    const { status, body } = this.problemDetailsFactory.create(exception, request);\n    return { extensions: { problem: body, httpStatus: status } };\n  }\n}\n```\n\nThe `create` method signature is:\n\n```typescript\ncreate(exception: unknown, request: Rfc9457Request): { status: number; body: ProblemDetail }\n```\n\n- `status` is the definitive HTTP status code to use for the transport layer.\n- `body` is the RFC 9457 Problem Details object to serialize.\n\nThe factory applies the full resolution chain (mapper → decorator → validation → default → fallback) and all normalization rules (`type`, `instance`, `title`) regardless of how it is called.\n\n### Custom exception filter\n\nYou can build your own filter on top of `ProblemDetailsFactory` if you need to intercept specific exception types before the global filter sees them:\n\n```typescript\nimport { Catch, ArgumentsHost } from '@nestjs/common';\nimport { BaseExceptionFilter, HttpAdapterHost } from '@nestjs/core';\nimport { ProblemDetailsFactory, PROBLEM_CONTENT_TYPE } from '@camcima/nestjs-rfc9457';\n\n@Catch(MySpecialException)\nexport class MySpecialExceptionFilter extends BaseExceptionFilter {\n  constructor(\n    private readonly factory: ProblemDetailsFactory,\n    private readonly adapterHost: HttpAdapterHost,\n  ) {\n    super(adapterHost.httpAdapter);\n  }\n\n  catch(exception: MySpecialException, host: ArgumentsHost) {\n    const ctx = host.switchToHttp();\n    const request = ctx.getRequest();\n    const response = ctx.getResponse();\n\n    const { status, body } = this.factory.create(exception, request);\n\n    // Write through the HTTP adapter so the filter works on Express and\n    // Fastify alike, and set the RFC 9457 media type explicitly — the\n    // adapter's default is application/json, which would make the response\n    // non-conformant even though the body is correct. Pass a serialized\n    // string: given an object whose `statusCode` is >= 400, both adapters\n    // reset Content-Type to application/json.\n    const httpAdapter = this.adapterHost.httpAdapter;\n    httpAdapter.setHeader(response, 'Content-Type', PROBLEM_CONTENT_TYPE);\n    httpAdapter.reply(response, JSON.stringify(body), status);\n  }\n}\n```\n\n> `Content-Type: application/problem+json` is what tells a client the body is a\n> problem document. If you write the response yourself with `res.json(...)` you\n> get `application/json` and lose that signal — always set the header, whichever\n> mechanism you use.\n\n---\n\n## API Reference\n\n| Export                                         | Kind             | Description                                                                 |\n| ---------------------------------------------- | ---------------- | --------------------------------------------------------------------------- |\n| `Rfc9457Module`                                | Class            | Dynamic module. Use `forRoot(options?)` or `forRootAsync(options)`          |\n| `ProblemDetailsFactory`                        | Injectable class | Core resolver; injectable for use outside the HTTP filter                   |\n| `Rfc9457ExceptionFilter`                       | Injectable class | Global exception filter; registered automatically by the module             |\n| `ProblemType`                                  | Decorator        | Class decorator that attaches problem type metadata to exception classes    |\n| `ProblemDetailException`                       | Class            | Throw a complete problem document, extension members and headers included   |\n| `ProblemDetailExceptionOptions`                | Interface        | Options for `ProblemDetailException` (`headers`)                            |\n| `ProblemDetailWithStatus`                      | Type             | `ProblemDetail` with a required `status` — the `ProblemDetailException` arg |\n| `ProblemDetail`                                | Interface        | RFC 9457 response body shape with index signature for extension members     |\n| `ProblemTypeMetadata`                          | Interface        | Decorator options (`type`, `title`, `status`)                               |\n| `Rfc9457ModuleOptions`                         | Interface        | Options accepted by `forRoot()`                                             |\n| `Rfc9457OptionsFactory`                        | Interface        | Implement for `useClass` / `useExisting` async patterns                     |\n| `Rfc9457AsyncModuleOptions`                    | Interface        | Options accepted by `forRootAsync()`                                        |\n| `InstanceStrategy`                             | Type             | Union type for `instanceStrategy` option                                    |\n| `Rfc9457Request`                               | Interface        | Minimal request context compatible with Express and Fastify                 |\n| `Rfc9457ValidationException`                   | Class            | Exception wrapping structured `ValidationError[]`; thrown by Tier 2 factory |\n| `createRfc9457ValidationPipeExceptionFactory`  | Function         | Returns an `exceptionFactory` for `ValidationPipe` to enable Tier 2 errors  |\n| `Rfc9457ValidationPipeExceptionFactoryOptions` | Interface        | Options for `createRfc9457ValidationPipeExceptionFactory` (`status`)        |\n| `RFC9457_MODULE_OPTIONS`                       | Symbol           | DI token for the module options                                             |\n| `PROBLEM_CONTENT_TYPE`                         | Constant         | `'application/problem+json'`                                                |\n\n**Swagger subpath** (`@camcima/nestjs-rfc9457/swagger`):\n\n| Export                               | Kind      | Description                                                                           |\n| ------------------------------------ | --------- | ------------------------------------------------------------------------------------- |\n| `ProblemDetailDto`                   | Class     | Swagger DTO for the five standard RFC 9457 fields                                     |\n| `ValidationProblemDetailDto`         | Class     | Extends `ProblemDetailDto` with `errors: ValidationErrorDto[]`                        |\n| `ValidationErrorDto`                 | Class     | Swagger DTO for a structured validation error (`property`, `constraints`, `children`) |\n| `applyProblemDetailResponses`        | Function  | Auto-applies `@ApiResponse` decorators to all controllers via `DiscoveryService`      |\n| `ApplyProblemDetailResponsesOptions` | Interface | Options for `applyProblemDetailResponses`                                             |\n| `DiscoveredController`               | Interface | Structural controller view passed to the `filter` option                              |\n\n---\n\n## Example Responses\n\n### Basic 404 (no `typeBaseUri`)\n\n```typescript\nthrow new NotFoundException('User 42 not found');\n```\n\n```json\n{\n  \"type\": \"about:blank\",\n  \"title\": \"Not Found\",\n  \"status\": 404,\n  \"detail\": \"User 42 not found\"\n}\n```\n\n### Basic 404 (with `typeBaseUri` and `instanceStrategy: 'request-uri'`)\n\n```typescript\nRfc9457Module.forRoot({\n  typeBaseUri: 'https://api.example.com/problems',\n  instanceStrategy: 'request-uri',\n});\n\nthrow new NotFoundException('User 42 not found');\n// request path: /api/users/42\n```\n\n```json\n{\n  \"type\": \"https://api.example.com/problems/not-found\",\n  \"title\": \"Not Found\",\n  \"status\": 404,\n  \"detail\": \"User 42 not found\",\n  \"instance\": \"/api/users/42\"\n}\n```\n\n### Validation error (Tier 2 structured)\n\n```json\n{\n  \"type\": \"about:blank\",\n  \"title\": \"Bad Request\",\n  \"status\": 400,\n  \"detail\": \"Request validation failed\",\n  \"errors\": [\n    {\n      \"property\": \"email\",\n      \"constraints\": {\n        \"isEmail\": \"email must be an email\"\n      }\n    },\n    {\n      \"property\": \"address\",\n      \"children\": [\n        {\n          \"property\": \"zip\",\n          \"constraints\": {\n            \"isPostalCode\": \"zip must be a postal code\"\n          }\n        }\n      ]\n    }\n  ]\n}\n```\n\n### Custom problem type with `@ProblemType()`\n\n```typescript\n@ProblemType({\n  type: 'https://api.example.com/problems/insufficient-funds',\n  title: 'Insufficient Funds',\n  status: 422,\n})\nexport class InsufficientFundsException extends HttpException {\n  /* ... */\n}\n\nthrow new InsufficientFundsException(50, 100);\n```\n\n```json\n{\n  \"type\": \"https://api.example.com/problems/insufficient-funds\",\n  \"title\": \"Insufficient Funds\",\n  \"status\": 422,\n  \"detail\": \"Balance 50 is less than required 100\"\n}\n```\n\n### Catch-all 500 (with `catchAllExceptions: true`)\n\n```typescript\nthrow new Error('Connection refused');\n```\n\n```json\n{\n  \"type\": \"about:blank\",\n  \"title\": \"Internal Server Error\",\n  \"status\": 500\n}\n```\n\nInternal error messages are never included in the response to avoid leaking sensitive information.\n\n---\n\n## Examples\n\nSee the [nestjs-rfc9457-examples](https://github.com/camcima/nestjs-rfc9457-examples) repository for complete working NestJS applications demonstrating all features, including runnable demo scripts.\n\n---\n\n## Security\n\nVulnerability reports go through [GitHub Security Advisories](https://github.com/camcima/nestjs-rfc9457/security/advisories/new); see [SECURITY.md](SECURITY.md) for scope and what to include.\n\n### CI\n\n| Tool            | Purpose                                                  | Trigger                   |\n| --------------- | -------------------------------------------------------- | ------------------------- |\n| **CodeQL**      | Static analysis for security vulnerabilities             | Push, PR, weekly schedule |\n| **OSV-Scanner** | Dependency vulnerability scanning (production deps only) | Push, PR                  |\n| **Dependabot**  | Automated dependency and GitHub Actions updates          | Weekly PRs                |\n| **Codecov**     | Test coverage tracking                                   | Push, PR                  |\n\n### Local (via Lefthook)\n\n| Hook         | Tool                                             | Purpose                      |\n| ------------ | ------------------------------------------------ | ---------------------------- |\n| `pre-commit` | ESLint + Prettier                                | Code quality on staged files |\n| `pre-push`   | [Gitleaks](https://github.com/gitleaks/gitleaks) | Secret scanning before push  |\n\nGitleaks must be [installed locally](https://github.com/gitleaks/gitleaks#installing). The pre-push hook will skip if Gitleaks is not available.\n\n### Manual local checks\n\n```bash\n# Dependency audit (production only)\npnpm run audit:deps\n\n# Secret scanning\npnpm run audit:secrets\n\n# Full pnpm audit (all dependencies)\npnpm audit\n```\n\n---\n\n## Contributing\n\nContributions are welcome. Please open an issue before submitting a pull request for significant changes.\n\n```bash\n# Clone the repository\ngit clone https://github.com/camcima/nestjs-rfc9457.git\ncd nestjs-rfc9457\n\n# Install dependencies\npnpm install\n\n# Run unit tests\npnpm run test:unit\n\n# Run e2e tests\npnpm run test:e2e\n\n# Run all tests with coverage\npnpm run test:cov\n\n# Build\npnpm run build\n```\n\nThis project uses [Conventional Commits](https://www.conventionalcommits.org/) enforced by commitlint, and [Lefthook](https://github.com/evilmartians/lefthook) for pre-commit hooks (lint + format on staged files) plus a pre-push gitleaks scan of the commits being pushed.\n\n[CHANGELOG.md](CHANGELOG.md) is generated from those commit messages when a release is cut, so a pull request no longer needs a hand-written changelog entry — the commit subject is the entry. Entries written by hand before this switch are kept: the generator only prepends the new release section.\n\n---\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md"}