externalModule

tcmts.core.analyze.externalModule · #spvop5vd · term · runs on the server

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

used by