Last active
March 27, 2025 09:57
-
-
Save NuroDev/32c20979c92b9ddd82fb091e6c831286 to your computer and use it in GitHub Desktop.
π Bun HTTP import plugin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
preload = ['./path/to/plugin.ts'] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { OnLoadCallback, OnResolveCallback } from 'bun'; | |
const rx_absolute_path = /^\//; | |
const rx_any = /./; | |
const rx_bare_import = /^[^\.\/]/; // Matches bare imports like 'source-map-support' | |
const rx_http = /^https?:\/\//; | |
const rx_relative_path = /^\.\.?\//; | |
const loadHttpModule = | |
(prefix: string): OnLoadCallback => | |
async (args) => { | |
const href = `${prefix}${args.path}`; | |
try { | |
const response = await fetch(href); | |
if (!response.ok) | |
throw new Error(`HTTP ${response.status}: ${response.statusText}`); | |
const text = await response.text(); | |
return { | |
contents: text, | |
loader: 'js', | |
}; | |
} catch (error) { | |
throw new Error(`Failed to load module '${href}': ${error}`); | |
} | |
}; | |
const resolveHttpImport: OnResolveCallback = (args) => { | |
if (!rx_http.test(args.importer)) return; | |
// Create a URL object from the importer | |
const importerUrl = new URL(args.importer); | |
// Handle the path with any query parameters | |
let resolvedUrl: URL; | |
try { | |
resolvedUrl = new URL(args.path, importerUrl); | |
} catch (e) { | |
// If direct resolution fails, try a different approach | |
// This might be a bare import that needs to be resolved through esm.sh or similar | |
if (rx_bare_import.test(args.path)) { | |
// For bare imports from esm.sh, we'll pass them back to esm.sh | |
// Extract the base URL and append the new import | |
const baseUrl = | |
importerUrl.origin + | |
importerUrl.pathname.substring(0, importerUrl.pathname.lastIndexOf('/') + 1); | |
resolvedUrl = new URL(args.path, baseUrl); | |
} else { | |
throw e; | |
} | |
} | |
return { | |
path: resolvedUrl.pathname + resolvedUrl.search, // Include query parameters | |
namespace: resolvedUrl.protocol.replace(':', ''), // 'http' or 'https' | |
}; | |
}; | |
Bun.plugin({ | |
name: 'http_imports', | |
target: 'bun', | |
setup(build) { | |
// Handle relative paths from HTTP modules | |
build.onResolve({ filter: rx_relative_path }, resolveHttpImport); | |
// Handle absolute paths from HTTP modules | |
build.onResolve({ filter: rx_absolute_path }, resolveHttpImport); | |
// Load HTTP modules | |
build.onLoad({ filter: rx_any, namespace: 'http' }, loadHttpModule('http:')); | |
// Load HTTPS modules | |
build.onLoad({ filter: rx_any, namespace: 'https' }, loadHttpModule('https:')); | |
}, | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment