1// @ts-check
2// Node dev-mode hooks: run an alchemy checkout from source with no build.
3//
4// 1. A synchronous `resolve` hook (`module.registerHooks`) enables the
5// `bun` export condition for the monorepo's own packages (`alchemy`,
6// `@alchemy.run/*`, `@distilled.cloud/*`), whose exports map that
7// condition to `src/*.ts`. Under plain node the `import` condition
8// resolves built `lib/` output instead — requiring a `tsc -b` first,
9// and splitting the process across a src copy (the CLI) and a lib copy
10// (the user's stack, which imports `alchemy`) whenever lib is stale.
11// Packages without a `bun` condition (e.g. the published sigil) are
12// untouched — an enabled condition their exports never mention simply
13// doesn't match.
14// 2. node-utils handles the actual `.ts`/`.tsx` loading with Rolldown's Oxc
15// transformer and source maps. Node's built-in TypeScript support does not
16// cover TSX and cannot apply each package's nearest tsconfig.
17//
18// Dev-only: the launcher (`bin/cli.js`) and the dev supervisor pass this
19// via `--import` when spawning node in a checkout. Published installs run
20// bundled `.js` and never load it; this file is excluded from the tarball.
21// In a checkout, the source loader resolves from the workspace package.
22import { enableCompileCache, registerHooks } from "node:module";
23
24// See register-oxc.js: enabled before anything else loads so the whole graph —
25// the loader's rolldown dependency and every transformed workspace file —
26// is code-cached across the CLI, the dev exec child and the sidecars.
27enableCompileCache();
28
29/** @param {string} specifier */
30const isMonorepoPackage = (specifier) =>
31 specifier === "alchemy" ||
32 specifier.startsWith("alchemy/") ||
33 specifier.startsWith("@alchemy.run/") ||
34 specifier.startsWith("@distilled.cloud/");
35
36registerHooks({
37 resolve(specifier, context, nextResolve) {
38 if (!isMonorepoPackage(specifier)) return nextResolve(specifier, context);
39 return nextResolve(specifier, {
40 ...context,
41 conditions: ["bun", ...context.conditions],
42 });
43 },
44});
45
46// This import must happen after the condition hook is installed so a clean
47// checkout resolves node-utils to source without requiring a prior build.
48const { registerOxc } = await import("@alchemy.run/node-utils/register-oxc");
49
50// Oxc discovers the nearest tsconfig for each transformed file. Alchemy's
51// TSX therefore uses Alchemy's React settings while the user's config and its
52// dependencies retain their own compiler settings.
53registerOxc({ conditions: ["bun"] });