|
1 | 1 | import { createRequire } from 'node:module' |
2 | | - |
| 2 | +import { dirname, resolve, sep } from 'node:path' |
| 3 | +import { fileURLToPath } from 'node:url' |
3 | 4 | // createRequire works in both Bun and Node.js ESM contexts. |
4 | 5 | // Needed because this package is "type": "module" but uses require() for |
5 | 6 | // loading native .node addons — bare require is not available in Node.js ESM. |
6 | 7 | const nodeRequire = createRequire(import.meta.url) |
7 | 8 |
|
| 9 | +/** |
| 10 | + * Resolve the "vendor root" directory where native .node binaries live. |
| 11 | + * |
| 12 | + * - Dev mode: import.meta.url → packages/audio-capture-napi/src/index.ts |
| 13 | + * → vendor root = <project>/vendor/ |
| 14 | + * - Bun build: import.meta.url → dist/chunk-xxx.js |
| 15 | + * → vendor root = <project>/dist/vendor/ |
| 16 | + * - Vite build: import.meta.url → dist/chunks/chunk-xxx.js |
| 17 | + * → vendor root = <project>/dist/vendor/ |
| 18 | + */ |
| 19 | +function getVendorRoot(): string { |
| 20 | + const filePath = fileURLToPath(import.meta.url) |
| 21 | + const dir = dirname(filePath) |
| 22 | + const parts = dir.split(sep) |
| 23 | + const distIdx = parts.lastIndexOf('dist') |
| 24 | + if (distIdx !== -1) { |
| 25 | + return parts.slice(0, distIdx + 1).join(sep) + sep + 'vendor' |
| 26 | + } |
| 27 | + // Dev mode — go up from packages/audio-capture-napi/src/ to project root |
| 28 | + return resolve(dir, '..', '..', '..', 'vendor') |
| 29 | +} |
| 30 | + |
8 | 31 | type AudioCaptureNapi = { |
9 | 32 | startRecording( |
10 | 33 | onData: (data: Buffer) => void, |
@@ -56,15 +79,18 @@ function loadModule(): AudioCaptureNapi | null { |
56 | 79 | } |
57 | 80 | } |
58 | 81 |
|
59 | | - // Candidates 2-4: npm-install, dev/source, and workspace layouts. |
60 | | - // In bundled output, require() resolves relative to cli.js at the package root. |
61 | | - // In dev, it resolves relative to this file. When loaded from a workspace |
62 | | - // package (packages/audio-capture-napi/src/), we need an absolute path fallback. |
| 82 | + // Candidates 2-5: resolved vendor path + relative fallbacks. |
| 83 | + // The primary candidate uses getVendorRoot() to find the correct dist root |
| 84 | + // regardless of chunk nesting depth. Relative fallbacks cover edge cases. |
63 | 85 | const platformDir = `${process.arch}-${platform}` |
| 86 | + const binaryRel = `audio-capture/${platformDir}/audio-capture.node` |
| 87 | + const vendorRoot = getVendorRoot() |
64 | 88 | const fallbacks = [ |
65 | | - `./vendor/audio-capture/${platformDir}/audio-capture.node`, |
66 | | - `../audio-capture/${platformDir}/audio-capture.node`, |
67 | | - `${process.cwd()}/vendor/audio-capture/${platformDir}/audio-capture.node`, |
| 89 | + resolve(vendorRoot, binaryRel), |
| 90 | + `./vendor/${binaryRel}`, |
| 91 | + `../vendor/${binaryRel}`, |
| 92 | + `../../vendor/${binaryRel}`, |
| 93 | + `${process.cwd()}/vendor/${binaryRel}`, |
68 | 94 | ] |
69 | 95 | for (const p of fallbacks) { |
70 | 96 | try { |
|
0 commit comments