@lite-fsm/cli 0.1.0

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 (94) hide show
  1. package/LICENSE +21 -0
  2. package/dist/bin/lite-fsm.d.cts +2 -0
  3. package/dist/bin/lite-fsm.d.ts +2 -0
  4. package/dist/bin/lite-fsm.js +12 -0
  5. package/dist/cli/context.d.cts +21 -0
  6. package/dist/cli/context.d.ts +21 -0
  7. package/dist/cli/context.js +0 -0
  8. package/dist/cli/create-program.d.cts +6 -0
  9. package/dist/cli/create-program.d.ts +6 -0
  10. package/dist/cli/create-program.js +48 -0
  11. package/dist/cli/diagnostics.d.cts +15 -0
  12. package/dist/cli/diagnostics.d.ts +15 -0
  13. package/dist/cli/diagnostics.js +13 -0
  14. package/dist/cli/node-fs.d.cts +2 -0
  15. package/dist/cli/node-fs.d.ts +2 -0
  16. package/dist/cli/node-fs.js +33 -0
  17. package/dist/cli/result.d.cts +6 -0
  18. package/dist/cli/result.d.ts +6 -0
  19. package/dist/cli/result.js +8 -0
  20. package/dist/export-graph/command.d.cts +8 -0
  21. package/dist/export-graph/command.d.ts +8 -0
  22. package/dist/export-graph/command.js +30 -0
  23. package/dist/export-graph/export-document.d.cts +38 -0
  24. package/dist/export-graph/export-document.d.ts +38 -0
  25. package/dist/export-graph/export-document.js +35 -0
  26. package/dist/export-graph/options.d.cts +21 -0
  27. package/dist/export-graph/options.d.ts +21 -0
  28. package/dist/export-graph/options.js +40 -0
  29. package/dist/export-graph/run-export-graph.d.cts +10 -0
  30. package/dist/export-graph/run-export-graph.d.ts +10 -0
  31. package/dist/export-graph/run-export-graph.js +53 -0
  32. package/dist/export-graph/source-bundle.d.cts +12 -0
  33. package/dist/export-graph/source-bundle.d.ts +12 -0
  34. package/dist/export-graph/source-bundle.js +48 -0
  35. package/dist/export-graph/write-output.d.cts +10 -0
  36. package/dist/export-graph/write-output.d.ts +10 -0
  37. package/dist/export-graph/write-output.js +24 -0
  38. package/dist/output/format-diagnostics.d.cts +6 -0
  39. package/dist/output/format-diagnostics.d.ts +6 -0
  40. package/dist/output/format-diagnostics.js +33 -0
  41. package/dist/output/stable-json.d.cts +1 -0
  42. package/dist/output/stable-json.d.ts +1 -0
  43. package/dist/output/stable-json.js +72 -0
  44. package/dist/project/build-project-graph.d.cts +19 -0
  45. package/dist/project/build-project-graph.d.ts +19 -0
  46. package/dist/project/build-project-graph.js +64 -0
  47. package/dist/project/create-project-host.d.cts +4 -0
  48. package/dist/project/create-project-host.d.ts +4 -0
  49. package/dist/project/create-project-host.js +11 -0
  50. package/dist/project/module-resolver.d.cts +15 -0
  51. package/dist/project/module-resolver.d.ts +15 -0
  52. package/dist/project/module-resolver.js +111 -0
  53. package/dist/project/source-cache.d.cts +11 -0
  54. package/dist/project/source-cache.d.ts +11 -0
  55. package/dist/project/source-cache.js +55 -0
  56. package/dist/project/tsconfig.d.cts +15 -0
  57. package/dist/project/tsconfig.d.ts +15 -0
  58. package/dist/project/tsconfig.js +116 -0
  59. package/dist/visualize/command.d.cts +9 -0
  60. package/dist/visualize/command.d.ts +9 -0
  61. package/dist/visualize/command.js +35 -0
  62. package/dist/visualize/http.d.cts +11 -0
  63. package/dist/visualize/http.d.ts +11 -0
  64. package/dist/visualize/http.js +65 -0
  65. package/dist/visualize/open-browser.d.cts +22 -0
  66. package/dist/visualize/open-browser.d.ts +22 -0
  67. package/dist/visualize/open-browser.js +45 -0
  68. package/dist/visualize/options.d.cts +16 -0
  69. package/dist/visualize/options.d.ts +16 -0
  70. package/dist/visualize/options.js +51 -0
  71. package/dist/visualize/routes.d.cts +2 -0
  72. package/dist/visualize/routes.d.ts +2 -0
  73. package/dist/visualize/routes.js +24 -0
  74. package/dist/visualize/run-visualize.d.cts +32 -0
  75. package/dist/visualize/run-visualize.d.ts +32 -0
  76. package/dist/visualize/run-visualize.js +81 -0
  77. package/dist/visualize/server.d.cts +40 -0
  78. package/dist/visualize/server.d.ts +40 -0
  79. package/dist/visualize/server.js +90 -0
  80. package/dist/visualize/session.d.cts +34 -0
  81. package/dist/visualize/session.d.ts +34 -0
  82. package/dist/visualize/session.js +137 -0
  83. package/dist/visualize/static-assets.d.cts +17 -0
  84. package/dist/visualize/static-assets.d.ts +17 -0
  85. package/dist/visualize/static-assets.js +87 -0
  86. package/dist/visualize/types.d.cts +65 -0
  87. package/dist/visualize/types.d.ts +65 -0
  88. package/dist/visualize/types.js +0 -0
  89. package/dist/visualizer/assets/MachineCanvasGraph-CHpVij2M.css +1 -0
  90. package/dist/visualizer/assets/MachineCanvasGraph-DuWIhVsu.js +30 -0
  91. package/dist/visualizer/assets/index-CZYnsrxd.js +42381 -0
  92. package/dist/visualizer/assets/index-DMdcz3e2.css +2 -0
  93. package/dist/visualizer/index.html +13 -0
  94. package/package.json +57 -0
@@ -0,0 +1,48 @@
1
+ import { resolve } from "node:path";
2
+ import { cliDiagnostic } from "../cli/diagnostics.js";
3
+ import { normalizeAbsolutePath, normalizePath } from "../project/source-cache.js";
4
+ const sourcePath = (projectRoot, fileName) => normalizeAbsolutePath(resolve(projectRoot, fileName));
5
+ const createProjectGraphSourceBundle = (context, projectRoot, files) => {
6
+ const sourceFiles = [];
7
+ for (const file of files) {
8
+ const absolutePath = sourcePath(projectRoot, file.fileName);
9
+ try {
10
+ if (!context.fs.fileExists(absolutePath)) {
11
+ return {
12
+ ok: false,
13
+ diagnostics: [
14
+ cliDiagnostic(
15
+ "LFC_SOURCE_BUNDLE_FILE_UNREADABLE",
16
+ "error",
17
+ `Source file '${file.fileName}' could not be embedded in the graph export.`,
18
+ { file: normalizePath(absolutePath) }
19
+ )
20
+ ]
21
+ };
22
+ }
23
+ sourceFiles.push({
24
+ fileName: file.fileName,
25
+ language: file.language,
26
+ hash: file.hash,
27
+ text: context.fs.readFile(absolutePath)
28
+ });
29
+ } catch (error) {
30
+ const message = error instanceof Error ? error.message : String(error);
31
+ return {
32
+ ok: false,
33
+ diagnostics: [
34
+ cliDiagnostic(
35
+ "LFC_SOURCE_BUNDLE_FILE_UNREADABLE",
36
+ "error",
37
+ `Source file '${file.fileName}' could not be embedded in the graph export: ${message}`,
38
+ { file: normalizePath(absolutePath) }
39
+ )
40
+ ]
41
+ };
42
+ }
43
+ }
44
+ return { ok: true, sources: { files: sourceFiles } };
45
+ };
46
+ export {
47
+ createProjectGraphSourceBundle
48
+ };
@@ -0,0 +1,10 @@
1
+ import type { CliContext } from "../cli/context.js";
2
+ import type { CliDiagnostic } from "../cli/diagnostics.js";
3
+ export type WriteOutputResult = {
4
+ ok: true;
5
+ outputPath: string;
6
+ } | {
7
+ ok: false;
8
+ diagnostics: CliDiagnostic[];
9
+ };
10
+ export declare const writeOutput: (context: CliContext, outputPath: string, contents: string) => WriteOutputResult;
@@ -0,0 +1,10 @@
1
+ import type { CliContext } from "../cli/context.js";
2
+ import type { CliDiagnostic } from "../cli/diagnostics.js";
3
+ export type WriteOutputResult = {
4
+ ok: true;
5
+ outputPath: string;
6
+ } | {
7
+ ok: false;
8
+ diagnostics: CliDiagnostic[];
9
+ };
10
+ export declare const writeOutput: (context: CliContext, outputPath: string, contents: string) => WriteOutputResult;
@@ -0,0 +1,24 @@
1
+ import { dirname, resolve } from "node:path";
2
+ import { cliDiagnostic } from "../cli/diagnostics.js";
3
+ import { normalizeAbsolutePath } from "../project/source-cache.js";
4
+ const writeOutput = (context, outputPath, contents) => {
5
+ const absoluteOutputPath = normalizeAbsolutePath(resolve(context.cwd, outputPath));
6
+ try {
7
+ context.fs.mkdir(dirname(absoluteOutputPath), { recursive: true });
8
+ context.fs.writeFile(absoluteOutputPath, contents);
9
+ return { ok: true, outputPath: absoluteOutputPath };
10
+ } catch (error) {
11
+ const message = error instanceof Error ? error.message : String(error);
12
+ return {
13
+ ok: false,
14
+ diagnostics: [
15
+ cliDiagnostic("LFC_WRITE_FAILED", "error", `Failed to write graph export: ${message}`, {
16
+ file: absoluteOutputPath
17
+ })
18
+ ]
19
+ };
20
+ }
21
+ };
22
+ export {
23
+ writeOutput
24
+ };
@@ -0,0 +1,6 @@
1
+ import type { GraphDiagnostic } from "@lite-fsm/graph";
2
+ import type { CliDiagnostic } from "../cli/diagnostics.js";
3
+ type PrintableDiagnostic = CliDiagnostic | GraphDiagnostic;
4
+ export declare const formatDiagnostic: (diagnostic: PrintableDiagnostic) => string;
5
+ export declare const formatDiagnostics: (diagnostics: readonly PrintableDiagnostic[]) => string;
6
+ export {};
@@ -0,0 +1,6 @@
1
+ import type { GraphDiagnostic } from "@lite-fsm/graph";
2
+ import type { CliDiagnostic } from "../cli/diagnostics.js";
3
+ type PrintableDiagnostic = CliDiagnostic | GraphDiagnostic;
4
+ export declare const formatDiagnostic: (diagnostic: PrintableDiagnostic) => string;
5
+ export declare const formatDiagnostics: (diagnostics: readonly PrintableDiagnostic[]) => string;
6
+ export {};
@@ -0,0 +1,33 @@
1
+ const diagnosticFile = (diagnostic) => {
2
+ if ("file" in diagnostic && diagnostic.file) return diagnostic.file;
3
+ if (!diagnostic.loc || !("fileName" in diagnostic.loc)) return void 0;
4
+ return diagnostic.loc.fileName;
5
+ };
6
+ const diagnosticLine = (diagnostic) => {
7
+ if (!diagnostic.loc) return void 0;
8
+ if ("line" in diagnostic.loc) return diagnostic.loc.line;
9
+ return diagnostic.loc.start.line;
10
+ };
11
+ const diagnosticColumn = (diagnostic) => {
12
+ if (!diagnostic.loc) return void 0;
13
+ if ("line" in diagnostic.loc) return "column" in diagnostic.loc ? diagnostic.loc.column : void 0;
14
+ return diagnostic.loc.start.column;
15
+ };
16
+ const formatDiagnostic = (diagnostic) => {
17
+ const file = diagnosticFile(diagnostic);
18
+ const line = diagnosticLine(diagnostic);
19
+ const column = diagnosticColumn(diagnostic);
20
+ const location = file ? ` ${file}${line === void 0 ? "" : `:${line}:${column ?? 1}`}` : "";
21
+ const hint = "hint" in diagnostic && diagnostic.hint ? `
22
+ hint: ${diagnostic.hint}` : "";
23
+ return `${diagnostic.severity.toUpperCase()} ${diagnostic.code}${location}: ${diagnostic.message}${hint}`;
24
+ };
25
+ const formatDiagnostics = (diagnostics) => {
26
+ if (diagnostics.length === 0) return "";
27
+ return `${diagnostics.map(formatDiagnostic).join("\n")}
28
+ `;
29
+ };
30
+ export {
31
+ formatDiagnostic,
32
+ formatDiagnostics
33
+ };
@@ -0,0 +1 @@
1
+ export declare const stringifyStableJson: (value: unknown) => string;
@@ -0,0 +1 @@
1
+ export declare const stringifyStableJson: (value: unknown) => string;
@@ -0,0 +1,72 @@
1
+ const KEY_ORDER = [
2
+ "version",
3
+ "createdBy",
4
+ "package",
5
+ "entry",
6
+ "path",
7
+ "tsconfigPath",
8
+ "graph",
9
+ "source",
10
+ "filename",
11
+ "language",
12
+ "kind",
13
+ "entryFileName",
14
+ "files",
15
+ "fileName",
16
+ "roles",
17
+ "hash",
18
+ "machines",
19
+ "managers",
20
+ "diagnostics",
21
+ "code",
22
+ "severity",
23
+ "message",
24
+ "machineId",
25
+ "loc",
26
+ "start",
27
+ "end",
28
+ "line",
29
+ "column",
30
+ "offset",
31
+ "hint",
32
+ "id",
33
+ "index",
34
+ "variableName",
35
+ "exportName",
36
+ "managerKeys",
37
+ "machineRefs",
38
+ "key",
39
+ "machineId",
40
+ "states",
41
+ "transitions",
42
+ "emissions",
43
+ "reducerCases"
44
+ ];
45
+ const keyRanks = new Map(KEY_ORDER.map((key, index) => [key, index]));
46
+ const orderedKeys = (value) => {
47
+ return Object.keys(value).sort((left, right) => {
48
+ const leftRank = keyRanks.get(left) ?? Number.MAX_SAFE_INTEGER;
49
+ const rightRank = keyRanks.get(right) ?? Number.MAX_SAFE_INTEGER;
50
+ return leftRank === rightRank ? left.localeCompare(right) : leftRank - rightRank;
51
+ });
52
+ };
53
+ const isPlainObject = (value) => {
54
+ return typeof value === "object" && value !== null && !Array.isArray(value);
55
+ };
56
+ const stableValue = (value) => {
57
+ if (Array.isArray(value)) return value.map(stableValue);
58
+ if (!isPlainObject(value)) return value;
59
+ const next = {};
60
+ for (const key of orderedKeys(value)) {
61
+ const child = value[key];
62
+ if (child !== void 0) next[key] = stableValue(child);
63
+ }
64
+ return next;
65
+ };
66
+ const stringifyStableJson = (value) => {
67
+ return `${JSON.stringify(stableValue(value), null, 2)}
68
+ `;
69
+ };
70
+ export {
71
+ stringifyStableJson
72
+ };
@@ -0,0 +1,19 @@
1
+ import { type LiteFsmGraphProjectResult } from "@lite-fsm/graph";
2
+ import type { CliContext } from "../cli/context.js";
3
+ import type { CliDiagnostic } from "../cli/diagnostics.js";
4
+ export type ProjectGraphBuildOptions = {
5
+ entry: string;
6
+ tsconfig?: string;
7
+ };
8
+ export type ProjectGraphBuildResult = {
9
+ project: {
10
+ entryPath: string;
11
+ absoluteEntryPath: string;
12
+ projectRoot: string;
13
+ tsconfigPath?: string;
14
+ };
15
+ graphResult?: LiteFsmGraphProjectResult;
16
+ diagnostics: CliDiagnostic[];
17
+ blocking: boolean;
18
+ };
19
+ export declare const buildProjectGraph: (context: CliContext, options: ProjectGraphBuildOptions) => ProjectGraphBuildResult;
@@ -0,0 +1,19 @@
1
+ import { type LiteFsmGraphProjectResult } from "@lite-fsm/graph";
2
+ import type { CliContext } from "../cli/context.js";
3
+ import type { CliDiagnostic } from "../cli/diagnostics.js";
4
+ export type ProjectGraphBuildOptions = {
5
+ entry: string;
6
+ tsconfig?: string;
7
+ };
8
+ export type ProjectGraphBuildResult = {
9
+ project: {
10
+ entryPath: string;
11
+ absoluteEntryPath: string;
12
+ projectRoot: string;
13
+ tsconfigPath?: string;
14
+ };
15
+ graphResult?: LiteFsmGraphProjectResult;
16
+ diagnostics: CliDiagnostic[];
17
+ blocking: boolean;
18
+ };
19
+ export declare const buildProjectGraph: (context: CliContext, options: ProjectGraphBuildOptions) => ProjectGraphBuildResult;
@@ -0,0 +1,64 @@
1
+ import { relative, resolve } from "node:path";
2
+ import { compileLiteFsmGraphProject } from "@lite-fsm/graph";
3
+ import { cliDiagnostic, hasBlockingCliDiagnostics } from "../cli/diagnostics.js";
4
+ import { createProjectHost } from "./create-project-host.js";
5
+ import { createProjectModuleResolver } from "./module-resolver.js";
6
+ import { createSourceCache, normalizeAbsolutePath, normalizePath } from "./source-cache.js";
7
+ import { resolveProjectTsconfig } from "./tsconfig.js";
8
+ const toDisplayPath = (path, cwd) => {
9
+ const relativePath = normalizePath(relative(cwd, path));
10
+ return relativePath === "" || !relativePath.startsWith("../") && relativePath !== ".." ? relativePath || "." : normalizePath(path);
11
+ };
12
+ const buildProjectGraph = (context, options) => {
13
+ const absoluteEntryPath = normalizeAbsolutePath(resolve(context.cwd, options.entry));
14
+ const tsconfig = resolveProjectTsconfig(context, {
15
+ entryFileName: absoluteEntryPath,
16
+ explicitTsconfigPath: options.tsconfig
17
+ });
18
+ const project = {
19
+ entryPath: toDisplayPath(absoluteEntryPath, normalizeAbsolutePath(context.cwd)),
20
+ absoluteEntryPath,
21
+ projectRoot: tsconfig.projectRoot,
22
+ tsconfigPath: tsconfig.tsconfigPath ? toDisplayPath(tsconfig.tsconfigPath, normalizeAbsolutePath(context.cwd)) : void 0
23
+ };
24
+ if (tsconfig.blocking) {
25
+ return {
26
+ project,
27
+ diagnostics: tsconfig.diagnostics,
28
+ blocking: true
29
+ };
30
+ }
31
+ try {
32
+ const sourceCache = createSourceCache(context.fs);
33
+ const resolver = createProjectModuleResolver({
34
+ compilerOptions: tsconfig.compilerOptions,
35
+ projectRoot: tsconfig.projectRoot,
36
+ sourceCache
37
+ });
38
+ const host = createProjectHost(sourceCache, resolver);
39
+ const graphResult = compileLiteFsmGraphProject({
40
+ entryFileName: absoluteEntryPath,
41
+ projectRoot: tsconfig.projectRoot,
42
+ host
43
+ });
44
+ return {
45
+ project,
46
+ graphResult,
47
+ diagnostics: tsconfig.diagnostics,
48
+ blocking: hasBlockingCliDiagnostics(tsconfig.diagnostics)
49
+ };
50
+ } catch (error) {
51
+ const message = error instanceof Error ? error.message : String(error);
52
+ return {
53
+ project,
54
+ diagnostics: [
55
+ ...tsconfig.diagnostics,
56
+ cliDiagnostic("LFC_GRAPH_PROJECT_FAILED", "error", `Project graph build failed unexpectedly: ${message}`)
57
+ ],
58
+ blocking: true
59
+ };
60
+ }
61
+ };
62
+ export {
63
+ buildProjectGraph
64
+ };
@@ -0,0 +1,4 @@
1
+ import type { LiteFsmGraphProjectHost } from "@lite-fsm/graph";
2
+ import type { ProjectModuleResolver } from "./module-resolver.js";
3
+ import type { SourceCache } from "./source-cache.js";
4
+ export declare const createProjectHost: (sourceCache: SourceCache, resolver: ProjectModuleResolver) => LiteFsmGraphProjectHost;
@@ -0,0 +1,4 @@
1
+ import type { LiteFsmGraphProjectHost } from "@lite-fsm/graph";
2
+ import type { ProjectModuleResolver } from "./module-resolver.js";
3
+ import type { SourceCache } from "./source-cache.js";
4
+ export declare const createProjectHost: (sourceCache: SourceCache, resolver: ProjectModuleResolver) => LiteFsmGraphProjectHost;
@@ -0,0 +1,11 @@
1
+ const createProjectHost = (sourceCache, resolver) => ({
2
+ readSource(fileName) {
3
+ return sourceCache.readSource(fileName);
4
+ },
5
+ resolveModule(input) {
6
+ return resolver.resolveModule(input);
7
+ }
8
+ });
9
+ export {
10
+ createProjectHost
11
+ };
@@ -0,0 +1,15 @@
1
+ import ts from "typescript";
2
+ import type { LiteFsmGraphProjectModuleResolution } from "@lite-fsm/graph";
3
+ import type { SourceCache } from "./source-cache.js";
4
+ export type ProjectModuleResolver = {
5
+ resolveModule(input: {
6
+ fromFileName: string;
7
+ moduleSpecifier: string;
8
+ }): LiteFsmGraphProjectModuleResolution;
9
+ };
10
+ export type ProjectModuleResolverOptions = {
11
+ compilerOptions: ts.CompilerOptions;
12
+ projectRoot: string;
13
+ sourceCache: SourceCache;
14
+ };
15
+ export declare const createProjectModuleResolver: ({ compilerOptions, projectRoot, sourceCache, }: ProjectModuleResolverOptions) => ProjectModuleResolver;
@@ -0,0 +1,15 @@
1
+ import ts from "typescript";
2
+ import type { LiteFsmGraphProjectModuleResolution } from "@lite-fsm/graph";
3
+ import type { SourceCache } from "./source-cache.js";
4
+ export type ProjectModuleResolver = {
5
+ resolveModule(input: {
6
+ fromFileName: string;
7
+ moduleSpecifier: string;
8
+ }): LiteFsmGraphProjectModuleResolution;
9
+ };
10
+ export type ProjectModuleResolverOptions = {
11
+ compilerOptions: ts.CompilerOptions;
12
+ projectRoot: string;
13
+ sourceCache: SourceCache;
14
+ };
15
+ export declare const createProjectModuleResolver: ({ compilerOptions, projectRoot, sourceCache, }: ProjectModuleResolverOptions) => ProjectModuleResolver;
@@ -0,0 +1,111 @@
1
+ import { extname, isAbsolute, relative, resolve } from "node:path";
2
+ import ts from "typescript";
3
+ import { normalizeAbsolutePath, normalizePath } from "./source-cache.js";
4
+ const SUPPORTED_EXTENSION = ".ts";
5
+ const isRelativeSpecifier = (moduleSpecifier) => {
6
+ return moduleSpecifier.startsWith("./") || moduleSpecifier.startsWith("../");
7
+ };
8
+ const isCoreSpecifier = (moduleSpecifier) => {
9
+ return moduleSpecifier === "@lite-fsm/core" || moduleSpecifier === "lite-fsm";
10
+ };
11
+ const explicitExtension = (moduleSpecifier) => {
12
+ const segments = moduleSpecifier.split("/");
13
+ const lastSegment = segments[segments.length - 1] ?? moduleSpecifier;
14
+ const extension = extname(lastSegment);
15
+ return extension === "" ? void 0 : extension;
16
+ };
17
+ const isInsideRoot = (fileName, projectRoot) => {
18
+ const relativePath = normalizePath(relative(projectRoot, fileName));
19
+ return relativePath === "" || !relativePath.startsWith("../") && relativePath !== ".." && !isAbsolute(relativePath);
20
+ };
21
+ const pathPatternToRegExp = (pattern) => {
22
+ const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
23
+ return new RegExp(`^${escaped}$`);
24
+ };
25
+ const matchesPaths = (moduleSpecifier, paths) => {
26
+ if (!paths) return false;
27
+ return Object.keys(paths).some((pattern) => pathPatternToRegExp(pattern).test(moduleSpecifier));
28
+ };
29
+ const isBaseUrlCandidate = (moduleSpecifier, baseUrl) => {
30
+ return Boolean(baseUrl) && !moduleSpecifier.startsWith("@") && !moduleSpecifier.startsWith("lite-fsm/");
31
+ };
32
+ const firstSpecifierSegment = (moduleSpecifier) => {
33
+ const separatorIndex = moduleSpecifier.indexOf("/");
34
+ return separatorIndex === -1 ? moduleSpecifier : moduleSpecifier.slice(0, separatorIndex);
35
+ };
36
+ const hasBaseUrlProjectPrefix = (moduleSpecifier, baseUrl, sourceCache) => {
37
+ const candidate = normalizeAbsolutePath(resolve(baseUrl, firstSpecifierSegment(moduleSpecifier)));
38
+ return sourceCache.fileExists(`${candidate}.ts`) || sourceCache.directoryExists(candidate);
39
+ };
40
+ const resolutionHost = (sourceCache) => ({
41
+ fileExists(path) {
42
+ return sourceCache.fileExists(path);
43
+ },
44
+ /* v8 ignore next 3 -- TypeScript only asks readFile for package metadata/declaration strategies outside the CLI source traversal path. */
45
+ readFile(path) {
46
+ return sourceCache.readSource(path);
47
+ },
48
+ directoryExists(path) {
49
+ return sourceCache.directoryExists(path);
50
+ },
51
+ /* v8 ignore next 3 -- realpath is supplied for TypeScript host completeness; current supported resolver paths do not require it. */
52
+ realpath(path) {
53
+ return sourceCache.realpath(path);
54
+ },
55
+ getCurrentDirectory() {
56
+ return "/";
57
+ }
58
+ });
59
+ const resolutionFromFileName = (moduleSpecifier, fileName, projectRoot) => {
60
+ const extension = extname(fileName);
61
+ if (extension !== SUPPORTED_EXTENSION) {
62
+ return {
63
+ kind: "unsupported-extension",
64
+ moduleSpecifier,
65
+ /* v8 ignore next -- unsupported resolved modules always have an extension in supported TypeScript resolution. */
66
+ extension: extension || "unknown"
67
+ };
68
+ }
69
+ if (!isInsideRoot(fileName, projectRoot)) return { kind: "external", moduleSpecifier };
70
+ return { kind: "resolved", fileName };
71
+ };
72
+ const createProjectModuleResolver = ({
73
+ compilerOptions,
74
+ projectRoot,
75
+ sourceCache
76
+ }) => {
77
+ const normalizedProjectRoot = normalizeAbsolutePath(projectRoot);
78
+ const host = resolutionHost(sourceCache);
79
+ return {
80
+ resolveModule({ fromFileName, moduleSpecifier }) {
81
+ if (isCoreSpecifier(moduleSpecifier)) return { kind: "core", moduleSpecifier };
82
+ if (moduleSpecifier.startsWith("lite-fsm/")) return { kind: "external", moduleSpecifier };
83
+ const extension = explicitExtension(moduleSpecifier);
84
+ if (extension && extension !== SUPPORTED_EXTENSION) {
85
+ return { kind: "unsupported-extension", moduleSpecifier, extension };
86
+ }
87
+ const relativeSpecifier = isRelativeSpecifier(moduleSpecifier);
88
+ const pathsCandidate = matchesPaths(moduleSpecifier, compilerOptions.paths);
89
+ const baseUrl = compilerOptions.baseUrl;
90
+ const baseUrlCandidate = isBaseUrlCandidate(moduleSpecifier, baseUrl);
91
+ const projectLocalCandidate = relativeSpecifier || pathsCandidate || baseUrlCandidate;
92
+ if (!projectLocalCandidate) return { kind: "external", moduleSpecifier };
93
+ const resolvedModule = ts.resolveModuleName(
94
+ moduleSpecifier,
95
+ normalizeAbsolutePath(fromFileName),
96
+ compilerOptions,
97
+ host
98
+ ).resolvedModule;
99
+ if (!resolvedModule) {
100
+ const unresolvedProjectLocal = relativeSpecifier || pathsCandidate || baseUrlCandidate && hasBaseUrlProjectPrefix(moduleSpecifier, baseUrl, sourceCache);
101
+ return unresolvedProjectLocal ? { kind: "not-found", moduleSpecifier } : { kind: "external", moduleSpecifier };
102
+ }
103
+ if (resolvedModule.isExternalLibraryImport) return { kind: "external", moduleSpecifier };
104
+ const resolvedFileName = normalizeAbsolutePath(resolve(resolvedModule.resolvedFileName));
105
+ return resolutionFromFileName(moduleSpecifier, resolvedFileName, normalizedProjectRoot);
106
+ }
107
+ };
108
+ };
109
+ export {
110
+ createProjectModuleResolver
111
+ };
@@ -0,0 +1,11 @@
1
+ import type { CliFileSystem } from "../cli/context.js";
2
+ export declare const normalizeAbsolutePath: (path: string) => string;
3
+ export declare const normalizePath: (path: string) => string;
4
+ export type SourceCache = {
5
+ readSource(path: string): string | undefined;
6
+ fileExists(path: string): boolean;
7
+ directoryExists(path: string): boolean;
8
+ realpath(path: string): string;
9
+ sourceHash(path: string): string | undefined;
10
+ };
11
+ export declare const createSourceCache: (fs: CliFileSystem) => SourceCache;
@@ -0,0 +1,11 @@
1
+ import type { CliFileSystem } from "../cli/context.js";
2
+ export declare const normalizeAbsolutePath: (path: string) => string;
3
+ export declare const normalizePath: (path: string) => string;
4
+ export type SourceCache = {
5
+ readSource(path: string): string | undefined;
6
+ fileExists(path: string): boolean;
7
+ directoryExists(path: string): boolean;
8
+ realpath(path: string): string;
9
+ sourceHash(path: string): string | undefined;
10
+ };
11
+ export declare const createSourceCache: (fs: CliFileSystem) => SourceCache;
@@ -0,0 +1,55 @@
1
+ import { createHash } from "node:crypto";
2
+ import { extname, resolve } from "node:path";
3
+ const toPosixPath = (path) => path.replace(/\\/g, "/");
4
+ const normalizeAbsolutePath = (path) => toPosixPath(resolve(path));
5
+ const normalizePath = (path) => toPosixPath(path);
6
+ const createSourceCache = (fs) => {
7
+ const sourceByPath = /* @__PURE__ */ new Map();
8
+ const fileExistsByPath = /* @__PURE__ */ new Map();
9
+ const directoryExistsByPath = /* @__PURE__ */ new Map();
10
+ const normalizeKey = (path) => normalizeAbsolutePath(path);
11
+ const fileExists = (path) => {
12
+ const key = normalizeKey(path);
13
+ const cached = fileExistsByPath.get(key);
14
+ if (cached !== void 0) return cached;
15
+ const exists = fs.fileExists(key);
16
+ fileExistsByPath.set(key, exists);
17
+ return exists;
18
+ };
19
+ const directoryExists = (path) => {
20
+ const key = normalizeKey(path);
21
+ const cached = directoryExistsByPath.get(key);
22
+ if (cached !== void 0) return cached;
23
+ const exists = fs.directoryExists(key);
24
+ directoryExistsByPath.set(key, exists);
25
+ return exists;
26
+ };
27
+ const readSource = (path) => {
28
+ const key = normalizeKey(path);
29
+ if (extname(key) !== ".ts") return void 0;
30
+ if (sourceByPath.has(key)) return sourceByPath.get(key);
31
+ const source = fileExists(key) ? fs.readFile(key) : void 0;
32
+ sourceByPath.set(key, source);
33
+ return source;
34
+ };
35
+ const sourceHash = (path) => {
36
+ const source = readSource(path);
37
+ if (source === void 0) return void 0;
38
+ return createHash("sha256").update(source).digest("hex");
39
+ };
40
+ return {
41
+ readSource,
42
+ fileExists,
43
+ directoryExists,
44
+ realpath(path) {
45
+ const key = normalizeKey(path);
46
+ return fs.realpath ? normalizeAbsolutePath(fs.realpath(key)) : key;
47
+ },
48
+ sourceHash
49
+ };
50
+ };
51
+ export {
52
+ createSourceCache,
53
+ normalizeAbsolutePath,
54
+ normalizePath
55
+ };
@@ -0,0 +1,15 @@
1
+ import ts from "typescript";
2
+ import type { CliContext } from "../cli/context.js";
3
+ import type { CliDiagnostic } from "../cli/diagnostics.js";
4
+ export type ProjectTsconfig = {
5
+ tsconfigPath?: string;
6
+ projectRoot: string;
7
+ compilerOptions: ts.CompilerOptions;
8
+ diagnostics: CliDiagnostic[];
9
+ blocking: boolean;
10
+ };
11
+ export type ResolveProjectTsconfigOptions = {
12
+ entryFileName: string;
13
+ explicitTsconfigPath?: string;
14
+ };
15
+ export declare const resolveProjectTsconfig: (context: CliContext, options: ResolveProjectTsconfigOptions) => ProjectTsconfig;
@@ -0,0 +1,15 @@
1
+ import ts from "typescript";
2
+ import type { CliContext } from "../cli/context.js";
3
+ import type { CliDiagnostic } from "../cli/diagnostics.js";
4
+ export type ProjectTsconfig = {
5
+ tsconfigPath?: string;
6
+ projectRoot: string;
7
+ compilerOptions: ts.CompilerOptions;
8
+ diagnostics: CliDiagnostic[];
9
+ blocking: boolean;
10
+ };
11
+ export type ResolveProjectTsconfigOptions = {
12
+ entryFileName: string;
13
+ explicitTsconfigPath?: string;
14
+ };
15
+ export declare const resolveProjectTsconfig: (context: CliContext, options: ResolveProjectTsconfigOptions) => ProjectTsconfig;