From 4affeb2c5cf3aef918dfa40cfb1aaaec5ddc07c4 Mon Sep 17 00:00:00 2001 From: AmineMaila Date: Wed, 22 Jul 2026 16:15:33 +0100 Subject: [PATCH] fix: replace async-exit-hook with exit-hook to preserve process.exitCode --- package-lock.json | 101 +++++++++--------- packages/embedded-postgres/package.json | 3 +- packages/embedded-postgres/src/index.ts | 13 ++- .../tests/helpers/exit-code-test.mjs | 10 ++ .../embedded-postgres/tests/index.test.ts | 23 ++++ 5 files changed, 89 insertions(+), 61 deletions(-) create mode 100644 packages/embedded-postgres/tests/helpers/exit-code-test.mjs diff --git a/package-lock.json b/package-lock.json index b24d183..62c092e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2627,12 +2627,6 @@ "@types/node": "*" } }, - "node_modules/@types/async-exit-hook": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/async-exit-hook/-/async-exit-hook-2.0.0.tgz", - "integrity": "sha512-RNjIyjnVZdcP5a1zeIPb5c0hq2nbJc/NOCLNKUAqeCw+J5z2zMcINISn9wybCWhczHnUu3VSUFy7ZCO6ir4ZRw==", - "dev": true - }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -3260,14 +3254,6 @@ "node": "*" } }, - "node_modules/async-exit-hook": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", - "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", @@ -4745,6 +4731,18 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/exit-hook": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-5.1.0.tgz", + "integrity": "sha512-INjr2xyxHo7bhAqf5ong++GZPPnpcuBcaXUKt03yf7Fie9yWD7FapL4teOU0+awQazGs5ucBh7xWs/AD+6nhog==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -10268,7 +10266,7 @@ }, "packages/darwin-arm64": { "name": "@embedded-postgres/darwin-arm64", - "version": "17.2.0-beta.14", + "version": "18.4.0-beta.17", "cpu": [ "arm64" ], @@ -10278,8 +10276,8 @@ "darwin" ], "devDependencies": { - "@embedded-postgres/downloader": "^17.2.0-beta.14", - "@embedded-postgres/symlink-reader": "^17.2.0-beta.14" + "@embedded-postgres/downloader": "^18.4.0-beta.17", + "@embedded-postgres/symlink-reader": "^18.4.0-beta.17" }, "engines": { "node": ">=16" @@ -10287,7 +10285,7 @@ }, "packages/darwin-x64": { "name": "@embedded-postgres/darwin-x64", - "version": "17.2.0-beta.14", + "version": "18.4.0-beta.17", "cpu": [ "x64" ], @@ -10297,8 +10295,8 @@ "darwin" ], "devDependencies": { - "@embedded-postgres/downloader": "^17.2.0-beta.14", - "@embedded-postgres/symlink-reader": "^17.2.0-beta.14" + "@embedded-postgres/downloader": "^18.4.0-beta.17", + "@embedded-postgres/symlink-reader": "^18.4.0-beta.17" }, "engines": { "node": ">=16" @@ -10306,7 +10304,7 @@ }, "packages/downloader": { "name": "@embedded-postgres/downloader", - "version": "17.2.0-beta.14", + "version": "18.4.0-beta.17", "license": "MIT", "dependencies": { "adm-zip": "^0.5.9", @@ -10323,15 +10321,14 @@ } }, "packages/embedded-postgres": { - "version": "17.2.0-beta.14", + "version": "18.4.0-beta.17", "license": "MIT", "dependencies": { - "async-exit-hook": "^2.0.1", + "exit-hook": "^5.1.0", "pg": "^8.7.3" }, "devDependencies": { - "@embedded-postgres/symlink-reader": "^17.2.0-beta.14", - "@types/async-exit-hook": "^2.0.0", + "@embedded-postgres/symlink-reader": "^18.4.0-beta.17", "@types/pg": "^8.6.5", "eslint": "^8.56.0", "typescript": "^4.7.3", @@ -10341,19 +10338,19 @@ "node": ">=16" }, "optionalDependencies": { - "@embedded-postgres/darwin-arm64": "^17.2.0-beta.14", - "@embedded-postgres/darwin-x64": "^17.2.0-beta.14", - "@embedded-postgres/linux-arm": "^17.2.0-beta.14", - "@embedded-postgres/linux-arm64": "^17.2.0-beta.14", - "@embedded-postgres/linux-ia32": "^17.2.0-beta.14", - "@embedded-postgres/linux-ppc64": "^17.2.0-beta.14", - "@embedded-postgres/linux-x64": "^17.2.0-beta.14", - "@embedded-postgres/windows-x64": "^17.2.0-beta.14" + "@embedded-postgres/darwin-arm64": "^18.4.0-beta.17", + "@embedded-postgres/darwin-x64": "^18.4.0-beta.17", + "@embedded-postgres/linux-arm": "^18.4.0-beta.17", + "@embedded-postgres/linux-arm64": "^18.4.0-beta.17", + "@embedded-postgres/linux-ia32": "^18.4.0-beta.17", + "@embedded-postgres/linux-ppc64": "^18.4.0-beta.17", + "@embedded-postgres/linux-x64": "^18.4.0-beta.17", + "@embedded-postgres/windows-x64": "^18.4.0-beta.17" } }, "packages/linux-arm": { "name": "@embedded-postgres/linux-arm", - "version": "17.2.0-beta.14", + "version": "18.4.0-beta.17", "cpu": [ "arm" ], @@ -10363,8 +10360,8 @@ "linux" ], "devDependencies": { - "@embedded-postgres/downloader": "^17.2.0-beta.14", - "@embedded-postgres/symlink-reader": "^17.2.0-beta.14" + "@embedded-postgres/downloader": "^18.4.0-beta.17", + "@embedded-postgres/symlink-reader": "^18.4.0-beta.17" }, "engines": { "node": ">=16" @@ -10372,7 +10369,7 @@ }, "packages/linux-arm64": { "name": "@embedded-postgres/linux-arm64", - "version": "17.2.0-beta.14", + "version": "18.4.0-beta.17", "cpu": [ "arm64" ], @@ -10382,8 +10379,8 @@ "linux" ], "devDependencies": { - "@embedded-postgres/downloader": "^17.2.0-beta.14", - "@embedded-postgres/symlink-reader": "^17.2.0-beta.14" + "@embedded-postgres/downloader": "^18.4.0-beta.17", + "@embedded-postgres/symlink-reader": "^18.4.0-beta.17" }, "engines": { "node": ">=16" @@ -10391,7 +10388,7 @@ }, "packages/linux-ia32": { "name": "@embedded-postgres/linux-ia32", - "version": "17.2.0-beta.14", + "version": "18.4.0-beta.17", "cpu": [ "ia32" ], @@ -10401,8 +10398,8 @@ "linux" ], "devDependencies": { - "@embedded-postgres/downloader": "^17.2.0-beta.14", - "@embedded-postgres/symlink-reader": "^17.2.0-beta.14" + "@embedded-postgres/downloader": "^18.4.0-beta.17", + "@embedded-postgres/symlink-reader": "^18.4.0-beta.17" }, "engines": { "node": ">=16" @@ -10410,7 +10407,7 @@ }, "packages/linux-ppc64": { "name": "@embedded-postgres/linux-ppc64", - "version": "17.2.0-beta.14", + "version": "18.4.0-beta.17", "cpu": [ "ppc64" ], @@ -10420,8 +10417,8 @@ "linux" ], "devDependencies": { - "@embedded-postgres/downloader": "^17.2.0-beta.14", - "@embedded-postgres/symlink-reader": "^17.2.0-beta.14" + "@embedded-postgres/downloader": "^18.4.0-beta.17", + "@embedded-postgres/symlink-reader": "^18.4.0-beta.17" }, "engines": { "node": ">=16" @@ -10429,7 +10426,7 @@ }, "packages/linux-x64": { "name": "@embedded-postgres/linux-x64", - "version": "17.2.0-beta.14", + "version": "18.4.0-beta.17", "cpu": [ "x64" ], @@ -10439,8 +10436,8 @@ "linux" ], "devDependencies": { - "@embedded-postgres/downloader": "^17.2.0-beta.14", - "@embedded-postgres/symlink-reader": "^17.2.0-beta.14" + "@embedded-postgres/downloader": "^18.4.0-beta.17", + "@embedded-postgres/symlink-reader": "^18.4.0-beta.17" }, "engines": { "node": ">=16" @@ -10448,7 +10445,7 @@ }, "packages/symlink-reader": { "name": "@embedded-postgres/symlink-reader", - "version": "17.2.0-beta.14", + "version": "18.4.0-beta.17", "license": "MIT", "devDependencies": { "eslint": "^8.56.0", @@ -10460,7 +10457,7 @@ }, "packages/windows-x64": { "name": "@embedded-postgres/windows-x64", - "version": "17.2.0-beta.14", + "version": "18.4.0-beta.17", "cpu": [ "x64" ], @@ -10470,8 +10467,8 @@ "win32" ], "devDependencies": { - "@embedded-postgres/downloader": "^17.2.0-beta.14", - "@embedded-postgres/symlink-reader": "^17.2.0-beta.14" + "@embedded-postgres/downloader": "^18.4.0-beta.17", + "@embedded-postgres/symlink-reader": "^18.4.0-beta.17" }, "engines": { "node": ">=16" diff --git a/packages/embedded-postgres/package.json b/packages/embedded-postgres/package.json index 7bbad91..95e9366 100644 --- a/packages/embedded-postgres/package.json +++ b/packages/embedded-postgres/package.json @@ -25,7 +25,6 @@ "license": "MIT", "devDependencies": { "@embedded-postgres/symlink-reader": "^18.4.0-beta.17", - "@types/async-exit-hook": "^2.0.0", "@types/pg": "^8.6.5", "eslint": "^8.56.0", "typescript": "^4.7.3", @@ -42,7 +41,7 @@ "@embedded-postgres/windows-x64": "^18.4.0-beta.17" }, "dependencies": { - "async-exit-hook": "^2.0.1", + "exit-hook": "^5.1.0", "pg": "^8.7.3" }, "publishConfig": { diff --git a/packages/embedded-postgres/src/index.ts b/packages/embedded-postgres/src/index.ts index b11391b..41aa547 100644 --- a/packages/embedded-postgres/src/index.ts +++ b/packages/embedded-postgres/src/index.ts @@ -5,7 +5,7 @@ import { platform, tmpdir, userInfo } from 'os'; import { ChildProcess, spawn, exec, execSync } from 'child_process'; import pg from 'pg'; -import AsyncExitHook from 'async-exit-hook'; +import { asyncExitHook } from 'exit-hook'; import getBinaries from './binary.js'; import { PostgresOptions } from './types.js'; @@ -430,17 +430,16 @@ async function execAsync(command: string) { * nicely shutdown all potentially started clusters, and we don't end up with * zombie processes. */ -async function gracefulShutdown(done: () => void) { +async function gracefulShutdown() { // Loop through all instances, stop them, and await the response await Promise.all([...instances].map((instance) => { return instance.stop(); })); - - // Let NodeJS know we're done - done(); } // Register graceful shutdown function -AsyncExitHook(gracefulShutdown); +asyncExitHook(gracefulShutdown, { + wait: 5000 +}); -export default EmbeddedPostgres; \ No newline at end of file +export default EmbeddedPostgres; diff --git a/packages/embedded-postgres/tests/helpers/exit-code-test.mjs b/packages/embedded-postgres/tests/helpers/exit-code-test.mjs new file mode 100644 index 0000000..7d1c578 --- /dev/null +++ b/packages/embedded-postgres/tests/helpers/exit-code-test.mjs @@ -0,0 +1,10 @@ +import EmbeddedPostgres from '../../dist/index.js'; + +const pg = new EmbeddedPostgres({ + port: 15433, + databaseDir: '/tmp/ep-exit-code-test', + persistent: false, + onLog: () => {}, +}); + +process.exitCode = 42; diff --git a/packages/embedded-postgres/tests/index.test.ts b/packages/embedded-postgres/tests/index.test.ts index 8acbb1a..f36e672 100644 --- a/packages/embedded-postgres/tests/index.test.ts +++ b/packages/embedded-postgres/tests/index.test.ts @@ -1,6 +1,7 @@ import { it, expect, afterEach } from 'vitest'; import fs from 'fs/promises'; import path from 'path'; +import { spawn } from 'child_process'; import EmbeddedPostgres from '../src/index.js'; import { PostgresOptions } from '../src/types.js'; import { beforeEach } from 'node:test'; @@ -159,4 +160,26 @@ it('should ensure binary files have correct permissions', async () => { const afterFixStat = await fs.stat(postgres); // Permissions should still be correct expect((afterFixStat.mode & expectedPermissions)).toBe(expectedPermissions); +}); + +it('should preserve a custom process.exitCode when the process exits (gracefulShutdown does not force exit 0)', async () => { + const scriptPath = new URL('./helpers/exit-code-test.mjs', import.meta.url).pathname; + + await new Promise((resolve, reject) => { + const child = spawn(process.execPath, [scriptPath], { + stdio: ['ignore', 'pipe', 'pipe'], + }); + + child.on('exit', (code) => { + try { + expect(code).toBe(42); + } catch (e) { + reject(e); + return; + } + resolve(); + }); + + child.on('error', reject); + }); }); \ No newline at end of file