{"_id":"@bymax-one/nest-core","_rev":"16-f8784ba519b4820da067802ced8b92e6","name":"@bymax-one/nest-core","dist-tags":{"latest":"1.6.0"},"versions":{"1.0.0":{"name":"@bymax-one/nest-core","version":"1.0.0","keywords":["nestjs","error-envelope","exception-filter","request-timing","pagination","health-check","prometheus","metrics","typescript"],"author":{"name":"Bymax One","email":"support@bymax.one"},"license":"MIT","_id":"@bymax-one/nest-core@1.0.0","maintainers":[{"name":"bymax.one","email":"bymaxone.core@gmail.com"},{"name":"msalvatti","email":"msalvatti@gmail.com"}],"homepage":"https://github.com/bymaxone/nest-core#readme","bugs":{"url":"https://github.com/bymaxone/nest-core/issues"},"dist":{"shasum":"d890b351107f8f13939e543f23a32cb9fd8f6645","tarball":"https://registry.npmjs.org/@bymax-one/nest-core/-/nest-core-1.0.0.tgz","fileCount":16,"integrity":"sha512-lWkeAooD4xtCxQo7LT2SlR2Yvxx5cYOfaa5p9QfdmyU36Q/f6xxRB+XLP8v6eFU+GvTy8gRMmlAbKEi7/9rOfw==","signatures":[{"sig":"MEYCIQCk6Rxbi2CWllzhBvGBfGb+n5qkEOKCuFg5whKAAyZHqgIhAKeMPhRjEbfBNOyov5vD6XdG4TiNlJkpgN2QiX9VUxaT","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":199143},"main":"./dist/index.cjs","type":"module","_from":"file:bymax-one-nest-core-1.0.0.tgz","types":"./dist/index.d.cts","module":"./dist/index.mjs","engines":{"node":">=24.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./health":{"import":{"types":"./dist/health/index.d.ts","default":"./dist/health/index.mjs"},"require":{"types":"./dist/health/index.d.cts","default":"./dist/health/index.cjs"}},"./pagination":{"import":{"types":"./dist/pagination/index.d.ts","default":"./dist/pagination/index.mjs"},"require":{"types":"./dist/pagination/index.d.cts","default":"./dist/pagination/index.cjs"}},"./package.json":"./package.json"},"scripts":{"lint":"eslint --no-error-on-unmatched-pattern src scripts test","size":"node scripts/check-size.mjs","test":"jest","build":"pnpm clean && tsup","clean":"node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"","dogfood":"node scripts/dogfood-smoke-test.mjs","release":"npm publish --provenance --access public","lint:fix":"eslint --no-error-on-unmatched-pattern src scripts test --fix","mutation":"stryker run","test:cov":"jest --coverage","test:e2e":"jest --config jest.e2e.config.ts","typecheck":"tsc --noEmit","test:watch":"jest --watch","test:cov:all":"jest --config jest.coverage.config.ts --coverage","check:exports":"attw --pack . --profile strict","check:runtime":"node scripts/check-consumer-runtime.mjs","check:published":"node scripts/check-published-surface.mjs","mutation:dry-run":"stryker run --dryRunOnly","mutation:incremental":"stryker run --incremental"},"_npmUser":{"name":"bymax.one","email":"bymaxone.core@gmail.com"},"_resolved":"/private/var/folders/zf/_zr7t0ms60x6rcwj5zxk90cr0000gn/T/bc01d253f5146273c6255d7dd895aa75/bymax-one-nest-core-1.0.0.tgz","_integrity":"sha512-lWkeAooD4xtCxQo7LT2SlR2Yvxx5cYOfaa5p9QfdmyU36Q/f6xxRB+XLP8v6eFU+GvTy8gRMmlAbKEi7/9rOfw==","repository":{"url":"git+https://github.com/bymaxone/nest-core.git","type":"git"},"_npmVersion":"11.13.0","description":"Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints, and an optional Prometheus metrics endpoint.","directories":{},"lint-staged":{"*.{json,md,yml,yaml}":["prettier --write"],"*.{ts,tsx,js,mjs,cjs}":["eslint --fix","prettier --write"]},"sideEffects":false,"_nodeVersion":"24.16.0","dependencies":{},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"typesVersions":{"*":{"health":["./dist/health/index.d.cts"],"pagination":["./dist/pagination/index.d.cts"]}},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.4.2","rxjs":"^7.8.0","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.39.4","globals":"^17.6.0","ts-jest":"^29.4.9","ts-node":"^10.9.2","prettier":"^3.8.3","supertest":"^7.2.2","@eslint/js":"^9.39.4","typescript":"^5.9.3","@types/jest":"^30.0.0","@types/node":"^24","lint-staged":"^17.2.0","prom-client":"^15.1.3","@nestjs/core":"^11.1.20","@nestjs/common":"^11.1.20","@types/express":"^5.0.6","@commitlint/cli":"^21.2.1","@nestjs/testing":"^11.1.20","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","eslint-plugin-import":"^2.32.0","@arethetypeswrong/cli":"^0.18.2","@stryker-mutator/core":"^9","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","eslint-plugin-security":"^4.0.0","@nestjs/platform-express":"^11.1.20","@typescript-eslint/parser":"^8.59.3","@stryker-mutator/jest-runner":"^9","@commitlint/config-conventional":"^21.2.0","@typescript-eslint/eslint-plugin":"^8.59.3","eslint-import-resolver-typescript":"^4.4.4","@stryker-mutator/typescript-checker":"^9"},"peerDependencies":{"rxjs":"^7.0.0","prom-client":"^15.0.0","@nestjs/core":"^11.1.18","@nestjs/common":"^11.0.16","reflect-metadata":"^0.2.0"},"peerDependenciesMeta":{"prom-client":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nest-core_1.0.0_1785841936327_0.9858775573619079","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@bymax-one/nest-core","version":"1.0.1","keywords":["nestjs","error-envelope","exception-filter","request-timing","pagination","health-check","prometheus","metrics","typescript"],"author":{"name":"Bymax One","email":"support@bymax.one"},"license":"MIT","_id":"@bymax-one/nest-core@1.0.1","maintainers":[{"name":"bymax.one","email":"bymaxone.core@gmail.com"},{"name":"msalvatti","email":"msalvatti@gmail.com"}],"homepage":"https://github.com/bymaxone/nest-core#readme","bugs":{"url":"https://github.com/bymaxone/nest-core/issues"},"dist":{"shasum":"4fd1d1f846b1280a65574f5945897dbd335ed86c","tarball":"https://registry.npmjs.org/@bymax-one/nest-core/-/nest-core-1.0.1.tgz","fileCount":16,"integrity":"sha512-n+5v1GLQSx7hYUrYMyvzcCzisJ+syzFD1fbCHirJqATw1vJ2dn6exfPdWQhTHLbpseXhsG6xxer8uC6lV8tTLQ==","signatures":[{"sig":"MEYCIQCY+f60QGyYfO/d7Pjsm2C/RdRGOudvHtXWj3TzCwEtoAIhAPdJqIHYF3tGrYdptqw5Ey9N+gHZ/N8AmIqSzujntofW","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bymax-one%2fnest-core@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":206409},"main":"./dist/index.cjs","pnpm":{"overrides":{"qs":"^6.15.2","esbuild":"^0.28.1","fast-uri":"^3.1.5","brace-expansion@1":"^1.1.18","brace-expansion@2":"^2.1.4","brace-expansion@5":"^5.0.9"}},"type":"module","types":"./dist/index.d.cts","module":"./dist/index.mjs","engines":{"node":">=24.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./health":{"import":{"types":"./dist/health/index.d.ts","default":"./dist/health/index.mjs"},"require":{"types":"./dist/health/index.d.cts","default":"./dist/health/index.cjs"}},"./pagination":{"import":{"types":"./dist/pagination/index.d.ts","default":"./dist/pagination/index.mjs"},"require":{"types":"./dist/pagination/index.d.cts","default":"./dist/pagination/index.cjs"}},"./package.json":"./package.json"},"gitHead":"fb378d512c2c1dfd3d0a8e0aed5a7c65e6b28e70","scripts":{"lint":"eslint --no-error-on-unmatched-pattern src scripts test","size":"node scripts/check-size.mjs","test":"jest","build":"pnpm clean && tsup","clean":"node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"","dogfood":"node scripts/dogfood-smoke-test.mjs","prepare":"husky","release":"npm publish --provenance --access public","lint:fix":"eslint --no-error-on-unmatched-pattern src scripts test --fix","mutation":"stryker run","test:cov":"jest --coverage","test:e2e":"jest --config jest.e2e.config.ts","typecheck":"tsc --noEmit","test:watch":"jest --watch","test:cov:all":"jest --config jest.coverage.config.ts --coverage","check:exports":"attw --pack . --profile strict","check:runtime":"node scripts/check-consumer-runtime.mjs","prepublishOnly":"pnpm clean && pnpm typecheck && pnpm lint && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published","check:published":"node scripts/check-published-surface.mjs","mutation:dry-run":"stryker run --dryRunOnly","mutation:incremental":"stryker run --incremental"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:143c9547-d2b9-447f-8cde-9267ff22f966"}},"repository":{"url":"git+https://github.com/bymaxone/nest-core.git","type":"git"},"_npmVersion":"11.16.0","description":"Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints, and an optional Prometheus metrics endpoint.","directories":{},"lint-staged":{"*.{json,md,yml,yaml}":["prettier --write"],"*.{ts,tsx,js,mjs,cjs}":["eslint --fix","prettier --write"]},"sideEffects":false,"_nodeVersion":"24.18.0","dependencies":{},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"typesVersions":{"*":{"health":["./dist/health/index.d.cts"],"pagination":["./dist/pagination/index.d.cts"]}},"_hasShrinkwrap":false,"packageManager":"pnpm@10.8.1","devDependencies":{"jest":"^30.4.2","rxjs":"^7.8.0","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.39.4","globals":"^17.6.0","ts-jest":"^29.4.9","ts-node":"^10.9.2","prettier":"^3.8.3","supertest":"^7.2.2","@eslint/js":"^9.39.4","typescript":"^5.9.3","@types/jest":"^30.0.0","@types/node":"^24","lint-staged":"^17.2.0","prom-client":"^15.1.3","@nestjs/core":"^11.1.20","@nestjs/common":"^11.1.20","@types/express":"^5.0.6","@commitlint/cli":"^21.2.1","@nestjs/testing":"^11.1.20","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","eslint-plugin-import":"^2.32.0","@arethetypeswrong/cli":"^0.18.2","@stryker-mutator/core":"^9","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","eslint-plugin-security":"^4.0.0","@nestjs/platform-express":"^11.1.20","@typescript-eslint/parser":"^8.59.3","@stryker-mutator/jest-runner":"^9","@commitlint/config-conventional":"^21.2.0","@typescript-eslint/eslint-plugin":"^8.59.3","eslint-import-resolver-typescript":"^4.4.4","@stryker-mutator/typescript-checker":"^9"},"peerDependencies":{"rxjs":"^7.0.0","prom-client":"^15.0.0","@nestjs/core":"^11.1.18","@nestjs/common":"^11.0.16","reflect-metadata":"^0.2.0"},"peerDependenciesMeta":{"prom-client":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nest-core_1.0.1_1785844832920_0.21627694380572038","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@bymax-one/nest-core","version":"1.1.0","keywords":["nestjs","error-envelope","exception-filter","request-timing","pagination","health-check","prometheus","metrics","openapi","swagger","opentelemetry","tracing","typescript"],"author":{"name":"Bymax One","email":"support@bymax.one"},"license":"MIT","_id":"@bymax-one/nest-core@1.1.0","maintainers":[{"name":"bymax.one","email":"bymaxone.core@gmail.com"},{"name":"msalvatti","email":"msalvatti@gmail.com"}],"homepage":"https://github.com/bymaxone/nest-core#readme","bugs":{"url":"https://github.com/bymaxone/nest-core/issues"},"dist":{"shasum":"e83d286e233da7aec855a78bf5f1bbeb4ec4718f","tarball":"https://registry.npmjs.org/@bymax-one/nest-core/-/nest-core-1.1.0.tgz","fileCount":24,"integrity":"sha512-yG+HSsLU1HjaBl+FQyalmbI10JTtYuxReDePbgTeeoM1DOp88WaUqA8tBc0yEuE7RB9vuentuKJueJgISmjL8w==","signatures":[{"sig":"MEYCIQDHDNj0QMIR0WRMKJVoDMBWE2PEMhZoVkuyNfzGrfal1AIhAJhHH/iRx/VOM60QuXxmTaTLhkd3iCCFB5K/O7ECPlTi","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bymax-one%2fnest-core@1.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":317281},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.cts","module":"./dist/index.mjs","engines":{"node":">=24.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./health":{"import":{"types":"./dist/health/index.d.ts","default":"./dist/health/index.mjs"},"require":{"types":"./dist/health/index.d.cts","default":"./dist/health/index.cjs"}},"./metrics":{"import":{"types":"./dist/metrics/index.d.ts","default":"./dist/metrics/index.mjs"},"require":{"types":"./dist/metrics/index.d.cts","default":"./dist/metrics/index.cjs"}},"./openapi":{"import":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.mjs"},"require":{"types":"./dist/openapi/index.d.cts","default":"./dist/openapi/index.cjs"}},"./pagination":{"import":{"types":"./dist/pagination/index.d.ts","default":"./dist/pagination/index.mjs"},"require":{"types":"./dist/pagination/index.d.cts","default":"./dist/pagination/index.cjs"}},"./package.json":"./package.json"},"gitHead":"019bc7b4f060d4a36df13e48207de0de9899dcfb","scripts":{"lint":"eslint --no-error-on-unmatched-pattern src scripts test","size":"node scripts/check-size.mjs","test":"jest","build":"pnpm clean && tsup","clean":"node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"","dogfood":"node scripts/dogfood-smoke-test.mjs","prepare":"husky","release":"npm publish --provenance --access public","lint:fix":"eslint --no-error-on-unmatched-pattern src scripts test --fix","mutation":"stryker run","test:cov":"jest --coverage","test:e2e":"jest --config jest.e2e.config.ts","typecheck":"tsc --noEmit","test:watch":"jest --watch","test:cov:all":"jest --config jest.coverage.config.ts --coverage","check:exports":"attw --pack . --profile strict","check:runtime":"node scripts/check-consumer-runtime.mjs","prepublishOnly":"pnpm clean && pnpm typecheck && pnpm lint && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published","check:published":"node scripts/check-published-surface.mjs","mutation:dry-run":"stryker run --dryRunOnly","mutation:incremental":"stryker run --incremental"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:143c9547-d2b9-447f-8cde-9267ff22f966"}},"repository":{"url":"git+https://github.com/bymaxone/nest-core.git","type":"git"},"_npmVersion":"11.16.0","description":"Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints with indicator discovery, an optional Prometheus metrics endpoint with a contribution contract, OpenAPI","directories":{},"lint-staged":{"*.{json,md,yml,yaml}":["prettier --write"],"*.{ts,tsx,js,mjs,cjs}":["eslint --fix","prettier --write"]},"sideEffects":false,"_nodeVersion":"24.18.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"typesVersions":{"*":{"health":["./dist/health/index.d.cts"],"metrics":["./dist/metrics/index.d.cts"],"openapi":["./dist/openapi/index.d.cts"],"pagination":["./dist/pagination/index.d.cts"]}},"_hasShrinkwrap":false,"packageManager":"pnpm@11.20.0","devDependencies":{"jest":"^30.4.2","rxjs":"^7.8.0","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.39.4","globals":"^17.6.0","ts-jest":"^29.4.9","ts-node":"^10.9.2","prettier":"^3.8.3","supertest":"^7.2.2","@eslint/js":"^9.39.4","typescript":"^5.9.3","@types/jest":"^30.0.0","@types/node":"^24","lint-staged":"^17.2.0","prom-client":"^15.1.3","@nestjs/core":"^11.1.20","@nestjs/common":"^11.1.20","@types/express":"^5.0.6","@commitlint/cli":"^21.2.1","@nestjs/swagger":"^11.4.6","@nestjs/testing":"^11.1.20","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","@opentelemetry/api":"^1.9.1","eslint-plugin-import":"^2.32.0","@arethetypeswrong/cli":"^0.18.2","@stryker-mutator/core":"^9","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","eslint-plugin-security":"^4.0.0","@nestjs/platform-express":"^11.1.20","@typescript-eslint/parser":"^8.59.3","@stryker-mutator/jest-runner":"^9","@commitlint/config-conventional":"^21.2.0","@typescript-eslint/eslint-plugin":"^8.59.3","eslint-import-resolver-typescript":"^4.4.4","@opentelemetry/context-async-hooks":"^2.10.0","@stryker-mutator/typescript-checker":"^9"},"peerDependencies":{"rxjs":"^7.0.0","prom-client":"^15.0.0","@nestjs/core":"^11.1.18","@nestjs/common":"^11.0.16","@nestjs/swagger":"^11.0.0","reflect-metadata":"^0.2.0","@opentelemetry/api":"^1.9.0"},"peerDependenciesMeta":{"prom-client":{"optional":true},"@nestjs/swagger":{"optional":true},"@opentelemetry/api":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nest-core_1.1.0_1786015793359_0.3565905468445545","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"@bymax-one/nest-core","version":"1.1.1","keywords":["nestjs","error-envelope","exception-filter","request-timing","pagination","health-check","prometheus","metrics","openapi","swagger","opentelemetry","tracing","typescript"],"author":{"name":"Bymax One","email":"support@bymax.one"},"license":"MIT","_id":"@bymax-one/nest-core@1.1.1","maintainers":[{"name":"bymax.one","email":"bymaxone.core@gmail.com"},{"name":"msalvatti","email":"msalvatti@gmail.com"}],"homepage":"https://github.com/bymaxone/nest-core#readme","bugs":{"url":"https://github.com/bymaxone/nest-core/issues"},"dist":{"shasum":"f39952e6f48387ce0f2a9b9012008dbb3988fb06","tarball":"https://registry.npmjs.org/@bymax-one/nest-core/-/nest-core-1.1.1.tgz","fileCount":24,"integrity":"sha512-C0aB+RUL425QQZw/co9N9XNmpeQKFQHOuJjSdafNaAik31lArEJQqE/g83F4G8EN3UYY4Do/O+HzEnFk2tyJ9A==","signatures":[{"sig":"MEQCIGn+2nnJV7JeSTM8SOZrBbTSshJnpWt8H3oLlSzi8wrXAiBF3vgh2UOKMfNA1O3HXCn5ZEJo+Goe0ZembU1D3QZQqQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bymax-one%2fnest-core@1.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":321635},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.cts","module":"./dist/index.mjs","engines":{"node":">=24.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./health":{"import":{"types":"./dist/health/index.d.ts","default":"./dist/health/index.mjs"},"require":{"types":"./dist/health/index.d.cts","default":"./dist/health/index.cjs"}},"./metrics":{"import":{"types":"./dist/metrics/index.d.ts","default":"./dist/metrics/index.mjs"},"require":{"types":"./dist/metrics/index.d.cts","default":"./dist/metrics/index.cjs"}},"./openapi":{"import":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.mjs"},"require":{"types":"./dist/openapi/index.d.cts","default":"./dist/openapi/index.cjs"}},"./pagination":{"import":{"types":"./dist/pagination/index.d.ts","default":"./dist/pagination/index.mjs"},"require":{"types":"./dist/pagination/index.d.cts","default":"./dist/pagination/index.cjs"}},"./package.json":"./package.json"},"gitHead":"d6cc32a24a15d5b83f4d740535fc19d5aa0848d0","scripts":{"lint":"eslint --no-error-on-unmatched-pattern src scripts test","size":"node scripts/check-size.mjs","test":"jest","build":"pnpm clean && tsup","clean":"node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"","dogfood":"node scripts/dogfood-smoke-test.mjs","prepare":"husky","release":"npm publish --provenance --access public","lint:fix":"eslint --no-error-on-unmatched-pattern src scripts test --fix","mutation":"stryker run","test:cov":"jest --coverage","test:e2e":"jest --config jest.e2e.config.ts","typecheck":"tsc --noEmit","test:watch":"jest --watch","test:cov:all":"jest --config jest.coverage.config.ts --coverage","check:exports":"attw --pack . --profile strict","check:mutants":"node scripts/check-mutation-directives.mjs","check:runtime":"node scripts/check-consumer-runtime.mjs","prepublishOnly":"pnpm clean && pnpm typecheck && pnpm lint && pnpm check:mutants && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published","check:published":"node scripts/check-published-surface.mjs","mutation:dry-run":"stryker run --dryRunOnly","mutation:incremental":"stryker run --incremental"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:143c9547-d2b9-447f-8cde-9267ff22f966"}},"repository":{"url":"git+https://github.com/bymaxone/nest-core.git","type":"git"},"_npmVersion":"11.16.0","description":"Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints with indicator discovery, an optional Prometheus metrics endpoint with a contribution contract, OpenAPI","directories":{},"lint-staged":{"*.{json,md,yml,yaml}":["prettier --write"],"*.{ts,tsx,js,mjs,cjs}":["eslint --fix","prettier --write"]},"sideEffects":false,"_nodeVersion":"24.18.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"typesVersions":{"*":{"health":["./dist/health/index.d.cts"],"metrics":["./dist/metrics/index.d.cts"],"openapi":["./dist/openapi/index.d.cts"],"pagination":["./dist/pagination/index.d.cts"]}},"_hasShrinkwrap":false,"packageManager":"pnpm@11.20.0","devDependencies":{"jest":"^30.4.2","rxjs":"^7.8.0","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.39.4","globals":"^17.6.0","ts-jest":"^29.4.9","ts-node":"^10.9.2","prettier":"^3.8.3","supertest":"^7.2.2","@eslint/js":"^9.39.4","typescript":"^5.9.3","@types/jest":"^30.0.0","@types/node":"^24","lint-staged":"^17.2.0","prom-client":"^15.1.3","@nestjs/core":"^11.1.20","@nestjs/common":"^11.1.20","@types/express":"^5.0.6","@commitlint/cli":"^21.2.1","@nestjs/swagger":"^11.4.6","@nestjs/testing":"^11.1.20","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","@opentelemetry/api":"^1.9.1","eslint-plugin-import":"^2.32.0","@arethetypeswrong/cli":"^0.18.2","@stryker-mutator/core":"^9","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","eslint-plugin-security":"^4.0.0","@nestjs/platform-express":"^11.1.20","@typescript-eslint/parser":"^8.59.3","@stryker-mutator/jest-runner":"^9","@commitlint/config-conventional":"^21.2.0","@typescript-eslint/eslint-plugin":"^8.59.3","eslint-import-resolver-typescript":"^4.4.4","@opentelemetry/context-async-hooks":"^2.10.0","@stryker-mutator/typescript-checker":"^9"},"peerDependencies":{"rxjs":"^7.0.0","prom-client":"^15.0.0","@nestjs/core":"^11.1.18","@nestjs/common":"^11.0.16","@nestjs/swagger":"^11.0.0","reflect-metadata":"^0.2.0","@opentelemetry/api":"^1.9.0"},"peerDependenciesMeta":{"prom-client":{"optional":true},"@nestjs/swagger":{"optional":true},"@opentelemetry/api":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nest-core_1.1.1_1786194011138_0.8567286003943324","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@bymax-one/nest-core","version":"1.2.0","keywords":["nestjs","error-envelope","exception-filter","request-timing","pagination","health-check","prometheus","metrics","openapi","swagger","opentelemetry","tracing","typescript"],"author":{"name":"Bymax One","email":"support@bymax.one"},"license":"MIT","_id":"@bymax-one/nest-core@1.2.0","maintainers":[{"name":"bymax.one","email":"bymaxone.core@gmail.com"},{"name":"msalvatti","email":"msalvatti@gmail.com"}],"homepage":"https://github.com/bymaxone/nest-core#readme","bugs":{"url":"https://github.com/bymaxone/nest-core/issues"},"dist":{"shasum":"a17fcda44dc7029fc03802eb10babd1fa686e0b3","tarball":"https://registry.npmjs.org/@bymax-one/nest-core/-/nest-core-1.2.0.tgz","fileCount":24,"integrity":"sha512-ryFEuF5zJB8zDqw9unb5p/GsbKVwM09YlvsxrNYgKz3q2gbUd7KSBcMeKzZDh4f4c4JVlygqP7OS1TPh6aW1dw==","signatures":[{"sig":"MEYCIQD/nwrPcdEDNmqaVv5UTadPV2Eh31STaJhq9Gtc+MvyjgIhAJkxpH0CJze2pmgAH1ou1tvoGuL3GVy94Qszy3FDt7Sl","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bymax-one%2fnest-core@1.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":325419},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.cts","module":"./dist/index.mjs","engines":{"node":">=24.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./health":{"import":{"types":"./dist/health/index.d.ts","default":"./dist/health/index.mjs"},"require":{"types":"./dist/health/index.d.cts","default":"./dist/health/index.cjs"}},"./metrics":{"import":{"types":"./dist/metrics/index.d.ts","default":"./dist/metrics/index.mjs"},"require":{"types":"./dist/metrics/index.d.cts","default":"./dist/metrics/index.cjs"}},"./openapi":{"import":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.mjs"},"require":{"types":"./dist/openapi/index.d.cts","default":"./dist/openapi/index.cjs"}},"./pagination":{"import":{"types":"./dist/pagination/index.d.ts","default":"./dist/pagination/index.mjs"},"require":{"types":"./dist/pagination/index.d.cts","default":"./dist/pagination/index.cjs"}},"./package.json":"./package.json"},"gitHead":"70ac3f557e7fd607be460b3e8ab921fc0f4d63dc","scripts":{"lint":"eslint --no-error-on-unmatched-pattern src scripts test","size":"node scripts/check-size.mjs","test":"jest","build":"pnpm clean && tsup","clean":"node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"","dogfood":"node scripts/dogfood-smoke-test.mjs","prepare":"husky","release":"npm publish --provenance --access public","lint:fix":"eslint --no-error-on-unmatched-pattern src scripts test --fix","mutation":"stryker run","test:cov":"jest --coverage","test:e2e":"jest --config jest.e2e.config.ts","typecheck":"tsc --noEmit","test:watch":"jest --watch","test:cov:all":"jest --config jest.coverage.config.ts --coverage","check:exports":"attw --pack . --profile strict","check:mutants":"node scripts/check-mutation-directives.mjs","check:runtime":"node scripts/check-consumer-runtime.mjs","mutation:full":"node -e \"require('node:fs').rmSync('reports/stryker-incremental.json',{force:true,recursive:true})\" && stryker run","prepublishOnly":"pnpm clean && pnpm typecheck && pnpm lint && pnpm check:mutants && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published","check:published":"node scripts/check-published-surface.mjs","mutation:dry-run":"stryker run --dryRunOnly"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:143c9547-d2b9-447f-8cde-9267ff22f966"}},"repository":{"url":"git+https://github.com/bymaxone/nest-core.git","type":"git"},"_npmVersion":"11.16.0","description":"Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints with indicator discovery, an optional Prometheus metrics endpoint with a contribution contract, OpenAPI","directories":{},"lint-staged":{"*.{json,md,yml,yaml}":["prettier --write"],"*.{ts,tsx,js,mjs,cjs}":["eslint --fix","prettier --write"]},"sideEffects":false,"_nodeVersion":"24.18.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"typesVersions":{"*":{"health":["./dist/health/index.d.cts"],"metrics":["./dist/metrics/index.d.cts"],"openapi":["./dist/openapi/index.d.cts"],"pagination":["./dist/pagination/index.d.cts"]}},"_hasShrinkwrap":false,"packageManager":"pnpm@11.20.0","devDependencies":{"jest":"^30.4.2","rxjs":"^7.8.0","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.39.4","globals":"^17.6.0","ts-jest":"^29.4.9","ts-node":"^10.9.2","prettier":"^3.8.3","supertest":"^7.2.2","@eslint/js":"^9.39.4","typescript":"^5.9.3","@types/jest":"^30.0.0","@types/node":"^24","lint-staged":"^17.2.0","prom-client":"^15.1.3","@nestjs/core":"^11.1.20","@nestjs/common":"^11.1.20","@types/express":"^5.0.6","@commitlint/cli":"^21.2.1","@nestjs/swagger":"^11.4.6","@nestjs/testing":"^11.1.20","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","@opentelemetry/api":"^1.9.1","eslint-plugin-import":"^2.32.0","@arethetypeswrong/cli":"^0.18.2","@stryker-mutator/core":"^9","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","eslint-plugin-security":"^4.0.0","@nestjs/platform-express":"^11.1.20","@typescript-eslint/parser":"^8.59.3","@stryker-mutator/jest-runner":"^9","@commitlint/config-conventional":"^21.2.0","@typescript-eslint/eslint-plugin":"^8.59.3","eslint-import-resolver-typescript":"^4.4.4","@opentelemetry/context-async-hooks":"^2.10.0","@stryker-mutator/typescript-checker":"^9"},"peerDependencies":{"rxjs":"^7.0.0","prom-client":"^15.0.0","@nestjs/core":"^11.1.18","@nestjs/common":"^11.0.16","@nestjs/swagger":"^11.0.0","reflect-metadata":"^0.2.0","@opentelemetry/api":"^1.9.0"},"peerDependenciesMeta":{"prom-client":{"optional":true},"@nestjs/swagger":{"optional":true},"@opentelemetry/api":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nest-core_1.2.0_1786205916897_0.8985274735086417","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"@bymax-one/nest-core","version":"1.2.1","keywords":["nestjs","error-envelope","exception-filter","request-timing","pagination","health-check","prometheus","metrics","openapi","swagger","opentelemetry","tracing","typescript"],"author":{"name":"Bymax One","email":"support@bymax.one"},"license":"MIT","_id":"@bymax-one/nest-core@1.2.1","maintainers":[{"name":"bymax.one","email":"bymaxone.core@gmail.com"},{"name":"msalvatti","email":"msalvatti@gmail.com"}],"homepage":"https://github.com/bymaxone/nest-core#readme","bugs":{"url":"https://github.com/bymaxone/nest-core/issues"},"dist":{"shasum":"b147c9dcb0ee3dd1a1fae963158a6e7e8112d39c","tarball":"https://registry.npmjs.org/@bymax-one/nest-core/-/nest-core-1.2.1.tgz","fileCount":24,"integrity":"sha512-lx6gsHboOkhJeMfq/noCXihnCMN2GgAI6B4xPjhp1LP9Y/YpJPqBYkv8OOnCH5ndrDVarWHuQ8Mbc4uE0BykJA==","signatures":[{"sig":"MEUCIQCeK95vkSnfYxIsti1UY+w2/00OUcdu67MeDlce8KsrFQIgX2IzC260uwaTx+EfbG1gqxlTTOJzpzElhihNHFH6okE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bymax-one%2fnest-core@1.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":328316},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.cts","module":"./dist/index.mjs","engines":{"node":">=24.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./health":{"import":{"types":"./dist/health/index.d.ts","default":"./dist/health/index.mjs"},"require":{"types":"./dist/health/index.d.cts","default":"./dist/health/index.cjs"}},"./metrics":{"import":{"types":"./dist/metrics/index.d.ts","default":"./dist/metrics/index.mjs"},"require":{"types":"./dist/metrics/index.d.cts","default":"./dist/metrics/index.cjs"}},"./openapi":{"import":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.mjs"},"require":{"types":"./dist/openapi/index.d.cts","default":"./dist/openapi/index.cjs"}},"./pagination":{"import":{"types":"./dist/pagination/index.d.ts","default":"./dist/pagination/index.mjs"},"require":{"types":"./dist/pagination/index.d.cts","default":"./dist/pagination/index.cjs"}},"./package.json":"./package.json"},"gitHead":"e7ad0226a9854570baa2c4a6df749a1dba0ea894","scripts":{"lint":"eslint --no-error-on-unmatched-pattern src scripts test","size":"node scripts/check-size.mjs","test":"jest","build":"pnpm clean && tsup","clean":"node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"","dogfood":"node scripts/dogfood-smoke-test.mjs","prepare":"husky","release":"npm publish --provenance --access public","lint:fix":"eslint --no-error-on-unmatched-pattern src scripts test --fix","mutation":"stryker run","test:cov":"jest --coverage","test:e2e":"jest --config jest.e2e.config.ts","typecheck":"tsc --noEmit","test:watch":"jest --watch","test:cov:all":"jest --config jest.coverage.config.ts --coverage","check:exports":"attw --pack . --profile strict","check:mutants":"node scripts/check-mutation-directives.mjs","check:runtime":"node scripts/check-consumer-runtime.mjs","mutation:full":"node -e \"require('node:fs').rmSync('reports/stryker-incremental.json',{force:true,recursive:true})\" && stryker run","prepublishOnly":"pnpm clean && pnpm typecheck && pnpm lint && pnpm check:mutants && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published","check:published":"node scripts/check-published-surface.mjs","mutation:dry-run":"stryker run --dryRunOnly"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:143c9547-d2b9-447f-8cde-9267ff22f966"}},"repository":{"url":"git+https://github.com/bymaxone/nest-core.git","type":"git"},"_npmVersion":"11.16.0","description":"Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints with indicator discovery, an optional Prometheus metrics endpoint with a contribution contract, OpenAPI","directories":{},"lint-staged":{"*.{json,md,yml,yaml}":["prettier --write"],"*.{ts,tsx,js,mjs,cjs}":["eslint --fix","prettier --write"]},"sideEffects":false,"_nodeVersion":"24.18.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"typesVersions":{"*":{"health":["./dist/health/index.d.cts"],"metrics":["./dist/metrics/index.d.cts"],"openapi":["./dist/openapi/index.d.cts"],"pagination":["./dist/pagination/index.d.cts"]}},"_hasShrinkwrap":false,"packageManager":"pnpm@11.20.0","devDependencies":{"jest":"^30.4.2","rxjs":"^7.8.0","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.39.4","globals":"^17.6.0","ts-jest":"^29.4.9","ts-node":"^10.9.2","prettier":"^3.8.3","supertest":"^7.2.2","@eslint/js":"^9.39.4","typescript":"^5.9.3","@types/jest":"^30.0.0","@types/node":"^24","lint-staged":"^17.2.0","prom-client":"^15.1.3","@nestjs/core":"^11.1.20","@nestjs/common":"^11.1.20","@types/express":"^5.0.6","@commitlint/cli":"^21.2.1","@nestjs/swagger":"^11.4.6","@nestjs/testing":"^11.1.20","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","@opentelemetry/api":"^1.9.1","eslint-plugin-import":"^2.32.0","@arethetypeswrong/cli":"^0.18.2","@stryker-mutator/core":"^9","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","eslint-plugin-security":"^4.0.0","@nestjs/platform-express":"^11.1.20","@typescript-eslint/parser":"^8.59.3","@stryker-mutator/jest-runner":"^9","@commitlint/config-conventional":"^21.2.0","@typescript-eslint/eslint-plugin":"^8.59.3","eslint-import-resolver-typescript":"^4.4.4","@opentelemetry/context-async-hooks":"^2.10.0","@stryker-mutator/typescript-checker":"^9"},"peerDependencies":{"rxjs":"^7.0.0","prom-client":"^15.0.0","@nestjs/core":"^11.1.18","@nestjs/common":"^11.0.16","@nestjs/swagger":"^11.0.0","reflect-metadata":"^0.2.0","@opentelemetry/api":"^1.9.0"},"peerDependenciesMeta":{"prom-client":{"optional":true},"@nestjs/swagger":{"optional":true},"@opentelemetry/api":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nest-core_1.2.1_1786215315183_0.4191558538735787","host":"s3://npm-registry-packages-npm-production"}},"1.2.2":{"name":"@bymax-one/nest-core","version":"1.2.2","keywords":["nestjs","error-envelope","exception-filter","request-timing","pagination","health-check","prometheus","metrics","openapi","swagger","opentelemetry","tracing","typescript"],"author":{"name":"Bymax One","email":"support@bymax.one"},"license":"MIT","_id":"@bymax-one/nest-core@1.2.2","maintainers":[{"name":"bymax.one","email":"bymaxone.core@gmail.com"},{"name":"msalvatti","email":"msalvatti@gmail.com"}],"homepage":"https://github.com/bymaxone/nest-core#readme","bugs":{"url":"https://github.com/bymaxone/nest-core/issues"},"dist":{"shasum":"bb563ebc41ed5a19638a7c51343c5ae24800df0d","tarball":"https://registry.npmjs.org/@bymax-one/nest-core/-/nest-core-1.2.2.tgz","fileCount":24,"integrity":"sha512-1kESH4wuw5i4qa6y9VOvumNoZjS+EI9fvhtS70C+DfBoOVirA2wDqIY5qtyyrwh2+vDuWVeJQ4zCHZ53mlLNJg==","signatures":[{"sig":"MEUCIEcnr+lMELrd1fxnzlQSIbkxzc+B0ZBPsKhc18by7swoAiEAnkDkt2Eoa/zCkZyS0oeuYeCQisieYsZkLtCaAexIVxk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bymax-one%2fnest-core@1.2.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":335802},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.cts","module":"./dist/index.mjs","engines":{"node":">=24.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./health":{"import":{"types":"./dist/health/index.d.ts","default":"./dist/health/index.mjs"},"require":{"types":"./dist/health/index.d.cts","default":"./dist/health/index.cjs"}},"./metrics":{"import":{"types":"./dist/metrics/index.d.ts","default":"./dist/metrics/index.mjs"},"require":{"types":"./dist/metrics/index.d.cts","default":"./dist/metrics/index.cjs"}},"./openapi":{"import":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.mjs"},"require":{"types":"./dist/openapi/index.d.cts","default":"./dist/openapi/index.cjs"}},"./pagination":{"import":{"types":"./dist/pagination/index.d.ts","default":"./dist/pagination/index.mjs"},"require":{"types":"./dist/pagination/index.d.cts","default":"./dist/pagination/index.cjs"}},"./package.json":"./package.json"},"gitHead":"bccae544d83fe54291535980face0d3f631942a6","scripts":{"lint":"eslint --no-error-on-unmatched-pattern src scripts test","size":"node scripts/check-size.mjs","test":"jest","build":"pnpm clean && tsup","clean":"node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"","dogfood":"node scripts/dogfood-smoke-test.mjs","prepare":"husky","release":"npm publish --provenance --access public","lint:fix":"eslint --no-error-on-unmatched-pattern src scripts test --fix","mutation":"stryker run","test:cov":"jest --coverage","test:e2e":"jest --config jest.e2e.config.ts","typecheck":"tsc --noEmit","test:watch":"jest --watch","test:cov:all":"jest --config jest.coverage.config.ts --coverage","check:exports":"attw --pack . --profile strict","check:mutants":"node scripts/check-mutation-directives.mjs","check:runtime":"node scripts/check-consumer-runtime.mjs","mutation:full":"node -e \"require('node:fs').rmSync('reports/stryker-incremental.json',{force:true,recursive:true})\" && stryker run","prepublishOnly":"pnpm clean && pnpm typecheck && pnpm lint && pnpm check:mutants && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published","check:published":"node scripts/check-published-surface.mjs","mutation:dry-run":"stryker run --dryRunOnly"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:143c9547-d2b9-447f-8cde-9267ff22f966"}},"repository":{"url":"git+https://github.com/bymaxone/nest-core.git","type":"git"},"_npmVersion":"11.16.0","description":"Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints with indicator discovery, an optional Prometheus metrics endpoint with a contribution contract, OpenAPI","directories":{},"lint-staged":{"*.{json,md,yml,yaml}":["prettier --write"],"*.{ts,tsx,js,mjs,cjs}":["eslint --fix","prettier --write"]},"sideEffects":false,"_nodeVersion":"24.18.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"typesVersions":{"*":{"health":["./dist/health/index.d.cts"],"metrics":["./dist/metrics/index.d.cts"],"openapi":["./dist/openapi/index.d.cts"],"pagination":["./dist/pagination/index.d.cts"]}},"_hasShrinkwrap":false,"packageManager":"pnpm@11.20.0","devDependencies":{"jest":"^30.4.2","rxjs":"^7.8.0","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.39.4","globals":"^17.6.0","ts-jest":"^29.4.9","ts-node":"^10.9.2","prettier":"^3.8.3","supertest":"^7.2.2","@eslint/js":"^9.39.4","typescript":"^5.9.3","@types/jest":"^30.0.0","@types/node":"^24","lint-staged":"^17.2.0","prom-client":"^15.1.3","@nestjs/core":"^11.1.20","@nestjs/common":"^11.1.20","@types/express":"^5.0.6","@commitlint/cli":"^21.2.1","@nestjs/swagger":"^11.4.6","@nestjs/testing":"^11.1.20","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","@opentelemetry/api":"^1.9.1","eslint-plugin-import":"^2.32.0","@arethetypeswrong/cli":"^0.18.2","@stryker-mutator/core":"^9","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","eslint-plugin-security":"^4.0.0","@nestjs/platform-express":"^11.1.20","@typescript-eslint/parser":"^8.59.3","@stryker-mutator/jest-runner":"^9","@commitlint/config-conventional":"^21.2.0","@typescript-eslint/eslint-plugin":"^8.59.3","eslint-import-resolver-typescript":"^4.4.4","@opentelemetry/context-async-hooks":"^2.10.0","@stryker-mutator/typescript-checker":"^9"},"peerDependencies":{"rxjs":"^7.0.0","prom-client":"^15.0.0","@nestjs/core":"^11.1.18","@nestjs/common":"^11.0.16","@nestjs/swagger":"^11.0.0","reflect-metadata":"^0.2.0","@opentelemetry/api":"^1.9.0"},"peerDependenciesMeta":{"prom-client":{"optional":true},"@nestjs/swagger":{"optional":true},"@opentelemetry/api":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nest-core_1.2.2_1786381375582_0.4810429911407581","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@bymax-one/nest-core","version":"1.3.0","keywords":["nestjs","error-envelope","exception-filter","request-timing","pagination","health-check","prometheus","metrics","openapi","swagger","opentelemetry","tracing","typescript"],"author":{"name":"Bymax One","email":"support@bymax.one"},"license":"MIT","_id":"@bymax-one/nest-core@1.3.0","maintainers":[{"name":"bymax.one","email":"bymaxone.core@gmail.com"},{"name":"msalvatti","email":"msalvatti@gmail.com"}],"homepage":"https://github.com/bymaxone/nest-core#readme","bugs":{"url":"https://github.com/bymaxone/nest-core/issues"},"dist":{"shasum":"d15f5993b41c069fbc4cd9dce0396a9ee17c5eca","tarball":"https://registry.npmjs.org/@bymax-one/nest-core/-/nest-core-1.3.0.tgz","fileCount":24,"integrity":"sha512-REFNcdpua3O2rObF+JAOeHyFspiVikI7LU38ZAFoHKG9api4/AasNSe0Q7v534/SuUbbzVxC7FzzOvepnmRgVw==","signatures":[{"sig":"MEUCIQCIUGjcjkMsDHSCLwWO73CRl7dGb0dD/vKKLGBO8ZW3YgIgYd0zHURlXmYIbkbEWPmfwJu4jFItIYu6LaoeOcjco/U=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bymax-one%2fnest-core@1.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":336476},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.cts","module":"./dist/index.mjs","engines":{"node":">=24.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./health":{"import":{"types":"./dist/health/index.d.ts","default":"./dist/health/index.mjs"},"require":{"types":"./dist/health/index.d.cts","default":"./dist/health/index.cjs"}},"./metrics":{"import":{"types":"./dist/metrics/index.d.ts","default":"./dist/metrics/index.mjs"},"require":{"types":"./dist/metrics/index.d.cts","default":"./dist/metrics/index.cjs"}},"./openapi":{"import":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.mjs"},"require":{"types":"./dist/openapi/index.d.cts","default":"./dist/openapi/index.cjs"}},"./pagination":{"import":{"types":"./dist/pagination/index.d.ts","default":"./dist/pagination/index.mjs"},"require":{"types":"./dist/pagination/index.d.cts","default":"./dist/pagination/index.cjs"}},"./package.json":"./package.json"},"gitHead":"a42858197bb9d7cc169c55ef69f75c4978925b34","scripts":{"lint":"eslint --no-error-on-unmatched-pattern src scripts test","size":"node scripts/check-size.mjs","test":"jest","build":"pnpm clean && tsup","clean":"node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"","dogfood":"node scripts/dogfood-smoke-test.mjs","prepare":"husky","release":"npm publish --provenance --access public","lint:fix":"eslint --no-error-on-unmatched-pattern src scripts test --fix","mutation":"stryker run","test:cov":"jest --coverage","test:e2e":"jest --config jest.e2e.config.ts","typecheck":"tsc --noEmit","test:watch":"jest --watch","test:cov:all":"jest --config jest.coverage.config.ts --coverage","check:exports":"attw --pack . --profile strict","check:mutants":"node scripts/check-mutation-directives.mjs","check:runtime":"node scripts/check-consumer-runtime.mjs","mutation:full":"node -e \"require('node:fs').rmSync('reports/stryker-incremental.json',{force:true,recursive:true})\" && stryker run","prepublishOnly":"pnpm clean && pnpm typecheck && pnpm lint && pnpm check:mutants && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published","check:published":"node scripts/check-published-surface.mjs","mutation:dry-run":"stryker run --dryRunOnly"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:143c9547-d2b9-447f-8cde-9267ff22f966"}},"repository":{"url":"git+https://github.com/bymaxone/nest-core.git","type":"git"},"_npmVersion":"11.16.0","description":"Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints with indicator discovery, an optional Prometheus metrics endpoint with a contribution contract, OpenAPI","directories":{},"lint-staged":{"*.{json,md,yml,yaml}":["prettier --write"],"*.{ts,tsx,js,mjs,cjs}":["eslint --fix","prettier --write"]},"sideEffects":false,"_nodeVersion":"24.18.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"typesVersions":{"*":{"health":["./dist/health/index.d.cts"],"metrics":["./dist/metrics/index.d.cts"],"openapi":["./dist/openapi/index.d.cts"],"pagination":["./dist/pagination/index.d.cts"]}},"_hasShrinkwrap":false,"packageManager":"pnpm@11.20.0","devDependencies":{"jest":"^30.4.2","rxjs":"^7.8.0","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.39.4","globals":"^17.6.0","ts-jest":"^29.4.9","ts-node":"^10.9.2","prettier":"^3.8.3","supertest":"^7.2.2","@eslint/js":"^9.39.4","typescript":"^5.9.3","@types/jest":"^30.0.0","@types/node":"^24","lint-staged":"^17.2.0","prom-client":"^15.1.3","@nestjs/core":"^11.1.20","@nestjs/common":"^11.1.20","@types/express":"^5.0.6","@commitlint/cli":"^21.2.1","@nestjs/swagger":"^11.4.6","@nestjs/testing":"^11.1.20","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","@opentelemetry/api":"^1.9.1","eslint-plugin-import":"^2.32.0","@arethetypeswrong/cli":"^0.18.2","@stryker-mutator/core":"^9","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","eslint-plugin-security":"^4.0.0","@nestjs/platform-express":"^11.1.20","@typescript-eslint/parser":"^8.59.3","@stryker-mutator/jest-runner":"^9","@commitlint/config-conventional":"^21.2.0","@typescript-eslint/eslint-plugin":"^8.59.3","eslint-import-resolver-typescript":"^4.4.4","@opentelemetry/context-async-hooks":"^2.10.0","@stryker-mutator/typescript-checker":"^9"},"peerDependencies":{"rxjs":"^7.0.0","prom-client":"^15.0.0","@nestjs/core":"^11.1.18","@nestjs/common":"^11.0.16","@nestjs/swagger":"^11.0.0","reflect-metadata":"^0.2.0","@opentelemetry/api":"^1.9.0"},"peerDependenciesMeta":{"prom-client":{"optional":true},"@nestjs/swagger":{"optional":true},"@opentelemetry/api":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nest-core_1.3.0_1786446199923_0.7967086553052036","host":"s3://npm-registry-packages-npm-production"}},"1.3.1":{"name":"@bymax-one/nest-core","version":"1.3.1","keywords":["nestjs","error-envelope","exception-filter","request-timing","pagination","health-check","prometheus","metrics","openapi","swagger","opentelemetry","tracing","typescript"],"author":{"name":"Bymax One","email":"support@bymax.one"},"license":"MIT","_id":"@bymax-one/nest-core@1.3.1","maintainers":[{"name":"bymax.one","email":"bymaxone.core@gmail.com"},{"name":"msalvatti","email":"msalvatti@gmail.com"}],"homepage":"https://github.com/bymaxone/nest-core#readme","bugs":{"url":"https://github.com/bymaxone/nest-core/issues"},"dist":{"shasum":"bb2777825c1796b8207b15ecc6d4e9f16a6a875f","tarball":"https://registry.npmjs.org/@bymax-one/nest-core/-/nest-core-1.3.1.tgz","fileCount":24,"integrity":"sha512-EY5ARhmbab5oc/hO3GDMcjMiVMBRrsQnc6daksMKjfY9eNh7b+tq1jL16troVfsb0V14zFJEMdFI1q7ndlq+kA==","signatures":[{"sig":"MEQCIEJcjH0itecYZ8dWNnduVYh1RpqnlTustPItDt5AU3hnAiBAFdz4dGKoN2CF5W9vyljf4Wor+XCTQjYhRbJ/AJjPWQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bymax-one%2fnest-core@1.3.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":344678},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.cts","module":"./dist/index.mjs","engines":{"node":">=24.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./health":{"import":{"types":"./dist/health/index.d.ts","default":"./dist/health/index.mjs"},"require":{"types":"./dist/health/index.d.cts","default":"./dist/health/index.cjs"}},"./metrics":{"import":{"types":"./dist/metrics/index.d.ts","default":"./dist/metrics/index.mjs"},"require":{"types":"./dist/metrics/index.d.cts","default":"./dist/metrics/index.cjs"}},"./openapi":{"import":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.mjs"},"require":{"types":"./dist/openapi/index.d.cts","default":"./dist/openapi/index.cjs"}},"./pagination":{"import":{"types":"./dist/pagination/index.d.ts","default":"./dist/pagination/index.mjs"},"require":{"types":"./dist/pagination/index.d.cts","default":"./dist/pagination/index.cjs"}},"./package.json":"./package.json"},"gitHead":"ce579fe8b6ae4423fa109b39cdf6d65f1a7c6c77","scripts":{"lint":"eslint --no-error-on-unmatched-pattern src scripts test","size":"node scripts/check-size.mjs","test":"jest","build":"pnpm clean && tsup","clean":"node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"","dogfood":"node scripts/dogfood-smoke-test.mjs","prepare":"husky","release":"npm publish --provenance --access public","lint:fix":"eslint --no-error-on-unmatched-pattern src scripts test --fix","mutation":"stryker run","test:cov":"jest --coverage","test:e2e":"jest --config jest.e2e.config.ts","typecheck":"tsc --noEmit","test:watch":"jest --watch","test:cov:all":"jest --config jest.coverage.config.ts --coverage","check:exports":"attw --pack . --profile strict","check:mutants":"node scripts/check-mutation-directives.mjs","check:runtime":"node scripts/check-consumer-runtime.mjs","mutation:full":"node -e \"require('node:fs').rmSync('reports/stryker-incremental.json',{force:true,recursive:true})\" && stryker run","prepublishOnly":"pnpm clean && pnpm typecheck && pnpm lint && pnpm check:mutants && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published","check:published":"node scripts/check-published-surface.mjs","mutation:dry-run":"stryker run --dryRunOnly"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:143c9547-d2b9-447f-8cde-9267ff22f966"}},"repository":{"url":"git+https://github.com/bymaxone/nest-core.git","type":"git"},"_npmVersion":"11.16.0","description":"Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints with indicator discovery, an optional Prometheus metrics endpoint with a contribution contract, OpenAPI","directories":{},"lint-staged":{"*.{json,md,yml,yaml}":["prettier --write"],"*.{ts,tsx,js,mjs,cjs}":["eslint --fix","prettier --write"]},"sideEffects":false,"_nodeVersion":"24.18.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"typesVersions":{"*":{"health":["./dist/health/index.d.cts"],"metrics":["./dist/metrics/index.d.cts"],"openapi":["./dist/openapi/index.d.cts"],"pagination":["./dist/pagination/index.d.cts"]}},"_hasShrinkwrap":false,"packageManager":"pnpm@11.20.0","devDependencies":{"jest":"^30.4.2","rxjs":"^7.8.0","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.39.4","globals":"^17.6.0","ts-jest":"^29.4.9","ts-node":"^10.9.2","prettier":"^3.8.3","supertest":"^7.2.2","@eslint/js":"^9.39.4","typescript":"^5.9.3","@types/jest":"^30.0.0","@types/node":"^24","lint-staged":"^17.2.0","prom-client":"^15.1.3","@nestjs/core":"^11.1.20","@nestjs/common":"^11.1.20","@types/express":"^5.0.6","@commitlint/cli":"^21.2.1","@nestjs/swagger":"^11.4.6","@nestjs/testing":"^11.1.20","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","@opentelemetry/api":"^1.9.1","eslint-plugin-import":"^2.32.0","@arethetypeswrong/cli":"^0.18.2","@stryker-mutator/core":"^9","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","eslint-plugin-security":"^4.0.0","@nestjs/platform-express":"^11.1.20","@typescript-eslint/parser":"^8.59.3","@stryker-mutator/jest-runner":"^9","@commitlint/config-conventional":"^21.2.0","@typescript-eslint/eslint-plugin":"^8.59.3","eslint-import-resolver-typescript":"^4.4.4","@opentelemetry/context-async-hooks":"^2.10.0","@stryker-mutator/typescript-checker":"^9"},"peerDependencies":{"rxjs":"^7.0.0","prom-client":"^15.0.0","@nestjs/core":"^11.1.18","@nestjs/common":"^11.0.16","@nestjs/swagger":"^11.0.0","reflect-metadata":"^0.2.0","@opentelemetry/api":"^1.9.0"},"peerDependenciesMeta":{"prom-client":{"optional":true},"@nestjs/swagger":{"optional":true},"@opentelemetry/api":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nest-core_1.3.1_1786478416280_0.6460499524830492","host":"s3://npm-registry-packages-npm-production"}},"1.3.2":{"name":"@bymax-one/nest-core","version":"1.3.2","keywords":["nestjs","error-envelope","exception-filter","request-timing","pagination","health-check","prometheus","metrics","openapi","swagger","opentelemetry","tracing","typescript"],"author":{"name":"Bymax One","email":"support@bymax.one"},"license":"MIT","_id":"@bymax-one/nest-core@1.3.2","maintainers":[{"name":"bymax.one","email":"bymaxone.core@gmail.com"},{"name":"msalvatti","email":"msalvatti@gmail.com"}],"homepage":"https://github.com/bymaxone/nest-core#readme","bugs":{"url":"https://github.com/bymaxone/nest-core/issues"},"dist":{"shasum":"8bdf93d097eae0086a6b44ddec0e99c268b4ab19","tarball":"https://registry.npmjs.org/@bymax-one/nest-core/-/nest-core-1.3.2.tgz","fileCount":24,"integrity":"sha512-V4djuxmKEd2iagD2bXvXLdr7bVEOS+f8G25qu3hygw+YujHWYyWa1cEG3Sj/byIcaRZDNc7IXxb/I2ZqllV8nQ==","signatures":[{"sig":"MEUCIQCosCi0+3oorbbzCFMHtPui7VoTwSXvzLcZfgi8jV1XEgIgJ+RXI2lYhrKoHFNmokEv682FuaTOqb/vUPo5Mu5ygRM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bymax-one%2fnest-core@1.3.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":390800},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.cts","module":"./dist/index.mjs","engines":{"node":">=24.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./health":{"import":{"types":"./dist/health/index.d.ts","default":"./dist/health/index.mjs"},"require":{"types":"./dist/health/index.d.cts","default":"./dist/health/index.cjs"}},"./metrics":{"import":{"types":"./dist/metrics/index.d.ts","default":"./dist/metrics/index.mjs"},"require":{"types":"./dist/metrics/index.d.cts","default":"./dist/metrics/index.cjs"}},"./openapi":{"import":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.mjs"},"require":{"types":"./dist/openapi/index.d.cts","default":"./dist/openapi/index.cjs"}},"./pagination":{"import":{"types":"./dist/pagination/index.d.ts","default":"./dist/pagination/index.mjs"},"require":{"types":"./dist/pagination/index.d.cts","default":"./dist/pagination/index.cjs"}},"./package.json":"./package.json"},"gitHead":"d857e57e0d94646a3d948a4b0b3ef3126f7f5039","scripts":{"lint":"eslint --no-error-on-unmatched-pattern src scripts test","size":"node scripts/check-size.mjs","test":"jest","build":"pnpm clean && tsup","clean":"node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"","dogfood":"node scripts/dogfood-smoke-test.mjs","prepare":"husky","release":"npm publish --provenance --access public","lint:fix":"eslint --no-error-on-unmatched-pattern src scripts test --fix","mutation":"stryker run","test:cov":"jest --coverage","test:e2e":"jest --config jest.e2e.config.ts","typecheck":"tsc --noEmit","test:watch":"jest --watch","test:cov:all":"jest --config jest.coverage.config.ts --coverage","check:exports":"attw --pack . --profile strict","check:mutants":"node scripts/check-mutation-directives.mjs","check:runtime":"node scripts/check-consumer-runtime.mjs","mutation:full":"node -e \"require('node:fs').rmSync('reports/stryker-incremental.json',{force:true,recursive:true})\" && stryker run","prepublishOnly":"pnpm clean && pnpm typecheck && pnpm lint && pnpm check:mutants && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published","check:published":"node scripts/check-published-surface.mjs","mutation:dry-run":"stryker run --dryRunOnly"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:143c9547-d2b9-447f-8cde-9267ff22f966"}},"repository":{"url":"git+https://github.com/bymaxone/nest-core.git","type":"git"},"_npmVersion":"11.16.0","description":"Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints with indicator discovery, an optional Prometheus metrics endpoint with a contribution contract, OpenAPI","directories":{},"lint-staged":{"*.{json,md,yml,yaml}":["prettier --write"],"*.{ts,tsx,js,mjs,cjs}":["eslint --fix","prettier --write"]},"sideEffects":false,"_nodeVersion":"24.18.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"typesVersions":{"*":{"health":["./dist/health/index.d.cts"],"metrics":["./dist/metrics/index.d.cts"],"openapi":["./dist/openapi/index.d.cts"],"pagination":["./dist/pagination/index.d.cts"]}},"_hasShrinkwrap":false,"packageManager":"pnpm@11.20.0","devDependencies":{"jest":"^30.4.2","rxjs":"^7.8.0","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.39.4","globals":"^17.6.0","ts-jest":"^29.4.9","ts-node":"^10.9.2","prettier":"^3.8.3","supertest":"^7.2.2","@eslint/js":"^9.39.4","typescript":"^5.9.3","@types/jest":"^30.0.0","@types/node":"^24","lint-staged":"^17.2.0","prom-client":"^15.1.3","@nestjs/core":"^11.1.20","@nestjs/common":"^11.1.20","@types/express":"^5.0.6","@commitlint/cli":"^21.2.1","@nestjs/swagger":"^11.4.6","@nestjs/testing":"^11.1.20","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","@opentelemetry/api":"^1.9.1","eslint-plugin-import":"^2.32.0","@arethetypeswrong/cli":"^0.18.2","@stryker-mutator/core":"^9","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","eslint-plugin-security":"^4.0.0","@nestjs/platform-express":"^11.1.20","@typescript-eslint/parser":"^8.59.3","@stryker-mutator/jest-runner":"^9","@commitlint/config-conventional":"^21.2.0","@typescript-eslint/eslint-plugin":"^8.59.3","eslint-import-resolver-typescript":"^4.4.4","@opentelemetry/context-async-hooks":"^2.10.0","@stryker-mutator/typescript-checker":"^9"},"peerDependencies":{"rxjs":"^7.0.0","prom-client":"^15.0.0","@nestjs/core":"^11.1.18","@nestjs/common":"^11.0.16","@nestjs/swagger":"^11.0.0","reflect-metadata":"^0.2.0","@opentelemetry/api":"^1.9.0"},"peerDependenciesMeta":{"prom-client":{"optional":true},"@nestjs/swagger":{"optional":true},"@opentelemetry/api":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nest-core_1.3.2_1786565259098_0.9069471859368907","host":"s3://npm-registry-packages-npm-production"}},"1.4.0":{"name":"@bymax-one/nest-core","version":"1.4.0","keywords":["nestjs","error-envelope","exception-filter","request-timing","pagination","health-check","prometheus","metrics","openapi","swagger","opentelemetry","tracing","typescript"],"author":{"name":"Bymax One","email":"support@bymax.one"},"license":"MIT","_id":"@bymax-one/nest-core@1.4.0","maintainers":[{"name":"bymax.one","email":"bymaxone.core@gmail.com"},{"name":"msalvatti","email":"msalvatti@gmail.com"}],"homepage":"https://github.com/bymaxone/nest-core#readme","bugs":{"url":"https://github.com/bymaxone/nest-core/issues"},"dist":{"shasum":"73c2104c7bb5e294d7f9b90550547f2d31729e0b","tarball":"https://registry.npmjs.org/@bymax-one/nest-core/-/nest-core-1.4.0.tgz","fileCount":24,"integrity":"sha512-0NZ0fvPogMuQwKkyPmFpAfBY32j/XcFj26X66qkM4NX95gen/HelxM5KClRVq/tAUVhpCE0Qjt5CD3BYI0Ez1g==","signatures":[{"sig":"MEUCIHEvh4YTDvFqtsDjgZPgRa2O1Pv1qM+Vp2tzagqmHIAeAiEArc8IvESyDOWHu+bSmcfqr0K4tn43c79MzquwAfQmbFI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bymax-one%2fnest-core@1.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":479762},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.cts","module":"./dist/index.mjs","engines":{"node":">=24.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./health":{"import":{"types":"./dist/health/index.d.ts","default":"./dist/health/index.mjs"},"require":{"types":"./dist/health/index.d.cts","default":"./dist/health/index.cjs"}},"./metrics":{"import":{"types":"./dist/metrics/index.d.ts","default":"./dist/metrics/index.mjs"},"require":{"types":"./dist/metrics/index.d.cts","default":"./dist/metrics/index.cjs"}},"./openapi":{"import":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.mjs"},"require":{"types":"./dist/openapi/index.d.cts","default":"./dist/openapi/index.cjs"}},"./pagination":{"import":{"types":"./dist/pagination/index.d.ts","default":"./dist/pagination/index.mjs"},"require":{"types":"./dist/pagination/index.d.cts","default":"./dist/pagination/index.cjs"}},"./package.json":"./package.json"},"gitHead":"42cc3a438f3a7cdb08b59438d96b28ee535ce074","scripts":{"lint":"eslint --no-error-on-unmatched-pattern src scripts test","size":"node scripts/check-size.mjs","test":"jest","build":"pnpm clean && tsup","clean":"node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"","dogfood":"node scripts/dogfood-smoke-test.mjs","prepare":"husky","release":"npm publish --provenance --access public","lint:fix":"eslint --no-error-on-unmatched-pattern src scripts test --fix","mutation":"stryker run","test:cov":"jest --coverage","test:e2e":"jest --config jest.e2e.config.ts","typecheck":"tsc --noEmit","test:watch":"jest --watch","test:cov:all":"jest --config jest.coverage.config.ts --coverage","check:exports":"attw --pack . --profile strict","check:mutants":"node scripts/check-mutation-directives.mjs","check:runtime":"node scripts/check-consumer-runtime.mjs","mutation:full":"node -e \"require('node:fs').rmSync('reports/stryker-incremental.json',{force:true,recursive:true})\" && stryker run","prepublishOnly":"pnpm clean && pnpm typecheck && pnpm lint && pnpm check:mutants && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published","check:published":"node scripts/check-published-surface.mjs","mutation:dry-run":"stryker run --dryRunOnly"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:143c9547-d2b9-447f-8cde-9267ff22f966"}},"repository":{"url":"git+https://github.com/bymaxone/nest-core.git","type":"git"},"_npmVersion":"11.16.0","description":"Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints with indicator discovery, an optional Prometheus metrics endpoint with a contribution contract, OpenAPI","directories":{},"lint-staged":{"*.{json,md,yml,yaml}":["prettier --write"],"*.{ts,tsx,js,mjs,cjs}":["eslint --fix","prettier --write"]},"sideEffects":false,"_nodeVersion":"24.18.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"typesVersions":{"*":{"health":["./dist/health/index.d.cts"],"metrics":["./dist/metrics/index.d.cts"],"openapi":["./dist/openapi/index.d.cts"],"pagination":["./dist/pagination/index.d.cts"]}},"_hasShrinkwrap":false,"packageManager":"pnpm@11.20.0","devDependencies":{"jest":"^30.4.2","rxjs":"^7.8.0","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.39.4","fastify":"^5.11.3","globals":"^17.6.0","ts-jest":"^29.4.9","ts-node":"^10.9.2","prettier":"^3.8.3","supertest":"^7.2.2","@eslint/js":"^9.39.4","typescript":"^5.9.3","@types/jest":"^30.0.0","@types/node":"^24","lint-staged":"^17.2.0","prom-client":"^15.1.3","@nestjs/core":"^11.1.20","@nestjs/common":"^11.1.20","@types/express":"^5.0.6","@commitlint/cli":"^21.2.1","@nestjs/swagger":"^11.4.6","@nestjs/testing":"^11.1.20","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","@opentelemetry/api":"^1.9.1","eslint-plugin-import":"^2.32.0","@arethetypeswrong/cli":"^0.18.2","@stryker-mutator/core":"^9","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","eslint-plugin-security":"^4.0.0","@nestjs/platform-express":"^11.1.20","@nestjs/platform-fastify":"^11.1.29","@typescript-eslint/parser":"^8.59.3","@stryker-mutator/jest-runner":"^9","@commitlint/config-conventional":"^21.2.0","@typescript-eslint/eslint-plugin":"^8.59.3","eslint-import-resolver-typescript":"^4.4.4","@opentelemetry/context-async-hooks":"^2.10.0","@stryker-mutator/typescript-checker":"^9"},"peerDependencies":{"rxjs":"^7.0.0","prom-client":"^15.0.0","@nestjs/core":"^11.1.18","@nestjs/common":"^11.0.16","@nestjs/swagger":"^11.0.0","reflect-metadata":"^0.2.0","@opentelemetry/api":"^1.9.0"},"peerDependenciesMeta":{"prom-client":{"optional":true},"@nestjs/swagger":{"optional":true},"@opentelemetry/api":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nest-core_1.4.0_1786624790704_0.9975818020745704","host":"s3://npm-registry-packages-npm-production"}},"1.5.0":{"name":"@bymax-one/nest-core","version":"1.5.0","keywords":["nestjs","error-envelope","exception-filter","request-timing","pagination","health-check","prometheus","metrics","openapi","swagger","opentelemetry","tracing","typescript"],"author":{"name":"Bymax One","email":"support@bymax.one"},"license":"MIT","_id":"@bymax-one/nest-core@1.5.0","maintainers":[{"name":"bymax.one","email":"bymaxone.core@gmail.com"},{"name":"msalvatti","email":"msalvatti@gmail.com"}],"homepage":"https://github.com/bymaxone/nest-core#readme","bugs":{"url":"https://github.com/bymaxone/nest-core/issues"},"dist":{"shasum":"74e0974f59ede2e9b5a57795c509da009af422b3","tarball":"https://registry.npmjs.org/@bymax-one/nest-core/-/nest-core-1.5.0.tgz","fileCount":24,"integrity":"sha512-4pimX38ilS0c3I3N7iyEwY5kVI/QtLyuXtohCbTXYprerwNEg0Q1HiiZzLA6bcFKkXdTt2NnQUcMvOlXO4JaqA==","signatures":[{"sig":"MEQCIDu1Ly7QdimH9qJLjLBvBs6sHkLvjNMXNGGU3wY8mWLzAiAE5/n2W+0K8MKLH9Ao8QKM8MS1RkaO0OuIUBhNYAbUdg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bymax-one%2fnest-core@1.5.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":489124},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.cts","module":"./dist/index.mjs","engines":{"node":">=24.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./health":{"import":{"types":"./dist/health/index.d.ts","default":"./dist/health/index.mjs"},"require":{"types":"./dist/health/index.d.cts","default":"./dist/health/index.cjs"}},"./metrics":{"import":{"types":"./dist/metrics/index.d.ts","default":"./dist/metrics/index.mjs"},"require":{"types":"./dist/metrics/index.d.cts","default":"./dist/metrics/index.cjs"}},"./openapi":{"import":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.mjs"},"require":{"types":"./dist/openapi/index.d.cts","default":"./dist/openapi/index.cjs"}},"./pagination":{"import":{"types":"./dist/pagination/index.d.ts","default":"./dist/pagination/index.mjs"},"require":{"types":"./dist/pagination/index.d.cts","default":"./dist/pagination/index.cjs"}},"./package.json":"./package.json"},"gitHead":"31f1bd76b949abf57fe4935c45a3f2f675246f7b","scripts":{"lint":"eslint --no-error-on-unmatched-pattern src scripts test","size":"node scripts/check-size.mjs","test":"jest","build":"pnpm clean && tsup","clean":"node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"","dogfood":"node scripts/dogfood-smoke-test.mjs","prepare":"husky","release":"npm publish --provenance --access public","lint:fix":"eslint --no-error-on-unmatched-pattern src scripts test --fix","mutation":"stryker run","test:cov":"jest --coverage","test:e2e":"jest --config jest.e2e.config.ts","typecheck":"tsc --noEmit","test:watch":"jest --watch","test:cov:all":"jest --config jest.coverage.config.ts --coverage","check:exports":"attw --pack . --profile strict","check:mutants":"node scripts/check-mutation-directives.mjs","check:runtime":"node scripts/check-consumer-runtime.mjs","mutation:full":"node -e \"require('node:fs').rmSync('reports/stryker-incremental.json',{force:true,recursive:true})\" && stryker run","prepublishOnly":"pnpm clean && pnpm typecheck && pnpm lint && pnpm check:mutants && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published","check:published":"node scripts/check-published-surface.mjs","mutation:dry-run":"stryker run --dryRunOnly"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:143c9547-d2b9-447f-8cde-9267ff22f966"}},"repository":{"url":"git+https://github.com/bymaxone/nest-core.git","type":"git"},"_npmVersion":"11.17.0","description":"Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints with indicator discovery, an optional Prometheus metrics endpoint with a contribution contract, OpenAPI","directories":{},"lint-staged":{"*.{json,md,yml,yaml}":["prettier --write"],"*.{ts,tsx,js,mjs,cjs}":["eslint --fix","prettier --write"]},"sideEffects":false,"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"typesVersions":{"*":{"health":["./dist/health/index.d.cts"],"metrics":["./dist/metrics/index.d.cts"],"openapi":["./dist/openapi/index.d.cts"],"pagination":["./dist/pagination/index.d.cts"]}},"_hasShrinkwrap":false,"packageManager":"pnpm@11.20.0","devDependencies":{"jest":"^30.4.2","rxjs":"^7.8.0","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.39.4","fastify":"^5.11.3","globals":"^17.6.0","ts-jest":"^29.4.9","ts-node":"^10.9.2","prettier":"^3.8.3","supertest":"^7.2.2","@eslint/js":"^9.39.4","typescript":"^5.9.3","@types/jest":"^30.0.0","@types/node":"^24","lint-staged":"^17.2.0","prom-client":"^15.1.3","@nestjs/core":"^11.1.20","@nestjs/common":"^11.1.20","@types/express":"^5.0.6","@commitlint/cli":"^21.2.1","@nestjs/swagger":"^11.4.6","@nestjs/testing":"^11.1.20","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","@opentelemetry/api":"^1.9.1","eslint-plugin-import":"^2.32.0","@arethetypeswrong/cli":"^0.18.2","@stryker-mutator/core":"^9","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","eslint-plugin-security":"^4.0.0","@nestjs/platform-express":"^11.1.20","@nestjs/platform-fastify":"^11.1.29","@typescript-eslint/parser":"^8.59.3","@stryker-mutator/jest-runner":"^9","@commitlint/config-conventional":"^21.2.0","@typescript-eslint/eslint-plugin":"^8.59.3","eslint-import-resolver-typescript":"^4.4.4","@opentelemetry/context-async-hooks":"^2.10.0","@stryker-mutator/typescript-checker":"^9"},"peerDependencies":{"rxjs":"^7.0.0","prom-client":"^15.0.0","@nestjs/core":"^11.1.18","@nestjs/common":"^11.0.16","@nestjs/swagger":"^11.0.0","reflect-metadata":"^0.2.0","@opentelemetry/api":"^1.9.0"},"peerDependenciesMeta":{"prom-client":{"optional":true},"@nestjs/swagger":{"optional":true},"@opentelemetry/api":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nest-core_1.5.0_1786800937673_0.9636186489718377","host":"s3://npm-registry-packages-npm-production"}},"1.5.1":{"name":"@bymax-one/nest-core","version":"1.5.1","keywords":["nestjs","error-envelope","exception-filter","request-timing","pagination","health-check","prometheus","metrics","openapi","swagger","opentelemetry","tracing","typescript"],"author":{"name":"Bymax One","email":"support@bymax.one"},"license":"MIT","_id":"@bymax-one/nest-core@1.5.1","maintainers":[{"name":"bymax.one","email":"bymaxone.core@gmail.com"},{"name":"msalvatti","email":"msalvatti@gmail.com"}],"homepage":"https://github.com/bymaxone/nest-core#readme","bugs":{"url":"https://github.com/bymaxone/nest-core/issues"},"dist":{"shasum":"27313ab785c017ada6ce911d4eb827ee5eb5eb86","tarball":"https://registry.npmjs.org/@bymax-one/nest-core/-/nest-core-1.5.1.tgz","fileCount":24,"integrity":"sha512-vz24cAlFTTIfe35qbuJyVXxEDCly/PQPA8KMUpcaU44lb4a5TZinWouck7ObYlV59HfW6iA16UA4S4oNWfbWSg==","signatures":[{"sig":"MEYCIQDSlzCHTgPMdvIb7SRYEYYayOLzeXyXJJ44CJDzZvIzUgIhAOU5jGK7QJnx3MK5JIz2ZpnlcFBXHopDIchNp+tAAhxp","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bymax-one%2fnest-core@1.5.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":495564},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.cts","module":"./dist/index.mjs","engines":{"node":">=24.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./health":{"import":{"types":"./dist/health/index.d.ts","default":"./dist/health/index.mjs"},"require":{"types":"./dist/health/index.d.cts","default":"./dist/health/index.cjs"}},"./metrics":{"import":{"types":"./dist/metrics/index.d.ts","default":"./dist/metrics/index.mjs"},"require":{"types":"./dist/metrics/index.d.cts","default":"./dist/metrics/index.cjs"}},"./openapi":{"import":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.mjs"},"require":{"types":"./dist/openapi/index.d.cts","default":"./dist/openapi/index.cjs"}},"./pagination":{"import":{"types":"./dist/pagination/index.d.ts","default":"./dist/pagination/index.mjs"},"require":{"types":"./dist/pagination/index.d.cts","default":"./dist/pagination/index.cjs"}},"./package.json":"./package.json"},"gitHead":"8a36b6db3e299ae6a06119c8f8a847cb2e2c15dc","scripts":{"lint":"eslint --no-error-on-unmatched-pattern src scripts test","size":"node scripts/check-size.mjs","test":"jest","build":"pnpm clean && tsup","clean":"node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"","dogfood":"node scripts/dogfood-smoke-test.mjs","prepare":"husky","release":"npm publish --provenance --access public","lint:fix":"eslint --no-error-on-unmatched-pattern src scripts test --fix","mutation":"stryker run","test:cov":"jest --coverage","test:e2e":"jest --config jest.e2e.config.ts","typecheck":"tsc --noEmit","test:watch":"jest --watch","test:cov:all":"jest --config jest.coverage.config.ts --coverage","check:exports":"attw --pack . --profile strict","check:mutants":"node scripts/check-mutation-directives.mjs","check:runtime":"node scripts/check-consumer-runtime.mjs","mutation:full":"node -e \"require('node:fs').rmSync('reports/stryker-incremental.json',{force:true,recursive:true})\" && stryker run","prepublishOnly":"pnpm clean && pnpm typecheck && pnpm lint && pnpm check:mutants && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published","check:published":"node scripts/check-published-surface.mjs","mutation:dry-run":"stryker run --dryRunOnly"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:143c9547-d2b9-447f-8cde-9267ff22f966"}},"repository":{"url":"git+https://github.com/bymaxone/nest-core.git","type":"git"},"_npmVersion":"11.17.0","description":"Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints with indicator discovery, an optional Prometheus metrics endpoint with a contribution contract, OpenAPI","directories":{},"lint-staged":{"*.{json,md,yml,yaml}":["prettier --write"],"*.{ts,tsx,js,mjs,cjs}":["eslint --fix","prettier --write"]},"sideEffects":false,"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"typesVersions":{"*":{"health":["./dist/health/index.d.cts"],"metrics":["./dist/metrics/index.d.cts"],"openapi":["./dist/openapi/index.d.cts"],"pagination":["./dist/pagination/index.d.cts"]}},"_hasShrinkwrap":false,"packageManager":"pnpm@11.20.0","devDependencies":{"jest":"^30.4.2","rxjs":"^7.8.0","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.39.4","fastify":"^5.11.3","globals":"^17.6.0","ts-jest":"^29.4.9","ts-node":"^10.9.2","prettier":"^3.8.3","supertest":"^7.2.2","@eslint/js":"^9.39.4","typescript":"^5.9.3","@types/jest":"^30.0.0","@types/node":"^24","lint-staged":"^17.2.0","prom-client":"^15.1.3","@nestjs/core":"^11.1.20","@nestjs/common":"^11.1.20","@types/express":"^5.0.6","@commitlint/cli":"^21.2.1","@nestjs/swagger":"^11.4.6","@nestjs/testing":"^11.1.20","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","@opentelemetry/api":"^1.9.1","eslint-plugin-import":"^2.32.0","@arethetypeswrong/cli":"^0.18.2","@stryker-mutator/core":"^9","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","eslint-plugin-security":"^4.0.0","@nestjs/platform-express":"^11.1.20","@nestjs/platform-fastify":"^11.1.29","@typescript-eslint/parser":"^8.59.3","@stryker-mutator/jest-runner":"^9","@commitlint/config-conventional":"^21.2.0","@typescript-eslint/eslint-plugin":"^8.59.3","eslint-import-resolver-typescript":"^4.4.4","@opentelemetry/context-async-hooks":"^2.10.0","@stryker-mutator/typescript-checker":"^9"},"peerDependencies":{"rxjs":"^7.0.0","prom-client":"^15.0.0","@nestjs/core":"^11.1.18","@nestjs/common":"^11.0.16","@nestjs/swagger":"^11.0.0","reflect-metadata":"^0.2.0","@opentelemetry/api":"^1.9.0"},"peerDependenciesMeta":{"prom-client":{"optional":true},"@nestjs/swagger":{"optional":true},"@opentelemetry/api":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nest-core_1.5.1_1786807152480_0.5226772640795596","host":"s3://npm-registry-packages-npm-production"}},"1.5.2":{"name":"@bymax-one/nest-core","version":"1.5.2","keywords":["nestjs","error-envelope","exception-filter","request-timing","pagination","health-check","prometheus","metrics","openapi","swagger","opentelemetry","tracing","typescript"],"author":{"name":"Bymax One","email":"support@bymax.one"},"license":"MIT","_id":"@bymax-one/nest-core@1.5.2","maintainers":[{"name":"bymax.one","email":"bymaxone.core@gmail.com"},{"name":"msalvatti","email":"msalvatti@gmail.com"}],"homepage":"https://github.com/bymaxone/nest-core#readme","bugs":{"url":"https://github.com/bymaxone/nest-core/issues"},"dist":{"shasum":"8f5530cebae4b927aaae157508128e69c17d985e","tarball":"https://registry.npmjs.org/@bymax-one/nest-core/-/nest-core-1.5.2.tgz","fileCount":24,"integrity":"sha512-u20fiGmGzaD+d0wqMql6EyCCRWpZ39wK5fJ6lhg3ayrXmblmEHPSWmEG6SNeqTZYZ3ZxXTl96QHZerH9/NI3Cw==","signatures":[{"sig":"MEUCIAJLQXTej4EHqiskMGAthqLTGvAqydvRWasxeXH7auZiAiEAkyKz8P6aTv8355HAwBJU1yJfmB0wJZsgyoXQWlTHsJk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bymax-one%2fnest-core@1.5.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":505441},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.cts","module":"./dist/index.mjs","engines":{"node":">=24.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./health":{"import":{"types":"./dist/health/index.d.ts","default":"./dist/health/index.mjs"},"require":{"types":"./dist/health/index.d.cts","default":"./dist/health/index.cjs"}},"./metrics":{"import":{"types":"./dist/metrics/index.d.ts","default":"./dist/metrics/index.mjs"},"require":{"types":"./dist/metrics/index.d.cts","default":"./dist/metrics/index.cjs"}},"./openapi":{"import":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.mjs"},"require":{"types":"./dist/openapi/index.d.cts","default":"./dist/openapi/index.cjs"}},"./pagination":{"import":{"types":"./dist/pagination/index.d.ts","default":"./dist/pagination/index.mjs"},"require":{"types":"./dist/pagination/index.d.cts","default":"./dist/pagination/index.cjs"}},"./package.json":"./package.json"},"gitHead":"6a2d46af7d1813bb8b416c13f00bded78ab1284a","scripts":{"lint":"eslint --no-error-on-unmatched-pattern src scripts test","size":"node scripts/check-size.mjs","test":"jest","build":"pnpm clean && tsup","clean":"node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"","dogfood":"node scripts/dogfood-smoke-test.mjs","prepare":"husky","release":"npm publish --provenance --access public","lint:fix":"eslint --no-error-on-unmatched-pattern src scripts test --fix","mutation":"stryker run","test:cov":"jest --coverage","test:e2e":"jest --config jest.e2e.config.ts","typecheck":"tsc --noEmit","test:watch":"jest --watch","test:cov:all":"jest --config jest.coverage.config.ts --coverage","check:exports":"attw --pack . --profile strict","check:mutants":"node scripts/check-mutation-directives.mjs","check:runtime":"node scripts/check-consumer-runtime.mjs","mutation:full":"node -e \"require('node:fs').rmSync('reports/stryker-incremental.json',{force:true,recursive:true})\" && stryker run","prepublishOnly":"pnpm clean && pnpm typecheck && pnpm lint && pnpm check:mutants && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published","check:published":"node scripts/check-published-surface.mjs","mutation:dry-run":"stryker run --dryRunOnly"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:143c9547-d2b9-447f-8cde-9267ff22f966"}},"repository":{"url":"git+https://github.com/bymaxone/nest-core.git","type":"git"},"_npmVersion":"11.17.0","description":"Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints with indicator discovery, an optional Prometheus metrics endpoint with a contribution contract, OpenAPI","directories":{},"lint-staged":{"*.{json,md,yml,yaml}":["prettier --write"],"*.{ts,tsx,js,mjs,cjs}":["eslint --fix","prettier --write"]},"sideEffects":false,"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"typesVersions":{"*":{"health":["./dist/health/index.d.cts"],"metrics":["./dist/metrics/index.d.cts"],"openapi":["./dist/openapi/index.d.cts"],"pagination":["./dist/pagination/index.d.cts"]}},"_hasShrinkwrap":false,"packageManager":"pnpm@11.20.0","devDependencies":{"jest":"^30.4.2","rxjs":"^7.8.0","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.39.4","fastify":"^5.11.3","globals":"^17.6.0","ts-jest":"^29.4.9","ts-node":"^10.9.2","prettier":"^3.8.3","supertest":"^7.2.2","@eslint/js":"^9.39.4","typescript":"^5.9.3","@types/jest":"^30.0.0","@types/node":"^24","lint-staged":"^17.2.0","prom-client":"^15.1.3","@nestjs/core":"^11.1.20","@nestjs/common":"^11.1.20","@types/express":"^5.0.6","@commitlint/cli":"^21.2.1","@nestjs/swagger":"^11.4.6","@nestjs/testing":"^11.1.20","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","@opentelemetry/api":"^1.9.1","eslint-plugin-import":"^2.32.0","@arethetypeswrong/cli":"^0.18.2","@stryker-mutator/core":"^9","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","eslint-plugin-security":"^4.0.0","@nestjs/platform-express":"^11.1.20","@nestjs/platform-fastify":"^11.1.29","@typescript-eslint/parser":"^8.59.3","@stryker-mutator/jest-runner":"^9","@commitlint/config-conventional":"^21.2.0","@typescript-eslint/eslint-plugin":"^8.59.3","eslint-import-resolver-typescript":"^4.4.4","@opentelemetry/context-async-hooks":"^2.10.0","@stryker-mutator/typescript-checker":"^9"},"peerDependencies":{"rxjs":"^7.0.0","prom-client":"^15.0.0","@nestjs/core":"^11.1.18","@nestjs/common":"^11.0.16","@nestjs/swagger":"^11.0.0","reflect-metadata":"^0.2.0","@opentelemetry/api":"^1.9.0"},"peerDependenciesMeta":{"prom-client":{"optional":true},"@nestjs/swagger":{"optional":true},"@opentelemetry/api":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nest-core_1.5.2_1786833961972_0.6640075099160252","host":"s3://npm-registry-packages-npm-production"}},"1.5.3":{"name":"@bymax-one/nest-core","version":"1.5.3","keywords":["nestjs","error-envelope","exception-filter","request-timing","pagination","health-check","prometheus","metrics","openapi","swagger","opentelemetry","tracing","typescript"],"author":{"name":"Bymax One","email":"support@bymax.one"},"license":"MIT","_id":"@bymax-one/nest-core@1.5.3","maintainers":[{"name":"bymax.one","email":"bymaxone.core@gmail.com"},{"name":"msalvatti","email":"msalvatti@gmail.com"}],"homepage":"https://github.com/bymaxone/nest-core#readme","bugs":{"url":"https://github.com/bymaxone/nest-core/issues"},"dist":{"shasum":"7ffbfdf2a590f41a3bc32672b9e7642b500daf92","tarball":"https://registry.npmjs.org/@bymax-one/nest-core/-/nest-core-1.5.3.tgz","fileCount":24,"integrity":"sha512-F1Cs1rymqgABVf3OaaWyr4nlHkIx+2V6146O0q863IVjnfeDYI5AxswuaLxKfvtIyay2MXLssSpcPgLPJIyJXg==","signatures":[{"sig":"MEUCIQDtfDG0bDoU3aeF4GQICVl46z4ERnEWhypOYvGWnue+YQIgb8tfZIcMi4CY05zjqRWvJHVZqayycLN1T+q2t9aTQgk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bymax-one%2fnest-core@1.5.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":523289},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.cts","module":"./dist/index.mjs","engines":{"node":">=24.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./health":{"import":{"types":"./dist/health/index.d.ts","default":"./dist/health/index.mjs"},"require":{"types":"./dist/health/index.d.cts","default":"./dist/health/index.cjs"}},"./metrics":{"import":{"types":"./dist/metrics/index.d.ts","default":"./dist/metrics/index.mjs"},"require":{"types":"./dist/metrics/index.d.cts","default":"./dist/metrics/index.cjs"}},"./openapi":{"import":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.mjs"},"require":{"types":"./dist/openapi/index.d.cts","default":"./dist/openapi/index.cjs"}},"./pagination":{"import":{"types":"./dist/pagination/index.d.ts","default":"./dist/pagination/index.mjs"},"require":{"types":"./dist/pagination/index.d.cts","default":"./dist/pagination/index.cjs"}},"./package.json":"./package.json"},"gitHead":"b2e9e955e7b2af74d201e6195ca26da397fc17a0","scripts":{"lint":"eslint --no-error-on-unmatched-pattern src scripts test","size":"node scripts/check-size.mjs","test":"jest","build":"pnpm clean && tsup","clean":"node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"","dogfood":"node scripts/dogfood-smoke-test.mjs","prepare":"husky","release":"npm publish --provenance --access public","lint:fix":"eslint --no-error-on-unmatched-pattern src scripts test --fix","mutation":"stryker run","test:cov":"jest --coverage","test:e2e":"jest --config jest.e2e.config.ts","typecheck":"tsc --noEmit","test:watch":"jest --watch","test:cov:all":"jest --config jest.coverage.config.ts --coverage","check:exports":"attw --pack . --profile strict","check:mutants":"node scripts/check-mutation-directives.mjs","check:runtime":"node scripts/check-consumer-runtime.mjs","mutation:full":"node -e \"require('node:fs').rmSync('reports/stryker-incremental.json',{force:true,recursive:true})\" && stryker run","prepublishOnly":"pnpm clean && pnpm typecheck && pnpm lint && pnpm check:mutants && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published","check:published":"node scripts/check-published-surface.mjs","mutation:dry-run":"stryker run --dryRunOnly"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:143c9547-d2b9-447f-8cde-9267ff22f966"}},"repository":{"url":"git+https://github.com/bymaxone/nest-core.git","type":"git"},"_npmVersion":"11.17.0","description":"Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints with indicator discovery, an optional Prometheus metrics endpoint with a contribution contract, OpenAPI","directories":{},"lint-staged":{"*.{json,md,yml,yaml}":["prettier --write"],"*.{ts,tsx,js,mjs,cjs}":["eslint --fix","prettier --write"]},"sideEffects":false,"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/","provenance":true},"typesVersions":{"*":{"health":["./dist/health/index.d.cts"],"metrics":["./dist/metrics/index.d.cts"],"openapi":["./dist/openapi/index.d.cts"],"pagination":["./dist/pagination/index.d.cts"]}},"_hasShrinkwrap":false,"packageManager":"pnpm@11.20.0","devDependencies":{"jest":"^30.4.2","rxjs":"^7.8.0","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.39.4","fastify":"^5.11.3","globals":"^17.6.0","ts-jest":"^29.4.9","ts-node":"^10.9.2","prettier":"^3.8.3","supertest":"^7.2.2","@eslint/js":"^9.39.4","typescript":"^5.9.3","@types/jest":"^30.0.0","@types/node":"^24","lint-staged":"^17.2.0","prom-client":"^15.1.3","@nestjs/core":"^11.1.20","@nestjs/common":"^11.1.20","@types/express":"^5.0.6","@commitlint/cli":"^21.2.1","@nestjs/swagger":"^11.4.6","@nestjs/testing":"^11.1.20","@types/supertest":"^7.2.0","reflect-metadata":"^0.2.2","@opentelemetry/api":"^1.9.1","eslint-plugin-import":"^2.32.0","@arethetypeswrong/cli":"^0.18.2","@stryker-mutator/core":"^9","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","eslint-plugin-security":"^4.0.0","@nestjs/platform-express":"^11.1.20","@nestjs/platform-fastify":"^11.1.29","@typescript-eslint/parser":"^8.59.3","@stryker-mutator/jest-runner":"^9","@commitlint/config-conventional":"^21.2.0","@typescript-eslint/eslint-plugin":"^8.59.3","eslint-import-resolver-typescript":"^4.4.4","@opentelemetry/context-async-hooks":"^2.10.0","@stryker-mutator/typescript-checker":"^9"},"peerDependencies":{"rxjs":"^7.0.0","prom-client":"^15.0.0","@nestjs/core":"^11.1.18","@nestjs/common":"^11.0.16","@nestjs/swagger":"^11.0.0","reflect-metadata":"^0.2.0","@opentelemetry/api":"^1.9.0"},"peerDependenciesMeta":{"prom-client":{"optional":true},"@nestjs/swagger":{"optional":true},"@opentelemetry/api":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nest-core_1.5.3_1787089944546_0.17809219322190284","host":"s3://npm-registry-packages-npm-production"}},"1.6.0":{"name":"@bymax-one/nest-core","version":"1.6.0","description":"Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints with indicator discovery, an optional Prometheus metrics endpoint with a contribution contract, OpenAPI","author":{"name":"Bymax One","email":"support@bymax.one"},"license":"MIT","homepage":"https://github.com/bymaxone/nest-core#readme","repository":{"type":"git","url":"git+https://github.com/bymaxone/nest-core.git"},"bugs":{"url":"https://github.com/bymaxone/nest-core/issues"},"type":"module","sideEffects":false,"main":"./dist/index.cjs","types":"./dist/index.d.cts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./pagination":{"import":{"types":"./dist/pagination/index.d.ts","default":"./dist/pagination/index.mjs"},"require":{"types":"./dist/pagination/index.d.cts","default":"./dist/pagination/index.cjs"}},"./health":{"import":{"types":"./dist/health/index.d.ts","default":"./dist/health/index.mjs"},"require":{"types":"./dist/health/index.d.cts","default":"./dist/health/index.cjs"}},"./metrics":{"import":{"types":"./dist/metrics/index.d.ts","default":"./dist/metrics/index.mjs"},"require":{"types":"./dist/metrics/index.d.cts","default":"./dist/metrics/index.cjs"}},"./openapi":{"import":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.mjs"},"require":{"types":"./dist/openapi/index.d.cts","default":"./dist/openapi/index.cjs"}},"./package.json":"./package.json"},"scripts":{"build":"pnpm clean && tsup","check:exports":"attw --pack . --profile strict","check:mutants":"node scripts/check-mutation-directives.mjs","check:published":"node scripts/check-published-surface.mjs","check:runtime":"node scripts/check-consumer-runtime.mjs","clean":"node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"","dogfood":"node scripts/dogfood-smoke-test.mjs","lint":"eslint --no-error-on-unmatched-pattern src scripts test","lint:fix":"eslint --no-error-on-unmatched-pattern src scripts test --fix","mutation":"stryker run","mutation:full":"node -e \"require('node:fs').rmSync('reports/stryker-incremental.json',{force:true,recursive:true})\" && stryker run","mutation:dry-run":"stryker run --dryRunOnly","prepare":"husky","prepublishOnly":"pnpm clean && pnpm typecheck && pnpm lint && pnpm check:mutants && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published","release":"npm publish --provenance --access public","size":"node scripts/check-size.mjs","test":"jest","test:cov":"jest --coverage","test:cov:all":"jest --config jest.coverage.config.ts --coverage","test:e2e":"jest --config jest.e2e.config.ts","test:watch":"jest --watch","typecheck":"tsc --noEmit"},"lint-staged":{"*.{ts,tsx,js,mjs,cjs}":["eslint --fix","prettier --write"],"*.{json,md,yml,yaml}":["prettier --write"]},"peerDependencies":{"@nestjs/common":"^11.0.16","@nestjs/core":"^11.1.18","@nestjs/swagger":"^11.0.0","@opentelemetry/api":"^1.9.0","prom-client":"^15.0.0","reflect-metadata":"^0.2.0","rxjs":"^7.0.0"},"peerDependenciesMeta":{"@nestjs/swagger":{"optional":true},"@opentelemetry/api":{"optional":true},"prom-client":{"optional":true}},"devDependencies":{"@arethetypeswrong/cli":"^0.18.2","@commitlint/cli":"^21.2.1","@commitlint/config-conventional":"^21.2.0","@eslint/js":"^9.39.4","@nestjs/common":"^11.1.20","@nestjs/core":"^11.1.20","@nestjs/platform-express":"^11.1.20","@nestjs/platform-fastify":"^11.1.29","@nestjs/swagger":"^11.4.6","@nestjs/testing":"^11.1.20","@opentelemetry/api":"^1.9.1","@opentelemetry/context-async-hooks":"^2.10.0","@stryker-mutator/core":"^9","@stryker-mutator/jest-runner":"^9","@stryker-mutator/typescript-checker":"^9","@types/express":"^5.0.6","@types/jest":"^30.0.0","@types/node":"^24","@types/supertest":"^7.2.0","@typescript-eslint/eslint-plugin":"^8.59.3","@typescript-eslint/parser":"^8.59.3","eslint":"^9.39.4","eslint-config-prettier":"^10.1.8","eslint-import-resolver-typescript":"^4.4.4","eslint-plugin-import":"^2.32.0","eslint-plugin-prettier":"^5.5.5","eslint-plugin-security":"^4.0.0","fastify":"^5.11.3","globals":"^17.6.0","husky":"^9.1.7","jest":"^30.4.2","lint-staged":"^17.2.0","prettier":"^3.8.3","prom-client":"^15.1.3","reflect-metadata":"^0.2.2","rxjs":"^7.8.0","supertest":"^7.2.2","ts-jest":"^29.4.9","ts-node":"^10.9.2","tsup":"^8.5.1","typescript":"^5.9.3"},"keywords":["nestjs","error-envelope","exception-filter","request-timing","pagination","health-check","prometheus","metrics","openapi","swagger","opentelemetry","tracing","typescript"],"packageManager":"pnpm@11.20.0","engines":{"node":">=24.0.0"},"publishConfig":{"access":"public","provenance":true,"registry":"https://registry.npmjs.org/"},"module":"./dist/index.mjs","typesVersions":{"*":{"pagination":["./dist/pagination/index.d.cts"],"health":["./dist/health/index.d.cts"],"openapi":["./dist/openapi/index.d.cts"],"metrics":["./dist/metrics/index.d.cts"]}},"gitHead":"4f16cefc73da665fe973c5a9026725398055335f","_id":"@bymax-one/nest-core@1.6.0","_nodeVersion":"24.19.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-/ASVg3MjkUcHB5v4zyF+YuhaXpASpfpH+q/fKZwNJTM5Nkf+LZx9JmOTCarvVqlrwWBv/lJ6dB/e+RAQbZi9kw==","shasum":"6207094929073d74ea258a2973098b126681ad88","tarball":"https://registry.npmjs.org/@bymax-one/nest-core/-/nest-core-1.6.0.tgz","fileCount":26,"unpackedSize":565767,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bymax-one%2fnest-core@1.6.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIBx8wRX7jkVZlhMnI0zm3ASJCxkwccEkWL8nl6nlkqdaAiB/LAV07BHBktlF+qFdMpD7KnN2U91iqWvnVN9mASMiow=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:143c9547-d2b9-447f-8cde-9267ff22f966"}},"directories":{},"maintainers":[{"name":"bymax.one","email":"bymaxone.core@gmail.com"},{"name":"msalvatti","email":"msalvatti@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/nest-core_1.6.0_1788090121981_0.23122369811086618"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-04T11:12:16.132Z","modified":"2026-08-30T11:42:02.482Z","1.0.0":"2026-08-04T11:12:16.475Z","1.0.1":"2026-08-04T12:00:33.088Z","1.1.0":"2026-08-06T11:29:53.499Z","1.1.1":"2026-08-08T13:00:11.304Z","1.2.0":"2026-08-08T16:18:37.041Z","1.2.1":"2026-08-08T18:55:15.335Z","1.2.2":"2026-08-10T17:02:55.747Z","1.3.0":"2026-08-11T11:03:20.074Z","1.3.1":"2026-08-11T20:00:16.679Z","1.3.2":"2026-08-12T20:07:39.260Z","1.4.0":"2026-08-13T12:39:50.861Z","1.5.0":"2026-08-15T13:35:37.832Z","1.5.1":"2026-08-15T15:19:12.622Z","1.5.2":"2026-08-15T22:46:02.128Z","1.5.3":"2026-08-18T21:52:24.699Z","1.6.0":"2026-08-30T11:42:02.134Z"},"bugs":{"url":"https://github.com/bymaxone/nest-core/issues"},"author":{"name":"Bymax One","email":"support@bymax.one"},"license":"MIT","homepage":"https://github.com/bymaxone/nest-core#readme","keywords":["nestjs","error-envelope","exception-filter","request-timing","pagination","health-check","prometheus","metrics","openapi","swagger","opentelemetry","tracing","typescript"],"repository":{"type":"git","url":"git+https://github.com/bymaxone/nest-core.git"},"description":"Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints with indicator discovery, an optional Prometheus metrics endpoint with a contribution contract, OpenAPI","maintainers":[{"name":"bymax.one","email":"bymaxone.core@gmail.com"},{"name":"msalvatti","email":"msalvatti@gmail.com"}],"readme":"<p align=\"center\">\n  <img src=\"https://img.shields.io/badge/%40bymax--one-nest--core-000000?style=for-the-badge&logo=nestjs&logoColor=E0234E\" alt=\"@bymax-one/nest-core\" />\n</p>\n\n<h1 align=\"center\">@bymax-one/nest-core</h1>\n\n<p align=\"center\">\n  <strong>Zero-dependency application foundation kit for NestJS</strong><br />\n  <sub>Error Envelope · Request Timing · Offset &amp; Cursor Pagination · Health Probes · Prometheus Metrics · Zero Runtime Dependencies</sub>\n</p>\n\n<p align=\"center\">\n  <a href=\"https://www.npmjs.com/package/@bymax-one/nest-core\"><img src=\"https://img.shields.io/npm/v/@bymax-one/nest-core?style=flat-square&colorA=000000&colorB=000000\" alt=\"npm version\" /></a>\n  <a href=\"https://www.npmjs.com/package/@bymax-one/nest-core\"><img src=\"https://img.shields.io/npm/dm/@bymax-one/nest-core?style=flat-square&colorA=000000&colorB=000000\" alt=\"npm downloads\" /></a>\n  <a href=\"https://github.com/bymaxone/nest-core/actions/workflows/ci.yml\"><img src=\"https://img.shields.io/github/actions/workflow/status/bymaxone/nest-core/ci.yml?branch=main&style=flat-square&colorA=000000&label=CI\" alt=\"CI status\" /></a>\n  <a href=\"https://github.com/bymaxone/nest-core/actions/workflows/ci.yml\"><img src=\"https://img.shields.io/badge/coverage-100%25-brightgreen?style=flat-square&colorA=000000\" alt=\"coverage\" /></a>\n  <a href=\"https://github.com/bymaxone/nest-core/blob/main/docs/mutation_testing_results.md\"><img src=\"https://img.shields.io/badge/mutation-100%25-brightgreen?style=flat-square&colorA=000000\" alt=\"mutation score\" /></a>\n  <a href=\"https://scorecard.dev/viewer/?uri=github.com/bymaxone/nest-core\"><img src=\"https://api.scorecard.dev/projects/github.com/bymaxone/nest-core/badge?style=flat-square\" alt=\"OpenSSF Scorecard\" /></a>\n  <a href=\"https://github.com/bymaxone/nest-core/blob/main/LICENSE\"><img src=\"https://img.shields.io/github/license/bymaxone/nest-core?style=flat-square&colorA=000000&colorB=000000\" alt=\"license\" /></a>\n  <a href=\"https://www.typescriptlang.org/\"><img src=\"https://img.shields.io/badge/TypeScript-strict-3178C6?style=flat-square&logo=typescript&logoColor=white\" alt=\"TypeScript\" /></a>\n  <a href=\"https://nodejs.org/\"><img src=\"https://img.shields.io/badge/Node.js-24%2B-339933?style=flat-square&logo=node.js&logoColor=white\" alt=\"Node.js\" /></a>\n</p>\n\n<p align=\"center\">\n  <a href=\"https://github.com/bymaxone/nest-core\">GitHub</a> ·\n  <a href=\"https://github.com/bymaxone/nest-core/issues\">Issues</a> ·\n  <a href=\"#-quick-start\">Quick Start</a> ·\n  <a href=\"#-api-reference\">API Reference</a> ·\n  <a href=\"https://github.com/bymaxone/nest-core-example\">Example App</a>\n</p>\n\n---\n\n## ✨ Overview\n\n`@bymax-one/nest-core` is the layer every service in a fleet ends up writing for itself: one\nerror shape, one timing sample, one pagination contract, one health probe, one metrics\nendpoint. Writing it per service is how five services end up answering the same failure five\ndifferent ways, and how a client integration breaks because one of them changed its error\nbody.\n\nIt ships `\"dependencies\": {}`. Everything it touches — NestJS, `rxjs`, `reflect-metadata`, and\nthe three optional peers behind the features that need them (`prom-client`, `@nestjs/swagger`,\n`@opentelemetry/api`) — is a peer whose version you already control. A feature you leave off\nnever loads its peer, which the release gate asserts against the packed tarball.\n\n### Why nest-core?\n\n- **One error shape, fleet-wide.** A versioned code catalog and a fixed envelope, so a client\n  writes one error handler instead of one per service — and an unknown failure becomes a\n  generic 500 rather than whatever the framework happened to serialize.\n- **Features register only when enabled.** Turning metrics off does not leave a disabled\n  provider in the container; it leaves no provider, and `prom-client` is never imported. That\n  is what lets it stay an optional peer.\n- **Pagination without a provider.** `./pagination` is pure functions on their own subpath —\n  no module to import, nothing to inject, usable from a script or a test.\n- **Health that cannot hang.** An indicator that rejects becomes a `down` entry from its\n  top-level message alone, truncated; a slow one is converted by the aggregator rather than\n  holding the probe open.\n\n---\n\n## 🔥 Features\n\n### 🚨 Errors\n\n- ✅ **Stable envelope** — one JSON shape for every error an application returns:\n  `statusCode`, `code`, `message`, `details`, `correlationId`, `timestamp`, `path`\n- ✅ **Versioned code catalog** — `BYMAX_NOT_FOUND`, `BYMAX_CONFLICT`, `BYMAX_BAD_GATEWAY`\n  and the rest, exported as constants so a client maps a `code` rather than a message string\n- ✅ **Internals stay internal** — an unknown error becomes a generic 500; its message and\n  stack are captured for your logger, and reach the body only under `exposeInternals`\n- ✅ **Correlation id** — resolved through `BYMAX_CORRELATION_PROVIDER`, so the id comes from\n  wherever your request context already keeps it\n\n### ⏱️ Observability\n\n- ✅ **Request timing** — one sample per closed request, rejections included, handed to the sink you register;\n  the library stores nothing itself\n- ✅ **Slow-request flag** — samples above `slowRequestThresholdMs` are marked, so a sink can\n  branch without re-deriving the threshold\n- ✅ **Prometheus endpoint** — opt-in scrape route over `BYMAX_METRICS_REGISTRY`;\n  `prom-client` is imported only when it is enabled\n- ✅ **Contributed metrics** — a provider marked `@BymaxMetricsContributor()` publishes its\n  own collectors on that same registry, so an imported library's metrics land in your scrape\n- ✅ **Trace correlation** — reads the active OpenTelemetry span, so timing samples (and,\n  when you opt in, error envelopes) carry the trace id; never creates a span or an SDK\n- ✅ **OpenAPI document, development only** — one bootstrap call publishes an interactive\n  UI carrying the schemas this package owns; in production it is never served, guarded twice\n\n### 📄 Pagination & Health\n\n- ✅ **Offset and cursor** — `normalizePageQuery` / `buildPageResult` and\n  `normalizeCursorQuery` / `buildCursorResult`, pure functions with no NestJS involvement\n- ✅ **Opaque cursors** — `encodeCursor` / `decodeCursor` round-trip a token a client carries\n  back, treated as untrusted input on the way in\n- ✅ **Liveness and readiness** — separate endpoints, so a slow dependency fails readiness\n  without restarting the pod\n- ✅ **Pluggable indicators** — implement `IHealthIndicator` against a client you already own\n  and register it under the `BYMAX_HEALTH_INDICATORS` multi-token\n- ✅ **Discovered indicators** — opt in, and any provider marked\n  `@BymaxHealthIndicator()` joins readiness: a library you import brings its own check\n\n### 🧩 Developer Experience\n\n- ✅ **Zero runtime dependencies** — `@nestjs/*`, `rxjs` and `reflect-metadata` arrive as\n  peers, so you pin the versions\n- ✅ **Five subpaths** — the module, plus `./pagination`, `./health`, `./metrics` and\n  `./openapi` that a package can import without pulling the module in\n- ✅ **Dual-format output** — ESM + CJS with declarations for each format, verified against\n  the packed tarball on every run\n- ✅ **Independent features** — each is enabled on its own; the providers for the rest are\n  never registered\n- ✅ **Typed end to end** — TypeScript `strict` with `exactOptionalPropertyTypes` and\n  `noUncheckedIndexedAccess`; zero `any`\n\n---\n\n## 📦 Subpath Exports\n\n| Subpath        | Contents                                                                                                                                                                                                                                                            |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `.`            | `BymaxCoreModule`, the error envelope and its code catalog, the request-timing middleware, the DI tokens, and every option type                                                                                                                                     |\n| `./pagination` | `normalizePageQuery`, `buildPageResult`, `normalizeCursorQuery`, `buildCursorResult`, `encodeCursor`, `decodeCursor` and their types — pure functions, no NestJS provider involved                                                                                  |\n| `./health`     | `IHealthIndicator`, `HealthResponse`, the indicator contracts and the `@BymaxHealthIndicator()` marker, so a package that only implements an indicator does not import the module                                                                                   |\n| `./metrics`    | `IMetricsContributor` and the `@BymaxMetricsContributor()` marker, so a package that only publishes metrics imports neither the module nor its DI tokens. The one subpath whose types name `prom-client`, which anyone implementing the contract already depends on |\n| `./openapi`    | `applyBymaxOpenApi`, the one bootstrap call that builds and mounts the OpenAPI document — separate so an application that never documents its API never loads the code that does                                                                                    |\n\nEach subpath ships ESM and CommonJS with its own `.d.ts` and `.d.cts`, so\n`require()` and `import` both resolve the declarations meant for them.\n\n### Install\n\n```bash\npnpm add @bymax-one/nest-core @nestjs/common @nestjs/core reflect-metadata rxjs\n```\n\nAdd `prom-client` if you enable the metrics feature, `@nestjs/swagger` if you\nenable the OpenAPI feature, and `@opentelemetry/api` if you enable trace\ncorrelation. All three are optional peer dependencies: none is required, or ever\nloaded, unless you turn its feature on.\n\n```bash\npnpm add prom-client\npnpm add @opentelemetry/api\npnpm add -D @nestjs/swagger\n```\n\n`@nestjs/swagger` belongs in `devDependencies`: the document is never served in\nproduction, so a production install has no reason to carry it.\n\n## 🚀 Quick Start\n\n```typescript\nimport { Module } from '@nestjs/common'\nimport { BymaxCoreModule } from '@bymax-one/nest-core'\n\n@Module({\n  imports: [BymaxCoreModule.forRoot()]\n})\nexport class AppModule {}\n```\n\nWith no options, `forRoot()` enables the error envelope, request timing, and\nhealth endpoints, and leaves metrics off. Every documented default is listed\nin the [configuration reference](#-configuration) below.\n\n## 🏭 Production Wiring with `forRootAsync`\n\nThe standard pattern in real applications: resolve options from your own\nconfiguration service, so behavior can vary by environment without a second\ncode path.\n\n```typescript\nimport { Module } from '@nestjs/common'\nimport { BymaxCoreModule } from '@bymax-one/nest-core'\n\n@Module({\n  imports: [\n    BymaxCoreModule.forRootAsync({\n      inject: [AppConfigService],\n      useFactory: (config: AppConfigService) => ({\n        envelope: { exposeInternals: config.env === 'development' },\n        timing: { slowRequestThresholdMs: 1_000 },\n        metrics: { enabled: config.env === 'production' }\n      })\n    })\n  ]\n})\nexport class AppModule {}\n```\n\n`isGlobal` is a module extra, not part of the options object, defaulting to\n`true`:\n\n```typescript\nBymaxCoreModule.forRoot({ isGlobal: false })\n```\n\n## ⚙️ Configuration\n\nEvery block is optional; an omitted block, or an omitted field within it,\nfalls back to the documented default. Pass only what you want to change.\n\n### `environment`\n\nThe one top-level option rather than a block, because it describes the\ndeployment rather than a feature.\n\n| Option        | Type     | Default | Description                                                                           |\n| ------------- | -------- | ------- | ------------------------------------------------------------------------------------- |\n| `environment` | `string` | unset   | The environment this deployment runs in, read only where `NODE_ENV` declares nothing. |\n\nSet it when your application validates its own environment variable and does not\nalso set `NODE_ENV`. `NODE_ENV` wins whenever it says anything, so this can never\nserve the OpenAPI document in a runtime that named itself production. Full rules\nand the classification table: [Production is a closed door](#production-is-a-closed-door).\n\n### `envelope`\n\n| Option            | Type      | Default | Description                                                                                    |\n| ----------------- | --------- | ------- | ---------------------------------------------------------------------------------------------- |\n| `enabled`         | `boolean` | `true`  | Registers the global exception filter.                                                         |\n| `exposeInternals` | `boolean` | `false` | Includes the original message and stack of unknown errors. Development only, never production. |\n\n### `timing`\n\n| Option                   | Type      | Default | Description                                                                    |\n| ------------------------ | --------- | ------- | ------------------------------------------------------------------------------ |\n| `enabled`                | `boolean` | `true`  | Applies the request-timing middleware to every route.                          |\n| `slowRequestThresholdMs` | `number`  | unset   | Samples above this duration are flagged `slow: true`. Absent means never slow. |\n\n### `health`\n\n| Option                  | Type      | Default    | Description                                                                                                             |\n| ----------------------- | --------- | ---------- | ----------------------------------------------------------------------------------------------------------------------- |\n| `enabled`               | `boolean` | `true`     | Registers the health controller.                                                                                        |\n| `path`                  | `string`  | `'health'` | Route prefix: `GET /<path>/live`, `GET /<path>/ready`.                                                                  |\n| `indicatorTimeoutMs`    | `number`  | `5000`     | Per-indicator timeout before a check reports down.                                                                      |\n| `exposeIndicatorErrors` | `boolean` | `false`    | Includes the failing indicator's message in the response under `details.error`. Never enable in production — see below. |\n| `autoDiscover`          | `boolean` | `false`    | Also aggregates every provider marked `@BymaxHealthIndicator()`, anywhere in the application.                           |\n\nOn `forRoot`, `enabled` and `path` are applied at module-definition time: a\ndisabled feature registers no controller, and a custom `path` mounts the routes.\nOn `forRootAsync`, options resolve after the module is defined, so the health\ncontroller is always registered at the default path and enforces `enabled` and\nthe default path with a request-time guard; a disabled or custom-path async\nconfiguration fails fast at the route rather than at boot.\n\n### `metrics`\n\n| Option                  | Type                     | Default     | Description                                                                                      |\n| ----------------------- | ------------------------ | ----------- | ------------------------------------------------------------------------------------------------ |\n| `enabled`               | `boolean`                | `false`     | Registers the metrics controller and the registry.                                               |\n| `path`                  | `string`                 | `'metrics'` | Route serving the Prometheus scrape.                                                             |\n| `defaultLabels`         | `Record<string, string>` | `{}`        | Static labels attached to every metric.                                                          |\n| `collectDefaultMetrics` | `boolean`                | `true`      | Collects `prom-client`'s process CPU, memory, and event-loop metrics.                            |\n| `authToken`             | `string`                 | _(unset)_   | Bearer required to scrape. Unset leaves the endpoint open; empty/whitespace is rejected at boot. |\n\nAs with `health`, `enabled` and `path` register conditionally on `forRoot`. On\n`forRootAsync` the metrics controller is always registered at the default path\nand enforces `enabled` and the default path with a request-time guard, so a\ndisabled or custom-path async configuration fails fast at the route.\n\nBy default the scrape endpoint is **open** — the exposition publishes the route\ninventory and, with `collectDefaultMetrics`, process internals to any caller. Set\n`authToken` to require `Authorization: Bearer <token>` (the scheme is matched\ncase-insensitively; the token is compared in constant time), or protect the route at\nyour edge (network policy, ingress auth). A token configured empty or whitespace-only\nis rejected at boot rather than silently ignored, so a mistyped secret fails loud\ninstead of leaving the endpoint open:\n\n```ts\nBymaxCoreModule.forRoot({\n  metrics: { enabled: true, authToken: process.env.METRICS_TOKEN }\n})\n// Scrape: curl -H \"Authorization: Bearer $METRICS_TOKEN\" http://host/metrics\n```\n\n### `telemetry`\n\n| Option          | Type      | Default | Description                                                                     |\n| --------------- | --------- | ------- | ------------------------------------------------------------------------------- |\n| `enabled`       | `boolean` | `false` | Reads the active span and carries its ids into timing samples and the log seam. |\n| `exposeTraceId` | `boolean` | `false` | Also publishes `traceId` in the error-envelope body served to the client.       |\n\n### `openapi`\n\n| Option               | Type                                       | Default       | Description                                                                         |\n| -------------------- | ------------------------------------------ | ------------- | ----------------------------------------------------------------------------------- |\n| `enabled`            | `boolean`                                  | `false`       | Builds and serves the document. Ignored in production, where it is always off.      |\n| `path`               | `string`                                   | `'docs'`      | Route serving the interactive UI.                                                   |\n| `jsonPath`           | `string`                                   | `'docs-json'` | Route serving the raw JSON document.                                                |\n| `title`              | `string`                                   | `'API'`       | Document title.                                                                     |\n| `description`        | `string`                                   | `''`          | Document description.                                                               |\n| `version`            | `string`                                   | `'1.0.0'`     | Document version, independent of the package version.                               |\n| `servers`            | `{ url, description? }[]`                  | `[]`          | Servers advertised by the document.                                                 |\n| `securitySchemes`    | `Record<string, object>`                   | `{}`          | Security schemes copied into the document's components.                             |\n| `security`           | `SecurityRequirement[]`                    | `[]`          | The requirement every operation carries unless it says otherwise.                   |\n| `operationSecurity`  | `OperationSecurityMap`                     | `{}`          | Per-operation overrides. An empty array marks that operation public.                |\n| `operationIdFactory` | `(controller, method, version?) => string` | peer default  | Names the operations. Leave unset and nothing an existing client generated changes. |\n| `includeCoreSchemas` | `boolean`                                  | `true`        | Contributes this package's own schemas and references them from the responses.      |\n\nUnlike `health` and `metrics`, this block behaves identically on `forRoot` and\n`forRootAsync`: the document is mounted from the bootstrap helper, after the\noptions have resolved, so a custom `path` is honored on both registration paths.\n\n#### Documenting authentication\n\nSet the default on the document and mark the exceptions. `security` names\nschemes declared in `securitySchemes`; `operationSecurity` overrides it for one\noperation, and an **empty array is how the specification says \"public\"** — which\nmatters more than it looks, because an operation with _absent_ security inherits\nthe document default, so a generated client would attach credentials to your\nregistration endpoint.\n\n```ts\nopenapi: {\n  enabled: true,\n  securitySchemes: {\n    cookieAuth: { type: 'apiKey', in: 'cookie', name: 'access_token' },\n    refreshCookie: { type: 'apiKey', in: 'cookie', name: 'refresh_token' }\n  },\n  security: [{ cookieAuth: [] }],\n  operationSecurity: {\n    'POST /auth/login': [],\n    'POST /auth/register': [],\n    'POST /auth/refresh': [{ refreshCookie: [] }]\n  }\n}\n```\n\nAn operation that already declares its own requirement — because you decorated\nthe handler — is never overwritten, on either path.\n\n#### The operation key is a contract\n\nKeys are `\"<METHOD> <path>\"`, and the format is documented rather than\nincidental: a sibling library can ship a plain-data map of its own operations\nkeyed this way, so you spread it in instead of restating which of its routes are\npublic. Import `OperationSecurityMap` to have that map checked at the library's\nown compile time — it is a type-only export, so nothing couples at runtime.\n\n- The method is **uppercase**, separated by exactly one space.\n- The path is written **exactly as it appears in the generated document**:\n  leading slash, OpenAPI template braces (`/users/{id}`), no trailing slash, and\n  **including any global prefix**. `@nestjs/swagger` puts\n  `app.setGlobalPrefix('api')` into the documented paths, so the key becomes\n  `'POST /api/auth/login'` in an application that sets one.\n\nBecause of that last point, a library shipping such a map should expose a\n**function taking the prefix**, not a frozen constant — the call site is the only\nplace that knows it:\n\n```ts\n// in the library\nexport function authOperationSecurity(prefix = ''): OperationSecurityMap { /* … */ }\n\n// in the application\noperationSecurity: { ...authOperationSecurity('api'), ...myOwnOverrides }\n```\n\nA requirement naming a scheme that is not declared **fails the document build**\ntoo, listing the names that missed and the ones the document defines. A\nrequirement is a reference, and a reference to nothing yields a document whose\nsecurity cannot be resolved: a client generator looks the name up, finds\nnothing, and either fails or emits an unauthenticated client.\n\nA key matching no operation **fails the document build**, listing both the keys\nthat missed and the operations that exist. Silence would be worse: a route\nrenamed out from under a stale key would quietly inherit the document default\nand be documented as authenticated when it is not, or the reverse. Failing is\nsafe here in a way it rarely is — the document is only ever built outside\nproduction, so this can only stop a developer.\n\nOne consequence for conditionally-registered routes: the map is static wiring\nwhile a route may not be. If an operation belongs to a feature you register per\nenvironment — your own conditional module, or a library feature toggled off\nsomewhere — a key naming it fails the boot in whichever docs-enabled environment\nlacks that route. That is the intended loud behavior, so build the map the same\nway you build the modules: assemble it per feature and spread the fragments in,\nrather than writing one flat literal that outlives the routes it names.\n\nThat last sentence cuts both ways, and the consequence is worth stating rather\nthan discovering. **These checks only run when the document is actually built.**\nWith `openapi.enabled` false, or in a production runtime where the feature is\nforced off, nothing validates: a stale key, a renamed route, or a requirement\nnaming a scheme you deleted all sit there quietly until someone turns the\ndocument on. That is deliberate — refusing to boot a production service over a\ndocumentation setting it never serves would be the wrong trade — but it means\nthe errors surface on a developer's machine or in CI, **not** at the moment the\nconfiguration went wrong. If you gate the document behind an environment flag,\nmake sure at least one environment that runs your tests has it on, or these\nchecks never fire.\n\n#### When an operation ends up requiring nothing\n\nThe checks above catch a requirement that points at nothing. The opposite\nmistake — an operation that ends up pointing at _no requirement at all_ — breaks\nnothing, and that is what makes it dangerous. It is a valid document. No name\ndangles. The runtime still answers `401`. A document test that asserts only the\noperations you enumerated stays green. The only thing that changed is that a\nclient generated from the document now sends no credentials.\n\nThe edit that produces it is ordinary: a library starts describing its own\nroutes, its adoption note tells you to delete the entries you had written for\nthem, and the document-level `security` default is sitting in the same options\nblock and goes with them. Every route _you_ own then reads as public.\n\nSo the document build says so, once, naming the operations:\n\n```\n[BymaxCoreModule] a client generated from the OpenAPI document will send no\ncredentials to 2 operation(s): GET /examples, POST /orders. They state no\nsecurity requirement, the document declares no default, and other operations in\nit do state one — so this is more often a missing openapi.security default than\na public API. Set openapi.security, or state the intent per operation with an\nexplicit [] in openapi.operationSecurity.\n```\n\nIt is a **warning, not a failure**: an API that is public on purpose is a\nlegitimate configuration, and failing a boot over one would be worse than the\nsilence it replaces. The trigger is deliberately narrow, so the line stays worth\nreading:\n\n| Condition                                               | Why                                                                                                                    |\n| ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |\n| The document declares no top-level `security`           | With a default present, a bare operation inherits it. An explicit `security: []` counts as an answer, not an omission. |\n| At least one other operation _does_ state a requirement | Somebody described a posture on purpose, so the bare ones beside it are an omission rather than a public API.          |\n| The operation is not one of this package's own          | A health probe carrying nothing is the correct description of a route an orchestrator polls without a credential.      |\n\nThe escape hatch is to say what you mean, in the document's own vocabulary\nrather than by silencing output: `operationSecurity: { 'GET /examples': [] }`\nmarks the operation public, and it stops being reported. A library can do the\nsame for its own routes by contributing `security: []` in its fragment.\n\n**There is one shape this warning cannot report.** If you remove _every_\nrequirement at once — no library describing anything, no decorator, no override,\nno document default — the second condition above is never met: nothing states a\nrequirement, so there are no bare operations sitting _beside_ described ones.\nThat follows from the trigger and therefore holds in every version; it is not a\ngap a later release closes, and a reader who expects one is exactly the reader\nwho stops checking.\n\nThe limit belongs to **anything reading only the rendered document**. Such a\ndocument is indistinguishable from that of an API which is public on purpose —\nboth are a set of operations asking for nothing — and this package cannot tell\nthem apart without also warning at every genuinely public API, which is how a\nwarning earns the right to be ignored.\n\n**Your own suite has no such handicap, because you know which one you are.**\nAssert it, and the check runs on every commit rather than when somebody\nremembers to look:\n\n```ts\nit('still requires a credential everywhere it should', () => {\n  const document = buildYourDocument()\n\n  // Assert the default you expect, not merely that one exists. `[]` is a\n  // defined value that requires nothing, so a \"toBeDefined\" check passes for\n  // a default that degraded to empty — which is the regression this test is\n  // here to catch, wearing the shape of a pass.\n  expect(document.security).toEqual([{ cookieAuth: [] }])\n\n  // An explicit `[]` is how an operation says \"public\". The set of operations\n  // saying it should be the set you meant — no more, no fewer.\n  expect(publicOperationsOf(document)).toEqual(['POST /auth/login'])\n})\n```\n\nRender-and-diff keeps a narrower job, and it is a good one: when you are\n_changing_ something — adopting a library that describes its own routes, moving\na default — render with and without the change and compare the operations you\nmount. It shows you what moved without your having to predict it. Then turn what\nit showed you into an assertion, so the next change is caught rather than\ninspected.\n\n#### A contributed scheme's presence is part of the contributor's configuration\n\nA library contributes security schemes, and **which** ones it contributes can\ndepend on how you configured it. Any of them, gated on any of its inputs, and\noften on more than one — the scheme you have in mind may be the absent one, and\nthe setting you are thinking of may not be the only gate. The names are stable;\ntheir presence is not.\n\nThat has one consequence worth stating as a rule, because getting it wrong\nproduces a failure at either end of the loudness scale:\n\n> Derive a document-level default from **the same configuration the contributor\n> reads**, never from the scheme names, and never from what the document\n> happened to contain before you adopted the library.\n\nWriting the name as a literal is correct only for the configuration you wrote it\nagainst. Under a configuration that declares that scheme plus another, the\ndefault still resolves but describes one of two credentials the route accepts —\n**quietly incomplete**. Under one that declares it not at all, the name resolves\nto nothing and the document build **fails** with the undeclared-scheme error\nabove. Guarding on whether the scheme exists is the tempting fix and it is the\nwrong one: it clears the case that already announced itself and ships the one\nthat does not.\n\nNote what a document-level default does not let you _say_. Its entries are\n**alternatives** — any one of them satisfies an operation — and they apply to\nevery operation that states nothing. So a backend whose routes sit behind **two\ndifferent credential families** can certainly list both, and nothing rejects it:\nthe result is a document asserting that _either_ credential works for _every_\ninheriting route. That is not an incomplete document, it is a false one, and it\nis false in the permissive direction — it tells a client that a credential the\nroute will reject is one the route accepts.\n\nGive the majority family the default and the minority explicit\n`operationSecurity` entries. Those outrank the default, and an operation\ncarrying one is never named by the warning above, because it states a\nrequirement.\n\n## 🔑 DI Tokens\n\nEvery token is a `Symbol`. `BYMAX_CORRELATION_PROVIDER`,\n`BYMAX_HEALTH_INDICATORS` and `BYMAX_HEALTH_TRANSITION_SINK` are consumed with\n`@Optional()` and are not bound by the module: provide either from your own module to supply your own\nimplementation, otherwise the internal fallback in the last column applies.\n`BYMAX_TIMING_SINK` and `BYMAX_METRICS_REGISTRY` behave differently on\n`forRootAsync`, where options resolve after the module is defined: there the\nmodule always binds and exports both (the timing sink as the metrics bridge or a\nno-op, the registry as a guarded placeholder when metrics are off), so a\nconsumer `BYMAX_TIMING_SINK` override is honored on `forRoot` but shadowed on\n`forRootAsync`. Follow the pattern in\n[Integration with `@bymax-one/nest-logger`](#-integration-with-bymax-onenest-logger)\nbelow.\n\n| Token                          | Provides                              | When you do not provide one                                                                                       |\n| ------------------------------ | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |\n| `BYMAX_CORE_OPTIONS`           | The resolved `BymaxCoreModuleOptions` | always set by the module                                                                                          |\n| `BYMAX_CORRELATION_PROVIDER`   | `ICorrelationIdProvider`              | internal no-op (omits `correlationId`)                                                                            |\n| `BYMAX_TIMING_SINK`            | `ITimingSink`                         | internal no-op, or the metrics bridge when timing and metrics are both enabled                                    |\n| `BYMAX_HEALTH_INDICATORS`      | `IHealthIndicator[]`                  | treated as an empty indicator set                                                                                 |\n| `BYMAX_HEALTH_TRANSITION_SINK` | `IHealthTransitionSink`               | no sink; readiness transitions go to Nest's logger instead (binding one stands that line down)                    |\n| `BYMAX_METRICS_REGISTRY`       | the `prom-client` `Registry`          | bound when metrics are enabled; on `forRootAsync` always registered, guarded-placeholder when off                 |\n| `BYMAX_TRACE_CONTEXT`          | `ITraceContextProvider`               | bound on every path: the OpenTelemetry reader when telemetry is enabled, a no-op that resolves no trace otherwise |\n\n## 🚨 Error Envelope\n\nEvery error that leaves an application registered with the envelope feature\nfollows this exact, versioned shape:\n\n```json\n{\n  \"statusCode\": 404,\n  \"code\": \"BYMAX_NOT_FOUND\",\n  \"message\": \"Invoice inv_123 was not found\",\n  \"details\": [{ \"field\": \"id\", \"issue\": \"unknown identifier\" }],\n  \"correlationId\": \"8f14e45f-ceea-4677-a9de-6ec3f1f0a1b2\",\n  \"timestamp\": \"2026-07-16T12:00:00.000Z\",\n  \"path\": \"/invoices/inv_123\"\n}\n```\n\n| Field           | Type              | Presence | Notes                                              |\n| --------------- | ----------------- | -------- | -------------------------------------------------- |\n| `statusCode`    | number            | always   | HTTP status.                                       |\n| `code`          | string            | always   | Stable, machine-readable code.                     |\n| `message`       | string            | always   | Human-readable, safe for end users.                |\n| `details`       | array or object   | optional | Structured context, for example validation issues. |\n| `correlationId` | string            | optional | Present when a correlation provider is bound.      |\n| `timestamp`     | string (ISO 8601) | always   | Time the error was formatted.                      |\n| `path`          | string            | always   | Request URL path.                                  |\n\nCodes are stable strings under a reserved `BYMAX_` prefix, derived from the\nHTTP status: `BYMAX_NOT_FOUND` for 404, `BYMAX_VALIDATION_FAILED` for the\nshape a validation pipe produces, `BYMAX_INTERNAL_ERROR` for anything\nunmapped, and so on. Throw an `HttpException` whose response object carries\nyour own `code` and the filter passes it through verbatim:\n\n```typescript\nimport { BadRequestException } from '@nestjs/common'\n\nthrow new BadRequestException({ code: 'INVOICE_OVERDUE', message: 'Invoice is overdue' })\n```\n\n### What the filter classifies from, and what it cannot\n\nAn error raised before any handler ran — a malformed JSON body, a payload over\nthe size limit — still becomes a clean `4xx` envelope rather than a 500. The\nfilter recognizes those by **shape**, not by class: it honours an error that\nmarks itself `expose: true` with a `4xx` status, which is the `http-errors`\nconvention Node's body pipeline follows. Nothing in the application failed, so\nit is not routed through the unexpected-error seam either.\n\n**An error that carries no such marking is a 500, including when a client\ncaused it.** The clearest case is depth: a body of a few kilobytes nested\nthousands of levels deep overflows the stack during validation and surfaces as\n`RangeError: Maximum call stack size exceeded` — well under any size limit, and\nanswered `500 BYMAX_INTERNAL_ERROR`.\n\nThat is deliberate, and the alternative is worse. Mapping `RangeError` to a\n`4xx` would make the filter infer causation from an error class, and it would be\nwrong exactly where it matters: a genuine stack overflow in your own code is a\n`500` that should page someone, and relabelling it as a client error would hide\nthe failure the `500` exists to surface. By the time the filter sees the error,\nthe body that caused it is gone.\n\n**So body-shape limits are the application's floor, not the filter's.** Cap\nnesting depth and the request is rejected as the `400` it is, instead of\nbecoming a `5xx` that pollutes your error rate and writes a stack per request.\n\n**Position it after the body parser and before validation** — that window is the\nonly place the body exists in a form you can measure and nothing has walked it\nyet. Earlier there is nothing to inspect; later the overflow has already\nhappened, which is the failure you are trying to prevent.\n\n**Where that window is depends on the adapter, and the obvious answer is wrong\non Express.** Measured against a real Nest application:\n\n| Registration point                       | `req.body` when it runs |\n| ---------------------------------------- | ----------------------- |\n| `app.use(...)` in `bootstrap.ts`         | **`undefined`**         |\n| Module middleware, `configure(consumer)` | the parsed body         |\n\nNest registers its own parser during `app.init()`, so a middleware added with\n`app.use()` before that is mounted _ahead_ of it — a depth guard there inspects\nnothing and silently protects nothing. Register it as module middleware\ninstead. On Fastify the ordering differs again, since Nest middleware runs\nthrough `@fastify/middie` ahead of body parsing; a `preValidation` hook is the\nplace to look, and it is worth measuring rather than assuming.\n\n**Registering it in the right place is not enough — the route pattern silently\nskips paths too.** This package hit the same trap with its own timing\nmiddleware, and the measured behaviour is in `core.module.ts`:\n\n| `forRoutes(...)` | Express        | Fastify          |\n| ---------------- | -------------- | ---------------- |\n| `'*splat'`       | skips the root | —                |\n| `'{*splat}'`     | skips `/api`   | every path       |\n| `'/'`            | every path     | matches `/` only |\n\nSo the named-wildcard form every migration guide reaches for leaves `POST /`\nunguarded on Express. A consumer measured exactly that: with `'*path'`, a\n2000-level body to the root returned `404` because the middleware never ran;\nwith `'{*path}'`, `400`. If your application mounts nothing at the root, both\nforms answer `4xx` and the status alone cannot tell you which one you have.\n\n**Verify by behaviour, not by wiring — this is the part worth insisting on.**\nChecking where the middleware is registered is what the consumer above did; it\nlooked correct, they confirmed it to us, and the guard was inert. Send a body\nnested past your ceiling and require your own rejection:\n\n```ts\nit('refuses a body nested past the ceiling', async () => {\n  const deep = JSON.parse(`${'['.repeat(2000)}${']'.repeat(2000)}`)\n\n  const res = await request(app.getHttpServer()).post('/anything').send({ name: deep })\n\n  // Match your guard's own message, not the status: a validation pipe rejects\n  // this shape with a 400 as well, so a status assertion passes with the floor\n  // removed and proves nothing.\n  expect(res.body.message).toBe('Request body is nested too deeply.')\n})\n```\n\nUse a depth that actually overflows, and assert the guard's own message. A test\nat a depth your DTO validation already rejects passes identically with the guard\ndeleted — which is a check that cannot produce a negative result, and the reason\nthis defect survived a green suite.\n\nA depth ceiling well above anything a legitimate payload nests and well below\nwhat exhausts the stack leaves a wide margin: one consumer runs `32`, against\nthe ~2000 levels that overflow. Walk the parsed body iteratively — a recursive\ndepth check on a hostile payload overflows the stack it was written to protect.\n\n## ⏱️ Request Timing\n\nOne `RequestTimingSample` is delivered to whatever implements `ITimingSink` for\n**every request the server closes** — not only the ones a handler answered:\n\n```typescript\nexport interface RequestTimingSample {\n  method: string\n  route: string\n  statusCode: number\n  durationMs: number\n  slow: boolean\n}\n```\n\n### Rejected requests are counted too\n\nThe recorder is middleware (`BymaxTimingMiddleware`), applied to every route by\n`BymaxCoreModule` when `timing.enabled` is `true`. That placement is the whole\npoint. Nest runs **middleware → guards → interceptors → pipes → handler**, so a\nrequest rejected by a guard never reaches an interceptor, and a request matching\nno route never reaches a controller. A recorder sitting in either place is blind\nto exactly the traffic that matters during an incident:\n\n| What happens                   | Status | Visible to an interceptor | Visible here |\n| ------------------------------ | ------ | ------------------------- | ------------ |\n| Handler answers                | `2xx`  | ✅                        | ✅           |\n| Authentication guard rejects   | `401`  | ❌                        | ✅           |\n| Authorization guard rejects    | `403`  | ❌                        | ✅           |\n| Rate limiter sheds the request | `429`  | ❌                        | ✅           |\n| No route matches               | `404`  | ❌                        | ✅           |\n| Client hangs up mid-request    | —      | ❌                        | ✅           |\n\nA credential-stuffing run is a flood of `401`s, route enumeration is a flood of\n`404`s, and a throttler doing its job is a flood of `429`s. All three used to\nleave the error graph flat.\n\nRequests that matched no route are recorded under the fixed label\n`UNMATCHED_ROUTE` (`<unmatched>`), never the path that was requested. The raw\npath is attacker-controlled, and a metrics label that follows it lets anyone\nmint one time series per probe until the process runs out of memory.\n\nThe sample is emitted when the connection closes, so a client that hangs up\nbefore the response finishes is still counted — that is what a scanner does, and\n`durationMs` covers guards and middleware as well as the handler.\n\nAn aborted request keeps whatever status the response held, which is `200` in\nNode unless something settled another one. No sentinel status is introduced:\nthat would change the value of `status_code=\"200\"` series that already exist in\nyour dashboards, without any change in traffic.\n\n**Express and Fastify behave identically here**, and that is asserted end to\nend on both. It needs saying because the two platforms disagree underneath: Nest\nruns middleware on Fastify through `@fastify/middie`, which hands it the raw\n`IncomingMessage` carrying no route metadata, and `forRoutes('/')` is a mount on\nExpress but an exact match on Fastify. The module resolves both for you.\n\n> **One gap remains, and it is Nest's scoping rule, not a setting.** Module\n> middleware is scoped to the global prefix, so with `setGlobalPrefix('api')` a\n> request to `/nope` — outside the prefix entirely — reaches no middleware and\n> is not recorded. Requests to `/api/nope` are recorded normally, under\n> `<unmatched>`, so a scan that probes below your prefix is still visible; only\n> one that probes above it is not. Covering that too is not supported yet: the\n> module has no way to register the recorder outside its own scope, and\n> `BymaxTimingMiddleware` is only provided when `timing` is enabled — at which\n> point the module already applies it, so resolving and re-registering it would\n> double-count. If you need it, open an issue rather than wiring it by hand.\n\nBind your own sink by providing `BYMAX_TIMING_SINK` from your own module, the\nsame override pattern shown below for the correlation provider. This applies on\nthe `forRoot` path; on `forRootAsync` the module owns `BYMAX_TIMING_SINK` (the\nmetrics bridge or a no-op) so a consumer binding is shadowed there:\n\n```typescript\nimport { Global, Module } from '@nestjs/common'\nimport { BYMAX_TIMING_SINK, type ITimingSink } from '@bymax-one/nest-core'\n\nclass LoggerTimingSink implements ITimingSink {\n  record(sample: import('@bymax-one/nest-core').RequestTimingSample): void {\n    // forward to your own logger or telemetry pipeline\n  }\n}\n\n@Global()\n@Module({\n  providers: [{ provide: BYMAX_TIMING_SINK, useClass: LoggerTimingSink }],\n  exports: [BYMAX_TIMING_SINK]\n})\nexport class ObservabilityModule {}\n```\n\nA sink that fails cannot reach the request: both a synchronous throw and a\nrejection from an `async record()` are absorbed. Write it `async` if the backend\nbehind it is async — the `void` return type accepts it, and the rejection is\ncaught. The failure is swallowed rather than logged, unlike a health transition\nsink, because this runs on every request and a systematically failing sink would\notherwise become a second flood beside the first.\n\n## 📄 Pagination\n\nFramework-neutral, pure functions on the `./pagination` subpath: no NestJS\nprovider, no ORM awareness. Your repository translates the normalized query\ninto its own persistence call.\n\n### Offset pagination\n\n```typescript\nimport { Controller, Get, Query } from '@nestjs/common'\nimport {\n  buildPageResult,\n  normalizePageQuery,\n  type PageResult\n} from '@bymax-one/nest-core/pagination'\n\n@Controller('invoices')\nexport class InvoiceController {\n  constructor(private readonly invoices: InvoiceRepository) {}\n\n  @Get()\n  async list(@Query() raw: Record<string, unknown>): Promise<PageResult<Invoice>> {\n    const query = normalizePageQuery(raw, { maxLimit: 50, maxOffset: 100_000 })\n    const { rows, total } = await this.invoices.findPage(query)\n    return buildPageResult(rows, total, query)\n  }\n}\n```\n\n#### Bound the offset, not just the page size\n\n`maxLimit` caps how many rows a request reads. `maxOffset` caps how far in it\nstarts — and on an offset-paginated database that is the half that costs:\n\n```\nGET /invoices?page=1000000000&limit=20     →  OFFSET 19999999980\n```\n\nTwenty bytes of query, and Postgres walks the table to reach a page that does\nnot exist. The page index has a floor of `1` and an arithmetic guard that keeps\n`(page - 1) * limit` an exact integer, but nothing bounds the product itself\nunless you say so.\n\n`maxOffset` is **absent by default and deliberately so**: legitimate deep paging\nexists, and a silent ceiling would change the rows a working query returns. Set\nit wherever the page index reaches SQL and your dataset has a knowable ceiling.\n`0` is a valid bound and means \"the first page only\".\n\nClamping matches how `maxLimit` already behaves — the resolved values come back\nin `meta`, so a caller that cares can compare what it asked for against what it\ngot.\n\n### Cursor pagination\n\n```typescript\nimport { Controller, Get, Query } from '@nestjs/common'\nimport {\n  buildCursorResult,\n  decodeCursor,\n  normalizeCursorQuery,\n  type CursorResult\n} from '@bymax-one/nest-core/pagination'\n\n@Controller('invoices')\nexport class InvoiceCursorController {\n  constructor(private readonly invoices: InvoiceRepository) {}\n\n  @Get('cursor')\n  async list(@Query() raw: Record<string, unknown>): Promise<CursorResult<Invoice>> {\n    const query = normalizeCursorQuery(raw, { maxLimit: 50 })\n    const after = query.cursor ? decodeCursor<{ id: string }>(query.cursor) : undefined\n    // fetch limit + 1 rows ordered after `after`, the fetch-one-extra convention\n    const rows = await this.invoices.findAfter(after, query.limit + 1)\n    return buildCursorResult(rows, query.limit, (last) => ({ id: last.id }))\n  }\n}\n```\n\nA malformed or tampered cursor rejects with `BYMAX_VALIDATION_FAILED`. Cursors\nare opaque `base64url` strings but are neither encrypted nor signed: encode\nordering keys only, never sensitive data.\n\n## ❤️ Health\n\nLiveness always replies `200` with an empty checks array; readiness runs\nevery registered indicator concurrently and replies `200` only when every\nindicator reports `up`, `503` otherwise, naming every check either way.\n\nA failing indicator is named but not quoted: the response says which check is\ndown, and the reason goes to the logger. See\n[the security model](#-security-model) for why, and\n`health.exposeIndicatorErrors` if you want the message in the response while\ndebugging locally.\n\n```json\n{ \"status\": \"ok\", \"checks\": [{ \"name\": \"redis\", \"status\": \"up\" }] }\n```\n\nImplement `IHealthIndicator` against a client you already own:\n\n```typescript\nimport { Injectable } from '@nestjs/common'\nimport type { HealthIndicatorResult, IHealthIndicator } from '@bymax-one/nest-core/health'\n\n@Injectable()\nexport class RedisHealthIndicator implements IHealthIndicator {\n  readonly name = 'redis'\n\n  constructor(private readonly redis: RedisClient) {}\n\n  async check(): Promise<HealthIndicatorResult> {\n    await this.redis.ping()\n    return { status: 'up' }\n  }\n}\n```\n\nRegister it under the shared `BYMAX_HEALTH_INDICATORS` token from your own\nmodule, the same override pattern used throughout this README:\n\n```typescript\nimport { Global, Module } from '@nestjs/common'\nimport { BYMAX_HEALTH_INDICATORS } from '@bymax-one/nest-core'\n\n@Global()\n@Module({\n  providers: [\n    RedisHealthIndicator,\n    {\n      provide: BYMAX_HEALTH_INDICATORS,\n      useFactory: (r: RedisHealthIndicator) => [r],\n      inject: [RedisHealthIndicator]\n    }\n  ],\n  exports: [BYMAX_HEALTH_INDICATORS]\n})\nexport class HealthIndicatorsModule {}\n```\n\nA rejecting, throwing, or slow indicator (past `indicatorTimeoutMs`) is\nconverted to a `down` entry with a safe, bounded diagnostic detail; it never\nhides the results of the other registered indicators.\n\n### A failing check leaves a record\n\nA readiness failure that nothing records is a `503` an orchestrator acts on with\nan empty log behind it, and diagnosing it means reproducing it. That is easy to\narrive at without deciding to: probe paths are the highest-volume request a\nbackend serves, so they are usually excluded from the HTTP log surface, and a\nwell-written indicator returns `{ status: 'down' }` rather than throwing —\nbecause readiness is typically unauthenticated and a driver's error carries\nhosts, ports and sometimes credentials.\n\nSo the aggregator records it. It holds the last state of every check and reports\neach **change** — never once per probe — to its own logger, and to a sink you\nbind:\n\n```typescript\nimport { Injectable } from '@nestjs/common'\nimport type { HealthTransition, IHealthTransitionSink } from '@bymax-one/nest-core/health'\n\n@Injectable()\nexport class HealthTransitionLogger implements IHealthTransitionSink {\n  constructor(private readonly logger: MyStructuredLogger) {}\n\n  record(transition: HealthTransition): void {\n    if (transition.isUp) {\n      this.logger.info('HEALTH_CHECK_RECOVERED', { check: transition.name })\n      return\n    }\n    this.logger.warn('HEALTH_CHECK_DEGRADED', {\n      check: transition.name,\n      cause: transition.cause.kind\n    })\n  }\n}\n```\n\nBind it under `BYMAX_HEALTH_TRANSITION_SINK` from your own `@Global()` module,\nthe same override pattern as the indicator token above.\n\nBinding nothing is supported, and is not the silent case: the transitions reach\nNest's logger instead, so a readiness failure always leaves a record. **Binding a\nsink stands that line down** — both destinations are usually the same logger, so\nkeeping it would put two records of one transition side by side, which is the\nnoise this feature exists to remove. Your sink receives the cause as structured\ndata, strictly more than the line renders, so what reaches the log after that is\nyour decision rather than this package's.\n\n`transition.cause` distinguishes the three ways a check can be down, which the\n`up`/`down` response body cannot:\n\n| `cause.kind`    | Meaning                                            | Carries     |\n| --------------- | -------------------------------------------------- | ----------- |\n| `reported-down` | The indicator answered, and reported it down.      | —           |\n| `rejected`      | The indicator rejected or threw.                   | `message`   |\n| `timed-out`     | The aggregator gave up after `indicatorTimeoutMs`. | `timeoutMs` |\n\n`timed-out` is the one that cannot be observed anywhere else. An indicator the\naggregator abandoned is never told, so it reports nothing — and a hung\ndependency is the common shape, not a refused one: a database under load, a\nnetwork partition and a paused container all hang, while a refusal comes back\nimmediately and would have been reported. That is why the rule lives in the\naggregator rather than in each backend: the obstacle is information, not effort.\n\nTwo details worth knowing before you rely on it. A first observation that is\n**failing** is reported, while a first observation that is healthy is not — a\nprocess that boots against a dependency already down would otherwise look\nhealthy in the log forever, whereas announcing every healthy check would write a\nline per dependency on every boot. And the cause is the one seen **at the\ntransition**: a dependency that stays down while its failure mode changes\nunderneath keeps the first cause, which is the cost of one line per outage\ninstead of one per probe.\n\nThe sink is called synchronously on the readiness path, so keep it cheap. A\nthrow is caught and logged rather than failing the probe — readiness answering\n`500` because its own logging broke would take a healthy deployment out of\nrotation — but do not use that as flow control.\n\n### Discovered indicators\n\nRegistering every indicator by hand stops scaling once the libraries an\napplication imports have their own health to report. Mark a provider instead,\nand turn discovery on:\n\n```typescript\n// in a library, or anywhere in your application\nimport { Injectable } from '@nestjs/common'\nimport { BymaxHealthIndicator } from '@bymax-one/nest-core/health'\nimport type { HealthIndicatorResult, IHealthIndicator } from '@bymax-one/nest-core/health'\n\n@BymaxHealthIndicator()\n@Injectable()\nexport class RedisHealthIndicator implements IHealthIndicator {\n  readonly name = 'redis'\n\n  async check(): Promise<HealthIndicatorResult> {\n    await this.redis.ping()\n    return { status: 'up' }\n  }\n}\n```\n\n```typescript\nBymaxCoreModule.forRoot({ health: { autoDiscover: true } })\n```\n\nReadiness now includes `redis` with nothing registered anywhere. The rules:\n\n| Rule                        | Behavior                                                                                                                                              |\n| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Marked, not shaped          | Only providers carrying the marker are collected. A provider that merely has `name` and `check` is ignored.                                           |\n| Explicit wins               | An indicator registered under `BYMAX_HEALTH_INDICATORS` keeps its name and its position; a discovered one with the same name is dropped.              |\n| Stable order                | Discovered indicators are sorted by name, so the `checks` array does not reshuffle between restarts.                                                  |\n| Marked but incomplete fails | A marked provider that does not implement `IHealthIndicator` fails the boot, naming the class. Skipping it would hide a check you believe is running. |\n| Scanned once                | The provider graph is walked at bootstrap, not per probe.                                                                                             |\n\nIt is off by default because it changes which failures can take an application\nout of rotation: with it on, a library you merely import gains the ability to\nfail your readiness probe. That is the point — the dependency understands its own\nhealth better than you do — but it is your decision, not something you inherit.\n\n`@BymaxHealthIndicator()` lives in `./health`, alongside the contract, so a\nlibrary that only ships an indicator never imports the module.\n\n## 📈 Metrics\n\nDisabled by default. Enabling it registers `GET /metrics`, serving Prometheus\ntext format from a dedicated `prom-client` registry:\n\n```typescript\nBymaxCoreModule.forRoot({ metrics: { enabled: true } })\n```\n\n`prom-client` is an optional peer, loaded lazily only when `metrics.enabled`\nis `true`. If you enable metrics without installing it, the module fails fast\nat boot with a descriptive error naming the missing package and the install\ncommand, rather than a cryptic resolution failure at the first scrape.\n\nWhen timing and metrics are both enabled, an internal bridge feeds two\ndefault HTTP metrics with a bounded label set:\n\n| Metric                          | Type      | Labels                           |\n| ------------------------------- | --------- | -------------------------------- |\n| `http_requests_total`           | counter   | `method`, `route`, `status_code` |\n| `http_request_duration_seconds` | histogram | `method`, `route`, `status_code` |\n\nInject `BYMAX_METRICS_REGISTRY` to register your own application metrics\nagainst the same registry the endpoint scrapes.\n\n### Contributed metrics\n\nInjecting the token works for your own code, but it makes a library depend on\nthis package's DI tokens — and therefore on the module. A library declares its\nmetrics instead:\n\n```typescript\n// in a library\nimport { Injectable } from '@nestjs/common'\nimport { BymaxMetricsContributor } from '@bymax-one/nest-core/metrics'\nimport type { IMetricsContributor, MetricsRegistry } from '@bymax-one/nest-core/metrics'\nimport { Gauge } from 'prom-client'\n\n@BymaxMetricsContributor()\n@Injectable()\nexport class QueueMetrics implements IMetricsContributor {\n  registerMetrics(registry: MetricsRegistry): void {\n    new Gauge({ name: 'bymax_queue_depth', help: 'Jobs waiting', registers: [registry] })\n  }\n}\n```\n\nEnable metrics and the contributor runs — there is no second flag:\n\n```typescript\nBymaxCoreModule.forRoot({ metrics: { enabled: true } })\n```\n\n| Rule               | Behavior                                                                                                                                                                              |\n| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Marked, not shaped | Only providers carrying the marker are called. A provider that merely has `registerMetrics` is never touched.                                                                         |\n| Called once        | At bootstrap, with the registry the scrape endpoint serves. Never per request, never per scrape.                                                                                      |\n| Stable order       | Contributors run sorted by class name, so a collision fails the same way on every boot.                                                                                               |\n| Named failures     | A registration failure — usually a metric name another library already claimed — fails the boot naming the contributor. `prom-client` names the metric; this names who registered it. |\n| Off with metrics   | With the metrics feature disabled, no contributor runs and `prom-client` is never loaded.                                                                                             |\n\n**Naming and labels.** Contributors share one registry and one namespace, so the\nconventions are part of the contract:\n\n- Prefix every metric with `bymax_<library>_` (`bymax_queue_depth`,\n  `bymax_cache_hits_total`). An application's own metrics need no prefix — they\n  have no one to collide with but themselves.\n- Follow Prometheus naming: `_total` for counters, `_seconds` for durations, base\n  units, no units in the middle of a name.\n- Keep labels bounded. Route templates, never raw paths; status codes, never\n  messages. **Never** a tenant, user, or request id — one unbounded label is\n  enough to make a scrape endpoint the most expensive route in a service.\n  `tenantId` deserves naming twice: every library in this family is\n  tenant-aware, so it is the first label anyone reaches for and it is unbounded\n  by construction.\n- **Publish the list.** A library that contributes metrics documents them in its\n  own README — name, type, labels. This package deliberately keeps no central\n  catalogue: a list of everyone else's metrics rots the moment a library ships a\n  new one. What it does require is that the list exists somewhere an operator\n  can find it.\n\n**Why these rules live here.** A Prometheus registry is a flat namespace, and\n`prom-client` rejects a duplicate metric name. If two libraries independently\npick `bymax_operations_total`, the collision surfaces at the **consumer's** boot\n— in an application neither library's CI ever assembles, as a hard failure, in\nfront of whoever wired the app. Neither library can test for it. A namespace\nrule is the only thing that prevents it, and it can only be arbitrated by the\ndependency they share, which is this package.\n\nThe rules are documentation, not enforcement. This package could inspect the\nregistry around each contributor and reject an unprefixed name, but that would\nneed a per-contributor prefix on the contract, and it would wrongly reject the\ncase that matters most — an **application's own** contributor, which has no\nbusiness being pushed into a `bymax_` namespace.\n\n## 📘 OpenAPI\n\nDisabled by default, and **never served in production**. Enabling it and calling\none helper during bootstrap publishes an interactive UI at `GET /docs` and the\nraw document at `GET /docs-json`:\n\n```typescript\n// app.module.ts — configuration lives with every other feature\nBymaxCoreModule.forRoot({ openapi: { enabled: true, title: 'Invoices API' } })\n```\n\n```typescript\n// main.ts — the one call that needs the application instance\nimport { NestFactory } from '@nestjs/core'\nimport { applyBymaxOpenApi } from '@bymax-one/nest-core/openapi'\nimport { AppModule } from './app.module'\n\nasync function bootstrap(): Promise<void> {\n  const app = await NestFactory.create(AppModule)\n  await applyBymaxOpenApi(app)\n  await app.listen(3000)\n}\n\nvoid bootstrap()\n```\n\n> [!IMPORTANT]\n> Call `applyBymaxOpenApi` **before** `app.listen()`. Mounting the document\n> re-registers routes on the HTTP adapter, and doing that against an\n> already-initialized Express 5 application replaces the router: the document\n> appears and every other route in the application — yours and this package's\n> health endpoints alike — starts returning 404.\n\nThe call is safe to make unconditionally. It returns what it did, so a template\ncan emit it once and never branch:\n\n| Result                                     | Meaning                                                 |\n| ------------------------------------------ | ------------------------------------------------------- |\n| `{ mounted: true, path }`                  | The UI and the document are served at `path`.           |\n| `{ mounted: false, reason: 'disabled' }`   | `openapi.enabled` is off.                               |\n| `{ mounted: false, reason: 'production' }` | The runtime is production. Nothing was built or served. |\n\n### Production is a closed door\n\n`NODE_ENV` decides, and the decision is fail-closed: only `development` and\n`test` are non-production. Any other value is production, and in production the\ndocument is never built and never mounted, whatever the configuration says. The\nguard runs twice, independently: the option resolver forces the feature off, and\nthe bootstrap helper classifies the runtime again without trusting that\nresolution.\n\n**`NODE_ENV` cannot be overridden.** With it set to anything, no option serves\nthe document in a runtime it named production.\n\nEnabling it in production is not an error, it is a no-op with a warning naming\nthe option that was ignored, so a single configuration can be shared across\nenvironments.\n\n#### When your application validates its own environment variable\n\nPlenty of applications parse an `APP_ENV` through a config schema and never set\n`NODE_ENV` at all. Those deployments used to be classified","readmeFilename":"README.md"}