@visulima/task-runner 0.0.1 → 1.0.0-alpha.2

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 (49) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +170 -36
  4. package/binding.js +204 -0
  5. package/dist/affected.d.ts +48 -0
  6. package/dist/cache.d.ts +103 -0
  7. package/dist/default-task-runner.d.ts +44 -0
  8. package/dist/file-access-tracker.d.ts +53 -0
  9. package/dist/fingerprint.d.ts +45 -0
  10. package/dist/framework-inference.d.ts +35 -0
  11. package/dist/graph-visualizer.d.ts +74 -0
  12. package/dist/incremental-hasher.d.ts +58 -0
  13. package/dist/index.d.ts +34 -0
  14. package/dist/index.js +20 -0
  15. package/dist/life-cycle.d.ts +36 -0
  16. package/dist/lockfile-hasher.d.ts +73 -0
  17. package/dist/native-binding.d.ts +64 -0
  18. package/dist/packem_shared/Cache-IYpTYVUC.js +298 -0
  19. package/dist/packem_shared/CompositeLifeCycle-7AtYw1dv.js +112 -0
  20. package/dist/packem_shared/FileAccessTracker-CrtBAt5D.js +239 -0
  21. package/dist/packem_shared/FingerprintManager-D6Y0erg-.js +227 -0
  22. package/dist/packem_shared/IncrementalFileHasher-Ds3J6dgb.js +151 -0
  23. package/dist/packem_shared/RemoteCache-BDqrnDEi.js +179 -0
  24. package/dist/packem_shared/TaskOrchestrator-BvYs3ONw.js +342 -0
  25. package/dist/packem_shared/TaskScheduler-CJilHDta.js +111 -0
  26. package/dist/packem_shared/TrackedTaskExecutor-BGUKFE-7.js +164 -0
  27. package/dist/packem_shared/collectFiles-ClXHnHhg.js +22 -0
  28. package/dist/packem_shared/computeTaskHash-BoCnnvIJ.js +356 -0
  29. package/dist/packem_shared/createTaskGraph-CcsFaSrz.js +164 -0
  30. package/dist/packem_shared/defaultTaskRunner-CrW4v5Ye.js +79 -0
  31. package/dist/packem_shared/detectFrameworks-CeFzKE6J.js +101 -0
  32. package/dist/packem_shared/extractPackageName-CbVNW-dr.js +189 -0
  33. package/dist/packem_shared/filterAffectedTasks-I-18zPg6.js +135 -0
  34. package/dist/packem_shared/findCycle-DF4_BRdO.js +212 -0
  35. package/dist/packem_shared/generateRunSummary-qn-_jKwt.js +134 -0
  36. package/dist/packem_shared/isNativeAvailable-BWhnZ4ES.js +19 -0
  37. package/dist/packem_shared/projectGraphToDot-VdTjHcVp.js +202 -0
  38. package/dist/packem_shared/utils-zO0ZRgtf.js +390 -0
  39. package/dist/remote-cache.d.ts +55 -0
  40. package/dist/run-summary.d.ts +89 -0
  41. package/dist/task-graph-utils.d.ts +39 -0
  42. package/dist/task-graph.d.ts +22 -0
  43. package/dist/task-hasher.d.ts +67 -0
  44. package/dist/task-orchestrator.d.ts +38 -0
  45. package/dist/task-scheduler.d.ts +18 -0
  46. package/dist/tracked-executor.d.ts +46 -0
  47. package/dist/types.d.ts +385 -0
  48. package/dist/utils.d.ts +39 -0
  49. package/package.json +72 -7
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Represents a file access recorded during task execution.
3
+ */
4
+ export interface FileAccess {
5
+ /** The absolute path of the file */
6
+ path: string;
7
+ /** The type of access */
8
+ type: "read" | "stat" | "readdir" | "missing";
9
+ }
10
+ /**
11
+ * Result of tracking file accesses during a command execution.
12
+ */
13
+ export interface TrackingResult {
14
+ /** All file accesses recorded */
15
+ accesses: FileAccess[];
16
+ /** The command exit code */
17
+ code: number;
18
+ /** The command stdout + stderr output */
19
+ output: string;
20
+ }
21
+ /**
22
+ * Tracks which files a child process accesses during execution.
23
+ *
24
+ * Uses `strace` on Linux to intercept syscalls (open, openat, stat, lstat, access, getdents).
25
+ * Falls back to no tracking on unsupported platforms.
26
+ */
27
+ export declare class FileAccessTracker {
28
+ #private;
29
+ constructor(workspaceRoot: string, excludePatterns?: RegExp[]);
30
+ /**
31
+ * Returns true if file access tracking is supported on the current platform.
32
+ */
33
+ isSupported(): boolean;
34
+ /**
35
+ * Runs a command and tracks all file system accesses.
36
+ * On unsupported platforms, runs the command without tracking.
37
+ */
38
+ track(command: string, options?: {
39
+ cwd?: string;
40
+ env?: Record<string, string | undefined>;
41
+ }): Promise<TrackingResult>;
42
+ /**
43
+ * Kills all active child processes. Called on abort/signal to prevent orphans.
44
+ */
45
+ killAll(): void;
46
+ }
47
+ /**
48
+ * Generates a preload script that can be used with NODE_OPTIONS to
49
+ * track file accesses in Node.js child processes.
50
+ *
51
+ * This is an alternative to strace that works cross-platform for Node.js processes.
52
+ */
53
+ export declare const generatePreloadScript: (outputPath: string) => string;
@@ -0,0 +1,45 @@
1
+ import type { FileAccess } from "./file-access-tracker.d.ts";
2
+ /**
3
+ * Represents a stored fingerprint for a task execution.
4
+ */
5
+ export interface TaskFingerprint {
6
+ /** Hash of the command arguments */
7
+ commandHash: string;
8
+ /** Directory listings recorded during execution (path -> sorted entries) */
9
+ directoryListings: Record<string, string[]>;
10
+ /** Hashes of fingerprinted environment variables */
11
+ envHashes: Record<string, string>;
12
+ /** Content hashes of files that were read during execution */
13
+ fileHashes: Record<string, string>;
14
+ /** Paths of files that were probed but didn't exist (ENOENT) */
15
+ missingFiles: string[];
16
+ }
17
+ /**
18
+ * Describes why a cache miss occurred.
19
+ */
20
+ export interface CacheMissReason {
21
+ currentHash?: string;
22
+ detail: string;
23
+ previousHash?: string;
24
+ type: "file-changed" | "file-created" | "file-deleted" | "directory-changed" | "env-changed" | "args-changed" | "no-fingerprint";
25
+ }
26
+ /**
27
+ * Manages task fingerprints for auto-detection caching.
28
+ *
29
+ * Records which files a task accesses during execution, stores content
30
+ * hashes, and on subsequent runs checks if any accessed file has changed.
31
+ */
32
+ export declare class FingerprintManager {
33
+ #private;
34
+ constructor(workspaceRoot: string);
35
+ createFingerprint(accesses: FileAccess[], command: string, args: Record<string, unknown>, envVariables: Record<string, string | undefined>, envPatterns?: string[], untrackedEnvVariables?: string[]): Promise<TaskFingerprint>;
36
+ /**
37
+ * Validates a stored fingerprint against the current state.
38
+ * Returns null if valid (cache hit), or an array of reasons (cache miss).
39
+ *
40
+ * Does NOT use the file hash cache — validation must see current disk state.
41
+ */
42
+ validate(fingerprint: TaskFingerprint): Promise<CacheMissReason[] | undefined>;
43
+ validateCommand(fingerprint: TaskFingerprint, command: string, args: Record<string, unknown>): CacheMissReason | undefined;
44
+ formatMissReasons(reasons: CacheMissReason[]): string;
45
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Detected framework information.
3
+ */
4
+ interface DetectedFramework {
5
+ /** The env var prefix(es) that should be included in task hashes */
6
+ envPrefixes: string[];
7
+ /** The framework name */
8
+ name: string;
9
+ }
10
+ /**
11
+ * Detects frameworks used in a project by inspecting its package.json dependencies.
12
+ * @param packageJsonPath Absolute path to the package.json file
13
+ * @returns Array of detected frameworks with their env prefixes
14
+ */
15
+ declare const detectFrameworks: (packageJsonPath: string) => Promise<DetectedFramework[]>;
16
+ /**
17
+ * Detects frameworks across all projects in a workspace and returns
18
+ * the env var patterns that should be included in task hashes.
19
+ * @param workspaceRoot The workspace root directory
20
+ * @param projects Map of project name to project configuration with root paths
21
+ * @returns Array of env var wildcard patterns (e.g., ["NEXT_PUBLIC_*", "VITE_*"])
22
+ */
23
+ declare const inferFrameworkEnvPatterns: (workspaceRoot: string, projects: Record<string, {
24
+ root: string;
25
+ }>) => Promise<string[]>;
26
+ /**
27
+ * For a specific project, detects frameworks and returns the matching
28
+ * env vars from the current environment.
29
+ * @param packageJsonPath Absolute path to the project's package.json
30
+ * @param env The current environment variables
31
+ * @returns Map of env var name to value for matching framework env vars
32
+ */
33
+ declare const getFrameworkEnvVariables: (packageJsonPath: string, env?: Record<string, string | undefined>) => Promise<Record<string, string>>;
34
+ export type { DetectedFramework };
35
+ export { detectFrameworks, getFrameworkEnvVariables, inferFrameworkEnvPatterns };
@@ -0,0 +1,74 @@
1
+ import type { ProjectGraph, TaskGraph } from "./types.d.ts";
2
+ /**
3
+ * Graph visualization output formats.
4
+ */
5
+ type GraphFormat = "dot" | "json" | "html" | "ascii";
6
+ /**
7
+ * Options for graph visualization.
8
+ */
9
+ interface GraphVisualizerOptions {
10
+ /** Show only affected/filtered tasks (highlight subset) */
11
+ focusedTasks?: string[];
12
+ /** Group tasks by project (default: true) */
13
+ groupByProject?: boolean;
14
+ /** Show task status colors (requires results) */
15
+ taskStatuses?: Map<string, "success" | "failure" | "skipped" | "local-cache" | "local-cache-kept-existing" | "remote-cache" | "running" | "pending">;
16
+ }
17
+ /**
18
+ * Exports a task graph in DOT format for Graphviz rendering.
19
+ * @example
20
+ * ```ts
21
+ * const dot = toGraphvizDot(taskGraph);
22
+ * // Render: dot -Tsvg -o graph.svg <<< "$dot"
23
+ * ```
24
+ */
25
+ declare const toGraphvizDot: (taskGraph: TaskGraph, options?: GraphVisualizerOptions) => string;
26
+ /**
27
+ * Exports the task graph as a JSON object suitable for visualization tools.
28
+ */
29
+ interface GraphJson {
30
+ edges: {
31
+ source: string;
32
+ target: string;
33
+ }[];
34
+ nodes: {
35
+ configuration?: string;
36
+ id: string;
37
+ project: string;
38
+ status?: string;
39
+ target: string;
40
+ }[];
41
+ roots: string[];
42
+ }
43
+ declare const toGraphJson: (taskGraph: TaskGraph, taskStatuses?: Map<string, string>) => {
44
+ edges: GraphJson["edges"];
45
+ nodes: GraphJson["nodes"];
46
+ roots: string[];
47
+ };
48
+ /**
49
+ * Generates a self-contained HTML file with an interactive task graph visualization.
50
+ * Uses a simple force-directed layout with SVG rendering (no external dependencies).
51
+ */
52
+ declare const toGraphHtml: (taskGraph: TaskGraph, options?: GraphVisualizerOptions) => string;
53
+ /**
54
+ * Renders the task graph as ASCII art for terminal display.
55
+ * @example
56
+ * ```
57
+ * Task Graph (6 tasks, 5 dependencies)
58
+ *
59
+ * app:build
60
+ * ├── lib-a:build
61
+ * │ └── lib-core:build
62
+ * └── lib-b:build
63
+ * └── lib-core:build (*)
64
+ *
65
+ * (*) = already shown above
66
+ * ```
67
+ */
68
+ declare const toGraphAscii: (taskGraph: TaskGraph, options?: GraphVisualizerOptions) => string;
69
+ /**
70
+ * Exports a project graph in DOT format.
71
+ */
72
+ declare const projectGraphToDot: (projectGraph: ProjectGraph) => string;
73
+ export type { GraphFormat, GraphJson, GraphVisualizerOptions };
74
+ export { projectGraphToDot, toGraphAscii, toGraphHtml, toGraphJson, toGraphvizDot };
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Incremental file hasher that only re-hashes files that have changed
3
+ * since the last run, based on mtime comparison.
4
+ *
5
+ * This is the key performance optimization used by Nx's daemon and
6
+ * Turborepo's daemon — on subsequent runs, only files whose mtime
7
+ * changed need to be re-read and re-hashed.
8
+ *
9
+ * The snapshot (path → { mtime, hash }) is kept in memory and can
10
+ * optionally be persisted to disk for cross-process reuse.
11
+ */
12
+ interface FileSnapshot {
13
+ /** xxh3-128 hash of file contents */
14
+ hash: string;
15
+ /** Last modification time in milliseconds */
16
+ mtimeMs: number;
17
+ /** File size in bytes (fast pre-check) */
18
+ size: number;
19
+ }
20
+ interface IncrementalHasherOptions {
21
+ /** Directories to skip (default: node_modules, .git, dist, coverage, .cache) */
22
+ ignoredDirs?: Set<string>;
23
+ /** File to persist the snapshot to (for cross-run reuse) */
24
+ snapshotPath?: string;
25
+ workspaceRoot: string;
26
+ }
27
+ declare class IncrementalFileHasher {
28
+ #private;
29
+ constructor(options: IncrementalHasherOptions);
30
+ /**
31
+ * Loads the snapshot from disk if available.
32
+ * Called automatically on first use.
33
+ */
34
+ load(): Promise<void>;
35
+ /**
36
+ * Persists the current snapshot to disk for cross-run reuse.
37
+ */
38
+ save(): Promise<void>;
39
+ /**
40
+ * Incrementally hashes all files in a directory.
41
+ *
42
+ * Only files whose mtime or size changed since the last snapshot
43
+ * are re-read and re-hashed. Unchanged files reuse the cached hash.
44
+ *
45
+ * Returns a map of relative paths → hashes.
46
+ */
47
+ hashDirectory(directoryPath: string): Promise<Record<string, string>>;
48
+ /**
49
+ * Returns how many files are in the snapshot (for diagnostics).
50
+ */
51
+ get snapshotSize(): number;
52
+ /**
53
+ * Clears the in-memory snapshot.
54
+ */
55
+ clear(): void;
56
+ }
57
+ export type { FileSnapshot, IncrementalHasherOptions };
58
+ export { IncrementalFileHasher };
@@ -0,0 +1,34 @@
1
+ export type { AffectedOptions, AffectedResult } from "./affected.d.ts";
2
+ export { filterAffectedTasks, getAffectedProjects, getChangedFiles } from "./affected.d.ts";
3
+ export type { CachedResult, CacheOptions } from "./cache.d.ts";
4
+ export { Cache, formatCacheSize, parseCacheSize } from "./cache.d.ts";
5
+ export { defaultTaskRunner } from "./default-task-runner.d.ts";
6
+ export type { FileAccess, TrackingResult } from "./file-access-tracker.d.ts";
7
+ export { FileAccessTracker, generatePreloadScript } from "./file-access-tracker.d.ts";
8
+ export type { CacheMissReason, TaskFingerprint } from "./fingerprint.d.ts";
9
+ export { FingerprintManager } from "./fingerprint.d.ts";
10
+ export type { DetectedFramework } from "./framework-inference.d.ts";
11
+ export { detectFrameworks, getFrameworkEnvVariables, inferFrameworkEnvPatterns } from "./framework-inference.d.ts";
12
+ export type { GraphFormat, GraphJson, GraphVisualizerOptions } from "./graph-visualizer.d.ts";
13
+ export { projectGraphToDot, toGraphAscii, toGraphHtml, toGraphJson, toGraphvizDot } from "./graph-visualizer.d.ts";
14
+ export type { FileSnapshot, IncrementalHasherOptions } from "./incremental-hasher.d.ts";
15
+ export { IncrementalFileHasher } from "./incremental-hasher.d.ts";
16
+ export { CompositeLifeCycle, ConsoleLifeCycle, EmptyLifeCycle } from "./life-cycle.d.ts";
17
+ export type { PackageLockfileHash, ResolvedDependency } from "./lockfile-hasher.d.ts";
18
+ export { extractPackageName, LockfileHasher, parseNpmLockfile, parsePnpmLockfile, parseYarnLockfile } from "./lockfile-hasher.d.ts";
19
+ export { isNativeAvailable, loadNativeBindings } from "./native-binding.d.ts";
20
+ export type { RemoteCacheOptions } from "./remote-cache.d.ts";
21
+ export { RemoteCache } from "./remote-cache.d.ts";
22
+ export type { RunSummary, TaskSummary } from "./run-summary.d.ts";
23
+ export { generateRunSummary, writeRunSummary } from "./run-summary.d.ts";
24
+ export { createTaskGraph, getTaskId, parseTaskId } from "./task-graph.d.ts";
25
+ export { findCycle, findCycles, getDependentTasks, getLeafTasks, getTransitiveDependencies, makeAcyclic, reverseTaskGraph, walkTaskGraph, } from "./task-graph-utils.d.ts";
26
+ export type { TaskHasher, TaskHasherOptions } from "./task-hasher.d.ts";
27
+ export { computeTaskHash, InProcessTaskHasher } from "./task-hasher.d.ts";
28
+ export type { TaskOrchestratorOptions } from "./task-orchestrator.d.ts";
29
+ export { TaskOrchestrator } from "./task-orchestrator.d.ts";
30
+ export { TaskScheduler } from "./task-scheduler.d.ts";
31
+ export type { TrackedExecutionResult } from "./tracked-executor.d.ts";
32
+ export { TrackedTaskExecutor } from "./tracked-executor.d.ts";
33
+ export type { EnvironmentInput, ExternalDependencyInput, FileSetInput, InputDefinition, LifeCycleInterface, NamedInputs, ProjectConfiguration, ProjectGraph, ProjectGraphDependency, ProjectGraphProjectNode, RuntimeInput, TargetConfiguration, TargetDependencyConfig, Task, TaskExecutionOptions, TaskExecutor, TaskGraph, TaskHashDetails, TaskResult, TaskResults, TaskRunnerContext, TaskRunnerOptions, TasksRunner, TaskStatus, TaskTarget, WorkspaceConfiguration, } from "./types.d.ts";
34
+ export { collectFiles, createFailureResult, hashFile, hashStrings, readPackageDeps, resolveTaskCwd, sortObjectKeys, uniqueId } from "./utils.d.ts";
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ export { filterAffectedTasks, getAffectedProjects, getChangedFiles } from './packem_shared/filterAffectedTasks-I-18zPg6.js';
2
+ export { Cache, formatCacheSize, parseCacheSize } from './packem_shared/Cache-IYpTYVUC.js';
3
+ export { defaultTaskRunner } from './packem_shared/defaultTaskRunner-CrW4v5Ye.js';
4
+ export { FileAccessTracker, generatePreloadScript } from './packem_shared/FileAccessTracker-CrtBAt5D.js';
5
+ export { FingerprintManager } from './packem_shared/FingerprintManager-D6Y0erg-.js';
6
+ export { detectFrameworks, getFrameworkEnvVariables, inferFrameworkEnvPatterns } from './packem_shared/detectFrameworks-CeFzKE6J.js';
7
+ export { projectGraphToDot, toGraphAscii, toGraphHtml, toGraphJson, toGraphvizDot } from './packem_shared/projectGraphToDot-VdTjHcVp.js';
8
+ export { IncrementalFileHasher } from './packem_shared/IncrementalFileHasher-Ds3J6dgb.js';
9
+ export { CompositeLifeCycle, ConsoleLifeCycle, EmptyLifeCycle } from './packem_shared/CompositeLifeCycle-7AtYw1dv.js';
10
+ export { LockfileHasher, extractPackageName, parseNpmLockfile, parsePnpmLockfile, parseYarnLockfile } from './packem_shared/extractPackageName-CbVNW-dr.js';
11
+ export { isNativeAvailable, loadNativeBindings } from './packem_shared/isNativeAvailable-BWhnZ4ES.js';
12
+ export { RemoteCache } from './packem_shared/RemoteCache-BDqrnDEi.js';
13
+ export { generateRunSummary, writeRunSummary } from './packem_shared/generateRunSummary-qn-_jKwt.js';
14
+ export { createTaskGraph, getTaskId, parseTaskId } from './packem_shared/createTaskGraph-CcsFaSrz.js';
15
+ export { findCycle, findCycles, getDependentTasks, getLeafTasks, getTransitiveDependencies, makeAcyclic, reverseTaskGraph, walkTaskGraph } from './packem_shared/findCycle-DF4_BRdO.js';
16
+ export { InProcessTaskHasher, computeTaskHash } from './packem_shared/computeTaskHash-BoCnnvIJ.js';
17
+ export { TaskOrchestrator } from './packem_shared/TaskOrchestrator-BvYs3ONw.js';
18
+ export { TaskScheduler } from './packem_shared/TaskScheduler-CJilHDta.js';
19
+ export { TrackedTaskExecutor } from './packem_shared/TrackedTaskExecutor-BGUKFE-7.js';
20
+ export { c as collectFiles, a as createFailureResult, h as hashFile, b as hashStrings, r as readPackageDeps, d as resolveTaskCwd, s as sortObjectKeys, u as uniqueId } from './packem_shared/utils-zO0ZRgtf.js';
@@ -0,0 +1,36 @@
1
+ import type { LifeCycleInterface, Task, TaskResult, TaskStatus } from "./types.d.ts";
2
+ /**
3
+ * Combines multiple lifecycle handlers into one.
4
+ * Each event is forwarded to all registered handlers.
5
+ */
6
+ declare class CompositeLifeCycle implements LifeCycleInterface {
7
+ #private;
8
+ constructor(lifeCycles: LifeCycleInterface[]);
9
+ startCommand(): void;
10
+ endCommand(): void;
11
+ scheduleTask(task: Task): void;
12
+ startTasks(tasks: Task[]): void;
13
+ endTasks(taskResults: TaskResult[]): void;
14
+ printTaskTerminalOutput(task: Task, status: TaskStatus, terminalOutput: string): void;
15
+ printCacheMiss(task: Task, reasons: string): void;
16
+ }
17
+ /**
18
+ * A lifecycle handler that logs task progress to the console.
19
+ */
20
+ declare class ConsoleLifeCycle implements LifeCycleInterface {
21
+ #private;
22
+ constructor(verbose?: boolean);
23
+ startCommand(): void;
24
+ endCommand(): void;
25
+ scheduleTask(task: Task): void;
26
+ startTasks(tasks: Task[]): void;
27
+ endTasks(taskResults: TaskResult[]): void;
28
+ printTaskTerminalOutput(_task: Task, _status: TaskStatus, terminalOutput: string): void;
29
+ printCacheMiss(task: Task, reasons: string): void;
30
+ }
31
+ /**
32
+ * A no-op lifecycle handler. Useful as a default.
33
+ */
34
+ declare class EmptyLifeCycle implements LifeCycleInterface {
35
+ }
36
+ export { CompositeLifeCycle, ConsoleLifeCycle, EmptyLifeCycle };
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Resolved dependency entry from a lockfile.
3
+ */
4
+ interface ResolvedDependency {
5
+ /** The package name */
6
+ name: string;
7
+ /** The resolved version */
8
+ version: string;
9
+ }
10
+ /**
11
+ * Result of parsing a lockfile for a specific package.
12
+ */
13
+ interface PackageLockfileHash {
14
+ /** The resolved dependencies that were included in the hash */
15
+ dependencies: ResolvedDependency[];
16
+ /** Hash of the resolved dependencies relevant to this package */
17
+ hash: string;
18
+ }
19
+ /**
20
+ * Extracts a package name from a node_modules path.
21
+ * E.g., "node_modules/@scope/name" -> "@scope/name",
22
+ * "node_modules/name" -> "name",
23
+ * "node_modules/.package-lock.json" -> undefined.
24
+ */
25
+ declare const extractPackageName: (path: string) => string | undefined;
26
+ /**
27
+ * Parses package-lock.json (npm v2/v3 format) to extract resolved versions.
28
+ * The v2/v3 format uses a flat "packages" map with paths like "node_modules/pkg-name".
29
+ */
30
+ declare const parseNpmLockfile: (content: string) => Map<string, string>;
31
+ /**
32
+ * Parses pnpm-lock.yaml to extract resolved versions.
33
+ * Uses a lightweight regex-based parser to avoid a YAML dependency.
34
+ */
35
+ declare const parsePnpmLockfile: (content: string) => Map<string, string>;
36
+ /**
37
+ * Parses yarn.lock to extract resolved versions.
38
+ * Works with both Yarn Classic (v1) and Berry (v2+) formats.
39
+ */
40
+ declare const parseYarnLockfile: (content: string) => Map<string, string>;
41
+ /**
42
+ * Smart lockfile hasher that only hashes the resolved versions
43
+ * of a package's actual dependencies, not the entire lockfile.
44
+ *
45
+ * This matches Turborepo's smart lockfile hashing behavior:
46
+ * changing the lockfile only busts cache for affected packages.
47
+ *
48
+ * Supports:
49
+ * - package-lock.json (npm v2/v3)
50
+ * - pnpm-lock.yaml (pnpm)
51
+ * - yarn.lock (Yarn Classic + Berry)
52
+ */
53
+ declare class LockfileHasher {
54
+ #private;
55
+ constructor(workspaceRoot: string);
56
+ /**
57
+ * Computes a hash based only on the resolved dependency versions
58
+ * relevant to a specific package.
59
+ * @param packageJsonPath Path to the package.json (relative to workspace root)
60
+ * @returns Hash of the relevant lockfile entries, or undefined if no lockfile found
61
+ */
62
+ hashForPackage(packageJsonPath: string): Promise<PackageLockfileHash | undefined>;
63
+ /**
64
+ * Returns the type of lockfile detected, or undefined if none found.
65
+ */
66
+ get lockfileType(): "npm" | "pnpm" | "yarn" | undefined;
67
+ /**
68
+ * Clears the cached lockfile data.
69
+ */
70
+ clearCache(): void;
71
+ }
72
+ export type { PackageLockfileHash, ResolvedDependency };
73
+ export { extractPackageName, LockfileHasher, parseNpmLockfile, parsePnpmLockfile, parseYarnLockfile };
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Optional native bindings for performance-critical operations.
3
+ *
4
+ * The native addon (Rust via napi-rs) provides:
5
+ * - Parallel file hashing using rayon + xxHash xxh3-128
6
+ * - Optimized task hash computation
7
+ * - Fast graph operations (cycle detection, topological sort)
8
+ *
9
+ * Falls back to pure TypeScript implementations when the native
10
+ * addon is not available (not compiled, wrong platform, etc.).
11
+ *
12
+ * Build with: pnpm build:native
13
+ * The napi v3 CLI outputs the .node file to the package root.
14
+ */
15
+ interface NativeFileHash {
16
+ hash: string;
17
+ path: string;
18
+ }
19
+ interface NativeTaskHashDetails {
20
+ command: string;
21
+ implicit_deps?: string[][];
22
+ nodes: string[][];
23
+ runtime?: string[][];
24
+ }
25
+ interface NativeTaskGraph {
26
+ edges: string[][];
27
+ task_ids: string[];
28
+ }
29
+ interface NativeCycleResult {
30
+ cycle: string[];
31
+ has_cycle: boolean;
32
+ }
33
+ interface NativeBindings {
34
+ collectFiles: (directory: string) => string[];
35
+ computeTaskHash: (details: NativeTaskHashDetails) => string;
36
+ findAllCycles: (graph: NativeTaskGraph) => string[][];
37
+ findBackEdges: (graph: NativeTaskGraph) => string[][];
38
+ findCycle: (graph: NativeTaskGraph) => NativeCycleResult;
39
+ getDependentTasks: (graph: NativeTaskGraph, taskId: string) => string[];
40
+ getTransitiveDeps: (graph: NativeTaskGraph, taskId: string) => string[];
41
+ hashCommand: (project: string, target: string, configuration: string | undefined, overridesJson: string) => string;
42
+ hashEnvVar: (name: string, value: string) => string;
43
+ hashFile: (filePath: string) => string;
44
+ hashFilesBatch: (filePaths: string[], workspaceRoot: string) => NativeFileHash[];
45
+ hashFilesInDirectory: (directory: string, workspaceRoot: string) => NativeFileHash[];
46
+ hashString: (input: string) => string;
47
+ hashStrings: (inputs: string[]) => string;
48
+ topologicalSort: (graph: NativeTaskGraph) => string[];
49
+ }
50
+ /**
51
+ * Attempts to load the native addon. Returns undefined if unavailable.
52
+ * The result is cached after the first attempt.
53
+ *
54
+ * napi v3 outputs the .node file to the package root as
55
+ * `task-runner-native.&lt;platform>.node`. The napi-generated binding.js
56
+ * handles platform detection automatically.
57
+ */
58
+ declare const loadNativeBindings: () => NativeBindings | undefined;
59
+ /**
60
+ * Returns true if the native addon is loaded and available.
61
+ */
62
+ declare const isNativeAvailable: () => boolean;
63
+ export type { NativeBindings, NativeCycleResult, NativeFileHash, NativeTaskGraph, NativeTaskHashDetails };
64
+ export { isNativeAvailable, loadNativeBindings };