diff --git a/README.md b/README.md index 0163aa3..4fe1cbb 100644 --- a/README.md +++ b/README.md @@ -95,3 +95,21 @@ case, the resolved filename of the module being patched is appended. For example, if we are patching `lib/index.js` in the `foo` package, and we set a base directory of `/tmp/dump/`, then the patched code will be written to `/tmp/dump/foo/lib/index.js`. + +### Diagnostics Hook + +A diagnostics hook can be set which is called every time a module is transformed +or transformation fails. This hook will only work with the synchronous +`registerHooks` because the older `register` runs in a different thread. + +```js +import { setDiagnosticsHook } from '@apm-js-collab/tracing-hooks/hook-sync.mjs' + +setDiagnosticsHook(({ url, moduleName, error }) => { + if(error) { + // injection failed + } else { + // injection succeeded + } +}) +``` \ No newline at end of file diff --git a/hook-sync.mjs b/hook-sync.mjs index 6706979..2b221a1 100644 --- a/hook-sync.mjs +++ b/hook-sync.mjs @@ -1 +1 @@ -export { initializeSync as initialize, loadSync as load, resolveSync as resolve } from './hook.mjs' +export { initializeSync as initialize, loadSync as load, resolveSync as resolve, setDiagnosticsHook } from './hook.mjs' diff --git a/hook.mjs b/hook.mjs index 0b30ca0..2cc5613 100644 --- a/hook.mjs +++ b/hook.mjs @@ -11,6 +11,12 @@ let transformers = null let packages = null let instrumentator = null +let diagnosticsHook; + +export function setDiagnosticsHook(hook) { + diagnosticsHook = hook +} + export async function initialize(data = {}) { return initializeSync(data) } @@ -79,12 +85,18 @@ export function loadResult(url, result) { const transformedCode = transformer.transform(code.toString('utf8'), 'unknown') result.source = transformedCode?.code result.shortCircuit = true + if (diagnosticsHook) { + diagnosticsHook({ url, moduleName: transformer.moduleName }) + } } catch(err) { debug('Error transforming module %s: %o', url, err) + if (diagnosticsHook) { + diagnosticsHook({ url, moduleName: transformer.moduleName, error: err }) + } } finally { transformer.free() } } return result -} +} \ No newline at end of file diff --git a/package.json b/package.json index 6dce029..efbc5b5 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "lib" ], "dependencies": { - "@apm-js-collab/code-transformer": "^0.13.0", + "@apm-js-collab/code-transformer": "^0.14.0", "debug": "^4.4.1", "module-details-from-path": "^1.0.4" }, diff --git a/test/hook-sync.test.mjs b/test/hook-sync.test.mjs index c856cff..b427da1 100644 --- a/test/hook-sync.test.mjs +++ b/test/hook-sync.test.mjs @@ -201,3 +201,25 @@ test('should default initialization to not crash if not defined', async (t) => { const snapshot = await snap(result.source) assert.deepEqual(result.source, snapshot) }) + +test('should rewrite code and call diagnostics hook', async (t) => { + const { syncLoaderRewriter, snap } = t.ctx + syncLoaderRewriter.setDiagnosticsHook(({url, moduleName, error}) => { + assert.equal(url, `file://${esmPath}`) + assert.equal(moduleName, 'esm-pkg') + assert.equal(error, undefined) + }) + const esmPath = path.join(import.meta.dirname, './example-deps/lib/node_modules/esm-pkg/foo.js') + function resolveFn() { + return { url: `file://${esmPath}` } + } + function nextLoad() { + const data = readFileSync(esmPath, 'utf8') + return { + format: 'module', + source: data + } + } + const url = syncLoaderRewriter.resolve('esm-pkg', {}, resolveFn) + syncLoaderRewriter.load(url.url, {}, nextLoad) +}) \ No newline at end of file