diff --git a/lib/transport-stream.js b/lib/transport-stream.js index 9da0ff8ce..b152fc9ff 100644 --- a/lib/transport-stream.js +++ b/lib/transport-stream.js @@ -31,8 +31,10 @@ async function loadTransportStreamBuilder (target) { // See this PR for details: https://github.com/pinojs/thread-stream/pull/34 if ((error.code === 'ENOTDIR' || error.code === 'ERR_MODULE_NOT_FOUND')) { fn = realRequire(target) - } else if (error.code === undefined) { + } else if (error.code === undefined || error.code === 'ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING') { // When bundled with pkg, an undefined error is thrown when called with realImport + // When bundled with pkg and using node v20, an ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING error is thrown when called with realImport + // More info at: https://github.com/pinojs/thread-stream/issues/143 fn = realRequire(decodeURIComponent(target)) } else { throw error diff --git a/package.json b/package.json index b1d181d6a..76bf66bde 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "@types/flush-write-stream": "^1.0.0", "@types/node": "^20.2.3", "@types/tap": "^15.0.6", + "@yao-pkg/pkg": "^5.11.5", "airtap": "4.0.4", "benchmark": "^2.1.4", "bole": "^5.0.5", diff --git a/test/pkg/index.js b/test/pkg/index.js new file mode 100644 index 000000000..762a62ff7 --- /dev/null +++ b/test/pkg/index.js @@ -0,0 +1,46 @@ +'use strict' + +const os = require('os') +const { join } = require('path') +const { readFile } = require('fs').promises +const { watchFileCreated, file } = require('../helper') +const { test } = require('tap') +const pino = require('../../pino') + +const { pid } = process +const hostname = os.hostname() + +/** + * This file is packaged using pkg in order to test if transport-stream.js works in that context + */ + +test('pino.transport with worker destination overridden by bundler and mjs transport', async ({ same, teardown }) => { + globalThis.__bundlerPathsOverrides = { + 'pino-worker': join(__dirname, '..', '..', 'lib/worker.js') + } + + const destination = file() + const transport = pino.transport({ + targets: [ + { + target: join(__dirname, '..', 'fixtures', 'ts', 'to-file-transport.es2017.cjs'), + options: { destination } + } + ] + }) + + teardown(transport.end.bind(transport)) + const instance = pino(transport) + instance.info('hello') + await watchFileCreated(destination) + const result = JSON.parse(await readFile(destination)) + delete result.time + same(result, { + pid, + hostname, + level: 30, + msg: 'hello' + }) + + globalThis.__bundlerPathsOverrides = undefined +}) diff --git a/test/pkg/pkg.config.json b/test/pkg/pkg.config.json new file mode 100644 index 000000000..a7d2b990c --- /dev/null +++ b/test/pkg/pkg.config.json @@ -0,0 +1,17 @@ +{ + "pkg": { + "assets": [ + "../../lib/worker.js", + "../../lib/transport-stream.js", + "../../test/fixtures/ts/to-file-transport.es2017.cjs", + "../../node_modules/pino-abstract-transport/index.js" + ], + "targets": [ + "node14", + "node16", + "node18", + "node20" + ], + "outputPath": "test/pkg" + } +} \ No newline at end of file diff --git a/test/pkg/pkg.test.js b/test/pkg/pkg.test.js new file mode 100644 index 000000000..1def2f897 --- /dev/null +++ b/test/pkg/pkg.test.js @@ -0,0 +1,56 @@ +'use strict' + +const { test } = require('tap') +const config = require('./pkg.config.json') +const { promisify } = require('util') +const { unlink } = require('fs/promises') +const { join } = require('path') +const { platform } = require('process') +const exec = promisify(require('child_process').exec) + +/** + * The following regex is for tesintg the deprecation warning that is thrown by the `punycode` module. + * Exact text that it's matching is: + * (node:1234) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. + Please use a userland alternative instead. + + (Use `node --trace-deprecation ...` to show where the warning was created) + */ +const deprecationWarningRegex = /^\(\w+:\d+\)\s\[[\w|\d]+\]\sDeprecationWarning: The `punycode` module is deprecated\.\s+Please use a userland alternative instead\.\s+\(Use `node --trace-deprecation \.\.\.` to show where the warning was created\)\s+$/ + +test('worker test when packaged into executable using pkg', async (t) => { + const packageName = 'index' + + // package the app into several node versions, check config for more info + const filePath = `${join(__dirname, packageName)}.js` + const configPath = join(__dirname, 'pkg.config.json') + const { stderr } = await exec(`npx pkg ${filePath} --config ${configPath}`) + + // there should be no error when packaging + const expectedvalue = stderr === '' || deprecationWarningRegex.test(stderr) + t.ok(expectedvalue) + + // pkg outputs files in the following format by default: {filename}-{node version} + for (const target of config.pkg.targets) { + // execute the packaged test + let executablePath = `${join(config.pkg.outputPath, packageName)}-${target}` + + // when on windows, we need the .exe extension + if (platform === 'win32') { + executablePath = `${executablePath}.exe` + } else { + executablePath = `./${executablePath}` + } + + const { stderr } = await exec(executablePath) + + // check if there were no errors + const expectedvalue = stderr === '' || deprecationWarningRegex.test(stderr) + t.ok(expectedvalue) + + // clean up afterwards + await unlink(executablePath) + } + + t.end() +})