diff --git a/.changeset/wise-ladybugs-nail.md b/.changeset/wise-ladybugs-nail.md new file mode 100644 index 00000000000..c2e47010682 --- /dev/null +++ b/.changeset/wise-ladybugs-nail.md @@ -0,0 +1,5 @@ +--- +"@fuel-ts/account": patch +--- + +fix: enable `fuel-core` node cleanup to work in Bun diff --git a/packages/account/package.json b/packages/account/package.json index d1d78a1d269..5702f108368 100644 --- a/packages/account/package.json +++ b/packages/account/package.json @@ -68,7 +68,6 @@ "ramda": "^0.30.1" }, "devDependencies": { - "type-fest": "^4.26.1", "@fuel-ts/hasher": "workspace:*", "@fuel-ts/math": "workspace:*", "@fuel-ts/utils": "workspace:*", @@ -76,8 +75,9 @@ "@graphql-codegen/typescript": "^4.0.9", "@graphql-codegen/typescript-generic-sdk": "^4.0.1", "@graphql-codegen/typescript-operations": "^4.2.3", + "@internal/utils": "workspace:*", "@types/ramda": "^0.30.2", "get-graphql-schema": "^2.1.2", - "@internal/utils": "workspace:*" + "type-fest": "^4.26.1" } } diff --git a/packages/account/src/test-utils/launchNode.test.ts b/packages/account/src/test-utils/launchNode.test.ts index 46091a0ef8f..410ca85ac32 100644 --- a/packages/account/src/test-utils/launchNode.test.ts +++ b/packages/account/src/test-utils/launchNode.test.ts @@ -30,7 +30,7 @@ vi.mock('fs', async () => { */ describe('launchNode', () => { test('using ephemeral port 0 is possible', async () => { - const { cleanup, port, url } = await launchNode({ port: '0' }); + const { cleanup, port, url } = await launchNode({ port: '0', loggingEnabled: false }); expect(await fetch(url)).toBeTruthy(); expect(port).not.toEqual('0'); @@ -38,7 +38,7 @@ describe('launchNode', () => { }); it('cleanup kills the started node', async () => { - const { cleanup, url } = await launchNode(); + const { cleanup, url } = await launchNode({ loggingEnabled: false }); expect(await fetch(url)).toBeTruthy(); cleanup(); @@ -57,7 +57,7 @@ describe('launchNode', () => { const spawnSpy = vi.spyOn(childProcessMod, 'spawn'); const killSpy = vi.spyOn(process, 'kill'); - const { cleanup, pid } = await launchNode(); + const { cleanup, pid } = await launchNode({ loggingEnabled: false }); const spawnOptions = spawnSpy.mock.calls[0][2]; expect(spawnOptions.detached).toBeTruthy(); @@ -74,7 +74,7 @@ describe('launchNode', () => { process.env.FUEL_CORE_PATH = ''; - const { result } = await safeExec(async () => launchNode()); + const { result } = await safeExec(async () => launchNode({ loggingEnabled: false })); const command = spawnSpy.mock.calls[0][0]; expect(command).toEqual('fuel-core'); @@ -95,7 +95,7 @@ describe('launchNode', () => { const fuelCorePath = './my-fuel-core-binary-path'; const { error } = await safeExec(async () => { - await launchNode({ fuelCorePath, loggingEnabled: true }); + await launchNode({ fuelCorePath, loggingEnabled: false }); }); expect(error).toBeTruthy(); @@ -107,7 +107,7 @@ describe('launchNode', () => { test('reads FUEL_CORE_PATH environment variable for fuel-core binary', async () => { const spawnSpy = vi.spyOn(childProcessMod, 'spawn'); process.env.FUEL_CORE_PATH = 'fuels-core'; - const { cleanup, url } = await launchNode(); + const { cleanup, url } = await launchNode({ loggingEnabled: false }); await Provider.create(url); const command = spawnSpy.mock.calls[0][0]; @@ -152,7 +152,7 @@ describe('launchNode', () => { }); test('logs fuel-core outputs via console.log', async () => { - const logSpy = vi.spyOn(console, 'log'); + const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); const { cleanup } = await launchNode({ loggingEnabled: true }); const logs = logSpy.mock.calls.map((call) => call[0]); @@ -162,7 +162,7 @@ describe('launchNode', () => { test('cleanup removes temporary directory', async () => { const mkdirSyncSpy = vi.spyOn(fsMod, 'mkdirSync'); - const { cleanup } = await launchNode(); + const { cleanup } = await launchNode({ loggingEnabled: false }); expect(mkdirSyncSpy).toHaveBeenCalledTimes(1); const tempDirPath = mkdirSyncSpy.mock.calls[0][0]; @@ -252,4 +252,18 @@ describe('launchNode', () => { `fuel-core node under pid ${pid} does not exist. The node might have been killed before cleanup was called. Exiting cleanly.` ); }); + + test('should clean up when unable to kill process with "RangeError: pid must be a positive integer" error', async () => { + const killSpy = vi.spyOn(process, 'kill').mockImplementationOnce(() => { + throw new RangeError('pid must be a positive integer'); + }); + + const { pid, cleanup } = await launchNode({ loggingEnabled: false }); + + cleanup(); + + expect(killSpy).toBeCalledTimes(2); + expect(killSpy).toBeCalledWith(-pid); + expect(killSpy).toBeCalledWith(+pid); + }); }); diff --git a/packages/account/src/test-utils/launchNode.ts b/packages/account/src/test-utils/launchNode.ts index 9a5a6f61ddc..a4371ab023c 100644 --- a/packages/account/src/test-utils/launchNode.ts +++ b/packages/account/src/test-utils/launchNode.ts @@ -236,6 +236,10 @@ export const launchNode = async ({ console.log( `fuel-core node under pid ${child.pid} does not exist. The node might have been killed before cleanup was called. Exiting cleanly.` ); + } else if (error.message.includes('pid must be a positive integer')) { + // This is a workaround for a bug with Bun. + // See: https://github.com/oven-sh/bun/issues/8787 + process.kill(+child.pid); } else { throw e; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index aab96793da5..2754d6a4ae4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6863,9 +6863,6 @@ packages: async@3.2.5: resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} - async@3.2.6: - resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} - asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -24715,8 +24712,6 @@ snapshots: async@3.2.5: {} - async@3.2.6: {} - asynckit@0.4.0: {} at-least-node@1.0.0: {} @@ -29475,7 +29470,7 @@ snapshots: jake@10.8.7: dependencies: - async: 3.2.6 + async: 3.2.5 chalk: 4.1.2 filelist: 1.0.4 minimatch: 3.1.2 @@ -30626,7 +30621,7 @@ snapshots: markdown-link-check@3.12.2: dependencies: - async: 3.2.6 + async: 3.2.5 chalk: 5.3.0 commander: 12.1.0 link-check: 5.4.0 diff --git a/tsconfig.test.json b/tsconfig.test.json index 96ad5020fb9..0ca9f42bd9a 100644 --- a/tsconfig.test.json +++ b/tsconfig.test.json @@ -3,6 +3,6 @@ "compilerOptions": { "noEmit": true }, - "include": ["**/*.test.ts"], + "include": ["**/*.test.ts", "**/*.d.ts"], "exclude": ["node_modules", "apps/docs/src/**/*.test.ts"] }