{"_id":"@tygra/nestjs-graceful-shutdown","_rev":"3-e6bb3254fada0c2a42aa3e7a7a42b597","name":"@tygra/nestjs-graceful-shutdown","dist-tags":{"latest":"2.0.0"},"versions":{"1.0.0":{"name":"@tygra/nestjs-graceful-shutdown","version":"1.0.0","keywords":["nestjs","nest.js","nest","graceful shutdown","graceful-shutdown","graceful","gracefully","http-shutdown","http shutdown","http-terminate","http-terminator","http terminate","shutdown","terminate","application","server","node.js","nodejs","node","http","https","docker","kubernetes","prometheus","keep-alive","close"],"author":{"url":"https://tygra.io","name":"Tygra","email":"hi@tygra.io"},"license":"MIT","_id":"@tygra/nestjs-graceful-shutdown@1.0.0","maintainers":[{"name":"hienngm","email":"hienngm99@gmail.com"}],"contributors":[{"url":"https://github.com/hienngm","name":"hienngm","email":"hienngm99@gmail.com"}],"homepage":"https://github.com/tygra-io/nestjs-graceful-shutdown#readme","bugs":{"url":"https://github.com/tygra-io/nestjs-graceful-shutdown/issues"},"ava":{"files":["test/**/*.spec.ts"],"require":["ts-node/register/transpile-only"],"extensions":["ts"]},"nyc":{"exclude":["**/*.spec.js"],"extends":"@istanbuljs/nyc-config-typescript"},"dist":{"shasum":"1cd86e940f25ae6a2eb34f7b947a797cf188b7d8","tarball":"https://registry.npmjs.org/@tygra/nestjs-graceful-shutdown/-/nestjs-graceful-shutdown-1.0.0.tgz","fileCount":15,"integrity":"sha512-us5Ylvbs+9YTmz0DFEh1J0mdlY1ltKl2fA6ZOE1krKzf5L9aqiWqGvHkJ0KtMjDlYH1IVvV46FNdoNIRgJ0eYw==","signatures":[{"sig":"MEUCIQDTiELFRZiAscYKbu9fWEJXzdF4izLi5A0C7068V0lM3wIgLUv1E5qM2l2P+Auo/9roy+Vg7eK7yicXweWvphKzJq4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":31302},"main":"build/main/index.js","types":"build/main/index.d.ts","config":{"commitizen":{"path":"cz-conventional-changelog"}},"engines":{"node":">=14"},"gitHead":"2c3b84c4d5b3eb8552e0866bc0c81c7304f44c2c","scripts":{"cov":"run-s build test:unit cov:html cov:lcov && open-cli coverage/index.html","doc":"run-s doc:html && open-cli build/docs/index.html","fix":"run-s fix:*","test":"run-s build test:*","build":"run-p build:*","version":"standard-version","cov:html":"nyc report --reporter=html","cov:lcov":"nyc report --reporter=lcov","cov:send":"run-s cov:lcov && codecov","doc:html":"typedoc src/ --exclude **/*.spec.ts --target ES6 --mode file --out build/docs","doc:json":"typedoc src/ --exclude **/*.spec.ts --target ES6 --mode file --json build/docs/typedoc.json","fix:lint":"eslint src --ext .ts --fix","check-cli":"run-s test diff-integration-tests check-integration-tests","cov:check":"nyc report && nyc check-coverage --lines 100 --functions 100 --branches 100","test:lint":"eslint src --ext .ts","test:unit":"nyc --silent ava --verbose --serial","build:main":"tsc -p tsconfig.build.json","reset-hard":"git clean -dfx && git reset --hard && npm i","watch:test":"nyc ava --watch","doc:publish":"gh-pages -m \"[ci skip] Updates\" -d build/docs","watch:build":"tsc -p tsconfig.json -w","fix:prettier":"prettier \"src/**/*.ts\" --write","test:prettier":"prettier \"src/**/*.ts\" --list-different","test:spelling":"cspell \"{README.md,.github/*.md,src/**/*.ts}\"","prepare-release":"run-s reset-hard test cov:check doc:html version doc:publish","diff-integration-tests":"mkdir -p diff && rm -rf diff/test && cp -r test diff/test && rm -rf diff/test/test-*/.git && cd diff && git init --quiet && git add -A && git commit --quiet --no-verify --allow-empty -m 'WIP' && echo '\\n\\nCommitted most recent integration test output in the \"diff\" directory. Review the changes with \"cd diff && git diff HEAD\" or your preferred git diff viewer.'","check-integration-tests":"run-s check-integration-test:*"},"_npmUser":{"name":"hienngm","email":"hienngm99@gmail.com"},"prettier":{"singleQuote":true},"repository":{"url":"git+https://github.com/tygra-io/nestjs-graceful-shutdown.git","type":"git"},"_npmVersion":"10.9.3","description":"A powerful package for gracefully shutting down NestJS applications","directories":{},"_nodeVersion":"22.20.0","dependencies":{"@tygra/http-terminator":"^2.0.0"},"_hasShrinkwrap":false,"devDependencies":{"ava":"^3.15.0","got":"^11.8.2","nyc":"^15.1.0","delay":"^5.0.0","execa":"^7.1.1","sinon":"^11.1.2","cspell":"^4.1.0","eslint":"^7.8.0","codecov":"^3.5.0","ts-node":"^9.0.0","typedoc":"^0.24.7","gh-pages":"^3.1.0","open-cli":"^7.2.0","prettier":"^2.1.1","typescript":"^4.0.2","npm-run-all":"^4.1.5","@nestjs/core":"^9.4.2","@nestjs/common":"^9.4.2","agentkeepalive":"^4.1.4","@ava/typescript":"^4.0.0","reflect-metadata":"^0.1.12","standard-version":"^9.0.0","eslint-plugin-import":"^2.22.0","eslint-config-prettier":"^6.11.0","@nestjs/platform-express":"^9.4.2","@nestjs/platform-fastify":"^9.4.2","@typescript-eslint/parser":"^4.0.1","cz-conventional-changelog":"^3.3.0","eslint-plugin-eslint-comments":"^3.2.0","@typescript-eslint/eslint-plugin":"^4.0.1","@istanbuljs/nyc-config-typescript":"^1.0.1"},"peerDependencies":{"@nestjs/common":"*"},"_npmOperationalInternal":{"tmp":"tmp/nestjs-graceful-shutdown_1.0.0_1761647367269_0.641904590791218","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@tygra/nestjs-graceful-shutdown","version":"2.0.0","keywords":["nestjs","nest.js","nest","graceful shutdown","graceful-shutdown","graceful","gracefully","http-shutdown","http shutdown","http-terminate","http-terminator","http terminate","shutdown","terminate","application","server","node.js","nodejs","node","http","https","docker","kubernetes","prometheus","keep-alive","close"],"author":{"url":"https://tygra.io","name":"Tygra","email":"hi@tygra.io"},"license":"MIT","_id":"@tygra/nestjs-graceful-shutdown@2.0.0","maintainers":[{"name":"hienngm","email":"hienngm99@gmail.com"}],"contributors":[{"url":"https://github.com/hienngm","name":"hienngm","email":"hienngm99@gmail.com"}],"homepage":"https://github.com/tygra-io/nestjs-graceful-shutdown#readme","bugs":{"url":"https://github.com/tygra-io/nestjs-graceful-shutdown/issues"},"ava":{"files":["test/**/*.spec.ts"],"require":["ts-node/register/transpile-only"],"extensions":["ts"]},"nyc":{"exclude":["**/*.spec.js"],"extends":"@istanbuljs/nyc-config-typescript"},"dist":{"shasum":"b2fd6c2816608cbc61197e2b8fba0ec97bc33fc1","tarball":"https://registry.npmjs.org/@tygra/nestjs-graceful-shutdown/-/nestjs-graceful-shutdown-2.0.0.tgz","fileCount":15,"integrity":"sha512-OqzjxMslR53/7M4jRCTirH6f30V1per0N6nUKkDYLOe4jHzHZf5/a97qbx+uqkw/oIFU5wG/oZnCagWZngBGjw==","signatures":[{"sig":"MEUCIQDi4Oumhi4J3VKuhargHjTt1aAAp2uE0tzsiJQVr73WpQIgePFd6/t3JMO42YRVJ/h49jeOUl0DVl9Qq3LOuFvJK2g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@tygra%2fnestjs-graceful-shutdown@2.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":31302},"main":"build/main/index.js","types":"build/main/index.d.ts","config":{"commitizen":{"path":"cz-conventional-changelog"}},"engines":{"node":">=14"},"gitHead":"ba3832c25c24697b209a1bf90b2f797d557e3d60","scripts":{"cov":"run-s build test:unit cov:html cov:lcov && open-cli coverage/index.html","doc":"run-s doc:html && open-cli build/docs/index.html","fix":"run-s fix:*","test":"run-s build test:*","build":"run-p build:*","version":"standard-version","cov:html":"nyc report --reporter=html","cov:lcov":"nyc report --reporter=lcov","cov:send":"run-s cov:lcov && codecov","doc:html":"typedoc src/ --exclude **/*.spec.ts --target ES6 --mode file --out build/docs","doc:json":"typedoc src/ --exclude **/*.spec.ts --target ES6 --mode file --json build/docs/typedoc.json","fix:lint":"eslint src --ext .ts --fix","check-cli":"run-s test diff-integration-tests check-integration-tests","cov:check":"nyc report && nyc check-coverage --lines 100 --functions 100 --branches 100","test:lint":"eslint src --ext .ts","test:unit":"nyc --silent ava --verbose --serial","build:main":"tsc -p tsconfig.build.json","reset-hard":"git clean -dfx && git reset --hard && npm i","watch:test":"nyc ava --watch","doc:publish":"gh-pages -m \"[ci skip] Updates\" -d build/docs","watch:build":"tsc -p tsconfig.json -w","fix:prettier":"prettier \"src/**/*.ts\" --write","test:prettier":"prettier \"src/**/*.ts\" --list-different","test:spelling":"cspell \"{README.md,.github/*.md,src/**/*.ts}\"","prepare-release":"run-s reset-hard test cov:check doc:html version doc:publish","diff-integration-tests":"mkdir -p diff && rm -rf diff/test && cp -r test diff/test && rm -rf diff/test/test-*/.git && cd diff && git init --quiet && git add -A && git commit --quiet --no-verify --allow-empty -m 'WIP' && echo '\\n\\nCommitted most recent integration test output in the \"diff\" directory. Review the changes with \"cd diff && git diff HEAD\" or your preferred git diff viewer.'","check-integration-tests":"run-s check-integration-test:*"},"_npmUser":{"name":"hienngm","email":"hienngm99@gmail.com"},"prettier":{"singleQuote":true},"repository":{"url":"git+https://github.com/tygra-io/nestjs-graceful-shutdown.git","type":"git"},"_npmVersion":"10.8.2","description":"A powerful package for gracefully shutting down NestJS applications","directories":{},"_nodeVersion":"20.19.5","dependencies":{"@tygra/http-terminator":"^2.0.0"},"_hasShrinkwrap":false,"devDependencies":{"ava":"^3.15.0","got":"^11.8.2","nyc":"^15.1.0","delay":"^5.0.0","execa":"^7.1.1","sinon":"^11.1.2","cspell":"^4.1.0","eslint":"^7.8.0","codecov":"^3.5.0","ts-node":"^9.0.0","typedoc":"^0.24.7","gh-pages":"^3.1.0","open-cli":"^7.2.0","prettier":"^2.1.1","typescript":"^4.0.2","npm-run-all":"^4.1.5","@nestjs/core":"^9.4.2","@nestjs/common":"^9.4.2","agentkeepalive":"^4.1.4","@ava/typescript":"^4.0.0","reflect-metadata":"^0.1.12","standard-version":"^9.0.0","eslint-plugin-import":"^2.22.0","eslint-config-prettier":"^6.11.0","@nestjs/platform-express":"^9.4.2","@nestjs/platform-fastify":"^9.4.2","@typescript-eslint/parser":"^4.0.1","cz-conventional-changelog":"^3.3.0","eslint-plugin-eslint-comments":"^3.2.0","@typescript-eslint/eslint-plugin":"^4.0.1","@istanbuljs/nyc-config-typescript":"^1.0.1"},"peerDependencies":{"@nestjs/common":"*"},"_npmOperationalInternal":{"tmp":"tmp/nestjs-graceful-shutdown_2.0.0_1761647681340_0.8479691465642494","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2025-10-28T10:29:27.209Z","modified":"2025-11-27T18:17:55.708Z","1.0.0":"2025-10-28T10:29:27.491Z","2.0.0":"2025-10-28T10:34:41.534Z"},"bugs":{"url":"https://github.com/tygra-io/nestjs-graceful-shutdown/issues"},"author":{"url":"https://tygra.io","name":"Tygra","email":"hi@tygra.io"},"license":"MIT","homepage":"https://github.com/tygra-io/nestjs-graceful-shutdown#readme","keywords":["nestjs","nest.js","nest","graceful shutdown","graceful-shutdown","graceful","gracefully","http-shutdown","http shutdown","http-terminate","http-terminator","http terminate","shutdown","terminate","application","server","node.js","nodejs","node","http","https","docker","kubernetes","prometheus","keep-alive","close"],"repository":{"url":"git+https://github.com/tygra-io/nestjs-graceful-shutdown.git","type":"git"},"description":"A powerful package for gracefully shutting down NestJS applications","contributors":[{"url":"https://github.com/hienngm","name":"hienngm","email":"hienngm99@gmail.com"}],"maintainers":[{"email":"hienngm99@gmail.com","name":"hienngm"},{"email":"hi@tygra.io","name":"tygra.io"}],"readme":"<p align=\"center\">\n<a href=\"https://nestjs.com/\" target=\"blank\"><img src=\"https://nestjs.com/img/logo-small.svg\" width=\"120\" alt=\"Nest Logo\" /></a>\n</p>\n<h1 align=\"center\">NestJS Graceful Shutdown 🐈</h1>\n\n<p align=\"center\">\n  Elevate your NestJS application with seamless and reliable server shutdowns, guaranteeing uninterrupted user experiences and effortless handling of critical shutdown scenarios.\n  <p align=\"center\">\n    <a href=\"https://www.npmjs.com/package/@tygra/nestjs-graceful-shutdown\" target=\"_blank\"><img alt=\"npm version\" src=\"https://img.shields.io/npm/v/@tygra/nestjs-graceful-shutdown\" /></a>\n    <a href=\"https://www.npmjs.com/package/@tygra/nestjs-graceful-shutdown\" target=\"_blank\"><img alt=\"NPM\" src=\"https://img.shields.io/npm/l/@tygra/nestjs-graceful-shutdown\" /></a>\n    <a href=\"https://www.npmjs.com/package/@tygra/nestjs-graceful-shutdown\" target=\"_blank\"><img alt=\"npm downloads\" src=\"https://img.shields.io/npm/dm/@tygra/nestjs-graceful-shutdown\" /></a>\n     <a href=\"https://coveralls.io/github/tygra-io/nestjs-graceful-shutdown?branch=main\" target=\"_blank\"><img alt=\"coverage\" src=\"https://coveralls.io/repos/github/tygra-io/nestjs-graceful-shutdown/badge.svg?branch=main\" /></a>\n  </p>\n</p>\n\n## Table of Contents\n\n- [What's New](#whats-new)\n- [Description](#description)\n- [Installation](#installation)\n- [Example](#example)\n- [Configuration](#configuration)\n- [Testing Instructions](#testing-instructions)\n- [Contact and Feedback](#contact-and-feedback)\n- [License](#license)\n\n## What's New\n\n### Enhanced Reliability & Test Coverage\n\n- **Comprehensive test coverage**: Achieved >99% statement coverage and >87% branch coverage with 44+ test cases\n- **Robust error handling**: Improved fallback mechanisms and graceful degradation when termination fails\n- **Edge case coverage**: Extensive testing of error scenarios including cleanup failures, termination errors, and signal handling\n- **Production-ready**: Ensures your application never hangs, with intelligent fallback to direct server close\n\n## Description\n\nDon't let your server hang indefinitely!\n\nWhen you explicitly call `app.close()` or if the process receive a special system signal (such as SIGTERM) after correctly invoking `enableShutdownHooks` during application bootstrap (check out the <a href=\"https://docs.nestjs.com/fundamentals/lifecycle-events#application-shutdown\" target=\"_blank\">NestJS docs</a>), the server stops accepting new connections while maintaining existing ones. This leads to your server hanging indefinitely due to lingering keep-alive connections or unresponsive requests.\n\nPowered by the robust <a href=\"https://www.npmjs.com/package/@tygra/http-terminator\" target=\"_blank\">`@tygra/http-terminator`</a> library and backed by NestJS's built-in shutdown hooks, `@tygra/nestjs-graceful-shutdown` ensures graceful communication with clients currently receiving responses from your server during the shutdown process. Experience a reliable and hassle-free server shutdown with ease.\n\n## Installation\n\nYou can install the library using npm:\n\n```\nnpm install @tygra/nestjs-graceful-shutdown\n```\n\n> **Note:** `@tygra/http-terminator` is automatically installed as a dependency when you install `@tygra/nestjs-graceful-shutdown`.\n\n## Example\n\nTo integrate `@tygra/nestjs-graceful-shutdown` into your NestJS application, follow these steps:\n\n1. First, import the module with `GracefulShutdownModule.forRoot(...)` or `GracefulShutdownModule.forRootAsync(...)` into your root `AppModule`. (refer to the module configuration documentation [below](#configuration)).\n\n```ts\nimport { GracefulShutdownModule } from '@tygra/nestjs-graceful-shutdown';\n\n@Module({\n  imports: [GracefulShutdownModule.forRoot()],\n  ...\n})\nclass AppModule {}\n```\n\n2. Next, set up graceful shutdown for your NestJS application by calling the `setupGracefulShutdown(...)` function.\n\n> ⚠️ **Warning:** `@tygra/nestjs-graceful-shutdown` will automatically enable the shutdown hooks. Avoid calling `enableShutdownHooks` separately in your application, as it may lead to unexpected behavior. For more information on NestJS application lifecycle, refer to the <a href =\"https://docs.nestjs.com/fundamentals/lifecycle-events#application-shutdown\" target=\"_blank\">NestJS documentation</a>.\n\n```typescript\nimport { setupGracefulShutdown } from '@tygra/nestjs-graceful-shutdown';\nimport { NestFactory } from '@nestjs/core';\nimport { AppModule } from './app.module';\n\nasync function bootstrap() {\n  const app = await NestFactory.create(AppModule);\n  // Additional configuration for your NestJS app\n\n  setupGracefulShutdown({ app });\n\n  await app.listen(3000);\n\n  // Note: Timeout is used for illustration of\n  // delayed termination purposes only.\n  setTimeout(() => {\n    process.kill(process.pid, 'SIGTERM');\n  }, 5000);\n}\nbootstrap();\n```\n\nPlease note that the above code snippets demonstrate the basic setup of `@tygra/nestjs-graceful-shutdown` in your NestJS application. Make sure to adjust the code based on your specific application requirements and configuration.\n\n## Configuration\n\n### Configuration interface\n\nThe following interface is used for `GracefulShutdownModule` configuration:\n\n```ts\ninterface IGracefulShutdownConfigOptions {\n  /**\n   * Cleanup function for releasing application resources\n   * during server shutdown.\n   */\n  cleanup?: (app: INestApplication, signal?: string) => any;\n  /**\n   * The duration in milliseconds before forcefully\n   * terminating a connection.\n   * Defaults: 5000 (5 seconds).\n   */\n  gracefulShutdownTimeout?: number;\n}\n```\n\nThe following interface is used for `setupGracefulShutdown` function parameters:\n\n```ts\ninterface ISetupFunctionParams {\n  /**\n   * Your NestJS application.\n   */\n  app: INestApplication;\n  /**\n   * Shutdown signals that the application should listen to.\n   * By default, it listens to all ShutdownSignals.\n   */\n  signals?: ShutdownSignal[] | string[];\n}\n```\n\n### Zero configuration\n\nJust import `GracefulShutdownModule` to `AppModule`:\n\n```ts\nimport { GracefulShutdownModule } from '@tygra/nestjs-graceful-shutdown';\n\n@Module({\n  imports: [GracefulShutdownModule.forRoot()],\n  ...\n})\nclass AppModule {}\n```\n\n### Synchronous configuration\n\nUse `GracefulShutdownModule.forRoot` method with argument of [Configuration interface](#configuration-interface):\n\n```ts\nimport { GracefulShutdownModule } from '@tygra/nestjs-graceful-shutdown';\n\n@Module({\n  imports: [\n    GracefulShutdownModule.forRoot({\n      cleanup: async (app, signal) => {\n        // releasing resources\n      },\n      gracefulShutdownTimeout:\n        Number(process.env.GRACEFUL_SHUTDOWN_TIMEOUT ?? 10000),\n    })\n  ],\n  ...\n})\nclass AppModule {}\n```\n\n### Asynchronous configuration\n\nWith `GracefulShutdownModule.forRootAsync` you can, for example, import your `ConfigModule` and inject `ConfigService` to use it in `useFactory` method.\n\n`useFactory` should return object with [Configuration interface](#configuration-interface)\n\nHere's an example:\n\n```ts\nimport { GracefulShutdownModule } from '@tygra/nestjs-graceful-shutdown';\n\n@Injectable()\nclass ConfigService {\n  public readonly timeout = 10000;\n}\n\n@Module({\n  providers: [ConfigService],\n  exports: [ConfigService]\n})\nclass ConfigModule {}\n\n@Module({\n  imports: [\n    GracefulShutdownModule.forRootAsync({\n      imports: [ConfigModule],\n      inject: [ConfigService],\n      useFactory: async (config: ConfigService) => {\n        await somePromise();\n        return {\n          gracefulShutdownTimeout: config.timeout,\n        };\n      }\n    })\n  ],\n  ...\n})\nclass AppModule {}\n```\n\n### Testing Instructions\n\nWhen testing, you may need to override the graceful shutdown module with a mock module. Thanks to NestJS, this can easily be achieved using `overrideModule`. See the following example:\n\n```typescript\nconst moduleFixture: TestingModule = await Test.createTestingModule({\n  imports: [AppModule],\n})\n  .overrideModule(GracefulShutdownModule)\n  .useModule(MockModule)\n  .compile();\n```\n\nIf you don't want to use a `MockModule`, you can use `app.listen()` instead of `app.init()` in your test file.\n\n```typescript\nbeforeEach(async () => {\n  const moduleFixture: TestingModule = await Test.createTestingModule({\n    imports: [AppModule],\n  }).compile();\n\n  app = moduleFixture.createNestApplication();\n  setupGracefulShutdown({ app });\n  await app.listen();\n});\n```\n\n## Contact and Feedback\n\nFeel free to reach out if you have any ideas, comments, or questions.\n\nBest regards,\n\nHien\n\n## License\n\nThis library is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.\n","readmeFilename":"README.md"}