mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-08 09:37:47 +03:00
62 lines
2.3 KiB
TypeScript
62 lines
2.3 KiB
TypeScript
import { Script, constants } from "node:vm"
|
|
import { registerHooks } from "node:module"
|
|
import { statSync } from "node:fs"
|
|
import path from "node:path"
|
|
import { pathToFileURL } from "node:url"
|
|
|
|
export async function importModule(specifier: string) {
|
|
const imported = (await new Script(`import(${JSON.stringify(specifier)})`, {
|
|
importModuleDynamically: constants.USE_MAIN_CONTEXT_DEFAULT_LOADER,
|
|
}).runInThisContext()) as unknown
|
|
if (typeof imported !== "object" || imported === null) return imported
|
|
|
|
const module = imported as Record<string, unknown>
|
|
const exports = module["module.exports"]
|
|
if (exports !== module.default || (typeof exports !== "object" && typeof exports !== "function") || exports === null)
|
|
return imported
|
|
return Object.assign({}, module, exports)
|
|
}
|
|
|
|
export function resolveModule(specifier: string, directory: string) {
|
|
// Node only accepts import.meta.resolve's parent URL behind an experimental
|
|
// flag. Scope this synchronous resolution to the caller's package directory
|
|
// through the supported resolver hook instead.
|
|
const hook = registerHooks({
|
|
resolve(specifier, context, nextResolve) {
|
|
return nextResolve(specifier, { ...context, parentURL: pathToFileURL(path.join(directory, "package.json")).href })
|
|
},
|
|
})
|
|
try {
|
|
const resolve = (target: string) => {
|
|
const resolved = import.meta.resolve(path.isAbsolute(target) ? pathToFileURL(target).href : target)
|
|
if (resolved.startsWith("file:")) statSync(new URL(resolved))
|
|
return resolved
|
|
}
|
|
try {
|
|
return resolve(specifier)
|
|
} catch (error) {
|
|
if (path.extname(specifier) || !missing(error)) throw error
|
|
// Node does not infer extensions for local files or legacy package
|
|
// subpaths. Resolve each candidate natively so package exports still apply.
|
|
for (const extension of [".ts", ".tsx", ".js", ".jsx", ".mts", ".mjs", ".cts", ".cjs"]) {
|
|
try {
|
|
return resolve(specifier + extension)
|
|
} catch (cause) {
|
|
if (!missing(cause)) throw cause
|
|
}
|
|
}
|
|
throw error
|
|
}
|
|
} finally {
|
|
hook.deregister()
|
|
}
|
|
}
|
|
|
|
function missing(error: unknown) {
|
|
return (
|
|
error instanceof Error &&
|
|
"code" in error &&
|
|
["ENOENT", "ENOTDIR", "ERR_MODULE_NOT_FOUND"].includes(String(error.code))
|
|
)
|
|
}
|