providePackages

tcmts.cli.provided.providePackages · #jxkvhdml · term · runs on the server

uses node:path

Provide the packages scratch file file (with text text) imports that the project doesn't have installed at the range chosen for it: installed into the cache, and recorded for the editor in .tcm/packages.json.

import type { CodebaseCore } from "#codebase/tcmts/cli/codebase";
import { EMPTY, importedPackages, rangeFor, recordForEditor } from "#codebase/tcmts/cli/provided";
import type { Provided } from "#codebase/tcmts/cli/provided";
import type { CompilerOptions, PackageResolver } from "#codebase/tcmts/core/program";
import { HOST_MODULES } from "#codebase/tcmts/core/types";
import type { ExtRef } from "#codebase/tcmts/core/types";
import { ensureExternals, npmAlias } from "#codebase/tcmts/loader/packages";
import path_1 from "node:path";

export function providePackages(
  cb: CodebaseCore,
  file: string,
  text: string,
  options: CompilerOptions,
): Provided {
  const dirs = new Map<string, string>();
  const exts: ExtRef[] = [];
  for (const name of importedPackages(file, text, options)) {
    // a module where the code runs provides (`vscode`): only its types are provided
    const pkg = HOST_MODULES.get(name) ?? name;
    const r = rangeFor(cb, pkg, file, text);
    if (!r || r.project) continue;
    const module = `npm:${pkg}@${r.range}`;
    exts.push({ module, subpath: "", export: "*" });
    dirs.set(name, path_1.join(cb.lay.cacheDir, "node_modules", npmAlias(module)));
  }
  recordForEditor(cb, file, dirs);
  if (!dirs.size) return EMPTY;
  ensureExternals(cb.lay, exts);
  const from = path_1.join(cb.lay.cacheDir, "index.ts");
  const resolver: PackageResolver = Object.assign(
    (name: string) =>
      dirs.has(name) ? { specifier: path_1.basename(dirs.get(name)!), from } : undefined,
    {
      key: JSON.stringify([...dirs].sort()),
    },
  );
  return { resolver, dirs };
}

uses

used by