|
1 | 1 | /** |
2 | | - * ESM preload shim that provides `require` in ESM modules. |
| 2 | + * ESM preload shim that provides `require` in ESM modules and handles |
| 3 | + * `with { type: "file" }` import attributes in tsx dev mode. |
3 | 4 | * |
4 | 5 | * The source code uses bare `require()` for lazy loading (circular dependency |
5 | 6 | * breaking, optional features). This works natively in Bun and in the CJS |
|
13 | 14 | * must use a file-local `createRequire(import.meta.url)` instead of relying |
14 | 15 | * on this global shim. |
15 | 16 | * |
| 17 | + * `with { type: "file" }` import attributes are used to embed sidecar files |
| 18 | + * (e.g. the Ink UI app). Bun supports this natively; esbuild's |
| 19 | + * text-import-plugin handles it at build time. In tsx dev mode neither |
| 20 | + * applies, so we register a loader hook that returns the file path as a |
| 21 | + * string — matching Bun's native behaviour. |
| 22 | + * |
16 | 23 | * Usage: NODE_OPTIONS="--import ./script/require-shim.mjs" tsx script/... |
17 | 24 | * Or in package.json scripts via the `pnpm tsx` alias. |
18 | 25 | */ |
19 | 26 |
|
20 | | -import { createRequire } from "node:module"; |
| 27 | +import { createRequire, registerHooks } from "node:module"; |
21 | 28 |
|
22 | 29 | if (typeof globalThis.require === "undefined") { |
23 | 30 | globalThis.require = createRequire( |
24 | 31 | new URL("../package.json", import.meta.url) |
25 | 32 | ); |
26 | 33 | } |
| 34 | + |
| 35 | +// Handle `with { type: "file" }` import attributes in Node.js dev mode. |
| 36 | +// Bun supports this natively; esbuild's text-import-plugin handles it at |
| 37 | +// build time. In tsx dev mode neither applies, so we register a synchronous |
| 38 | +// hook that returns the file path as a string — matching Bun's behaviour. |
| 39 | +// registerHooks() is available from Node 22.15+ (our minimum). |
| 40 | +registerHooks({ |
| 41 | + load(url, context, nextLoad) { |
| 42 | + if (context.importAttributes?.type === "file") { |
| 43 | + return { |
| 44 | + format: "module", |
| 45 | + shortCircuit: true, |
| 46 | + source: `export default ${JSON.stringify(new URL(url).pathname)};`, |
| 47 | + }; |
| 48 | + } |
| 49 | + return nextLoad(url, context); |
| 50 | + }, |
| 51 | +}); |
0 commit comments