@decohere/flux 0.0.1-dev.11 → 0.0.1-dev.111

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +247 -0
  2. package/commonjs/src/deferred-script-runner.js +56 -0
  3. package/commonjs/src/flux.command.js +2 -2
  4. package/commonjs/src/flux.js +56 -0
  5. package/commonjs/src/flux.module.js +8 -7
  6. package/commonjs/src/hot-reload-server.js +302 -215
  7. package/commonjs/src/index.js +34 -2
  8. package/commonjs/src/rewrite-serve-specifier.js +59 -0
  9. package/commonjs/src/run.action.js +47 -0
  10. package/commonjs/src/run.command.js +65 -0
  11. package/commonjs/src/serve.action.js +76 -5
  12. package/commonjs/src/serve.command.js +34 -3
  13. package/commonjs/src/slice-serve.js +130 -0
  14. package/commonjs/src/source-module-loader.js +311 -0
  15. package/commonjs/src/static-imports.js +37 -0
  16. package/es6/src/deferred-script-runner.js +46 -0
  17. package/es6/src/flux.command.js +2 -2
  18. package/es6/src/flux.js +41 -0
  19. package/es6/src/flux.module.js +8 -7
  20. package/es6/src/hot-reload-server.js +283 -172
  21. package/es6/src/index.js +5 -3
  22. package/es6/src/rewrite-serve-specifier.js +49 -0
  23. package/es6/src/run.action.js +37 -0
  24. package/es6/src/run.command.js +55 -0
  25. package/es6/src/serve.action.js +71 -7
  26. package/es6/src/serve.command.js +34 -3
  27. package/es6/src/slice-serve.js +105 -0
  28. package/es6/src/source-module-loader.js +255 -0
  29. package/es6/src/static-imports.js +27 -0
  30. package/package.json +7 -6
  31. package/types/src/deferred-script-runner.d.ts +18 -0
  32. package/types/src/flux.d.ts +43 -0
  33. package/types/src/flux.module.d.ts +2 -0
  34. package/types/src/hot-reload-server.d.ts +55 -22
  35. package/types/src/index.d.ts +8 -1
  36. package/types/src/rewrite-serve-specifier.d.ts +14 -0
  37. package/types/src/run.action.d.ts +15 -0
  38. package/types/src/run.command.d.ts +11 -0
  39. package/types/src/serve.action.d.ts +11 -1
  40. package/types/src/serve.command.d.ts +6 -0
  41. package/types/src/slice-serve.d.ts +52 -0
  42. package/types/src/source-module-loader.d.ts +81 -0
  43. package/types/src/static-imports.d.ts +5 -0
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The module specifiers a compiled ES module names in `import … from`, `export … from`, bare
3
+ * `import "x"` and literal `import("x")`.
4
+ *
5
+ * Only a hint for compiling ahead (#661): a specifier it misses is compiled when Node loads it,
6
+ * and one it finds by mistake (an import written inside a string) costs one extra compile. So a
7
+ * scan of SWC's output is enough; it never decides what runs.
8
+ */ const STATIC = /\b(?:import|export)\s*(?:[\w$*{},\s]+?\s*from\s*)?["']([^"'\n]+)["']/g;
9
+ const DYNAMIC = /\bimport\s*\(\s*["']([^"'\n]+)["']\s*\)/g;
10
+ function scan(code) {
11
+ const found = new Set();
12
+ for (const pattern of [
13
+ STATIC,
14
+ DYNAMIC
15
+ ]){
16
+ for (const match of code.matchAll(pattern)){
17
+ const specifier = match[1];
18
+ if (specifier != null) found.add(specifier);
19
+ }
20
+ }
21
+ return [
22
+ ...found
23
+ ];
24
+ }
25
+ export const staticImports = {
26
+ scan
27
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decohere/flux",
3
- "version": "0.0.1-dev.11",
3
+ "version": "0.0.1-dev.111",
4
4
  "description": "Hot module reload server for Node.js ESM applications",
5
5
  "keywords": [
6
6
  "typescript",
@@ -25,11 +25,12 @@
25
25
  "test": "echo \"Error: no test specified\" && exit 1"
26
26
  },
27
27
  "dependencies": {
28
- "@decohere/crucible": "0.0.1-dev.11",
29
- "@decohere/forge": "0.0.1-dev.11",
30
- "@decohere/mesh": "0.0.1-dev.11",
31
- "@decohere/nexus": "0.0.1-dev.11",
32
- "@decohere/scribe": "0.0.1-dev.11",
28
+ "@decohere/crucible": "0.0.1-dev.111",
29
+ "@decohere/forge": "0.0.1-dev.111",
30
+ "@decohere/mesh": "0.0.1-dev.111",
31
+ "@decohere/nexus": "0.0.1-dev.111",
32
+ "@decohere/scribe": "0.0.1-dev.111",
33
+ "commander": "^13.1.0",
33
34
  "rxjs": "^7.8.2"
34
35
  },
35
36
  "devDependencies": {}
@@ -0,0 +1,18 @@
1
+ import { type ChildProcess } from "node:child_process";
2
+ export type DeferredScriptStart = {
3
+ readonly label: string;
4
+ readonly cwd: string;
5
+ readonly script: string;
6
+ /** Workspace root used to detect pnpm/npm/yarn. */
7
+ readonly workspaceRoot: string;
8
+ };
9
+ /**
10
+ * Nixpacks-style child processes for foreign packages in a flux serve slice.
11
+ * Killed when the Flux container disposes (SIGINT → RootModule teardown).
12
+ */
13
+ export declare class DeferredScriptRunner implements AsyncDisposable {
14
+ private readonly logger;
15
+ private readonly children;
16
+ start(options: DeferredScriptStart): ChildProcess;
17
+ [Symbol.asyncDispose](): Promise<void>;
18
+ }
@@ -0,0 +1,43 @@
1
+ import type { Workspace } from "@decohere/mesh";
2
+ import { HotReloadServer } from "./hot-reload-server.js";
3
+ export type FluxRunOptions = {
4
+ /** Mesh/Forge configuration name. Defaults to `debug` (`--configuration`). */
5
+ configuration?: string;
6
+ /** Arguments forwarded to the entry (bin-style `process.argv.slice(2)`). */
7
+ args?: string[];
8
+ /**
9
+ * Pre-built Workspace instead of `WorkspaceFactory`.
10
+ * Useful in tests to skip filesystem discovery.
11
+ */
12
+ workspace?: Workspace;
13
+ };
14
+ export type FluxServeOptions = {
15
+ /** Mesh/Forge configuration name. Defaults to `debug` (`--configuration`). */
16
+ configuration?: string;
17
+ /** Name of the project to serve. Defaults to the first project in the workspace. */
18
+ project?: string;
19
+ /**
20
+ * Multiple Flux app package names to boot in one process (directory slice).
21
+ * When set, takes precedence over {@link project}.
22
+ */
23
+ projects?: readonly string[];
24
+ /**
25
+ * Pre-built Workspace instead of `WorkspaceFactory`.
26
+ * Useful in tests to skip filesystem discovery.
27
+ */
28
+ workspace?: Workspace;
29
+ /**
30
+ * Quiet window in milliseconds after the last affecting save before a reboot.
31
+ * Raise this for agent save trains.
32
+ */
33
+ rebootDebounceMs?: number;
34
+ };
35
+ declare function run(entry: string, options?: FluxRunOptions): Promise<unknown>;
36
+ declare function serve(options?: FluxServeOptions): Promise<HotReloadServer>;
37
+ declare function dispose(): void;
38
+ export declare const flux: {
39
+ run: typeof run;
40
+ serve: typeof serve;
41
+ dispose: typeof dispose;
42
+ };
43
+ export {};
@@ -2,12 +2,14 @@ import type { WorkspaceFactoryOptions } from "@decohere/nexus/cli";
2
2
  import { ModuleManifest } from "@decohere/nexus/cli";
3
3
  import type { ContainerBuilder } from "@decohere/nexus/composition";
4
4
  import { FluxCommand } from "./flux.command.js";
5
+ import { RunAction } from "./run.action.js";
5
6
  import { ServeAction } from "./serve.action.js";
6
7
  export declare class FluxModule extends ModuleManifest {
7
8
  readonly id = "flux";
8
9
  readonly command: typeof FluxCommand;
9
10
  readonly actions: {
10
11
  serve: typeof ServeAction;
12
+ run: typeof RunAction;
11
13
  };
12
14
  registerServices(builder: ContainerBuilder): void;
13
15
  createWorkspace(options: WorkspaceFactoryOptions): Promise<import("@decohere/mesh").Workspace>;
@@ -1,5 +1,12 @@
1
1
  import { EventEmitter } from "node:events";
2
2
  import type { Workspace } from "@decohere/mesh";
3
+ /** Default quiet window before a file-change reboot. */
4
+ export declare const DEFAULT_REBOOT_DEBOUNCE_MS = 250;
5
+ export declare function resolveRebootDebounceMs(value: number | undefined): number;
6
+ /** Info-level HMR start block — keep `flux reboot` in the text so operators can search the buffer. */
7
+ export declare function formatFluxRebootStart(labels: readonly string[], triggers?: readonly string[]): string;
8
+ /** Info-level HMR finish block. */
9
+ export declare function formatFluxRebootReady(labels: readonly string[], elapsedMs: number): string;
3
10
  export interface HotReloadServerEvents {
4
11
  start: [];
5
12
  reboot: [];
@@ -9,56 +16,82 @@ export interface HotReloadServerOptions {
9
16
  buildConfig: string;
10
17
  /** Name of the project to serve. Defaults to the first project in the workspace. */
11
18
  project?: string;
19
+ /**
20
+ * Multiple Flux app package names to boot in one process (directory slice).
21
+ * When set, takes precedence over {@link project}.
22
+ */
23
+ projects?: readonly string[];
12
24
  /**
13
25
  * Pre-built Workspace instance to use instead of running WorkspaceFactory.
14
26
  * Useful in tests to bypass filesystem-based workspace discovery.
15
27
  */
16
28
  workspace?: Workspace;
29
+ /**
30
+ * Quiet window in milliseconds after the last affecting save before a reboot.
31
+ * Defaults to {@link DEFAULT_REBOOT_DEBOUNCE_MS}. Raise this for agent save trains.
32
+ */
33
+ rebootDebounceMs?: number;
17
34
  }
18
35
  export declare class HotReloadServer extends EventEmitter<HotReloadServerEvents> {
19
36
  private readonly logger;
37
+ private readonly loader;
20
38
  private disposed;
21
- private hooksRegistered;
22
- private entryModulePath;
23
- private entryModule?;
24
- private workspace?;
39
+ /** Absolute entry paths currently served (one or more Flux apps). */
40
+ private entries;
41
+ private pendingEntryReboots;
42
+ /** Source paths that scheduled the next reboot (cleared when that reboot starts). */
43
+ private pendingTriggers;
25
44
  private watchSubscription?;
26
- /** Map from absolute .ts source file path to project info */
27
- private fileInfoMap;
28
45
  private moduleCache;
29
46
  private dependencies;
30
- private transpileCache;
31
- private transpiler;
47
+ private rebootTail;
48
+ private rebootDebounceGen;
49
+ private rebootInFlight;
50
+ private rebootFollowUp;
51
+ private rebootQueued;
52
+ /** Modules whose reverse-graph edges are pruned at reboot, not on schedule. */
53
+ private pendingGraphPrune;
54
+ private scheduleReboot;
32
55
  start(options: HotReloadServerOptions): Promise<void>;
33
56
  dispose(): Promise<void>;
34
57
  [Symbol.asyncDispose](): Promise<void>;
58
+ private bootEntries;
35
59
  private bootEntry;
36
- private reboot;
60
+ private bindScheduleReboot;
61
+ private requestReboot;
62
+ private runReboot;
63
+ private disposeEntries;
37
64
  private disposeEntry;
38
- private scheduleReboot;
39
- private resolveWorkspace;
40
- private resolveProject;
41
- private buildFileInfoMap;
42
- private registerHooks;
43
- /**
44
- * Pre-next specifier rewriter: if specifier is a .js import that maps to a
45
- * known .ts source file, returns the versioned .ts file URL so next() never
46
- * tries to load a non-existent .js file from disk.
47
- */
48
- private rewriteJsToTs;
65
+ private requireWorkspace;
66
+ private resolveProjects;
49
67
  /**
50
68
  * Post-next dependency tracker: records which source files import which
51
69
  * other source files so that reloadIfAffected can traverse the graph.
52
70
  */
53
71
  private onPostResolve;
54
- private loadTs;
55
72
  private onFileChange;
73
+ /**
74
+ * A failed boot (e.g. importing a file that doesn't exist yet) may have recorded no
75
+ * dependency edges, so the graph can't tell whether this save fixes it. Any source
76
+ * add or change retries failed entries (#512).
77
+ */
78
+ private retryFailedEntries;
56
79
  private reloadIfAffected;
80
+ /**
81
+ * Every module that imports `moduleId`, directly or transitively. Visits each module
82
+ * once: import graphs share modules (diamonds) and may legally contain cycles (#515).
83
+ */
57
84
  private getDependencyGraph;
58
85
  private trackDependency;
59
86
  private getCachedOrNew;
60
87
  private versionModule;
61
- private invalidateModule;
88
+ private invalidateModuleCaches;
89
+ private prunePendingDependencyEdges;
90
+ /** Remove these modules as parents so boot can rebuild edges without stale importers. */
91
+ private pruneDependencyParents;
62
92
  private invalidateAllSourceFiles;
63
93
  private isSelf;
94
+ private labelsFor;
95
+ private takeTriggers;
96
+ private formatTrigger;
64
97
  }
@@ -1,4 +1,11 @@
1
+ export { DeferredScriptRunner } from "./deferred-script-runner.js";
2
+ export type { FluxRunOptions, FluxServeOptions } from "./flux.js";
3
+ export { flux } from "./flux.js";
1
4
  export { FluxModule } from "./flux.module.js";
2
5
  export type { HotReloadServerOptions } from "./hot-reload-server.js";
3
- export { HotReloadServer } from "./hot-reload-server.js";
6
+ export { DEFAULT_REBOOT_DEBOUNCE_MS, HotReloadServer } from "./hot-reload-server.js";
7
+ export type { RunOptions } from "./run.action.js";
4
8
  export type { ServeOptions } from "./serve.action.js";
9
+ export { type ClassifiedSlice, classifySliceProject, classifySliceProjects, normalizeSlicePrefix, projectsInSlice, projectsInSlices, resolveDeferScript, type SliceKind, type SliceProjectView, } from "./slice-serve.js";
10
+ export type { SourceModuleLoaderOptions } from "./source-module-loader.js";
11
+ export { SourceModuleLoader } from "./source-module-loader.js";
@@ -0,0 +1,14 @@
1
+ export type RewriteServeSpecifierOptions = {
2
+ specifier: string;
3
+ parentUrl: string;
4
+ isWatchedTs: (absolutePath: string) => boolean;
5
+ resolveBare: (specifier: string) => string | null;
6
+ versionFileUrl: (fileUrl: string) => string;
7
+ };
8
+ /**
9
+ * Map a resolve-hook specifier to a versioned watched `.ts` file URL.
10
+ * Covers relative `.js` / `.ts` / extensionless imports, directory imports (`./models` is
11
+ * `./models/index.ts`), and bare workspace package names and subpaths. Flux compiles without
12
+ * SWC's own path resolution, so this is the only place imports are mapped to sources (#513).
13
+ */
14
+ export declare function rewriteServeSpecifier(options: RewriteServeSpecifierOptions): string | null;
@@ -0,0 +1,15 @@
1
+ import { Workspace } from "@decohere/mesh";
2
+ import { type Action, ActionResponse } from "@decohere/nexus/cli";
3
+ export type RunOptions = {
4
+ /** Absolute or cwd-relative path to a `.ts` entry file. */
5
+ entry: string;
6
+ configuration: string;
7
+ /** Arguments forwarded to the entry (bin-style `process.argv.slice(2)`). */
8
+ args?: string[];
9
+ };
10
+ export declare class RunAction implements Action<RunOptions> {
11
+ private readonly workspace;
12
+ private readonly logger;
13
+ constructor(workspace: Workspace);
14
+ run(options: RunOptions): Promise<ActionResponse>;
15
+ }
@@ -0,0 +1,11 @@
1
+ import { DecohereCommand } from "@decohere/nexus/cli";
2
+ import { RunAction } from "./run.action.js";
3
+ export declare class RunCommand extends DecohereCommand {
4
+ get actions(): (typeof RunAction)[];
5
+ constructor(name: string);
6
+ /**
7
+ * Commander passes positionals before options when `<entry> [args...]` is declared.
8
+ * The CLI host ModuleFactory expects `(opts, cmd)` — normalize and stash entry/args on opts.
9
+ */
10
+ action(fn: (...args: any[]) => void | Promise<void>): this;
11
+ }
@@ -1,13 +1,23 @@
1
1
  import { Workspace } from "@decohere/mesh";
2
2
  import { type Action, ActionResponse } from "@decohere/nexus/cli";
3
+ import { DeferredScriptRunner } from "./deferred-script-runner.js";
3
4
  import { HotReloadServer } from "./hot-reload-server.js";
4
5
  export type ServeOptions = {
5
6
  configuration: string;
6
7
  project?: string;
8
+ /** One or more module directory tokens (`funding`, `shell`, `projects/funding`). */
9
+ slices?: string[];
10
+ rebootDebounceMs?: number;
7
11
  };
8
12
  export declare class ServeAction implements Action<ServeOptions> {
9
13
  private readonly server;
10
14
  private readonly workspace;
11
- constructor(server: HotReloadServer, workspace: Workspace);
15
+ private readonly deferredScripts;
16
+ private readonly logger;
17
+ constructor(server: HotReloadServer, workspace: Workspace, deferredScripts: DeferredScriptRunner);
12
18
  run(options: ServeOptions): Promise<ActionResponse>;
19
+ private runSlices;
20
+ private toSliceViews;
21
+ private toSliceView;
22
+ private findProject;
13
23
  }
@@ -3,4 +3,10 @@ import { ServeAction } from "./serve.action.js";
3
3
  export declare class ServeCommand extends DecohereCommand {
4
4
  get actions(): (typeof ServeAction)[];
5
5
  constructor(name: string);
6
+ runsUntilStopped(): boolean;
7
+ /**
8
+ * Commander passes positional args before options when `[slices...]` is declared.
9
+ * The CLI host ModuleFactory expects `(opts, cmd)` — normalize here.
10
+ */
11
+ action(fn: (...args: any[]) => void | Promise<void>): this;
6
12
  }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Directory-slice helpers for `flux serve <dir>…` — classify Mesh packages as
3
+ * Flux apps, Nixpacks-style script deferrals, or libraries to skip.
4
+ */
5
+ export type SliceProjectView = {
6
+ readonly name: string;
7
+ /** Relative project dir from workspace root (e.g. `projects/funding/api`). */
8
+ readonly projectDirectory: string;
9
+ readonly main: string;
10
+ readonly scripts: Record<string, string>;
11
+ };
12
+ export type SliceKind = "flux" | "defer" | "skip";
13
+ export type ClassifiedSlice = {
14
+ readonly flux: SliceProjectView[];
15
+ readonly defer: SliceProjectView[];
16
+ readonly skip: SliceProjectView[];
17
+ };
18
+ /** Preferred package scripts for foreign toolchains (Nixpacks-style). */
19
+ export declare const DEFER_SCRIPT_CANDIDATES: readonly ["dev", "serve"];
20
+ /**
21
+ * Normalize a CLI slice token to a `projects/…` prefix without a trailing slash.
22
+ * `funding` and `projects/funding` both become `projects/funding`.
23
+ */
24
+ export declare function normalizeSlicePrefix(slice: string): string;
25
+ /**
26
+ * True when `projectDirectory` belongs to the slice token.
27
+ *
28
+ * Matches:
29
+ * - nested: `projects/funding`, `projects/funding/api`
30
+ * - flat dotted package dirs: `projects/funding.web` for token `funding`
31
+ *
32
+ * Does not match siblings that only share a string prefix (`funding` vs `funding-fee.api`).
33
+ */
34
+ export declare function isUnderSlice(projectDirectory: string, slicePrefix: string): boolean;
35
+ export declare function projectsInSlice(projects: readonly SliceProjectView[], slice: string): SliceProjectView[];
36
+ /** Union of packages under any of the slice tokens (deduped by package name). */
37
+ export declare function projectsInSlices(projects: readonly SliceProjectView[], slices: readonly string[]): SliceProjectView[];
38
+ /** Script invokes Flux (in-process serve stays on Flux, not deferred). */
39
+ export declare function isFluxOwnedScript(script: string): boolean;
40
+ /**
41
+ * First Nixpacks-style serve script that is not Flux-owned.
42
+ * Prefers `dev`, then `serve`.
43
+ */
44
+ export declare function resolveDeferScript(scripts: Record<string, string>): string | undefined;
45
+ /** Convention: Flux Node apps use `main` ending in `main.ts` / `main.tsx`. */
46
+ export declare function isFluxAppMain(main: string): boolean;
47
+ /**
48
+ * Classify one package. Foreign serve scripts win over `main.ts` (Vite apps
49
+ * often have a main entry but must not be HMR-booted by Flux).
50
+ */
51
+ export declare function classifySliceProject(project: SliceProjectView): SliceKind;
52
+ export declare function classifySliceProjects(projects: readonly SliceProjectView[], slices: string | readonly string[]): ClassifiedSlice;
@@ -0,0 +1,81 @@
1
+ import type { ResolveFnOutput } from "node:module";
2
+ import type { Project, Workspace } from "@decohere/mesh";
3
+ export interface SourceModuleLoaderOptions {
4
+ /** Build configuration name. */
5
+ buildConfig: string;
6
+ /**
7
+ * Pre-built Workspace instance to use instead of running WorkspaceFactory.
8
+ * Useful in tests to bypass filesystem-based workspace discovery.
9
+ */
10
+ workspace?: Workspace;
11
+ /**
12
+ * Map a watched `.ts` file URL for ESM resolution.
13
+ * Hot reload passes a `?version=` bust; one-shot run uses identity.
14
+ */
15
+ versionFileUrl?: (fileUrl: string) => string;
16
+ /** Optional post-resolve hook (e.g. dependency tracking for HMR). */
17
+ onResolved?: (result: ResolveFnOutput, parentUrl: string) => void;
18
+ }
19
+ /**
20
+ * Registers Node ESM resolve/load hooks and SWC-transpiles workspace `.ts`
21
+ * on the fly. No file watching and no entry reboot — that belongs to
22
+ * {@link HotReloadServer}.
23
+ */
24
+ export declare class SourceModuleLoader {
25
+ private readonly logger;
26
+ private readonly transpiler;
27
+ private disposed;
28
+ private hooksRegistered;
29
+ private workspace?;
30
+ private buildConfig;
31
+ private fileInfoMap;
32
+ private transpileCache;
33
+ /** Bumped when a file's cached code is dropped, so an up-front compile already running can't put it back. */
34
+ private transpileVersions;
35
+ /** The source files each entry's walk reached, so a reboot only walks out from what changed. */
36
+ private reachedFrom;
37
+ /** Up-front compiles in flight, shared by entries booting at the same time. */
38
+ private compilingAhead;
39
+ /** SWC options per project, built on first use and kept until the next `configure()`. */
40
+ private swcConfigs;
41
+ private aliasPaths;
42
+ private aliasBaseUrl;
43
+ private versionFileUrl;
44
+ private onResolved?;
45
+ getWorkspace(): Workspace | undefined;
46
+ getBuildConfig(): string;
47
+ hasSourceFile(absolutePath: string): boolean;
48
+ sourceFilePaths(): IterableIterator<string>;
49
+ setSourceFile(absolutePath: string, project: Project): void;
50
+ configure(options: SourceModuleLoaderOptions): Promise<void>;
51
+ registerHooks(): void;
52
+ importEntry(absolutePath: string): Promise<unknown>;
53
+ invalidateTranspile(...absolutePaths: string[]): void;
54
+ dispose(): void;
55
+ private buildFileInfoMap;
56
+ /**
57
+ * Compiles the entry and the source files it imports, before Node imports it (#661). The load
58
+ * hook is synchronous, so it would compile one file at a time on the main thread; async SWC
59
+ * runs on the thread pool. Walks out from the entry, compiling each file's imports in parallel,
60
+ * so files the app never imports (tests, other apps) are not compiled. A reboot walks out only
61
+ * from the files it reached before that are no longer cached (the saved ones), so their new
62
+ * imports are found without visiting the rest of the graph again.
63
+ *
64
+ * A file that fails here is left out of the cache instead of failing the boot: the load hook
65
+ * then compiles it again and throws as before, naming the file. The walk is a hint; whatever
66
+ * it misses is compiled by the load hook when Node gets to it.
67
+ */
68
+ private compileAhead;
69
+ /** The file's compiled code, from the cache or compiled now; undefined if it isn't a source. */
70
+ private compiledAhead;
71
+ /** The source file a specifier names, mapped the way the resolve hook maps it. */
72
+ private sourcePathOf;
73
+ private loadTs;
74
+ /**
75
+ * The project's SWC options, built once: rebuilding them for every file was about a quarter
76
+ * of load time (#513). Import specifiers are left as written, without `jsc.paths` or
77
+ * `resolveFully`: the resolve hook maps them to source files (aliases, `.js` to `.ts`,
78
+ * directory indexes), so SWC does not resolve them a second time against the disk.
79
+ */
80
+ private swcConfigFor;
81
+ }
@@ -0,0 +1,5 @@
1
+ declare function scan(code: string): string[];
2
+ export declare const staticImports: {
3
+ scan: typeof scan;
4
+ };
5
+ export {};