@@ -6,22 +6,30 @@ import { describe, expect, test } from "bun:test";
66import { mkdirSync , mkdtempSync , readFileSync , rmSync , writeFileSync } from "node:fs" ;
77import { tmpdir } from "node:os" ;
88import { join } from "node:path" ;
9+ import { fileURLToPath } from "node:url" ;
910
1011describe ( "runtime bundling" , ( ) => {
1112 test ( "does not emit a static bun:sqlite import in Node bundles" , async ( ) => {
1213 const workDir = mkdtempSync ( join ( tmpdir ( ) , "config-engine-runtime-" ) ) ;
1314 const entryPath = join ( workDir , "entry.ts" ) ;
1415 const outDir = join ( workDir , "dist" ) ;
15- // Use a file:// URL so the import path is portable across platforms (including Windows).
16- const runtimeUrl = new URL ( "../src/runtime.ts" , import . meta. url ) . href ;
16+ // Resolve through a file:// URL, then back to a filesystem path: the bundler
17+ // resolves plain paths, and JSON.stringify escapes Windows separators safely.
18+ const runtimePath = fileURLToPath ( new URL ( "../src/runtime.ts" , import . meta. url ) ) ;
1719
1820 try {
1921 mkdirSync ( outDir , { recursive : true } ) ;
20- // Import openDatabase (not just isBun) so the bundler cannot tree-shake
21- // the SQLite adapter code — this ensures the bun:sqlite guard is actually tested.
22+ // The bundle is emitted as ESM, so mark the output directory as a module
23+ // package, otherwise Node parses the .js output as CommonJS and fails.
24+ writeFileSync ( join ( outDir , "package.json" ) , `${ JSON . stringify ( { type : "module" } ) } \n` ) ;
25+ // Actually reference openDatabase (not just import it) so the bundler cannot
26+ // tree-shake the SQLite adapter code, so the bun:sqlite guard is really
27+ // exercised by the bundle.
2228 writeFileSync (
2329 entryPath ,
24- `import { isBun, openDatabase } from ${ JSON . stringify ( runtimeUrl ) } ;\nconsole.log(isBun());\n` ,
30+ `import { isBun, openDatabase } from ${ JSON . stringify ( runtimePath ) } ;\n` +
31+ "console.log(isBun());\n" +
32+ "console.log(typeof openDatabase);\n" ,
2533 ) ;
2634
2735 const result = await Bun . build ( {
@@ -37,15 +45,20 @@ describe("runtime bundling", () => {
3745
3846 const outputPath = join ( outDir , "entry.js" ) ;
3947 const bundled = readFileSync ( outputPath , "utf8" ) ;
40- expect ( bundled ) . not . toMatch ( / (?: f r o m | i m p o r t ) \s + [ " ' ] b u n : s q l i t e [ " ' ] / ) ;
48+ // Allow for minified output: `from"bun:sqlite"`, `import"bun:sqlite"`,
49+ // and `require("bun:sqlite")` must all be absent.
50+ expect ( bundled ) . not . toMatch ( / (?: f r o m | i m p o r t | r e q u i r e \s * \( ) \s * [ " ' ] b u n : s q l i t e [ " ' ] / ) ;
4151
4252 const run = Bun . spawnSync ( [ "node" , outputPath ] , {
4353 stdout : "pipe" ,
4454 stderr : "pipe" ,
4555 } ) ;
4656
4757 expect ( run . exitCode ) . toBe ( 0 ) ;
48- expect ( new TextDecoder ( ) . decode ( run . stdout ) . trim ( ) ) . toBe ( "false" ) ;
58+ expect ( new TextDecoder ( ) . decode ( run . stdout ) . trim ( ) . split ( / \r ? \n / ) ) . toEqual ( [
59+ "false" ,
60+ "function" ,
61+ ] ) ;
4962 } finally {
5063 rmSync ( workDir , { recursive : true , force : true } ) ;
5164 }
0 commit comments