externalModule
uses node:module
A Node builtin or an npm package (version pinned from node_modules), as imported from file.
import { findPackage, observed, readPackage, SERVER_API, SERVER_HOST, TCM_SERVER_GONE, } from "#codebase/tcmts/core/analyze"; import type { AnalyzeHost } from "#codebase/tcmts/core/analyze"; import { TcmError } from "#codebase/tcmts/core/extract"; import { compareVersions, compatRange } from "#codebase/tcmts/core/semver"; import { HOST_MODULES, RETIRED_MODULES, SERVER_HOST_MODULE } from "#codebase/tcmts/core/types"; import type { ExtRef } from "#codebase/tcmts/core/types"; import { isBuiltin } from "node:module"; import path_2 from "node:path"; import type { Node as ts_Node } from "typescript/ast"; export function externalModule( spec: string, file: string, at: ts_Node, exportName: string, host?: AnalyzeHost, ): ExtRef { if (spec === SERVER_API) throw new TcmError(TCM_SERVER_GONE, at); if (spec === SERVER_HOST) return { module: SERVER_HOST_MODULE, subpath: "", export: exportName }; if (isBuiltin(spec)) return { module: spec.startsWith("node:") ? spec : `node:${spec}`, subpath: "", export: exportName, }; // tcm's own modules from before they were libraries, as code rendered from history imports them: what they were if ( RETIRED_MODULES.has(spec) && host && path_2.dirname(path_2.resolve(file)) === path_2.resolve(host.cacheDir) ) return { module: spec, subpath: "", export: exportName }; // provided by where the code runs (an editor's API): unversioned, like Node's own if (HOST_MODULES.has(spec)) return { module: spec, subpath: "", export: exportName }; const parts = spec.split("/"); const pkgName = spec.startsWith("@") ? parts.slice(0, 2).join("/") : parts[0]!; const subpath = parts.slice(pkgName.split("/").length).join("/"); // a package tcm provides (not installed in the project) is where the file's imports resolved it const provided = host?.packageDir?.(pkgName, file); const pkg = provided ? readPackage(provided) : findPackage(pkgName, path_2.dirname(file)); if (!pkg) throw new TcmError(`cannot find package '${pkgName}' in node_modules`, at); // the hash records the range semver calls compatible; the codebase's lock picks the version within it const module = `npm:${pkg.name}@${compatRange(pkg.version)}`; const seen = observed?.get(module); if (!seen || compareVersions(pkg.version, seen) > 0) observed?.set(module, pkg.version); return { module, subpath, export: exportName }; }
uses
- tcmts.core.analyze.AnalyzeHost
- tcmts.core.analyze.SERVER_API
- tcmts.core.analyze.SERVER_HOST
- tcmts.core.analyze.TCM_SERVER_GONE
- tcmts.core.analyze.findPackage
- tcmts.core.analyze.observed
- tcmts.core.analyze.readPackage
- tcmts.core.extract.TcmError
- tcmts.core.semver.compareVersions
- tcmts.core.semver.compatRange
- tcmts.core.types.ExtRef
- tcmts.core.types.HOST_MODULES
- tcmts.core.types.RETIRED_MODULES
- tcmts.core.types.SERVER_HOST_MODULE