UNPKG

@lit-protocol/esbuild-plugin-polyfill-node

Version:

ESBuild plugin for polyfilling Node.js builtins for edge and Deno

246 lines (245 loc) 7 kB
// src/index.ts import { fileURLToPath, pathToFileURL } from "url"; import { resolve, dirname } from "path"; var filename = typeof __filename === "undefined" ? fileURLToPath(import.meta.url) : __filename; var importMetaUrl = import.meta.url ?? pathToFileURL(filename).href; function polyfillNode(options = {}) { const { globals = {}, polyfills = {} } = options; const { global = true, __dirname = true, __filename: __filename2 = true, buffer = true, process = true, navigator = false, denoBuildOs = "linux" } = globals || { global: false, __dirname: false, __filename: false, buffer: false, process: false, navigator: false, denoBuildOs: "linux" }; polyfills.fs = polyfills.fs ?? "empty"; polyfills.crypto = polyfills.crypto ?? "empty"; polyfills.dns = polyfills.dns ?? "empty"; polyfills.dgram = polyfills.dgram ?? "empty"; polyfills.cluster = polyfills.cluster ?? "empty"; polyfills.repl = polyfills.repl ?? "empty"; polyfills.tls = polyfills.tls ?? "empty"; const moduleNames = [...jspmPolyiflls]; const filter = new RegExp(`^(node:)?(${moduleNames.join("|")})$`); return { name: "node-polyfills", async setup(build) { var _a; if (denoBuildOs !== false) { const desired = typeof denoBuildOs === "string" ? denoBuildOs : "x64"; const snippet = `;(()=>{try{const g=globalThis;const D=(g.Deno=g.Deno||{});const B=(D.build=D.build||{});if(B.os==null){B.os=${JSON.stringify(desired)};}}catch{}})();`; const prev = ((_a = build.initialOptions.banner) == null ? void 0 : _a.js) ?? ""; build.initialOptions.banner = { ...build.initialOptions.banner ?? {}, // Prepend to ensure we’re literally first. js: snippet + (prev ? "\n" + prev : "") }; } const fsResolved = await resolveImport(`@jspm/core/nodelibs/fs`); build.onResolve({ filter }, async ({ path }) => { const [, , moduleName] = path.match(filter); const polyfill = polyfills[moduleName] ?? true; if (polyfill === false) { return; } else if (polyfill === "empty") { return { path: resolve(dirname(filename), "../polyfills/empty.js") }; } else if (!jspmPolyiflls.has(moduleName)) { throw new Error("Cannot find polyfill for " + moduleName); } const resolved = resolve(fsResolved, `../../browser/${moduleName}.js`); return { path: resolved }; }); if (globals) { build.initialOptions.inject = build.initialOptions.inject || []; if (global) { resolve(dirname(filename), "../polyfills/global.js"); } if (__dirname) { build.initialOptions.inject.push( resolve(dirname(filename), "../polyfills/__dirname.js") ); } if (__filename2) { resolve(dirname(filename), "../polyfills/__filename.js"); } if (buffer) { build.initialOptions.inject.push( resolve(dirname(filename), "../polyfills/buffer.js") ); } if (process) { build.initialOptions.inject.push( resolve(dirname(filename), "../polyfills/process.js") ); } if (navigator) { build.initialOptions.inject.push( resolve(dirname(filename), "../polyfills/navigator.js") ); } } } }; } function polyfillNodeForDeno(options = {}) { const { stdVersion = "0.177.0", globals = true, polyfills = {} } = options; const moduleNames = [.../* @__PURE__ */ new Set([...denoPolyfills])]; const filter = new RegExp(`^(node:)?(${moduleNames.join("|")})$`); return { name: "node-polyfills", setup(build) { build.onResolve( { filter: /^virtual:deno-std-node-global$/ }, () => ({ path: `https://deno.land/std@${stdVersion}/node/global.ts`, external: true }) ); build.onResolve({ filter }, async ({ path }) => { const [, , moduleName] = path.match(filter); const polyfill = polyfills[moduleName] ?? true; if (polyfill === false) { return; } else if (polyfill === "empty") { return { path: resolve(dirname(filename), "../polyfills/empty.js") }; } else { if (!denoPolyfills.has(moduleName)) { throw new Error("Cannot find the Deno polyfill for " + moduleName); } return { path: `https://deno.land/std@${stdVersion}/node/${moduleName}.ts`, external: true }; } }); build.onLoad({ namespace: "polyfillNodeForDeno", filter: /.*/ }, () => ({ contents: denoGlobalsContents(stdVersion) })); if (globals) { build.initialOptions.footer; build.initialOptions.inject = build.initialOptions.inject || []; build.initialOptions.inject.push( resolve(dirname(filename), "../polyfills/global-for-deno.js"), resolve(dirname(filename), "../polyfills/__dirname.js"), resolve(dirname(filename), "../polyfills/__filename.js") ); } } }; } var jspmPolyiflls = /* @__PURE__ */ new Set([ "_stream_duplex", "_stream_passthrough", "_stream_readable", "_stream_transform", "_stream_writable", "assert", "assert/strict", "async_hooks", "buffer", "child_process", "cluster", "console", "constants", "crypto", "dgram", "diagnostics_channel", "dns", "domain", "events", "fs", "fs/promises", "http", "http2", "https", "module", "net", "os", "path", "perf_hooks", "process", "punycode", "querystring", "readline", "repl", "stream", "string_decoder", "sys", "timers", "timers/promises", "tls", "tty", "url", "util", "v8", "vm", "wasi", "worker_threads", "zlib" ]); var denoPolyfills = /* @__PURE__ */ new Set([ "assert", "assert/strict", "buffer", "console", "constants", "crypto", "child_process", "dns", "events", "fs", "fs/promises", "http", "module", "net", "os", "path", "perf_hooks", "process", "querystring", "readline", "stream", "string_decoder", "sys", "timers", "timers/promises", "tty", "url", "util", "worker_threads" ]); var importMetaResolve; async function resolveImport(specifier) { if (!importMetaResolve) { importMetaResolve = (await import("import-meta-resolve")).resolve; } const resolved = await importMetaResolve(specifier, importMetaUrl); return fileURLToPath(resolved); } function denoGlobalsContents(stdVersion) { return ` import "https://deno.land/std@${stdVersion}/node/global.ts"; export const process = globalThis.process; export const Buffer = globalThis.Buffer; export const setImmediate = globalThis.setImmediate; export const clearImmediate = globalThis.clearImmediate; `; } export { polyfillNode, polyfillNodeForDeno };