@visulima/task-runner 1.0.0-alpha.6 → 1.0.0-alpha.8
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.
- package/CHANGELOG.md +34 -0
- package/dist/index.d.ts +2507 -49
- package/dist/index.js +9 -7
- package/dist/packem_shared/{TaskOrchestrator-rf45vW5c.js → TaskOrchestrator-UCMHCx8c.js} +68 -2
- package/dist/packem_shared/{buildForwardDependencyMap-DLPgKEto.js → buildForwardDependencyMap-0BJFMMPv.js} +1 -2
- package/dist/packem_shared/{computeTaskHash-DYqfrDGq.js → computeTaskHash-B5APHW7e.js} +1 -1
- package/dist/packem_shared/{createTaskGraph-B7nH0kY_.js → createTaskGraph-B5YrfAMx.js} +6 -2
- package/dist/packem_shared/{defaultTaskRunner-Cp7jCmIl.js → defaultTaskRunner-DzR0ld8F.js} +36 -4
- package/dist/packem_shared/expandTokensInString-C03AGAjh.js +46 -0
- package/dist/packem_shared/{extractPackageName-BllKetnz.js → extractPackageName-CbVNW-dr.js} +1 -2
- package/dist/packem_shared/getCurrentBranch-DsKPDoVj.js +153 -0
- package/dist/packem_shared/{parseCommands-D-IgF8Zh.js → parseCommands-CJ16ohOB.js} +7 -2
- package/index.js +556 -723
- package/package.json +14 -14
- package/dist/affected.d.ts +0 -82
- package/dist/archive.d.ts +0 -38
- package/dist/cache.d.ts +0 -138
- package/dist/chrome-trace.d.ts +0 -53
- package/dist/command-parser/expand-arguments.d.ts +0 -11
- package/dist/command-parser/expand-shortcut.d.ts +0 -15
- package/dist/command-parser/expand-wildcard.d.ts +0 -13
- package/dist/command-parser/index.d.ts +0 -18
- package/dist/command-parser/strip-quotes.d.ts +0 -6
- package/dist/concurrent-fallback.d.ts +0 -16
- package/dist/concurrent.d.ts +0 -23
- package/dist/default-task-runner.d.ts +0 -44
- package/dist/detect-shell.d.ts +0 -19
- package/dist/file-access-tracker.d.ts +0 -59
- package/dist/fingerprint.d.ts +0 -54
- package/dist/flow-controllers/index.d.ts +0 -7
- package/dist/flow-controllers/input-handler.d.ts +0 -44
- package/dist/flow-controllers/log-timings.d.ts +0 -18
- package/dist/flow-controllers/restart-process.d.ts +0 -21
- package/dist/flow-controllers/teardown.d.ts +0 -22
- package/dist/framework-inference.d.ts +0 -35
- package/dist/graph-visualizer.d.ts +0 -74
- package/dist/incremental-hasher.d.ts +0 -76
- package/dist/life-cycle.d.ts +0 -38
- package/dist/lockfile-hasher.d.ts +0 -73
- package/dist/log-reporter.d.ts +0 -34
- package/dist/native-binding.d.ts +0 -106
- package/dist/output-resolver.d.ts +0 -20
- package/dist/project-constraints.d.ts +0 -9
- package/dist/remote-cache.d.ts +0 -100
- package/dist/run-summary.d.ts +0 -111
- package/dist/task-graph-utils.d.ts +0 -39
- package/dist/task-graph.d.ts +0 -22
- package/dist/task-hasher.d.ts +0 -104
- package/dist/task-orchestrator.d.ts +0 -38
- package/dist/task-scheduler.d.ts +0 -41
- package/dist/terminal-buffer.d.ts +0 -29
- package/dist/tracked-executor.d.ts +0 -46
- package/dist/types.d.ts +0 -757
- package/dist/utils.d.ts +0 -39
package/dist/index.d.ts
CHANGED
|
@@ -1,49 +1,2507 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
1
|
+
import { Readable, Writable } from 'node:stream';
|
|
2
|
+
/**
|
|
3
|
+
* A predicate clause that can match a single value, a list of values
|
|
4
|
+
* (any-of), or — for env vars only — a `{ name, equals?, exists? }`
|
|
5
|
+
* triplet. `not.*` mirrors of every clause provide a negative form
|
|
6
|
+
* without having to wrap the whole `when` in a compound expression.
|
|
7
|
+
*
|
|
8
|
+
* Examples:
|
|
9
|
+
* `os: "linux"` — runs only on linux
|
|
10
|
+
* `os: ["linux", "darwin"]` — runs on linux or macOS
|
|
11
|
+
* `not.os: "windows"` — runs everywhere except windows
|
|
12
|
+
* `env: "CI"` — runs only when `process.env.CI` is truthy
|
|
13
|
+
* `env: { name: "NODE_ENV", equals: "production" }`
|
|
14
|
+
* `branch: ["main", "alpha"]`
|
|
15
|
+
* `ci: true` — runs only inside CI
|
|
16
|
+
*/
|
|
17
|
+
interface WhenCondition {
|
|
18
|
+
/** Match against the current git branch (HEAD). */
|
|
19
|
+
branch?: string | string[];
|
|
20
|
+
/**
|
|
21
|
+
* Run only when invoked inside CI when `true`, only outside CI
|
|
22
|
+
* when `false`. Detects CI via the `CI` env var (the convention
|
|
23
|
+
* GitHub Actions, GitLab, CircleCI, Jenkins, etc. all share).
|
|
24
|
+
*/
|
|
25
|
+
ci?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Match against environment variables. A bare string asserts the
|
|
28
|
+
* variable is set and non-empty; the object form lets you match
|
|
29
|
+
* an exact value or just assert presence/absence.
|
|
30
|
+
*/
|
|
31
|
+
env?: EnvMatcher | EnvMatcher[];
|
|
32
|
+
/** Negative mirrors. A task runs only when *all* `not.*` clauses fail. */
|
|
33
|
+
not?: {
|
|
34
|
+
branch?: string | string[];
|
|
35
|
+
ci?: boolean;
|
|
36
|
+
env?: EnvMatcher | EnvMatcher[];
|
|
37
|
+
os?: NodePlatform | NodePlatform[];
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Match `process.platform` (`"linux" | "darwin" | "win32" | "freebsd"
|
|
41
|
+
* | "openbsd" | "sunos" | "aix"`). Pass `"windows"` as an alias for
|
|
42
|
+
* `"win32"` — easier to remember and matches what people type.
|
|
43
|
+
*/
|
|
44
|
+
os?: NodePlatform | NodePlatform[];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* An environment-variable match. The string form is shorthand for
|
|
48
|
+
* `{ name, exists: true }` (set + non-empty). The object form
|
|
49
|
+
* supports either presence assertions or exact-value matching.
|
|
50
|
+
*/
|
|
51
|
+
type EnvMatcher = string | {
|
|
52
|
+
/** Match this exact value. Mutually exclusive with `exists`. */
|
|
53
|
+
equals?: string;
|
|
54
|
+
/** Assert the variable is set & non-empty (`true`) or unset/empty (`false`). */
|
|
55
|
+
exists?: boolean;
|
|
56
|
+
/** Variable name. */
|
|
57
|
+
name: string;
|
|
58
|
+
};
|
|
59
|
+
/** Aliased platform list — `"windows"` is sugar for Node's `"win32"`. */
|
|
60
|
+
type NodePlatform = "aix" | "darwin" | "freebsd" | "linux" | "openbsd" | "sunos" | "windows" | "win32";
|
|
61
|
+
/**
|
|
62
|
+
* Inputs for {@link evaluateWhen}. Pulled into a struct so tests can
|
|
63
|
+
* inject deterministic values and CLIs can reuse the same env/branch
|
|
64
|
+
* lookup across many task evaluations.
|
|
65
|
+
*/
|
|
66
|
+
interface WhenContext {
|
|
67
|
+
/** Current git branch. Pass an empty string when not in a repo. */
|
|
68
|
+
branch?: string;
|
|
69
|
+
/** Whether we're inside CI. Defaults to `process.env.CI` truthy check. */
|
|
70
|
+
ci?: boolean;
|
|
71
|
+
/** Environment variables to match against. Defaults to `process.env`. */
|
|
72
|
+
env?: Record<string, string | undefined>;
|
|
73
|
+
/** Platform string. Defaults to `process.platform`. */
|
|
74
|
+
platform?: NodePlatform;
|
|
75
|
+
}
|
|
76
|
+
declare const getCurrentBranch: (cwd: string) => string;
|
|
77
|
+
/** Test-only escape hatch — clears every cached branch result. */
|
|
78
|
+
declare const resetBranchCache: () => void;
|
|
79
|
+
/**
|
|
80
|
+
* Evaluates a {@link WhenCondition} against the supplied context (or the
|
|
81
|
+
* live process state when omitted). Returns `true` when the task should
|
|
82
|
+
* run, `false` when every positive clause matches and every `not.*`
|
|
83
|
+
* clause is also satisfied.
|
|
84
|
+
*
|
|
85
|
+
* Semantics:
|
|
86
|
+
* - All positive clauses must match (AND).
|
|
87
|
+
* - All `not.*` clauses must not match (AND).
|
|
88
|
+
* - Within a single clause, an array means any-of (OR).
|
|
89
|
+
* - An empty/undefined `when` always returns `true`.
|
|
90
|
+
*/
|
|
91
|
+
declare const evaluateWhen: (when: WhenCondition | undefined, context?: WhenContext) => boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Returns a short human-readable explanation of why a `when` clause
|
|
94
|
+
* skipped a task. Used by lifecycle handlers to print diagnostics.
|
|
95
|
+
* Returns an empty string when the condition evaluates to true.
|
|
96
|
+
*/
|
|
97
|
+
declare const explainWhen: (when: WhenCondition | undefined, context?: WhenContext) => string;
|
|
98
|
+
/**
|
|
99
|
+
* Represents a target that a task executes against.
|
|
100
|
+
*/
|
|
101
|
+
interface TaskTarget {
|
|
102
|
+
/** Optional configuration name */
|
|
103
|
+
configuration?: string;
|
|
104
|
+
/** The project name */
|
|
105
|
+
project: string;
|
|
106
|
+
/** The target name (e.g., "build", "test", "lint") */
|
|
107
|
+
target: string;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Represents a single task to be executed.
|
|
111
|
+
*/
|
|
112
|
+
/**
|
|
113
|
+
* Scheduling priority hint. The scheduler picks higher-priority tasks
|
|
114
|
+
* out of the ready-queue first; ties fall through to the graph-derived
|
|
115
|
+
* signals (dependent count, project depth).
|
|
116
|
+
*
|
|
117
|
+
* Use `"high"` for long-running leaves you want to kick off early
|
|
118
|
+
* (integration tests, e2e suites) so their wall-clock overlaps with
|
|
119
|
+
* the main build phase. Use `"low"` for work you don't mind deferring
|
|
120
|
+
* (linters, coverage uploads) when faster tasks contend for slots.
|
|
121
|
+
*/
|
|
122
|
+
type TaskPriority = "high" | "low" | "normal";
|
|
123
|
+
/**
|
|
124
|
+
* A single entry in a task's `outputs` list.
|
|
125
|
+
*
|
|
126
|
+
* - `string` — a literal path *or* a glob pattern relative to the
|
|
127
|
+
* workspace root. Prefix with `!` to exclude files the positive
|
|
128
|
+
* patterns would otherwise include (e.g. `"!dist/cache/**"`).
|
|
129
|
+
* - `{ auto: true }` — use whatever files the task actually wrote
|
|
130
|
+
* during execution (resolved from the file-access tracker). Lets
|
|
131
|
+
* authors who don't know their exact output layout cache results
|
|
132
|
+
* without listing every path. Silently behaves as "no outputs" when
|
|
133
|
+
* tracking isn't active for this task.
|
|
134
|
+
*/
|
|
135
|
+
type OutputSpec = string | {
|
|
136
|
+
auto: true;
|
|
137
|
+
};
|
|
138
|
+
interface Task {
|
|
139
|
+
/**
|
|
140
|
+
* When `true`, this task runs after the main task graph completes
|
|
141
|
+
* — even if upstream tasks failed or the run was interrupted.
|
|
142
|
+
* Used for cleanup, teardown, or notification tasks. Carried over
|
|
143
|
+
* from {@link TargetConfiguration.always} at task graph creation.
|
|
144
|
+
*/
|
|
145
|
+
always?: boolean;
|
|
146
|
+
/** Whether this task is eligible for caching */
|
|
147
|
+
cache?: boolean;
|
|
148
|
+
/** Hash of the task inputs for caching */
|
|
149
|
+
hash?: string;
|
|
150
|
+
/** Detailed hash information */
|
|
151
|
+
hashDetails?: TaskHashDetails;
|
|
152
|
+
/** Unique identifier for the task, typically "project:target:configuration" */
|
|
153
|
+
id: string;
|
|
154
|
+
/**
|
|
155
|
+
* Output patterns this task produces. Each entry is either a
|
|
156
|
+
* literal path, a glob (`"dist/**"`), a negative glob
|
|
157
|
+
* (`"!dist/cache/**"`), or `{ auto: true }` to pick up whatever
|
|
158
|
+
* files the task wrote during execution.
|
|
159
|
+
*/
|
|
160
|
+
outputs: OutputSpec[];
|
|
161
|
+
/** Overrides/extra options passed to the task */
|
|
162
|
+
overrides: Record<string, unknown>;
|
|
163
|
+
/** Whether this task supports parallel execution */
|
|
164
|
+
parallelism?: boolean;
|
|
165
|
+
/**
|
|
166
|
+
* Explicit scheduling priority. Outranks the scheduler's
|
|
167
|
+
* graph-derived heuristics. Defaults to `"normal"` when absent.
|
|
168
|
+
*/
|
|
169
|
+
priority?: TaskPriority;
|
|
170
|
+
/** The project root directory */
|
|
171
|
+
projectRoot?: string;
|
|
172
|
+
/** The target this task executes */
|
|
173
|
+
target: TaskTarget;
|
|
174
|
+
/**
|
|
175
|
+
* Predicate that gates execution. Evaluated by the orchestrator
|
|
176
|
+
* just before the task is launched; tasks whose `when` returns
|
|
177
|
+
* `false` are marked `"skipped"` without ever invoking the
|
|
178
|
+
* executor. Carried over from {@link TargetConfiguration.when}.
|
|
179
|
+
*/
|
|
180
|
+
when?: WhenCondition;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Represents detailed hash information for a task.
|
|
184
|
+
*/
|
|
185
|
+
interface TaskHashDetails {
|
|
186
|
+
/** The command hash */
|
|
187
|
+
command: string;
|
|
188
|
+
/** Hash of implicit dependencies */
|
|
189
|
+
implicitDeps?: Record<string, string>;
|
|
190
|
+
/** Hashes of input files */
|
|
191
|
+
nodes: Record<string, string>;
|
|
192
|
+
/** Hash of runtime values */
|
|
193
|
+
runtime?: Record<string, string>;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Represents a directed acyclic graph of tasks.
|
|
197
|
+
*/
|
|
198
|
+
interface TaskGraph {
|
|
199
|
+
/** Dependencies for each task */
|
|
200
|
+
dependencies: Record<string, string[]>;
|
|
201
|
+
/** Top-level tasks that no other task depends on (the final outputs to run) */
|
|
202
|
+
roots: string[];
|
|
203
|
+
/** All tasks in the graph, keyed by task ID */
|
|
204
|
+
tasks: Record<string, Task>;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Possible states of a task after execution.
|
|
208
|
+
*/
|
|
209
|
+
type TaskStatus = "success" | "failure" | "skipped" | "local-cache" | "local-cache-kept-existing" | "remote-cache";
|
|
210
|
+
/**
|
|
211
|
+
* Result of executing a task.
|
|
212
|
+
*/
|
|
213
|
+
interface TaskResult {
|
|
214
|
+
/** The exit code, if applicable */
|
|
215
|
+
code?: number;
|
|
216
|
+
/**
|
|
217
|
+
* Set when auto-fingerprint tracking was attempted for this task but
|
|
218
|
+
* returned zero workspace accesses — usually a static binary on
|
|
219
|
+
* macOS/Windows, where the Node preload can't attach. Caching is
|
|
220
|
+
* skipped to avoid persisting an empty fingerprint that would
|
|
221
|
+
* produce false cache hits on every subsequent run.
|
|
222
|
+
*/
|
|
223
|
+
emptyFingerprint?: boolean;
|
|
224
|
+
/** The end time of the task */
|
|
225
|
+
endTime?: number;
|
|
226
|
+
/**
|
|
227
|
+
* Set when the task modified one or more of its own tracked input
|
|
228
|
+
* files during execution. Caching is skipped in this case — the
|
|
229
|
+
* fingerprint captured before the run would mismatch the post-run
|
|
230
|
+
* contents and produce false cache hits on subsequent runs.
|
|
231
|
+
*/
|
|
232
|
+
selfModified?: boolean;
|
|
233
|
+
/** The start time of the task */
|
|
234
|
+
startTime?: number;
|
|
235
|
+
status: TaskStatus;
|
|
236
|
+
task: Task;
|
|
237
|
+
/** The terminal output produced during execution */
|
|
238
|
+
terminalOutput?: string;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Map of task results, keyed by task ID.
|
|
242
|
+
*/
|
|
243
|
+
type TaskResults = Map<string, TaskResult>;
|
|
244
|
+
/**
|
|
245
|
+
* Configuration for a project in the workspace.
|
|
246
|
+
*/
|
|
247
|
+
interface ProjectConfiguration {
|
|
248
|
+
/** Implicit dependencies on other projects */
|
|
249
|
+
implicitDependencies?: string[];
|
|
250
|
+
/**
|
|
251
|
+
* Project layer in the dependency hierarchy. Used by
|
|
252
|
+
* `enforceLayerRelationships` to ensure projects only depend on
|
|
253
|
+
* projects at the same or lower layer.
|
|
254
|
+
*
|
|
255
|
+
* Hierarchy (lowest → highest):
|
|
256
|
+
* `configuration < library < scaffolding < tool < automation < application`
|
|
257
|
+
*/
|
|
258
|
+
layer?: "application" | "automation" | "configuration" | "library" | "scaffolding" | "tool";
|
|
259
|
+
/** The project type */
|
|
260
|
+
projectType?: "library" | "application";
|
|
261
|
+
/** The root directory of the project, relative to workspace root */
|
|
262
|
+
root: string;
|
|
263
|
+
/** The source root directory */
|
|
264
|
+
sourceRoot?: string;
|
|
265
|
+
/** Tags for filtering */
|
|
266
|
+
tags?: string[];
|
|
267
|
+
/** Named targets and their configurations */
|
|
268
|
+
targets?: Record<string, TargetConfiguration>;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Configuration for a target within a project.
|
|
272
|
+
*/
|
|
273
|
+
interface TargetConfiguration {
|
|
274
|
+
/**
|
|
275
|
+
* When `true`, this target runs after the main task graph
|
|
276
|
+
* completes — even if upstream tasks failed. Useful for cleanup,
|
|
277
|
+
* teardown, notifications, or anything that should fire
|
|
278
|
+
* regardless of build outcome. Always-tasks are not part of the
|
|
279
|
+
* normal dependency graph and never block other tasks.
|
|
280
|
+
*/
|
|
281
|
+
always?: boolean;
|
|
282
|
+
/** Whether this target is cacheable */
|
|
283
|
+
cache?: boolean;
|
|
284
|
+
/** The command to run (alternative to executor) */
|
|
285
|
+
command?: string;
|
|
286
|
+
/** Named configurations (e.g., "production", "development") */
|
|
287
|
+
configurations?: Record<string, Record<string, unknown>>;
|
|
288
|
+
/** Other targets this target depends on */
|
|
289
|
+
dependsOn?: (string | TargetDependencyConfig)[];
|
|
290
|
+
/** The executor/command to run */
|
|
291
|
+
executor?: string;
|
|
292
|
+
/** Input patterns for cache invalidation */
|
|
293
|
+
inputs?: (string | InputDefinition)[];
|
|
294
|
+
/** Options passed to the executor */
|
|
295
|
+
options?: Record<string, unknown>;
|
|
296
|
+
/** Output patterns produced by this target */
|
|
297
|
+
outputs?: string[];
|
|
298
|
+
/** Whether this target supports parallel execution */
|
|
299
|
+
parallelism?: boolean;
|
|
300
|
+
/**
|
|
301
|
+
* Predicate that gates execution. When the condition evaluates
|
|
302
|
+
* to `false` for the current environment, the task is skipped
|
|
303
|
+
* (marked `"skipped"`, not failed). Combine with `os`, `env`,
|
|
304
|
+
* `branch`, and `ci` clauses for granular control:
|
|
305
|
+
*
|
|
306
|
+
* ```ts
|
|
307
|
+
* when: { os: "linux", ci: true, env: "DEPLOY_TOKEN" }
|
|
308
|
+
* ```
|
|
309
|
+
*/
|
|
310
|
+
when?: WhenCondition;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Defines a dependency on another target.
|
|
314
|
+
*/
|
|
315
|
+
interface TargetDependencyConfig {
|
|
316
|
+
/** Whether this is a dependency on the same project */
|
|
317
|
+
dependencies?: boolean;
|
|
318
|
+
/** Params to pass through */
|
|
319
|
+
params?: "forward" | "ignore";
|
|
320
|
+
/** The project name (if different from the current project) */
|
|
321
|
+
projects?: string | string[];
|
|
322
|
+
/** The target name */
|
|
323
|
+
target: string;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Defines an input for cache invalidation.
|
|
327
|
+
*/
|
|
328
|
+
type InputDefinition = FileSetInput | RuntimeInput | EnvironmentInput | ExternalDependencyInput;
|
|
329
|
+
/**
|
|
330
|
+
* Controls how a glob pattern is anchored.
|
|
331
|
+
* - "package" (default): pattern is resolved relative to the project root
|
|
332
|
+
* - "workspace": pattern is resolved relative to the workspace root
|
|
333
|
+
*/
|
|
334
|
+
type FileSetBase = "package" | "workspace";
|
|
335
|
+
/**
|
|
336
|
+
* An input based on file patterns.
|
|
337
|
+
*
|
|
338
|
+
* `fileset` may be a bare glob string (package-root relative) or an object
|
|
339
|
+
* form `{ pattern, base }` to anchor explicitly to the workspace root.
|
|
340
|
+
* Negation (`!` prefix) works in both forms.
|
|
341
|
+
*/
|
|
342
|
+
interface FileSetInput {
|
|
343
|
+
fileset: FileSetPattern | string;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Object form of a fileset pattern, for anchoring to the workspace root.
|
|
347
|
+
*/
|
|
348
|
+
interface FileSetPattern {
|
|
349
|
+
/** Anchor for the pattern. */
|
|
350
|
+
base: FileSetBase;
|
|
351
|
+
/** Glob pattern (may start with `!` for negation). */
|
|
352
|
+
pattern: string;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* An input based on a runtime command.
|
|
356
|
+
*/
|
|
357
|
+
interface RuntimeInput {
|
|
358
|
+
runtime: string;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* An input based on environment variables.
|
|
362
|
+
*/
|
|
363
|
+
interface EnvironmentInput {
|
|
364
|
+
env: string;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* An input based on external dependency versions.
|
|
368
|
+
*/
|
|
369
|
+
interface ExternalDependencyInput {
|
|
370
|
+
externalDependencies: string[];
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Defines tag-based dependency rules.
|
|
374
|
+
* Each key is a tag name. The value is the list of tags that a dependency
|
|
375
|
+
* must have at least one of, when the source project has that tag.
|
|
376
|
+
*
|
|
377
|
+
* Example: `{ "frontend": ["shared", "frontend"] }` means a project tagged
|
|
378
|
+
* "frontend" can only depend on projects tagged "shared" or "frontend".
|
|
379
|
+
*/
|
|
380
|
+
type TagRelationships = Record<string, string[]>;
|
|
381
|
+
/**
|
|
382
|
+
* Defines project-type-based dependency rules.
|
|
383
|
+
*/
|
|
384
|
+
interface TypeBoundaries {
|
|
385
|
+
/**
|
|
386
|
+
* Custom rules mapping project types to allowed dependency types.
|
|
387
|
+
* Example: `{ "application": ["library"] }` means applications can only
|
|
388
|
+
* depend on libraries.
|
|
389
|
+
*/
|
|
390
|
+
allowedDependencyTypes?: Record<string, string[]>;
|
|
391
|
+
/**
|
|
392
|
+
* When true, no project may depend on an "application" type project.
|
|
393
|
+
* Applications are typically deployment targets, not libraries.
|
|
394
|
+
* @default true
|
|
395
|
+
*/
|
|
396
|
+
enforceApplicationBoundary?: boolean;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Rules based on the dependency kind (dependencies vs devDependencies vs peerDependencies).
|
|
400
|
+
*/
|
|
401
|
+
interface DependencyKindRules {
|
|
402
|
+
/**
|
|
403
|
+
* When true, a "library" project must not have workspace-internal devDependencies
|
|
404
|
+
* on other libraries that are also in its production dependencies.
|
|
405
|
+
* Prevents publishing libraries that silently rely on dev-only workspace packages.
|
|
406
|
+
* @default false
|
|
407
|
+
*/
|
|
408
|
+
noDevDependencyOnProductionDep?: boolean;
|
|
409
|
+
/**
|
|
410
|
+
* When true, production `dependencies` must not point to "application" type projects.
|
|
411
|
+
* devDependencies on applications are allowed (e.g., for testing).
|
|
412
|
+
* @default false
|
|
413
|
+
*/
|
|
414
|
+
noProductionDependencyOnApplication?: boolean;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Configuration for project constraint enforcement.
|
|
418
|
+
*/
|
|
419
|
+
interface ConstraintsConfig {
|
|
420
|
+
/** Rules based on the dependency kind (static vs devDependency vs peerDependency) */
|
|
421
|
+
dependencyKindRules?: DependencyKindRules;
|
|
422
|
+
/**
|
|
423
|
+
* When true, projects can only depend on projects at the same or
|
|
424
|
+
* lower layer in the hierarchy:
|
|
425
|
+
*
|
|
426
|
+
* configuration < library < scaffolding < tool < automation < application
|
|
427
|
+
*
|
|
428
|
+
* Projects without an explicit `layer` are unconstrained.
|
|
429
|
+
* @default false
|
|
430
|
+
*/
|
|
431
|
+
enforceLayerRelationships?: boolean;
|
|
432
|
+
/** Tag-based dependency rules */
|
|
433
|
+
tagRelationships?: TagRelationships;
|
|
434
|
+
/** Project-type-based dependency rules */
|
|
435
|
+
typeBoundaries?: TypeBoundaries;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* A single constraint violation detected in the project graph.
|
|
439
|
+
*/
|
|
440
|
+
interface ConstraintViolation {
|
|
441
|
+
/** The project being depended on */
|
|
442
|
+
dependencyProject: string;
|
|
443
|
+
/** Human-readable description of the violation */
|
|
444
|
+
message: string;
|
|
445
|
+
/** The type of rule that was violated */
|
|
446
|
+
rule: "dependency-kind" | "layer-relationship" | "tag-relationship" | "type-boundary";
|
|
447
|
+
/** The project that has the invalid dependency */
|
|
448
|
+
sourceProject: string;
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Controls how far to traverse the dependency graph in a given direction.
|
|
452
|
+
* - "none": Don't traverse — only directly changed projects are included.
|
|
453
|
+
* - "direct": Include only immediate neighbors (one hop).
|
|
454
|
+
* - "deep": Include all transitive neighbors (full chain).
|
|
455
|
+
*/
|
|
456
|
+
type AffectedScope = "deep" | "direct" | "none";
|
|
457
|
+
/**
|
|
458
|
+
* Workspace configuration containing all project configurations.
|
|
459
|
+
*/
|
|
460
|
+
interface WorkspaceConfiguration {
|
|
461
|
+
/** All projects in the workspace, keyed by project name */
|
|
462
|
+
projects: Record<string, ProjectConfiguration>;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* The kind of dependency relationship between projects.
|
|
466
|
+
* - "static": Production dependency (from `dependencies` in package.json)
|
|
467
|
+
* - "dynamic": Dynamically resolved dependency (e.g., lazy imports)
|
|
468
|
+
* - "implicit": Declared via `implicitDependencies` in project config
|
|
469
|
+
* - "devDependency": Development-only dependency (from `devDependencies`)
|
|
470
|
+
* - "peerDependency": Peer dependency (from `peerDependencies`)
|
|
471
|
+
*/
|
|
472
|
+
type DependencyType = "devDependency" | "dynamic" | "implicit" | "peerDependency" | "static";
|
|
473
|
+
/**
|
|
474
|
+
* A dependency relationship in the project graph.
|
|
475
|
+
*/
|
|
476
|
+
interface ProjectGraphDependency {
|
|
477
|
+
/** The source project */
|
|
478
|
+
source: string;
|
|
479
|
+
/** The target project */
|
|
480
|
+
target: string;
|
|
481
|
+
/** The type of dependency */
|
|
482
|
+
type: DependencyType;
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* A node in the project graph.
|
|
486
|
+
*/
|
|
487
|
+
interface ProjectGraphProjectNode {
|
|
488
|
+
/** The project configuration */
|
|
489
|
+
data: ProjectConfiguration;
|
|
490
|
+
/** The project name */
|
|
491
|
+
name: string;
|
|
492
|
+
/** The type of project */
|
|
493
|
+
type: "library" | "application";
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* The project graph represents the dependency relationships between projects.
|
|
497
|
+
*/
|
|
498
|
+
interface ProjectGraph {
|
|
499
|
+
/** All dependency relationships */
|
|
500
|
+
dependencies: Record<string, ProjectGraphDependency[]>;
|
|
501
|
+
/** All project nodes, keyed by project name */
|
|
502
|
+
nodes: Record<string, ProjectGraphProjectNode>;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Named input definitions that can be referenced by name.
|
|
506
|
+
*/
|
|
507
|
+
interface NamedInputs {
|
|
508
|
+
[name: string]: (string | InputDefinition)[];
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Configuration for the task runner.
|
|
512
|
+
*/
|
|
513
|
+
interface TaskRunnerOptions {
|
|
514
|
+
/**
|
|
515
|
+
* Scan each task's resolved command text for `$VAR`/`${VAR}`
|
|
516
|
+
* references and automatically fingerprint those env vars. Catches
|
|
517
|
+
* tasks like `curl ${VERCEL_URL}/api` where the user forgot to
|
|
518
|
+
* declare the reference in `envVars`/`globalEnv`.
|
|
519
|
+
* @default false
|
|
520
|
+
*/
|
|
521
|
+
autoEnvVars?: boolean;
|
|
522
|
+
/**
|
|
523
|
+
* Enable auto-fingerprinting mode (Vite Task-style).
|
|
524
|
+
* When enabled, the task runner automatically tracks which files
|
|
525
|
+
* a task accesses during execution and uses that for cache invalidation
|
|
526
|
+
* instead of requiring manual input configuration.
|
|
527
|
+
*
|
|
528
|
+
* Falls back to explicit inputs (Nx-style) when file tracking
|
|
529
|
+
* is not supported on the current platform.
|
|
530
|
+
* @default false
|
|
531
|
+
*/
|
|
532
|
+
autoFingerprint?: boolean;
|
|
533
|
+
/**
|
|
534
|
+
* Whether to show cache miss diagnostics (why a cache miss occurred).
|
|
535
|
+
* @default false
|
|
536
|
+
*/
|
|
537
|
+
cacheDiagnostics?: boolean;
|
|
538
|
+
/** Directory for storing cache */
|
|
539
|
+
cacheDirectory?: string;
|
|
540
|
+
/**
|
|
541
|
+
* Dry-run mode: compute hashes and check cache but don't execute tasks.
|
|
542
|
+
* Useful for debugging cache hits/misses.
|
|
543
|
+
* @default false
|
|
544
|
+
*/
|
|
545
|
+
dryRun?: boolean;
|
|
546
|
+
/** Custom environment variables to include in hash */
|
|
547
|
+
envVars?: string[];
|
|
548
|
+
/**
|
|
549
|
+
* Environment variable patterns to include in auto-fingerprint.
|
|
550
|
+
* Supports wildcard patterns like "VITE_*".
|
|
551
|
+
* Only used when autoFingerprint is enabled.
|
|
552
|
+
*/
|
|
553
|
+
fingerprintEnvPatterns?: string[];
|
|
554
|
+
/**
|
|
555
|
+
* Enable framework environment variable inference.
|
|
556
|
+
* When true, automatically detects common frontend frameworks and includes
|
|
557
|
+
* their public env var prefixes in the task hash:
|
|
558
|
+
* - Next.js: NEXT_PUBLIC_*
|
|
559
|
+
* - Vite: VITE_*
|
|
560
|
+
* - Create React App: REACT_APP_*
|
|
561
|
+
* - Gatsby: GATSBY_*
|
|
562
|
+
* - Nuxt: NUXT_PUBLIC_*
|
|
563
|
+
* - Expo: EXPO_PUBLIC_*
|
|
564
|
+
*
|
|
565
|
+
* Matches Turborepo's framework inference behavior.
|
|
566
|
+
* @default false
|
|
567
|
+
*/
|
|
568
|
+
frameworkInference?: boolean;
|
|
569
|
+
/**
|
|
570
|
+
* Global environment variables that invalidate ALL task hashes.
|
|
571
|
+
* Matches Turborepo's `globalEnv`.
|
|
572
|
+
*/
|
|
573
|
+
globalEnv?: string[];
|
|
574
|
+
/**
|
|
575
|
+
* Global input files that invalidate ALL task hashes when changed.
|
|
576
|
+
* These are workspace-root-relative paths.
|
|
577
|
+
*
|
|
578
|
+
* Default: ["package-lock.json", "pnpm-lock.yaml", "yarn.lock",
|
|
579
|
+
* "tsconfig.base.json", ".env"]
|
|
580
|
+
*
|
|
581
|
+
* When any global input changes, every task's hash changes,
|
|
582
|
+
* forcing a full rebuild. This matches Turborepo's `globalDependencies`.
|
|
583
|
+
*/
|
|
584
|
+
globalInputs?: string[];
|
|
585
|
+
/**
|
|
586
|
+
* When `true`, file hashes are cached in a persistent mtime+size
|
|
587
|
+
* indexed snapshot under `node_modules/.cache/task-runner/`. On
|
|
588
|
+
* subsequent runs, unchanged files skip content re-reads — cuts
|
|
589
|
+
* cold-cache fingerprint time dramatically on large workspaces.
|
|
590
|
+
*
|
|
591
|
+
* Changed or new files still get full content hashing. Safe to
|
|
592
|
+
* leave on by default; overhead when nothing matches is a single
|
|
593
|
+
* `stat` call per file.
|
|
594
|
+
* @default false
|
|
595
|
+
*/
|
|
596
|
+
incrementalFileHashing?: boolean;
|
|
597
|
+
/** Maximum age of cache entries in milliseconds */
|
|
598
|
+
maxCacheAge?: number;
|
|
599
|
+
/** Maximum cache size (e.g., "1GB") */
|
|
600
|
+
maxCacheSize?: string;
|
|
601
|
+
/** Named inputs for cache invalidation */
|
|
602
|
+
namedInputs?: NamedInputs;
|
|
603
|
+
/**
|
|
604
|
+
* When `true`, the cache directory is partitioned by a hash of
|
|
605
|
+
* the resolved `globalEnv` values. Changing a globalEnv var moves
|
|
606
|
+
* cache writes into a new namespace; rolling it back reuses the
|
|
607
|
+
* old namespace and its hits. Without this option, any globalEnv
|
|
608
|
+
* change silently busts every cached entry.
|
|
609
|
+
*
|
|
610
|
+
* Keep disabled when globalEnv is stable across runs — the extra
|
|
611
|
+
* path depth offers no value, and misconfigured namespaces can
|
|
612
|
+
* hide stale hits.
|
|
613
|
+
* @default false
|
|
614
|
+
*/
|
|
615
|
+
namespaceByGlobalEnv?: boolean;
|
|
616
|
+
/** Maximum number of parallel tasks */
|
|
617
|
+
parallel?: number | boolean;
|
|
618
|
+
/**
|
|
619
|
+
* Remote cache configuration.
|
|
620
|
+
* When configured, the task runner will check the remote cache
|
|
621
|
+
* after a local cache miss, and upload results after execution.
|
|
622
|
+
*/
|
|
623
|
+
remoteCache?: {
|
|
624
|
+
/**
|
|
625
|
+
* Called when a fire-and-forget upload fails.
|
|
626
|
+
* Since uploads are non-blocking, errors are silently swallowed by default.
|
|
627
|
+
* Provide this callback to log or report upload failures.
|
|
628
|
+
*/
|
|
629
|
+
onUploadError?: (hash: string, error: unknown) => void;
|
|
630
|
+
/** Enable remote reads (default: true) */
|
|
631
|
+
read?: boolean;
|
|
632
|
+
/** Team/namespace for cache isolation */
|
|
633
|
+
teamId?: string;
|
|
634
|
+
/** Authentication token */
|
|
635
|
+
token?: string;
|
|
636
|
+
/** Remote cache server URL */
|
|
637
|
+
url: string;
|
|
638
|
+
/** Enable remote writes (default: true) */
|
|
639
|
+
write?: boolean;
|
|
640
|
+
};
|
|
641
|
+
/** Whether to skip cache reads */
|
|
642
|
+
skipNxCache?: boolean;
|
|
643
|
+
/**
|
|
644
|
+
* Enable smart lockfile hashing.
|
|
645
|
+
* Instead of hashing the entire lockfile (which busts ALL caches),
|
|
646
|
+
* only hash the resolved versions of each package's actual dependencies.
|
|
647
|
+
* This matches Turborepo's smart lockfile hashing behavior.
|
|
648
|
+
* @default false
|
|
649
|
+
*/
|
|
650
|
+
smartLockfileHashing?: boolean;
|
|
651
|
+
/**
|
|
652
|
+
* Generate a detailed JSON run summary after execution.
|
|
653
|
+
* When true, writes a summary file to `.task-runner/runs/` containing
|
|
654
|
+
* all task inputs, outputs, hashes, timings, and cache status.
|
|
655
|
+
*
|
|
656
|
+
* Useful for debugging cache misses and comparing runs.
|
|
657
|
+
* Matches Turborepo's `--summarize` flag.
|
|
658
|
+
* @default false
|
|
659
|
+
*/
|
|
660
|
+
summarize?: boolean;
|
|
661
|
+
/** Target-specific default configurations */
|
|
662
|
+
targetDefaults?: Record<string, Partial<TargetConfiguration>>;
|
|
663
|
+
/**
|
|
664
|
+
* Environment variables that should be passed to tasks but NOT
|
|
665
|
+
* included in the cache fingerprint. Useful for CI-specific vars.
|
|
666
|
+
* Only used when autoFingerprint is enabled.
|
|
667
|
+
*/
|
|
668
|
+
untrackedEnvVars?: string[];
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Options for executing a task.
|
|
672
|
+
*/
|
|
673
|
+
interface TaskExecutionOptions {
|
|
674
|
+
/** Whether to capture output */
|
|
675
|
+
captureOutput?: boolean;
|
|
676
|
+
/** The working directory */
|
|
677
|
+
cwd?: string;
|
|
678
|
+
/** Environment variables */
|
|
679
|
+
env?: Record<string, string>;
|
|
680
|
+
/** Stream output as it arrives */
|
|
681
|
+
streamOutput?: boolean;
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* A task executor function.
|
|
685
|
+
*/
|
|
686
|
+
type TaskExecutor = (task: Task, options: TaskExecutionOptions) => Promise<{
|
|
687
|
+
code: number;
|
|
688
|
+
terminalOutput: string;
|
|
689
|
+
}>;
|
|
690
|
+
/**
|
|
691
|
+
* The function type for a task runner.
|
|
692
|
+
*/
|
|
693
|
+
type TasksRunner = (tasks: Task[], options: TaskRunnerOptions, context: TaskRunnerContext) => Promise<TaskResults>;
|
|
694
|
+
/**
|
|
695
|
+
* Context provided to the task runner.
|
|
696
|
+
*/
|
|
697
|
+
interface TaskRunnerContext {
|
|
698
|
+
/** Lifecycle hooks */
|
|
699
|
+
lifeCycle: LifeCycleInterface;
|
|
700
|
+
/** The project graph */
|
|
701
|
+
projectGraph: ProjectGraph;
|
|
702
|
+
/** The task executor */
|
|
703
|
+
taskExecutor: TaskExecutor;
|
|
704
|
+
/** The task graph */
|
|
705
|
+
taskGraph: TaskGraph;
|
|
706
|
+
/** The workspace root directory */
|
|
707
|
+
workspaceRoot: string;
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* Input for a concurrent command -- either a string or a config object.
|
|
711
|
+
*/
|
|
712
|
+
type ConcurrentCommandInput = string | {
|
|
713
|
+
command: string;
|
|
714
|
+
cwd?: string;
|
|
715
|
+
env?: Record<string, string>;
|
|
716
|
+
name?: string; /** Initial PTY dimensions (only used when stdin is "pty"). */
|
|
717
|
+
ptySize?: {
|
|
718
|
+
cols: number;
|
|
719
|
+
rows: number;
|
|
720
|
+
};
|
|
721
|
+
stdin?: "inherit" | "null" | "pipe" | "pty";
|
|
722
|
+
};
|
|
723
|
+
/**
|
|
724
|
+
* Configuration for a single command to run concurrently.
|
|
725
|
+
*/
|
|
726
|
+
interface ConcurrentCommandConfig {
|
|
727
|
+
/** The command string to execute (passed to shell). */
|
|
728
|
+
command: string;
|
|
729
|
+
/** Working directory for the command. */
|
|
730
|
+
cwd?: string;
|
|
731
|
+
/** Additional environment variables merged with process env. */
|
|
732
|
+
env?: Record<string, string>;
|
|
733
|
+
/** Human-readable name for this command (used in prefixes/logs). */
|
|
734
|
+
name?: string;
|
|
735
|
+
/**
|
|
736
|
+
* Initial PTY dimensions. Only used when stdin is "pty".
|
|
737
|
+
* Defaults to 80x24 if not specified.
|
|
738
|
+
*/
|
|
739
|
+
ptySize?: {
|
|
740
|
+
cols: number;
|
|
741
|
+
rows: number;
|
|
742
|
+
};
|
|
743
|
+
/** Whether to use shell execution (default: true). */
|
|
744
|
+
shell?: boolean;
|
|
745
|
+
/**
|
|
746
|
+
* Stdin mode for the child process.
|
|
747
|
+
* - "null" (default): stdin closed, child cannot read input
|
|
748
|
+
* - "pipe": stdin is piped, can be written to programmatically
|
|
749
|
+
* - "inherit": child inherits parent's stdin (for interactive commands like vite dev)
|
|
750
|
+
* - "pty": child runs inside a pseudo-terminal (isatty() returns true, enables interactive prompts)
|
|
751
|
+
*/
|
|
752
|
+
stdin?: "inherit" | "null" | "pipe" | "pty";
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Options controlling the concurrent runner behavior.
|
|
756
|
+
*/
|
|
757
|
+
interface ConcurrentRunnerOptions {
|
|
758
|
+
/** Conditions under which to kill other processes: "success", "failure". */
|
|
759
|
+
killOthers?: ("failure" | "success")[];
|
|
760
|
+
/** Signal to send when killing processes (default: "SIGTERM"). */
|
|
761
|
+
killSignal?: string;
|
|
762
|
+
/** Milliseconds to wait after kill signal before sending SIGKILL (default: 5000). */
|
|
763
|
+
killTimeout?: number;
|
|
764
|
+
/** Maximum number of processes to run simultaneously. 0 = unlimited. */
|
|
765
|
+
maxProcesses?: number;
|
|
766
|
+
/** Callback for real-time process events. */
|
|
767
|
+
onEvent?: (event: ProcessEvent) => void;
|
|
768
|
+
/** Restart options for failed commands. */
|
|
769
|
+
restart?: {
|
|
770
|
+
/** Delay between restarts in ms. "exponential" for 2^attempt * 1000ms. */
|
|
771
|
+
delay?: number | "exponential";
|
|
772
|
+
/** Maximum restart attempts per command. 0 = no restarts. -1 = infinite. */
|
|
773
|
+
tries: number;
|
|
774
|
+
};
|
|
775
|
+
/**
|
|
776
|
+
* Custom shell path for command execution.
|
|
777
|
+
* Overrides the platform default (/bin/sh on Unix, cmd.exe on Windows).
|
|
778
|
+
* Automatically detected from npm's `script-shell` config if not set.
|
|
779
|
+
*/
|
|
780
|
+
shellPath?: string;
|
|
781
|
+
/** Success condition: "first", "last", "all", or "command-<name|index>". */
|
|
782
|
+
successCondition?: string;
|
|
783
|
+
/** Commands to run sequentially after all processes complete. */
|
|
784
|
+
teardown?: string[];
|
|
785
|
+
/** Working directory for teardown commands. */
|
|
786
|
+
teardownCwd?: string;
|
|
787
|
+
/** Print a timing summary table after completion. Default: false. */
|
|
788
|
+
timings?: boolean;
|
|
789
|
+
}
|
|
790
|
+
/**
|
|
791
|
+
* An event emitted during concurrent execution.
|
|
792
|
+
*/
|
|
793
|
+
interface ProcessEvent {
|
|
794
|
+
/** Command name (for close events). */
|
|
795
|
+
commandName?: string;
|
|
796
|
+
/** Duration in milliseconds (for close events). */
|
|
797
|
+
durationMs?: number;
|
|
798
|
+
/** Exit code (for close events). */
|
|
799
|
+
exitCode?: number;
|
|
800
|
+
/** Index of the command that produced this event. */
|
|
801
|
+
index: number;
|
|
802
|
+
/** Kill the child process/PTY. Only present on "started" events. */
|
|
803
|
+
kill?: (signal?: string) => void;
|
|
804
|
+
/** Whether the process was killed (for close events). */
|
|
805
|
+
killed?: boolean;
|
|
806
|
+
/** Event type: "stdout", "stderr", "close", "error", "started". */
|
|
807
|
+
kind: "close" | "error" | "started" | "stderr" | "stdout";
|
|
808
|
+
/** Error message (for error events). */
|
|
809
|
+
message?: string;
|
|
810
|
+
/** Resize the child's PTY. Only present on "started" events with stdin "pty". */
|
|
811
|
+
resize?: (cols: number, rows: number) => void;
|
|
812
|
+
/** Text content (for stdout/stderr events). */
|
|
813
|
+
text?: string;
|
|
814
|
+
/** Write data to the child's stdin (pipe) or PTY. Only present on "started" events. */
|
|
815
|
+
write?: (data: string) => void;
|
|
816
|
+
}
|
|
817
|
+
/**
|
|
818
|
+
* Result of a close event for a single command.
|
|
819
|
+
*/
|
|
820
|
+
interface ConcurrentCloseEvent {
|
|
821
|
+
/** The command string that was executed. */
|
|
822
|
+
command: string;
|
|
823
|
+
/** Duration in milliseconds. */
|
|
824
|
+
durationMs: number;
|
|
825
|
+
/** Exit code. -1 if killed by signal. */
|
|
826
|
+
exitCode: number;
|
|
827
|
+
/** Index of the command. */
|
|
828
|
+
index: number;
|
|
829
|
+
/** Whether the process was forcefully killed. */
|
|
830
|
+
killed: boolean;
|
|
831
|
+
/** The command name (if provided). */
|
|
832
|
+
name?: string;
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* Overall result of a concurrent run.
|
|
836
|
+
*/
|
|
837
|
+
interface ConcurrentRunResult {
|
|
838
|
+
/** Close events for all commands, in completion order. */
|
|
839
|
+
closeEvents: ConcurrentCloseEvent[];
|
|
840
|
+
/** Whether the run succeeded according to the success condition. */
|
|
841
|
+
success: boolean;
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* Interface for lifecycle event handlers.
|
|
845
|
+
*/
|
|
846
|
+
interface LifeCycleInterface {
|
|
847
|
+
endCommand?: () => void;
|
|
848
|
+
endTasks?: (taskResults: TaskResult[]) => void;
|
|
849
|
+
/**
|
|
850
|
+
* Called when a running task emits data on stderr, in the order the
|
|
851
|
+
* data arrives. Executors that support streaming output (`vis run`'s
|
|
852
|
+
* concurrent executor) forward chunks here verbatim. Executors that
|
|
853
|
+
* only buffer full output (e.g. the simple test executor) skip this
|
|
854
|
+
* hook — rely on `printTaskTerminalOutput` for the final dump.
|
|
855
|
+
*
|
|
856
|
+
* Handlers should be non-blocking; the orchestrator doesn't await.
|
|
857
|
+
*/
|
|
858
|
+
onTaskStderr?: (task: Task, chunk: string) => void;
|
|
859
|
+
/**
|
|
860
|
+
* Called when a running task emits data on stdout, in the order the
|
|
861
|
+
* data arrives. See {@link LifeCycleInterface.onTaskStderr} for
|
|
862
|
+
* semantics — same contract, different stream.
|
|
863
|
+
*/
|
|
864
|
+
onTaskStdout?: (task: Task, chunk: string) => void;
|
|
865
|
+
/** Called when a cache miss occurs with diagnostic information */
|
|
866
|
+
printCacheMiss?: (task: Task, reasons: string) => void;
|
|
867
|
+
/**
|
|
868
|
+
* Called when caching was skipped because auto-fingerprint tracking
|
|
869
|
+
* came back empty — a signal that the tracker (strace or Node
|
|
870
|
+
* preload) couldn't observe the task's file access, typically
|
|
871
|
+
* because it's a static binary on a platform without strace.
|
|
872
|
+
* `reason` is a short human-readable diagnostic.
|
|
873
|
+
*/
|
|
874
|
+
printEmptyFingerprintWarning?: (task: Task, reason: string) => void;
|
|
875
|
+
/**
|
|
876
|
+
* Called when caching is skipped because the task modified one or
|
|
877
|
+
* more of its own tracked inputs. `modifiedFiles` lists the
|
|
878
|
+
* workspace-relative paths that changed between pre- and
|
|
879
|
+
* post-execution hashes.
|
|
880
|
+
*/
|
|
881
|
+
printSelfModifyingSkip?: (task: Task, modifiedFiles: string[]) => void;
|
|
882
|
+
printTaskTerminalOutput?: (task: Task, status: TaskStatus, terminalOutput: string) => void;
|
|
883
|
+
/**
|
|
884
|
+
* Called when a task is skipped because its `when` clause did not
|
|
885
|
+
* match the current environment. `reason` is a short
|
|
886
|
+
* human-readable diagnostic produced by {@link import("./when-condition").explainWhen}.
|
|
887
|
+
*
|
|
888
|
+
* Co-fires with `printTaskTerminalOutput` (status `"skipped"`,
|
|
889
|
+
* output `"Skipped: [reason]"`). Pick one to render — implementing
|
|
890
|
+
* both will double-report the skip.
|
|
891
|
+
*/
|
|
892
|
+
printWhenSkip?: (task: Task, reason: string) => void;
|
|
893
|
+
scheduleTask?: (task: Task) => void;
|
|
894
|
+
startCommand?: () => void;
|
|
895
|
+
startTasks?: (tasks: Task[]) => void;
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Options for determining affected projects.
|
|
899
|
+
*/
|
|
900
|
+
interface AffectedOptions {
|
|
901
|
+
/** The base ref to compare against (default: "main") */
|
|
902
|
+
base?: string;
|
|
903
|
+
/**
|
|
904
|
+
* Control how far downstream (dependents of changed projects) to include.
|
|
905
|
+
* @default "deep"
|
|
906
|
+
*/
|
|
907
|
+
downstream?: AffectedScope;
|
|
908
|
+
/** The head ref to compare (default: "HEAD") */
|
|
909
|
+
head?: string;
|
|
910
|
+
/** Project graph for dependency resolution */
|
|
911
|
+
projectGraph: ProjectGraph;
|
|
912
|
+
/** All project configurations keyed by name */
|
|
913
|
+
projects: Record<string, ProjectConfiguration>;
|
|
914
|
+
/**
|
|
915
|
+
* Control how far upstream (dependencies of changed projects) to include.
|
|
916
|
+
* @default "none"
|
|
917
|
+
*/
|
|
918
|
+
upstream?: AffectedScope;
|
|
919
|
+
/** The workspace root directory */
|
|
920
|
+
workspaceRoot: string;
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* Result of affected detection.
|
|
924
|
+
*/
|
|
925
|
+
interface AffectedResult {
|
|
926
|
+
/** All affected projects (union of changed, downstream, and upstream) */
|
|
927
|
+
affectedProjects: string[];
|
|
928
|
+
/** Files that changed between base and head */
|
|
929
|
+
changedFiles: string[];
|
|
930
|
+
/** Projects that were directly changed */
|
|
931
|
+
changedProjects: string[];
|
|
932
|
+
/** Projects affected because they depend on changed projects */
|
|
933
|
+
downstreamProjects: string[];
|
|
934
|
+
/** Projects that changed projects depend on */
|
|
935
|
+
upstreamProjects: string[];
|
|
936
|
+
}
|
|
937
|
+
/**
|
|
938
|
+
* Builds a map from each project to the set of projects that depend on it (reverse/downstream).
|
|
939
|
+
*/
|
|
940
|
+
declare const buildReverseDependencyMap: (projectGraph: ProjectGraph) => Map<string, Set<string>>;
|
|
941
|
+
/**
|
|
942
|
+
* Builds a map from each project to the set of projects it depends on (forward/upstream).
|
|
943
|
+
*/
|
|
944
|
+
declare const buildForwardDependencyMap: (projectGraph: ProjectGraph) => Map<string, Set<string>>;
|
|
945
|
+
/**
|
|
946
|
+
* Expands a set of changed projects based on upstream/downstream scope settings.
|
|
947
|
+
* Returns a new set containing all affected projects.
|
|
948
|
+
*/
|
|
949
|
+
declare const expandAffected: (changedProjects: Set<string>, projectGraph: ProjectGraph, options: {
|
|
950
|
+
downstream: AffectedScope;
|
|
951
|
+
upstream: AffectedScope;
|
|
952
|
+
}) => {
|
|
953
|
+
affected: Set<string>;
|
|
954
|
+
downstream: Set<string>;
|
|
955
|
+
upstream: Set<string>;
|
|
956
|
+
};
|
|
957
|
+
/**
|
|
958
|
+
* Gets the list of files changed between two git refs.
|
|
959
|
+
* Uses execFile with argument arrays to prevent command injection.
|
|
960
|
+
*/
|
|
961
|
+
declare const getChangedFiles: (workspaceRoot: string, base: string, head: string) => Promise<string[]>;
|
|
962
|
+
/**
|
|
963
|
+
* Determines which projects are affected by changes between two git refs.
|
|
964
|
+
*
|
|
965
|
+
* Uses `git diff` to find changed files, maps them to projects based on
|
|
966
|
+
* project roots, then walks the project dependency graph to find all
|
|
967
|
+
* transitively affected projects.
|
|
968
|
+
*
|
|
969
|
+
* This is the same strategy used by `nx affected` and `turbo run --filter=[base...]`.
|
|
970
|
+
*/
|
|
971
|
+
declare const getAffectedProjects: (options: AffectedOptions) => Promise<AffectedResult>;
|
|
972
|
+
/**
|
|
973
|
+
* Filters tasks to only include those that are affected by changes.
|
|
974
|
+
*/
|
|
975
|
+
declare const filterAffectedTasks: (taskIds: string[], affectedProjects: Set<string>) => string[];
|
|
976
|
+
/**
|
|
977
|
+
* Represents a file access recorded during task execution.
|
|
978
|
+
*
|
|
979
|
+
* Write-intent accesses (`"write"`) are emitted when a task opens a file
|
|
980
|
+
* with `O_WRONLY`/`O_RDWR`/`O_CREAT`/`O_TRUNC` flags (strace) or calls
|
|
981
|
+
* `writeFile`/`appendFile`/`unlink`/`rename` (preload script).
|
|
982
|
+
* The orchestrator uses the overlap of reads and writes to the same
|
|
983
|
+
* workspace path to detect self-modifying tasks and skip caching.
|
|
984
|
+
*/
|
|
985
|
+
interface FileAccess {
|
|
986
|
+
/** The absolute path of the file */
|
|
987
|
+
path: string;
|
|
988
|
+
/** The type of access */
|
|
989
|
+
type: "missing" | "read" | "readdir" | "stat" | "write";
|
|
990
|
+
}
|
|
991
|
+
/**
|
|
992
|
+
* Result of tracking file accesses during a command execution.
|
|
993
|
+
*/
|
|
994
|
+
interface TrackingResult {
|
|
995
|
+
/** All file accesses recorded */
|
|
996
|
+
accesses: FileAccess[];
|
|
997
|
+
/** The command exit code */
|
|
998
|
+
code: number;
|
|
999
|
+
/** The command stdout + stderr output */
|
|
1000
|
+
output: string;
|
|
1001
|
+
}
|
|
1002
|
+
/**
|
|
1003
|
+
* Tracks which files a child process accesses during execution.
|
|
1004
|
+
*
|
|
1005
|
+
* Uses `strace` on Linux to intercept syscalls (open, openat, stat, lstat, access, getdents).
|
|
1006
|
+
* Falls back to no tracking on unsupported platforms.
|
|
1007
|
+
*/
|
|
1008
|
+
declare class FileAccessTracker {
|
|
1009
|
+
#private;
|
|
1010
|
+
constructor(workspaceRoot: string, excludePatterns?: RegExp[]);
|
|
1011
|
+
/**
|
|
1012
|
+
* Returns true if file access tracking is supported on the current platform.
|
|
1013
|
+
*/
|
|
1014
|
+
isSupported(): boolean;
|
|
1015
|
+
/**
|
|
1016
|
+
* Runs a command and tracks all file system accesses.
|
|
1017
|
+
* On unsupported platforms, runs the command without tracking.
|
|
1018
|
+
*/
|
|
1019
|
+
track(command: string, options?: {
|
|
1020
|
+
cwd?: string;
|
|
1021
|
+
env?: Record<string, string | undefined>;
|
|
1022
|
+
}): Promise<TrackingResult>;
|
|
1023
|
+
/**
|
|
1024
|
+
* Kills all active child processes. Called on abort/signal to prevent orphans.
|
|
1025
|
+
*/
|
|
1026
|
+
killAll(): void;
|
|
1027
|
+
}
|
|
1028
|
+
/**
|
|
1029
|
+
* Generates a preload script that can be used with NODE_OPTIONS to
|
|
1030
|
+
* track file accesses in Node.js child processes.
|
|
1031
|
+
*
|
|
1032
|
+
* This is an alternative to strace that works cross-platform for Node.js processes.
|
|
1033
|
+
*/
|
|
1034
|
+
declare const generatePreloadScript: (outputPath: string) => string;
|
|
1035
|
+
/**
|
|
1036
|
+
* Represents a stored fingerprint for a task execution.
|
|
1037
|
+
*/
|
|
1038
|
+
interface TaskFingerprint {
|
|
1039
|
+
/** Hash of the command arguments */
|
|
1040
|
+
commandHash: string;
|
|
1041
|
+
/** Directory listings recorded during execution (path -> sorted entries) */
|
|
1042
|
+
directoryListings: Record<string, string[]>;
|
|
1043
|
+
/** Hashes of fingerprinted environment variables */
|
|
1044
|
+
envHashes: Record<string, string>;
|
|
1045
|
+
/** Content hashes of files that were read during execution */
|
|
1046
|
+
fileHashes: Record<string, string>;
|
|
1047
|
+
/** Paths of files that were probed but didn't exist (ENOENT) */
|
|
1048
|
+
missingFiles: string[];
|
|
1049
|
+
/**
|
|
1050
|
+
* Workspace-relative paths that were both read **and** written
|
|
1051
|
+
* during execution. Populated when the tracker emits
|
|
1052
|
+
* {@link FileAccess} entries with `"write"` type. The orchestrator
|
|
1053
|
+
* uses a non-empty value here to skip caching a self-modifying
|
|
1054
|
+
* task, whose fingerprint would otherwise capture post-write state
|
|
1055
|
+
* and trigger false cache hits.
|
|
1056
|
+
*/
|
|
1057
|
+
modifiedInputs?: string[];
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Describes why a cache miss occurred.
|
|
1061
|
+
*/
|
|
1062
|
+
interface CacheMissReason {
|
|
1063
|
+
currentHash?: string;
|
|
1064
|
+
detail: string;
|
|
1065
|
+
previousHash?: string;
|
|
1066
|
+
type: "file-changed" | "file-created" | "file-deleted" | "directory-changed" | "env-changed" | "args-changed" | "no-fingerprint";
|
|
1067
|
+
}
|
|
1068
|
+
/**
|
|
1069
|
+
* Manages task fingerprints for auto-detection caching.
|
|
1070
|
+
*
|
|
1071
|
+
* Records which files a task accesses during execution, stores content
|
|
1072
|
+
* hashes, and on subsequent runs checks if any accessed file has changed.
|
|
1073
|
+
*/
|
|
1074
|
+
declare class FingerprintManager {
|
|
1075
|
+
#private;
|
|
1076
|
+
constructor(workspaceRoot: string);
|
|
1077
|
+
createFingerprint(accesses: FileAccess[], command: string, args: Record<string, unknown>, envVariables: Record<string, string | undefined>, envPatterns?: string[], untrackedEnvVariables?: string[]): Promise<TaskFingerprint>;
|
|
1078
|
+
/**
|
|
1079
|
+
* Validates a stored fingerprint against the current state.
|
|
1080
|
+
* Returns null if valid (cache hit), or an array of reasons (cache miss).
|
|
1081
|
+
*
|
|
1082
|
+
* Does NOT use the file hash cache — validation must see current disk state.
|
|
1083
|
+
*/
|
|
1084
|
+
validate(fingerprint: TaskFingerprint): Promise<CacheMissReason[] | undefined>;
|
|
1085
|
+
validateCommand(fingerprint: TaskFingerprint, command: string, args: Record<string, unknown>): CacheMissReason | undefined;
|
|
1086
|
+
formatMissReasons(reasons: CacheMissReason[]): string;
|
|
1087
|
+
}
|
|
1088
|
+
/**
|
|
1089
|
+
* Represents a cached task result.
|
|
1090
|
+
*/
|
|
1091
|
+
interface CachedResult {
|
|
1092
|
+
/** The exit code of the original task execution */
|
|
1093
|
+
code: number;
|
|
1094
|
+
/** The auto-fingerprint data, if auto-fingerprinting was used */
|
|
1095
|
+
fingerprint?: TaskFingerprint;
|
|
1096
|
+
/** The hash that was used as the cache key */
|
|
1097
|
+
hash: string;
|
|
1098
|
+
/** The terminal output of the original task execution */
|
|
1099
|
+
terminalOutput: string;
|
|
1100
|
+
}
|
|
1101
|
+
/**
|
|
1102
|
+
* Options for creating a Cache instance.
|
|
1103
|
+
*/
|
|
1104
|
+
interface CacheOptions {
|
|
1105
|
+
/** The cache directory (defaults to `{workspaceRoot}/.task-runner-cache`) */
|
|
1106
|
+
cacheDirectory?: string;
|
|
1107
|
+
/**
|
|
1108
|
+
* Optional isolation namespace appended to the cache directory
|
|
1109
|
+
* as `<cacheDir>/ns/<namespace>`. When the caller derives the
|
|
1110
|
+
* namespace from the resolved global-env fingerprint, flipping an
|
|
1111
|
+
* env var sends writes into a new namespace while keeping the old
|
|
1112
|
+
* namespace intact — rolling the env back restores the old hits.
|
|
1113
|
+
*
|
|
1114
|
+
* Filesystem-safe segment; callers are responsible for sanitising
|
|
1115
|
+
* (slashes/colons would break path resolution).
|
|
1116
|
+
*/
|
|
1117
|
+
cacheNamespace?: string;
|
|
1118
|
+
/** Maximum age of cache entries in milliseconds (default: 7 days) */
|
|
1119
|
+
maxCacheAge?: number;
|
|
1120
|
+
/** Maximum cache size (e.g., "500MB", "1GB") */
|
|
1121
|
+
maxCacheSize?: string;
|
|
1122
|
+
/** The workspace root directory */
|
|
1123
|
+
workspaceRoot: string;
|
|
1124
|
+
}
|
|
1125
|
+
/**
|
|
1126
|
+
* Directory name (relative to `workspaceRoot`) where the task runner writes
|
|
1127
|
+
* its cache by default. Exported so callers that manage the cache from the
|
|
1128
|
+
* outside — e.g. a CLI `cache clean` command — can reach the same default
|
|
1129
|
+
* without hard-coding the literal.
|
|
1130
|
+
*/
|
|
1131
|
+
declare const DEFAULT_CACHE_DIRECTORY_NAME = ".task-runner-cache";
|
|
1132
|
+
/**
|
|
1133
|
+
* Parses a human-readable cache size string into bytes.
|
|
1134
|
+
* Delegates to @visulima/humanizer's parseBytes with base-2 (1024) multipliers.
|
|
1135
|
+
*/
|
|
1136
|
+
declare const parseCacheSize: (sizeString: string) => number;
|
|
1137
|
+
/**
|
|
1138
|
+
* Formats a byte count into a human-readable string.
|
|
1139
|
+
* Delegates to @visulima/humanizer's formatBytes with base-2 (1024) multipliers.
|
|
1140
|
+
*/
|
|
1141
|
+
declare const formatCacheSize: (bytes: number) => string;
|
|
1142
|
+
/**
|
|
1143
|
+
* Local file-based cache for task results.
|
|
1144
|
+
*
|
|
1145
|
+
* Cache structure:
|
|
1146
|
+
* ```
|
|
1147
|
+
* .task-runner-cache/
|
|
1148
|
+
* <hash>/
|
|
1149
|
+
* outputs/ (Archived build outputs)
|
|
1150
|
+
* code (Exit code)
|
|
1151
|
+
* terminalOutput (Captured terminal output)
|
|
1152
|
+
* fingerprint.json (Auto-fingerprint data, optional)
|
|
1153
|
+
* .commit (Marker indicating complete cache entry)
|
|
1154
|
+
* .task-index.json (Task ID -> hash mapping for auto-fingerprint)
|
|
1155
|
+
* ```
|
|
1156
|
+
*
|
|
1157
|
+
* Atomicity: Cache entries are written to a temporary directory first,
|
|
1158
|
+
* then renamed into place. The `.commit` marker ensures readers only
|
|
1159
|
+
* see complete entries.
|
|
1160
|
+
*/
|
|
1161
|
+
declare class Cache {
|
|
1162
|
+
#private;
|
|
1163
|
+
constructor(options: CacheOptions);
|
|
1164
|
+
/**
|
|
1165
|
+
* Gets the cache directory path.
|
|
1166
|
+
*/
|
|
1167
|
+
get cacheDirectory(): string;
|
|
1168
|
+
/**
|
|
1169
|
+
* Retrieves a cached result for the given task hash.
|
|
1170
|
+
* Returns undefined if no valid cache entry exists.
|
|
1171
|
+
*/
|
|
1172
|
+
get(hash: string): Promise<CachedResult | undefined>;
|
|
1173
|
+
/**
|
|
1174
|
+
* Stores a task result in the cache.
|
|
1175
|
+
*
|
|
1176
|
+
* Uses atomic write: builds the entry in a temporary directory,
|
|
1177
|
+
* then renames into place to avoid partial reads by concurrent processes.
|
|
1178
|
+
*
|
|
1179
|
+
* `outputs` accepts the richer `OutputSpec[]` shape — glob
|
|
1180
|
+
* patterns, negative globs, and `{ auto: true }` entries. Pass
|
|
1181
|
+
* `autoWrites` alongside `{ auto: true }` so the resolver knows
|
|
1182
|
+
* which files the task actually wrote; otherwise auto entries
|
|
1183
|
+
* contribute nothing.
|
|
1184
|
+
*/
|
|
1185
|
+
put(hash: string, terminalOutput: string, outputs: OutputSpec[], code: number, fingerprint?: TaskFingerprint, autoWrites?: ReadonlyArray<string>): Promise<void>;
|
|
1186
|
+
/**
|
|
1187
|
+
* Restores cached outputs from the compressed `outputs.tar.br`
|
|
1188
|
+
* archive. Returns `true` either when the archive was extracted
|
|
1189
|
+
* successfully OR when the entry simply has no outputs to restore.
|
|
1190
|
+
*
|
|
1191
|
+
* The restore flow stages into a temp directory, then swaps each
|
|
1192
|
+
* top-level entry into place (see {@link restoreOutputsCompressed})
|
|
1193
|
+
* so a mid-restore failure never destroys the user's working tree.
|
|
1194
|
+
* The `outputs` parameter is no longer consulted at restore time —
|
|
1195
|
+
* the archive is authoritative, and top-level entries in the
|
|
1196
|
+
* extracted staging become the set of swap roots. Still accepted
|
|
1197
|
+
* for backward compat.
|
|
1198
|
+
*/
|
|
1199
|
+
restoreOutputs(hash: string, _outputs?: OutputSpec[]): Promise<boolean>;
|
|
1200
|
+
/**
|
|
1201
|
+
* Retrieves the most recent cached result for a task by its ID.
|
|
1202
|
+
* Used in auto-fingerprint mode where the hash is derived from
|
|
1203
|
+
* tracked file accesses rather than computed upfront.
|
|
1204
|
+
*/
|
|
1205
|
+
getByTaskId(taskId: string): Promise<CachedResult | undefined>;
|
|
1206
|
+
/**
|
|
1207
|
+
* Stores the mapping from task ID to cache hash.
|
|
1208
|
+
* Uses a write queue to serialize concurrent writes and prevent lost updates.
|
|
1209
|
+
* Each write is atomic (temp file + rename).
|
|
1210
|
+
*/
|
|
1211
|
+
setTaskIndex(taskId: string, hash: string): Promise<void>;
|
|
1212
|
+
/**
|
|
1213
|
+
* Removes old cache entries that exceed the maximum age,
|
|
1214
|
+
* and enforces the maximum cache size by evicting oldest entries.
|
|
1215
|
+
*/
|
|
1216
|
+
removeOldEntries(): Promise<void>;
|
|
1217
|
+
/**
|
|
1218
|
+
* Clears the entire cache.
|
|
1219
|
+
*/
|
|
1220
|
+
clear(): Promise<void>;
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Summary of a single task execution.
|
|
1224
|
+
*/
|
|
1225
|
+
interface TaskSummary {
|
|
1226
|
+
/** Whether the task was cacheable */
|
|
1227
|
+
cacheable: boolean;
|
|
1228
|
+
/** Cache status */
|
|
1229
|
+
cacheStatus: "HIT" | "MISS" | "REMOTE_HIT" | "SKIPPED";
|
|
1230
|
+
/** Dependencies on other tasks */
|
|
1231
|
+
dependencies: string[];
|
|
1232
|
+
/** Duration in milliseconds */
|
|
1233
|
+
duration: number | undefined;
|
|
1234
|
+
/** End time (ISO 8601) */
|
|
1235
|
+
endTime: string | undefined;
|
|
1236
|
+
/** Exit code */
|
|
1237
|
+
exitCode: number | undefined;
|
|
1238
|
+
/** The computed cache hash */
|
|
1239
|
+
hash: string | undefined;
|
|
1240
|
+
/** Detailed hash information */
|
|
1241
|
+
hashDetails: TaskHashDetails | undefined;
|
|
1242
|
+
/** The task's declared outputs (glob patterns, literals, or `{ auto: true }`). */
|
|
1243
|
+
outputs: OutputSpec[];
|
|
1244
|
+
/** Start time (ISO 8601) */
|
|
1245
|
+
startTime: string | undefined;
|
|
1246
|
+
/** The task target */
|
|
1247
|
+
target: {
|
|
1248
|
+
configuration?: string;
|
|
1249
|
+
project: string;
|
|
1250
|
+
target: string;
|
|
1251
|
+
};
|
|
1252
|
+
/** The task ID (e.g., "app:build") */
|
|
1253
|
+
taskId: string;
|
|
1254
|
+
}
|
|
1255
|
+
/**
|
|
1256
|
+
* Complete summary of a task runner execution.
|
|
1257
|
+
*/
|
|
1258
|
+
interface RunSummary {
|
|
1259
|
+
/** Total duration in milliseconds */
|
|
1260
|
+
duration: number;
|
|
1261
|
+
/** Run end time (ISO 8601) */
|
|
1262
|
+
endTime: string;
|
|
1263
|
+
/** Environment info */
|
|
1264
|
+
environment: {
|
|
1265
|
+
/** Architecture */
|
|
1266
|
+
arch: string;
|
|
1267
|
+
/** Node.js version */
|
|
1268
|
+
nodeVersion: string;
|
|
1269
|
+
/** Platform */
|
|
1270
|
+
platform: string;
|
|
1271
|
+
};
|
|
1272
|
+
/** Unique run ID */
|
|
1273
|
+
id: string;
|
|
1274
|
+
/** Run start time (ISO 8601) */
|
|
1275
|
+
startTime: string;
|
|
1276
|
+
/** Overall execution statistics */
|
|
1277
|
+
stats: {
|
|
1278
|
+
/** Number of cached tasks (local + remote) */
|
|
1279
|
+
cached: number;
|
|
1280
|
+
/** Number of failed tasks */
|
|
1281
|
+
failed: number;
|
|
1282
|
+
/** Number of skipped tasks */
|
|
1283
|
+
skipped: number;
|
|
1284
|
+
/** Number of successful tasks */
|
|
1285
|
+
succeeded: number;
|
|
1286
|
+
/** Total number of tasks */
|
|
1287
|
+
total: number;
|
|
1288
|
+
};
|
|
1289
|
+
/** The task graph used for this run */
|
|
1290
|
+
taskGraph: {
|
|
1291
|
+
dependencies: Record<string, string[]>;
|
|
1292
|
+
roots: string[];
|
|
1293
|
+
};
|
|
1294
|
+
/** Summary of each task */
|
|
1295
|
+
tasks: TaskSummary[];
|
|
1296
|
+
}
|
|
1297
|
+
/**
|
|
1298
|
+
* Generates a run summary from task results.
|
|
1299
|
+
*/
|
|
1300
|
+
declare const generateRunSummary: (results: TaskResults, taskGraph: TaskGraph, startTime: number) => RunSummary;
|
|
1301
|
+
/**
|
|
1302
|
+
* Writes the run summary to a JSON file in the `.task-runner/runs/` directory.
|
|
1303
|
+
* @param summary The run summary to write
|
|
1304
|
+
* @param workspaceRoot The workspace root directory
|
|
1305
|
+
* @returns The path to the written summary file
|
|
1306
|
+
*/
|
|
1307
|
+
declare const writeRunSummary: (summary: RunSummary, workspaceRoot: string) => Promise<string>;
|
|
1308
|
+
/**
|
|
1309
|
+
* Path where the most-recent run summary is persisted.
|
|
1310
|
+
* Consumers (e.g. CLIs exposing `--last-details`) read this file
|
|
1311
|
+
* to replay or render the previous run without re-executing.
|
|
1312
|
+
*/
|
|
1313
|
+
declare const getLastRunSummaryPath: (workspaceRoot: string) => string;
|
|
1314
|
+
/**
|
|
1315
|
+
* Persists `summary` as the most-recent run summary at
|
|
1316
|
+
* `.task-runner/last-summary.json`, overwriting any previous entry.
|
|
1317
|
+
*
|
|
1318
|
+
* This is the companion to {@link readLastRunSummary} and powers
|
|
1319
|
+
* CLI surfaces that display "last run" details without re-running tasks.
|
|
1320
|
+
* @returns The path to the written summary file
|
|
1321
|
+
*/
|
|
1322
|
+
declare const writeLastRunSummary: (summary: RunSummary, workspaceRoot: string) => Promise<string>;
|
|
1323
|
+
/**
|
|
1324
|
+
* Reads the most-recent run summary written by {@link writeLastRunSummary}.
|
|
1325
|
+
* Returns `undefined` when no previous run has been recorded or the file
|
|
1326
|
+
* cannot be parsed — callers should render an informational message
|
|
1327
|
+
* instead of treating this as an error.
|
|
1328
|
+
*/
|
|
1329
|
+
declare const readLastRunSummary: (workspaceRoot: string) => Promise<RunSummary | undefined>;
|
|
1330
|
+
/**
|
|
1331
|
+
* A single event in the Chrome Tracing JSON format. Chrome's
|
|
1332
|
+
* chrome://tracing viewer and Perfetto both accept an array of these.
|
|
1333
|
+
*
|
|
1334
|
+
* Fields track the subset we actually emit:
|
|
1335
|
+
* - `ph: "X"` — "complete" span (has duration)
|
|
1336
|
+
* - `ph: "s"` / `ph: "f"` — flow start / finish (connects two spans)
|
|
1337
|
+
*
|
|
1338
|
+
* See the Chrome Trace Event Format spec on docs.google.com
|
|
1339
|
+
* (document id: 1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU)
|
|
1340
|
+
* for the full specification.
|
|
1341
|
+
*/
|
|
1342
|
+
interface ChromeTraceEvent {
|
|
1343
|
+
args?: Record<string, unknown>;
|
|
1344
|
+
/** Event category — grouped in the viewer's search/filter UI. */
|
|
1345
|
+
cat: string;
|
|
1346
|
+
/** Duration in microseconds — only set for `ph: "X"` events. */
|
|
1347
|
+
dur?: number;
|
|
1348
|
+
/** Flow ID — used to draw an arrow from flow-start to flow-finish. */
|
|
1349
|
+
id?: number;
|
|
1350
|
+
/** Human label shown on the timeline. */
|
|
1351
|
+
name: string;
|
|
1352
|
+
/**
|
|
1353
|
+
* Event phase:
|
|
1354
|
+
* - `"X"` — complete (span with duration)
|
|
1355
|
+
* - `"s"` — flow start
|
|
1356
|
+
* - `"f"` — flow finish
|
|
1357
|
+
* - `"M"` — metadata
|
|
1358
|
+
*/
|
|
1359
|
+
ph: "f" | "M" | "s" | "X";
|
|
1360
|
+
pid: number;
|
|
1361
|
+
tid: number;
|
|
1362
|
+
/** Timestamp in microseconds. */
|
|
1363
|
+
ts: number;
|
|
1364
|
+
}
|
|
1365
|
+
/**
|
|
1366
|
+
* Converts a {@link RunSummary} into a Chrome Tracing event list that
|
|
1367
|
+
* renders as a gantt chart in chrome://tracing or Perfetto.
|
|
1368
|
+
*
|
|
1369
|
+
* Each task becomes a `"X"` span; dependency edges become flow arrows
|
|
1370
|
+
* from the dependency's finish to the dependent task's start.
|
|
1371
|
+
* Parallel tasks are assigned synthetic `tid` values (lane 0, 1, 2, …)
|
|
1372
|
+
* based on the smallest free lane at the task's start time, so the
|
|
1373
|
+
* timeline clearly shows concurrency without requiring real thread IDs.
|
|
1374
|
+
*/
|
|
1375
|
+
declare const toChromeTrace: (summary: RunSummary) => ChromeTraceEvent[];
|
|
1376
|
+
/**
|
|
1377
|
+
* Writes a Chrome Tracing JSON file at `outputPath`. Consumers (e.g.
|
|
1378
|
+
* a CLI `--profile out.json` flag) call this after the run completes
|
|
1379
|
+
* with a RunSummary produced by the task orchestrator.
|
|
1380
|
+
*/
|
|
1381
|
+
declare const writeChromeTrace: (summary: RunSummary, outputPath: string) => Promise<void>;
|
|
1382
|
+
/**
|
|
1383
|
+
* Context for token interpolation.
|
|
1384
|
+
*
|
|
1385
|
+
* Currently the only first-class token group is `affected` (and its alias
|
|
1386
|
+
* `changed_files`). Pass `affected.files` (workspace-relative paths) and
|
|
1387
|
+
* the renderer will substitute it into command strings such as
|
|
1388
|
+
* `eslint ${affected.files}` or `prettier ${changed_files | flag '--file'}`.
|
|
1389
|
+
*
|
|
1390
|
+
* Optional `projectRoot` makes paths relative to a single project root,
|
|
1391
|
+
* stripping the leading prefix and the immediately following `/`. Files
|
|
1392
|
+
* outside the root are dropped — token interpolation only emits paths
|
|
1393
|
+
* the task can actually act on.
|
|
1394
|
+
*/
|
|
1395
|
+
interface TokenContext {
|
|
1396
|
+
/** Affected/changed files, relative to workspace root. */
|
|
1397
|
+
affectedFiles?: string[];
|
|
1398
|
+
/**
|
|
1399
|
+
* When set, paths are rewritten relative to this project root and
|
|
1400
|
+
* files outside the root are filtered out.
|
|
1401
|
+
*/
|
|
1402
|
+
projectRoot?: string;
|
|
1403
|
+
}
|
|
1404
|
+
/**
|
|
1405
|
+
* Expands token references in a single command string.
|
|
1406
|
+
*
|
|
1407
|
+
* Supported tokens:
|
|
1408
|
+
* `${affected.files}` — space-joined, shell-quoted paths
|
|
1409
|
+
* `${changed_files}` — alias of `affected.files`
|
|
1410
|
+
* `${affected.files | flag '--file'}` — `--file path1 --file path2 ...`
|
|
1411
|
+
*
|
|
1412
|
+
* Unknown tokens are left in place — they may be environment-variable
|
|
1413
|
+
* references the shell will expand at runtime, and silently dropping
|
|
1414
|
+
* them would mask bugs in user commands.
|
|
1415
|
+
*
|
|
1416
|
+
* Escape with a leading backslash (`\${affected.files}`) to emit the
|
|
1417
|
+
* literal token without expansion. Note: the regex consumes at most
|
|
1418
|
+
* one leading backslash, so `\\${...}` collapses to `\${...}` rather
|
|
1419
|
+
* than producing a literal backslash followed by the literal token.
|
|
1420
|
+
* Use a different surrounding quoting scheme if you need a real
|
|
1421
|
+
* backslash adjacent to a token.
|
|
1422
|
+
*/
|
|
1423
|
+
declare const expandTokensInString: (command: string, context: TokenContext) => string;
|
|
1424
|
+
/**
|
|
1425
|
+
* Pipeline-friendly variant of {@link expandTokensInString} that takes
|
|
1426
|
+
* and returns a `ConcurrentCommandConfig`. Plays the same role as
|
|
1427
|
+
* {@link import("./expand-arguments").expandArguments} so it can slot
|
|
1428
|
+
* into {@link import("./index").parseCommands} as a normal step.
|
|
1429
|
+
*/
|
|
1430
|
+
declare const expandTokens: (config: ConcurrentCommandConfig, context: TokenContext) => ConcurrentCommandConfig;
|
|
1431
|
+
/**
|
|
1432
|
+
* Expands argument placeholders in command strings.
|
|
1433
|
+
*
|
|
1434
|
+
* Placeholders:
|
|
1435
|
+
* {1}, {2}, ... -> specific positional argument
|
|
1436
|
+
* {@} -> all arguments, individually quoted
|
|
1437
|
+
* {*} -> all arguments as a single quoted string
|
|
1438
|
+
* \{1} -> literal {1} (escaped)
|
|
1439
|
+
*/
|
|
1440
|
+
declare const expandArguments: (config: ConcurrentCommandConfig, additionalArguments: string[]) => ConcurrentCommandConfig;
|
|
1441
|
+
/**
|
|
1442
|
+
* Expands package manager shortcuts into full commands.
|
|
1443
|
+
*
|
|
1444
|
+
* This parser transforms shorthand notation into proper package manager
|
|
1445
|
+
* invocations. No user input is involved -- command strings originate
|
|
1446
|
+
* from the calling code which reads package.json scripts.
|
|
1447
|
+
*
|
|
1448
|
+
* Examples:
|
|
1449
|
+
* npm:build -> npm run build
|
|
1450
|
+
* pnpm:test -> pnpm run test
|
|
1451
|
+
* node:script -> node --run script
|
|
1452
|
+
* deno:task -> deno task task
|
|
1453
|
+
*/
|
|
1454
|
+
declare const expandShortcut: (config: ConcurrentCommandConfig) => ConcurrentCommandConfig;
|
|
1455
|
+
/**
|
|
1456
|
+
* Expands wildcard patterns in package manager "run" commands.
|
|
1457
|
+
*
|
|
1458
|
+
* Reads scripts from package.json and matches against the wildcard pattern.
|
|
1459
|
+
* Returns one ConcurrentCommandConfig per matching script.
|
|
1460
|
+
*
|
|
1461
|
+
* Example: "npm run watch-*" with scripts { "watch-js": "...", "watch-css": "..." }
|
|
1462
|
+
* -> ["npm run watch-js", "npm run watch-css"]
|
|
1463
|
+
*
|
|
1464
|
+
* No user input is involved -- patterns come from the calling code.
|
|
1465
|
+
*/
|
|
1466
|
+
declare const expandWildcard: (config: ConcurrentCommandConfig) => ConcurrentCommandConfig | ConcurrentCommandConfig[];
|
|
1467
|
+
/**
|
|
1468
|
+
* Removes surrounding quotes from a command string.
|
|
1469
|
+
* Handles both single and double quotes.
|
|
1470
|
+
*/
|
|
1471
|
+
declare const stripQuotes: (config: ConcurrentCommandConfig) => ConcurrentCommandConfig;
|
|
1472
|
+
interface ParseCommandsOptions {
|
|
1473
|
+
/** Additional arguments for placeholder expansion ({1}, {@}, {*}). */
|
|
1474
|
+
additionalArguments?: string[];
|
|
1475
|
+
/**
|
|
1476
|
+
* Token interpolation context. When supplied, `${affected.files}`
|
|
1477
|
+
* and `${changed_files | flag '--file'}` references in command
|
|
1478
|
+
* strings are expanded before argument placeholder substitution.
|
|
1479
|
+
*/
|
|
1480
|
+
tokens?: TokenContext;
|
|
1481
|
+
}
|
|
1482
|
+
/**
|
|
1483
|
+
* Parse and expand command inputs through the full pipeline:
|
|
1484
|
+
* 1. Normalize string inputs to config objects
|
|
1485
|
+
* 2. Strip surrounding quotes
|
|
1486
|
+
* 3. Expand package manager shortcuts (npm:build -> npm run build)
|
|
1487
|
+
* 4. Expand wildcard patterns (npm run watch-* -> multiple commands)
|
|
1488
|
+
* 5. Expand token references (${affected.files}, ${changed_files | flag '...'})
|
|
1489
|
+
* 6. Expand argument placeholders ({1}, {@}, {*})
|
|
1490
|
+
*/
|
|
1491
|
+
declare const parseCommands: (inputs: ConcurrentCommandInput[], options?: ParseCommandsOptions) => ConcurrentCommandConfig[];
|
|
1492
|
+
/**
|
|
1493
|
+
* Run commands concurrently with output streaming and process management.
|
|
1494
|
+
*
|
|
1495
|
+
* Automatically uses the native Rust addon for performance when available,
|
|
1496
|
+
* falling back to a pure JavaScript implementation.
|
|
1497
|
+
*
|
|
1498
|
+
* Supports flow controllers:
|
|
1499
|
+
* - `restart`: retry failed commands with configurable delay/backoff
|
|
1500
|
+
* - `teardown`: run cleanup commands after all processes complete
|
|
1501
|
+
* - `timings`: print a timing summary table
|
|
1502
|
+
* @param commands Array of command strings or config objects
|
|
1503
|
+
* @param options Runner options (maxProcesses, killOthers, restart, teardown, etc.)
|
|
1504
|
+
* @returns Promise resolving to the run result with close events and success status
|
|
1505
|
+
*/
|
|
1506
|
+
declare const runConcurrently: (commands: ConcurrentCommandInput[], options?: ConcurrentRunnerOptions) => Promise<ConcurrentRunResult>;
|
|
1507
|
+
/**
|
|
1508
|
+
* Run commands concurrently using pure JavaScript (child_process.spawn).
|
|
1509
|
+
* This is the fallback when the native Rust addon is unavailable.
|
|
1510
|
+
*/
|
|
1511
|
+
declare const runConcurrentFallback: (commands: ConcurrentCommandConfig[], options: ConcurrentRunnerOptions) => Promise<ConcurrentRunResult>;
|
|
1512
|
+
/**
|
|
1513
|
+
* The default task runner implementation.
|
|
1514
|
+
*
|
|
1515
|
+
* Runs tasks with caching, scheduling, and lifecycle support.
|
|
1516
|
+
* Supports two caching modes:
|
|
1517
|
+
*
|
|
1518
|
+
* 1. **Nx-style** (default): Explicit input declarations with upfront hash computation.
|
|
1519
|
+
* 2. **Auto-fingerprint** (Vite Task-style): Set `autoFingerprint: true` to automatically
|
|
1520
|
+
* track file accesses and use them for cache invalidation.
|
|
1521
|
+
* @example
|
|
1522
|
+
* ```ts
|
|
1523
|
+
* import { defaultTaskRunner } from "@visulima/task-runner";
|
|
1524
|
+
*
|
|
1525
|
+
* // Nx-style (explicit inputs)
|
|
1526
|
+
* const results = await defaultTaskRunner(tasks, options, context);
|
|
1527
|
+
*
|
|
1528
|
+
* // Vite Task-style (auto-fingerprinting)
|
|
1529
|
+
* const results = await defaultTaskRunner(tasks, {
|
|
1530
|
+
* ...options,
|
|
1531
|
+
* autoFingerprint: true,
|
|
1532
|
+
* fingerprintEnvPatterns: ["VITE_*", "NODE_ENV"],
|
|
1533
|
+
* cacheDiagnostics: true,
|
|
1534
|
+
* }, context);
|
|
1535
|
+
*
|
|
1536
|
+
* // With remote cache
|
|
1537
|
+
* const results = await defaultTaskRunner(tasks, {
|
|
1538
|
+
* ...options,
|
|
1539
|
+
* remoteCache: {
|
|
1540
|
+
* url: "https://cache.example.com",
|
|
1541
|
+
* token: process.env.CACHE_TOKEN,
|
|
1542
|
+
* teamId: "my-team",
|
|
1543
|
+
* },
|
|
1544
|
+
* }, context);
|
|
1545
|
+
*
|
|
1546
|
+
* // Dry-run (inspect hashes without executing)
|
|
1547
|
+
* const results = await defaultTaskRunner(tasks, {
|
|
1548
|
+
* ...options,
|
|
1549
|
+
* dryRun: true,
|
|
1550
|
+
* }, context);
|
|
1551
|
+
* ```
|
|
1552
|
+
*/
|
|
1553
|
+
declare const defaultTaskRunner: (_tasks: Task[], options: TaskRunnerOptions, context: TaskRunnerContext) => Promise<TaskResults>;
|
|
1554
|
+
/**
|
|
1555
|
+
* Detect the npm script-shell configuration.
|
|
1556
|
+
*
|
|
1557
|
+
* Returns the shell path if configured, or undefined to use platform defaults.
|
|
1558
|
+
* The result is cached after the first call.
|
|
1559
|
+
*/
|
|
1560
|
+
declare const detectScriptShell: () => string | undefined;
|
|
1561
|
+
interface InputHandlerOptions {
|
|
1562
|
+
/** Default command index to route unprefixed input to. Default: 0. */
|
|
1563
|
+
defaultTarget?: number;
|
|
1564
|
+
/** Stream to read input from. Default: process.stdin. */
|
|
1565
|
+
inputStream?: Readable;
|
|
1566
|
+
/** Whether to pause the input stream when all processes finish. Default: true. */
|
|
1567
|
+
pauseOnFinish?: boolean;
|
|
1568
|
+
}
|
|
1569
|
+
interface CommandStdin {
|
|
1570
|
+
index: number;
|
|
1571
|
+
name?: string;
|
|
1572
|
+
stdin: Writable;
|
|
1573
|
+
}
|
|
1574
|
+
/**
|
|
1575
|
+
* Creates an input handler that routes stdin to child processes.
|
|
1576
|
+
* @param commands Map of command index/name to their stdin streams
|
|
1577
|
+
* @param options Input handler configuration
|
|
1578
|
+
* @returns cleanup function to call when done
|
|
1579
|
+
*/
|
|
1580
|
+
declare const createInputHandler: (commands: CommandStdin[], options?: InputHandlerOptions) => (() => void);
|
|
1581
|
+
/**
|
|
1582
|
+
* Generate a timing summary table string from close events.
|
|
1583
|
+
* @param closeEvents Close events from the concurrent run (in completion order)
|
|
1584
|
+
* @returns Formatted table string
|
|
1585
|
+
*/
|
|
1586
|
+
declare const formatTimingTable: (closeEvents: ConcurrentCloseEvent[]) => string;
|
|
1587
|
+
/**
|
|
1588
|
+
* Print timing summary to a writable stream.
|
|
1589
|
+
* @param closeEvents Close events from the concurrent run
|
|
1590
|
+
* @param output Output stream (default: process.stdout)
|
|
1591
|
+
*/
|
|
1592
|
+
declare const logTimings: (closeEvents: ConcurrentCloseEvent[], output?: NodeJS.WritableStream) => void;
|
|
1593
|
+
interface RestartOptions {
|
|
1594
|
+
/** Delay between restarts in milliseconds. "exponential" for 2^attempt * 1000ms. */
|
|
1595
|
+
delay: number | "exponential";
|
|
1596
|
+
/** Maximum number of restart attempts per command. 0 = no restarts. -1 = infinite. */
|
|
1597
|
+
tries: number;
|
|
1598
|
+
}
|
|
1599
|
+
/**
|
|
1600
|
+
* Wraps a runner function to add restart-on-failure behavior.
|
|
1601
|
+
* @param runFn The underlying runner function (runConcurrently or runConcurrentFallback)
|
|
1602
|
+
* @param commands The original command configs
|
|
1603
|
+
* @param options Runner options
|
|
1604
|
+
* @param restartOptions Restart-specific options
|
|
1605
|
+
*/
|
|
1606
|
+
declare const withRestart: (runFunction: (commands: ConcurrentCommandConfig[], options: ConcurrentRunnerOptions) => Promise<ConcurrentRunResult>, commands: ConcurrentCommandConfig[], options: ConcurrentRunnerOptions, restartOptions: RestartOptions) => Promise<ConcurrentRunResult>;
|
|
1607
|
+
interface TeardownOptions {
|
|
1608
|
+
/** Commands to run in sequence after all processes complete. */
|
|
1609
|
+
commands: string[];
|
|
1610
|
+
/** Working directory for teardown commands. */
|
|
1611
|
+
cwd?: string;
|
|
1612
|
+
}
|
|
1613
|
+
/**
|
|
1614
|
+
* Run teardown commands sequentially.
|
|
1615
|
+
* Each command runs in the shell with inherited stdio.
|
|
1616
|
+
* If a command fails, subsequent commands are still attempted.
|
|
1617
|
+
* @returns Array of exit codes for each teardown command
|
|
1618
|
+
*/
|
|
1619
|
+
declare const runTeardown: (options: TeardownOptions) => Promise<number[]>;
|
|
1620
|
+
/**
|
|
1621
|
+
* Detected framework information.
|
|
1622
|
+
*/
|
|
1623
|
+
interface DetectedFramework {
|
|
1624
|
+
/** The env var prefix(es) that should be included in task hashes */
|
|
1625
|
+
envPrefixes: string[];
|
|
1626
|
+
/** The framework name */
|
|
1627
|
+
name: string;
|
|
1628
|
+
}
|
|
1629
|
+
/**
|
|
1630
|
+
* Detects frameworks used in a project by inspecting its package.json dependencies.
|
|
1631
|
+
* @param packageJsonPath Absolute path to the package.json file
|
|
1632
|
+
* @returns Array of detected frameworks with their env prefixes
|
|
1633
|
+
*/
|
|
1634
|
+
declare const detectFrameworks: (packageJsonPath: string) => Promise<DetectedFramework[]>;
|
|
1635
|
+
/**
|
|
1636
|
+
* Detects frameworks across all projects in a workspace and returns
|
|
1637
|
+
* the env var patterns that should be included in task hashes.
|
|
1638
|
+
* @param workspaceRoot The workspace root directory
|
|
1639
|
+
* @param projects Map of project name to project configuration with root paths
|
|
1640
|
+
* @returns Array of env var wildcard patterns (e.g., ["NEXT_PUBLIC_*", "VITE_*"])
|
|
1641
|
+
*/
|
|
1642
|
+
declare const inferFrameworkEnvPatterns: (workspaceRoot: string, projects: Record<string, {
|
|
1643
|
+
root: string;
|
|
1644
|
+
}>) => Promise<string[]>;
|
|
1645
|
+
/**
|
|
1646
|
+
* For a specific project, detects frameworks and returns the matching
|
|
1647
|
+
* env vars from the current environment.
|
|
1648
|
+
* @param packageJsonPath Absolute path to the project's package.json
|
|
1649
|
+
* @param env The current environment variables
|
|
1650
|
+
* @returns Map of env var name to value for matching framework env vars
|
|
1651
|
+
*/
|
|
1652
|
+
declare const getFrameworkEnvVariables: (packageJsonPath: string, env?: Record<string, string | undefined>) => Promise<Record<string, string>>;
|
|
1653
|
+
/**
|
|
1654
|
+
* Graph visualization output formats.
|
|
1655
|
+
*/
|
|
1656
|
+
type GraphFormat = "dot" | "json" | "html" | "ascii";
|
|
1657
|
+
/**
|
|
1658
|
+
* Options for graph visualization.
|
|
1659
|
+
*/
|
|
1660
|
+
interface GraphVisualizerOptions {
|
|
1661
|
+
/** Show only affected/filtered tasks (highlight subset) */
|
|
1662
|
+
focusedTasks?: string[];
|
|
1663
|
+
/** Group tasks by project (default: true) */
|
|
1664
|
+
groupByProject?: boolean;
|
|
1665
|
+
/** Show task status colors (requires results) */
|
|
1666
|
+
taskStatuses?: Map<string, "success" | "failure" | "skipped" | "local-cache" | "local-cache-kept-existing" | "remote-cache" | "running" | "pending">;
|
|
1667
|
+
}
|
|
1668
|
+
/**
|
|
1669
|
+
* Exports a task graph in DOT format for Graphviz rendering.
|
|
1670
|
+
* @example
|
|
1671
|
+
* ```ts
|
|
1672
|
+
* const dot = toGraphvizDot(taskGraph);
|
|
1673
|
+
* // Render: dot -Tsvg -o graph.svg <<< "$dot"
|
|
1674
|
+
* ```
|
|
1675
|
+
*/
|
|
1676
|
+
declare const toGraphvizDot: (taskGraph: TaskGraph, options?: GraphVisualizerOptions) => string;
|
|
1677
|
+
/**
|
|
1678
|
+
* Exports the task graph as a JSON object suitable for visualization tools.
|
|
1679
|
+
*/
|
|
1680
|
+
interface GraphJson {
|
|
1681
|
+
edges: {
|
|
1682
|
+
source: string;
|
|
1683
|
+
target: string;
|
|
1684
|
+
}[];
|
|
1685
|
+
nodes: {
|
|
1686
|
+
configuration?: string;
|
|
1687
|
+
id: string;
|
|
1688
|
+
project: string;
|
|
1689
|
+
status?: string;
|
|
1690
|
+
target: string;
|
|
1691
|
+
}[];
|
|
1692
|
+
roots: string[];
|
|
1693
|
+
}
|
|
1694
|
+
declare const toGraphJson: (taskGraph: TaskGraph, taskStatuses?: Map<string, string>) => {
|
|
1695
|
+
edges: GraphJson["edges"];
|
|
1696
|
+
nodes: GraphJson["nodes"];
|
|
1697
|
+
roots: string[];
|
|
1698
|
+
};
|
|
1699
|
+
/**
|
|
1700
|
+
* Generates a self-contained HTML file with an interactive task graph visualization.
|
|
1701
|
+
* Uses a simple force-directed layout with SVG rendering (no external dependencies).
|
|
1702
|
+
*/
|
|
1703
|
+
declare const toGraphHtml: (taskGraph: TaskGraph, options?: GraphVisualizerOptions) => string;
|
|
1704
|
+
/**
|
|
1705
|
+
* Renders the task graph as ASCII art for terminal display.
|
|
1706
|
+
* @example
|
|
1707
|
+
* ```
|
|
1708
|
+
* Task Graph (6 tasks, 5 dependencies)
|
|
1709
|
+
*
|
|
1710
|
+
* app:build
|
|
1711
|
+
* ├── lib-a:build
|
|
1712
|
+
* │ └── lib-core:build
|
|
1713
|
+
* └── lib-b:build
|
|
1714
|
+
* └── lib-core:build (*)
|
|
1715
|
+
*
|
|
1716
|
+
* (*) = already shown above
|
|
1717
|
+
* ```
|
|
1718
|
+
*/
|
|
1719
|
+
declare const toGraphAscii: (taskGraph: TaskGraph, options?: GraphVisualizerOptions) => string;
|
|
1720
|
+
/**
|
|
1721
|
+
* Exports a project graph in DOT format.
|
|
1722
|
+
*/
|
|
1723
|
+
declare const projectGraphToDot: (projectGraph: ProjectGraph) => string;
|
|
1724
|
+
/**
|
|
1725
|
+
* Incremental file hasher that only re-hashes files that have changed
|
|
1726
|
+
* since the last run, based on mtime comparison.
|
|
1727
|
+
*
|
|
1728
|
+
* This is the key performance optimization used by Nx's daemon and
|
|
1729
|
+
* Turborepo's daemon — on subsequent runs, only files whose mtime
|
|
1730
|
+
* changed need to be re-read and re-hashed.
|
|
1731
|
+
*
|
|
1732
|
+
* The snapshot (path → { mtime, hash }) is kept in memory and can
|
|
1733
|
+
* optionally be persisted to disk for cross-process reuse.
|
|
1734
|
+
*/
|
|
1735
|
+
interface FileSnapshot {
|
|
1736
|
+
/** xxh3-128 hash of file contents */
|
|
1737
|
+
hash: string;
|
|
1738
|
+
/** Last modification time in milliseconds */
|
|
1739
|
+
mtimeMs: number;
|
|
1740
|
+
/** File size in bytes (fast pre-check) */
|
|
1741
|
+
size: number;
|
|
1742
|
+
}
|
|
1743
|
+
interface IncrementalHasherOptions {
|
|
1744
|
+
/** Directories to skip (default: node_modules, .git, dist, coverage, .cache) */
|
|
1745
|
+
ignoredDirs?: Set<string>;
|
|
1746
|
+
/** File to persist the snapshot to (for cross-run reuse) */
|
|
1747
|
+
snapshotPath?: string;
|
|
1748
|
+
workspaceRoot: string;
|
|
1749
|
+
}
|
|
1750
|
+
declare class IncrementalFileHasher {
|
|
1751
|
+
#private;
|
|
1752
|
+
constructor(options: IncrementalHasherOptions);
|
|
1753
|
+
/**
|
|
1754
|
+
* Loads the snapshot from disk if available.
|
|
1755
|
+
* Called automatically on first use.
|
|
1756
|
+
*/
|
|
1757
|
+
load(): Promise<void>;
|
|
1758
|
+
/**
|
|
1759
|
+
* Persists the current snapshot to disk for cross-run reuse.
|
|
1760
|
+
*/
|
|
1761
|
+
save(): Promise<void>;
|
|
1762
|
+
/**
|
|
1763
|
+
* Incrementally hashes all files in a directory.
|
|
1764
|
+
*
|
|
1765
|
+
* Only files whose mtime or size changed since the last snapshot
|
|
1766
|
+
* are re-read and re-hashed. Unchanged files reuse the cached hash.
|
|
1767
|
+
*
|
|
1768
|
+
* Returns a map of relative paths → hashes.
|
|
1769
|
+
*/
|
|
1770
|
+
hashDirectory(directoryPath: string): Promise<Record<string, string>>;
|
|
1771
|
+
/**
|
|
1772
|
+
* Returns how many files are in the snapshot (for diagnostics).
|
|
1773
|
+
*/
|
|
1774
|
+
get snapshotSize(): number;
|
|
1775
|
+
/**
|
|
1776
|
+
* Clears the in-memory snapshot.
|
|
1777
|
+
*/
|
|
1778
|
+
clear(): void;
|
|
1779
|
+
/**
|
|
1780
|
+
* Looks up the cached hash for `absolutePath` when its mtime and
|
|
1781
|
+
* size match the snapshot; returns `undefined` otherwise. Callers
|
|
1782
|
+
* that already have a `stat` result (e.g. `InProcessTaskHasher`)
|
|
1783
|
+
* skip an extra syscall by passing it through directly.
|
|
1784
|
+
*
|
|
1785
|
+
* The snapshot is considered loaded on first call — lazy-load is
|
|
1786
|
+
* synchronous-friendly here because the caller already performed
|
|
1787
|
+
* an async `stat` before calling this method.
|
|
1788
|
+
*/
|
|
1789
|
+
getSnapshotHash(absolutePath: string, mtimeMs: number, size: number): string | undefined;
|
|
1790
|
+
/**
|
|
1791
|
+
* Writes a fresh snapshot entry after the caller has computed the
|
|
1792
|
+
* hash. Pairs with {@link IncrementalFileHasher.getSnapshotHash}
|
|
1793
|
+
* — after a miss, the caller hashes the file and records the
|
|
1794
|
+
* result here so the next run can reuse it.
|
|
1795
|
+
*/
|
|
1796
|
+
recordSnapshot(absolutePath: string, hash: string, mtimeMs: number, size: number): void;
|
|
1797
|
+
}
|
|
1798
|
+
/**
|
|
1799
|
+
* Combines multiple lifecycle handlers into one.
|
|
1800
|
+
* Each event is forwarded to all registered handlers.
|
|
1801
|
+
*/
|
|
1802
|
+
declare class CompositeLifeCycle implements LifeCycleInterface {
|
|
1803
|
+
#private;
|
|
1804
|
+
constructor(lifeCycles: LifeCycleInterface[]);
|
|
1805
|
+
startCommand(): void;
|
|
1806
|
+
endCommand(): void;
|
|
1807
|
+
scheduleTask(task: Task): void;
|
|
1808
|
+
startTasks(tasks: Task[]): void;
|
|
1809
|
+
endTasks(taskResults: TaskResult[]): void;
|
|
1810
|
+
printTaskTerminalOutput(task: Task, status: TaskStatus, terminalOutput: string): void;
|
|
1811
|
+
printCacheMiss(task: Task, reasons: string): void;
|
|
1812
|
+
onTaskStdout(task: Task, chunk: string): void;
|
|
1813
|
+
onTaskStderr(task: Task, chunk: string): void;
|
|
1814
|
+
}
|
|
1815
|
+
/**
|
|
1816
|
+
* A lifecycle handler that logs task progress to the console.
|
|
1817
|
+
*/
|
|
1818
|
+
declare class ConsoleLifeCycle implements LifeCycleInterface {
|
|
1819
|
+
#private;
|
|
1820
|
+
constructor(verbose?: boolean);
|
|
1821
|
+
startCommand(): void;
|
|
1822
|
+
endCommand(): void;
|
|
1823
|
+
scheduleTask(task: Task): void;
|
|
1824
|
+
startTasks(tasks: Task[]): void;
|
|
1825
|
+
endTasks(taskResults: TaskResult[]): void;
|
|
1826
|
+
printTaskTerminalOutput(_task: Task, _status: TaskStatus, terminalOutput: string): void;
|
|
1827
|
+
printCacheMiss(task: Task, reasons: string): void;
|
|
1828
|
+
}
|
|
1829
|
+
/**
|
|
1830
|
+
* A no-op lifecycle handler. Useful as a default.
|
|
1831
|
+
*/
|
|
1832
|
+
declare class EmptyLifeCycle implements LifeCycleInterface {}
|
|
1833
|
+
/**
|
|
1834
|
+
* Resolved dependency entry from a lockfile.
|
|
1835
|
+
*/
|
|
1836
|
+
interface ResolvedDependency {
|
|
1837
|
+
/** The package name */
|
|
1838
|
+
name: string;
|
|
1839
|
+
/** The resolved version */
|
|
1840
|
+
version: string;
|
|
1841
|
+
}
|
|
1842
|
+
/**
|
|
1843
|
+
* Result of parsing a lockfile for a specific package.
|
|
1844
|
+
*/
|
|
1845
|
+
interface PackageLockfileHash {
|
|
1846
|
+
/** The resolved dependencies that were included in the hash */
|
|
1847
|
+
dependencies: ResolvedDependency[];
|
|
1848
|
+
/** Hash of the resolved dependencies relevant to this package */
|
|
1849
|
+
hash: string;
|
|
1850
|
+
}
|
|
1851
|
+
/**
|
|
1852
|
+
* Extracts a package name from a node_modules path.
|
|
1853
|
+
* E.g., "node_modules/@scope/name" -> "@scope/name",
|
|
1854
|
+
* "node_modules/name" -> "name",
|
|
1855
|
+
* "node_modules/.package-lock.json" -> undefined.
|
|
1856
|
+
*/
|
|
1857
|
+
declare const extractPackageName: (path: string) => string | undefined;
|
|
1858
|
+
/**
|
|
1859
|
+
* Parses package-lock.json (npm v2/v3 format) to extract resolved versions.
|
|
1860
|
+
* The v2/v3 format uses a flat "packages" map with paths like "node_modules/pkg-name".
|
|
1861
|
+
*/
|
|
1862
|
+
declare const parseNpmLockfile: (content: string) => Map<string, string>;
|
|
1863
|
+
/**
|
|
1864
|
+
* Parses pnpm-lock.yaml to extract resolved versions.
|
|
1865
|
+
* Uses a lightweight regex-based parser to avoid a YAML dependency.
|
|
1866
|
+
*/
|
|
1867
|
+
declare const parsePnpmLockfile: (content: string) => Map<string, string>;
|
|
1868
|
+
/**
|
|
1869
|
+
* Parses yarn.lock to extract resolved versions.
|
|
1870
|
+
* Works with both Yarn Classic (v1) and Berry (v2+) formats.
|
|
1871
|
+
*/
|
|
1872
|
+
declare const parseYarnLockfile: (content: string) => Map<string, string>;
|
|
1873
|
+
/**
|
|
1874
|
+
* Smart lockfile hasher that only hashes the resolved versions
|
|
1875
|
+
* of a package's actual dependencies, not the entire lockfile.
|
|
1876
|
+
*
|
|
1877
|
+
* This matches Turborepo's smart lockfile hashing behavior:
|
|
1878
|
+
* changing the lockfile only busts cache for affected packages.
|
|
1879
|
+
*
|
|
1880
|
+
* Supports:
|
|
1881
|
+
* - package-lock.json (npm v2/v3)
|
|
1882
|
+
* - pnpm-lock.yaml (pnpm)
|
|
1883
|
+
* - yarn.lock (Yarn Classic + Berry)
|
|
1884
|
+
*/
|
|
1885
|
+
declare class LockfileHasher {
|
|
1886
|
+
#private;
|
|
1887
|
+
constructor(workspaceRoot: string);
|
|
1888
|
+
/**
|
|
1889
|
+
* Computes a hash based only on the resolved dependency versions
|
|
1890
|
+
* relevant to a specific package.
|
|
1891
|
+
* @param packageJsonPath Path to the package.json (relative to workspace root)
|
|
1892
|
+
* @returns Hash of the relevant lockfile entries, or undefined if no lockfile found
|
|
1893
|
+
*/
|
|
1894
|
+
hashForPackage(packageJsonPath: string): Promise<PackageLockfileHash | undefined>;
|
|
1895
|
+
/**
|
|
1896
|
+
* Returns the type of lockfile detected, or undefined if none found.
|
|
1897
|
+
*/
|
|
1898
|
+
get lockfileType(): "npm" | "pnpm" | "yarn" | undefined;
|
|
1899
|
+
/**
|
|
1900
|
+
* Clears the cached lockfile data.
|
|
1901
|
+
*/
|
|
1902
|
+
clearCache(): void;
|
|
1903
|
+
}
|
|
1904
|
+
/**
|
|
1905
|
+
* Output formatting mode for task terminal output.
|
|
1906
|
+
*
|
|
1907
|
+
* - `interleaved` **(default)**: emit each task's buffered output as-is
|
|
1908
|
+
* — lines from parallel tasks may intermix when streamed live.
|
|
1909
|
+
* - `labeled`: prefix every line with `[project#target]` so parallel
|
|
1910
|
+
* tasks remain distinguishable.
|
|
1911
|
+
* - `grouped`: buffer each task's output and print it as a single block
|
|
1912
|
+
* bracketed by `── project#target ──` header and blank-line footer.
|
|
1913
|
+
*
|
|
1914
|
+
* Matches the three modes exposed by vite-task's `--log` flag.
|
|
1915
|
+
*/
|
|
1916
|
+
type LogMode = "grouped" | "interleaved" | "labeled";
|
|
1917
|
+
/**
|
|
1918
|
+
* A lifecycle handler that renders task terminal output per {@link LogMode}.
|
|
1919
|
+
*
|
|
1920
|
+
* Operates on the buffered `printTaskTerminalOutput` signal the orchestrator
|
|
1921
|
+
* emits at task-completion. Line-by-line streaming is the consumer's
|
|
1922
|
+
* responsibility — a streaming reporter can wrap this one and emit buffered
|
|
1923
|
+
* output at the end of each task regardless of streaming choices.
|
|
1924
|
+
*/
|
|
1925
|
+
declare class LogReporter implements LifeCycleInterface {
|
|
1926
|
+
#private;
|
|
1927
|
+
constructor(mode: LogMode, write?: (chunk: string) => void);
|
|
1928
|
+
printTaskTerminalOutput(task: Task, _status: TaskStatus, terminalOutput: string): void;
|
|
1929
|
+
endTasks(_taskResults: TaskResult[]): void;
|
|
1930
|
+
}
|
|
1931
|
+
/**
|
|
1932
|
+
* Convenience factory matching vite-task's `createLogReporter(mode)` surface.
|
|
1933
|
+
* Consumers that already compose their own lifecycle handlers can instantiate
|
|
1934
|
+
* {@link LogReporter} directly.
|
|
1935
|
+
*/
|
|
1936
|
+
declare const createLogReporter: (mode: LogMode, write?: (chunk: string) => void) => LogReporter;
|
|
1937
|
+
interface NativeFileHash {
|
|
1938
|
+
hash: string;
|
|
1939
|
+
path: string;
|
|
1940
|
+
}
|
|
1941
|
+
interface NativeTaskHashDetails {
|
|
1942
|
+
command: string;
|
|
1943
|
+
implicit_deps?: string[][];
|
|
1944
|
+
nodes: string[][];
|
|
1945
|
+
runtime?: string[][];
|
|
1946
|
+
}
|
|
1947
|
+
interface NativeTaskGraph {
|
|
1948
|
+
edges: string[][];
|
|
1949
|
+
task_ids: string[];
|
|
1950
|
+
}
|
|
1951
|
+
interface NativeCycleResult {
|
|
1952
|
+
cycle: string[];
|
|
1953
|
+
has_cycle: boolean;
|
|
1954
|
+
}
|
|
1955
|
+
interface NativeConcurrentCommandConfig {
|
|
1956
|
+
command: string;
|
|
1957
|
+
cwd?: string;
|
|
1958
|
+
env?: Record<string, string>;
|
|
1959
|
+
name?: string;
|
|
1960
|
+
shell?: boolean;
|
|
1961
|
+
stdin?: string;
|
|
1962
|
+
}
|
|
1963
|
+
interface NativeConcurrentRunnerOptions {
|
|
1964
|
+
killOthers?: string[];
|
|
1965
|
+
killSignal?: string;
|
|
1966
|
+
killTimeout?: number;
|
|
1967
|
+
maxProcesses?: number;
|
|
1968
|
+
shellPath?: string;
|
|
1969
|
+
successCondition?: string;
|
|
1970
|
+
}
|
|
1971
|
+
interface NativeProcessEvent {
|
|
1972
|
+
commandName?: string;
|
|
1973
|
+
durationMs?: number;
|
|
1974
|
+
exitCode?: number;
|
|
1975
|
+
index: number;
|
|
1976
|
+
killed?: boolean;
|
|
1977
|
+
kind: string;
|
|
1978
|
+
message?: string;
|
|
1979
|
+
text?: string;
|
|
1980
|
+
}
|
|
1981
|
+
interface NativeConcurrentCloseEvent {
|
|
1982
|
+
command: string;
|
|
1983
|
+
durationMs: number;
|
|
1984
|
+
exitCode: number;
|
|
1985
|
+
index: number;
|
|
1986
|
+
killed: boolean;
|
|
1987
|
+
name?: string;
|
|
1988
|
+
}
|
|
1989
|
+
interface NativeConcurrentRunResult {
|
|
1990
|
+
closeEvents: NativeConcurrentCloseEvent[];
|
|
1991
|
+
success: boolean;
|
|
1992
|
+
}
|
|
1993
|
+
interface NativeBindings {
|
|
1994
|
+
collectFiles: (directory: string) => string[];
|
|
1995
|
+
computeTaskHash: (details: NativeTaskHashDetails) => string;
|
|
1996
|
+
findAllCycles: (graph: NativeTaskGraph) => string[][];
|
|
1997
|
+
findBackEdges: (graph: NativeTaskGraph) => string[][];
|
|
1998
|
+
findCycle: (graph: NativeTaskGraph) => NativeCycleResult;
|
|
1999
|
+
getDependentTasks: (graph: NativeTaskGraph, taskId: string) => string[];
|
|
2000
|
+
getMainWorktreeRoot: (workspaceRoot: string) => string | undefined | null;
|
|
2001
|
+
getTransitiveDeps: (graph: NativeTaskGraph, taskId: string) => string[];
|
|
2002
|
+
hashCommand: (project: string, target: string, configuration: string | undefined, overridesJson: string) => string;
|
|
2003
|
+
hashEnvVar: (name: string, value: string) => string;
|
|
2004
|
+
hashFile: (filePath: string) => string;
|
|
2005
|
+
hashFilesBatch: (filePaths: string[], workspaceRoot: string) => NativeFileHash[];
|
|
2006
|
+
hashFilesInDirectory: (directory: string, workspaceRoot: string) => NativeFileHash[];
|
|
2007
|
+
hashString: (input: string) => string;
|
|
2008
|
+
hashStrings: (inputs: string[]) => string;
|
|
2009
|
+
isLinkedWorktree: (workspaceRoot: string) => boolean;
|
|
2010
|
+
resetWorktreeCache: () => void;
|
|
2011
|
+
runConcurrent: (commands: NativeConcurrentCommandConfig[], options: NativeConcurrentRunnerOptions, onEvent: (event: NativeProcessEvent) => void) => Promise<NativeConcurrentRunResult>;
|
|
2012
|
+
runConcurrentBatch: (commands: NativeConcurrentCommandConfig[], options: NativeConcurrentRunnerOptions) => Promise<NativeConcurrentRunResult>;
|
|
2013
|
+
topologicalSort: (graph: NativeTaskGraph) => string[];
|
|
2014
|
+
}
|
|
2015
|
+
/**
|
|
2016
|
+
* Attempts to load the native addon. Returns undefined if unavailable.
|
|
2017
|
+
* The result is cached after the first attempt.
|
|
2018
|
+
*
|
|
2019
|
+
* napi v3 outputs the .node file to the package root as
|
|
2020
|
+
* `task-runner-native.<platform>.node`. The napi-generated index.js
|
|
2021
|
+
* handles platform detection automatically.
|
|
2022
|
+
*
|
|
2023
|
+
* Uses createRequire because the napi-generated index.js is CJS.
|
|
2024
|
+
*/
|
|
2025
|
+
declare const loadNativeBindings: () => NativeBindings | undefined;
|
|
2026
|
+
/**
|
|
2027
|
+
* Returns true if the native addon is loaded and available.
|
|
2028
|
+
*/
|
|
2029
|
+
declare const isNativeAvailable: () => boolean;
|
|
2030
|
+
/**
|
|
2031
|
+
* Expands a task's `OutputSpec[]` into the concrete file list to
|
|
2032
|
+
* archive:
|
|
2033
|
+
*
|
|
2034
|
+
* - literal paths → kept as-is (the archiver recursively copies
|
|
2035
|
+
* directories, so `"dist"` captures its whole tree);
|
|
2036
|
+
* - positive globs → expanded via `fs.glob`, filtered to files only;
|
|
2037
|
+
* - negatives (`!pattern`) → applied to the combined result;
|
|
2038
|
+
* - `{ auto: true }` → pulls in `autoWrites` entries that fall inside
|
|
2039
|
+
* the workspace.
|
|
2040
|
+
*
|
|
2041
|
+
* Returns deduped, sorted workspace-relative paths so archives are
|
|
2042
|
+
* byte-reproducible across invocations.
|
|
2043
|
+
*
|
|
2044
|
+
* Silent degradation: missing literal paths, empty glob matches, and
|
|
2045
|
+
* `{ auto: true }` without tracked writes all contribute nothing
|
|
2046
|
+
* rather than throwing.
|
|
2047
|
+
*/
|
|
2048
|
+
declare const resolveOutputs: (workspaceRoot: string, outputs: OutputSpec[] | undefined, autoWrites?: ReadonlyArray<string>) => Promise<string[]>;
|
|
2049
|
+
/**
|
|
2050
|
+
* Enforces project dependency constraints on a project graph.
|
|
2051
|
+
* @param projectGraph The workspace project graph to validate.
|
|
2052
|
+
* @param constraints The constraint rules to enforce.
|
|
2053
|
+
* @returns Array of violations found. Empty means all constraints pass.
|
|
2054
|
+
*/
|
|
2055
|
+
declare const enforceProjectConstraints: (projectGraph: ProjectGraph, constraints: ConstraintsConfig) => ConstraintViolation[];
|
|
2056
|
+
/**
|
|
2057
|
+
* Compression algorithm used for artifact tarballs on the wire.
|
|
2058
|
+
* - `"gzip"` (default): tar+gzip, matches Turborepo's protocol format
|
|
2059
|
+
* and stays interop-safe with existing remote cache servers.
|
|
2060
|
+
* - `"brotli"`: tar + Node brotli (BROTLI_MODE_TEXT, quality 4) — a
|
|
2061
|
+
* solid ratio/speed trade-off for source-tree tarballs. Both upload
|
|
2062
|
+
* and download sides must agree; switching invalidates existing
|
|
2063
|
+
* remote entries (they will simply re-populate on next run).
|
|
2064
|
+
*/
|
|
2065
|
+
type RemoteCacheCompression = "brotli" | "gzip";
|
|
2066
|
+
/**
|
|
2067
|
+
* HMAC signing configuration for cache integrity.
|
|
2068
|
+
*
|
|
2069
|
+
* When set, every upload carries an `X-Artifact-Signature` header
|
|
2070
|
+
* containing the HMAC-SHA256 digest of `hash | body`. On download,
|
|
2071
|
+
* the client recomputes the HMAC and rejects any artifact whose
|
|
2072
|
+
* signature doesn't match using a constant-time comparison.
|
|
2073
|
+
*
|
|
2074
|
+
* Prevents cache poisoning in shared team environments where a
|
|
2075
|
+
* compromised cache server (or a MITM) could inject malicious
|
|
2076
|
+
* artifacts. Unsigned entries (written before signing was enabled)
|
|
2077
|
+
* are accepted only when `verifyOnDownload === false` — the default.
|
|
2078
|
+
*/
|
|
2079
|
+
interface RemoteCacheSigning {
|
|
2080
|
+
/** Shared secret. Must be at least 16 characters. */
|
|
2081
|
+
secret: string;
|
|
2082
|
+
/**
|
|
2083
|
+
* Reject downloads whose signature doesn't match or is missing.
|
|
2084
|
+
* Set to `true` once every upload on your server is signed.
|
|
2085
|
+
* @default false
|
|
2086
|
+
*/
|
|
2087
|
+
verifyOnDownload?: boolean;
|
|
2088
|
+
}
|
|
2089
|
+
/**
|
|
2090
|
+
* Options for the remote cache.
|
|
2091
|
+
*/
|
|
2092
|
+
interface RemoteCacheOptions {
|
|
2093
|
+
/**
|
|
2094
|
+
* Compression format for artifact tarballs. Defaults to `"gzip"`
|
|
2095
|
+
* for Turborepo protocol compatibility.
|
|
2096
|
+
*/
|
|
2097
|
+
compression?: RemoteCacheCompression;
|
|
2098
|
+
/**
|
|
2099
|
+
* Called when a fire-and-forget upload fails.
|
|
2100
|
+
* Since uploads are non-blocking, errors are silently swallowed by default.
|
|
2101
|
+
* Provide this callback to log or report upload failures.
|
|
2102
|
+
*/
|
|
2103
|
+
onUploadError?: (hash: string, error: unknown) => void;
|
|
2104
|
+
/** Whether to enable remote cache reads */
|
|
2105
|
+
read?: boolean;
|
|
2106
|
+
/**
|
|
2107
|
+
* HMAC-SHA256 signing for upload integrity. When set, every
|
|
2108
|
+
* uploaded artifact carries an `X-Artifact-Signature` header;
|
|
2109
|
+
* downloads with `verifyOnDownload: true` reject unsigned or
|
|
2110
|
+
* tampered payloads.
|
|
2111
|
+
*/
|
|
2112
|
+
signing?: RemoteCacheSigning;
|
|
2113
|
+
/** Team ID or namespace for cache isolation */
|
|
2114
|
+
teamId?: string;
|
|
2115
|
+
/** Request timeout in milliseconds (default: 30000) */
|
|
2116
|
+
timeout?: number;
|
|
2117
|
+
/** Authentication token for the remote cache */
|
|
2118
|
+
token?: string;
|
|
2119
|
+
/** Remote cache server URL (e.g., "https://cache.example.com") */
|
|
2120
|
+
url: string;
|
|
2121
|
+
/** Whether to enable remote cache writes */
|
|
2122
|
+
write?: boolean;
|
|
2123
|
+
}
|
|
2124
|
+
/**
|
|
2125
|
+
* HTTP-based remote cache compatible with the Turborepo remote cache protocol.
|
|
2126
|
+
*
|
|
2127
|
+
* Protocol:
|
|
2128
|
+
* - GET /v8/artifacts/{hash}?teamId={team} -> retrieve cached artifact (gzipped tar)
|
|
2129
|
+
* - PUT /v8/artifacts/{hash}?teamId={team} -> store artifact
|
|
2130
|
+
* - POST /v8/artifacts/events -> analytics (optional)
|
|
2131
|
+
*
|
|
2132
|
+
* Authentication via `Authorization: Bearer {token}` header.
|
|
2133
|
+
*
|
|
2134
|
+
* The cache entry is a gzipped tarball containing the cache directory contents
|
|
2135
|
+
* (code, terminalOutput, fingerprint.json, outputs/, .commit).
|
|
2136
|
+
*/
|
|
2137
|
+
declare class RemoteCache {
|
|
2138
|
+
#private;
|
|
2139
|
+
constructor(options: RemoteCacheOptions);
|
|
2140
|
+
/**
|
|
2141
|
+
* Retrieves a cached artifact from the remote cache.
|
|
2142
|
+
* Returns the local path to the extracted cache entry, or undefined if not found.
|
|
2143
|
+
*/
|
|
2144
|
+
retrieve(hash: string, localCacheDirectory: string): Promise<boolean>;
|
|
2145
|
+
/**
|
|
2146
|
+
* Stores a cache entry in the remote cache.
|
|
2147
|
+
*/
|
|
2148
|
+
store(hash: string, localCacheDirectory: string): Promise<boolean>;
|
|
2149
|
+
/**
|
|
2150
|
+
* Checks if an artifact exists in the remote cache without downloading it.
|
|
2151
|
+
*/
|
|
2152
|
+
exists(hash: string): Promise<boolean>;
|
|
2153
|
+
}
|
|
2154
|
+
interface CreateTaskGraphOptions {
|
|
2155
|
+
/** The project graph */
|
|
2156
|
+
projectGraph: ProjectGraph;
|
|
2157
|
+
/** Target default configurations */
|
|
2158
|
+
targetDefaults?: Record<string, Partial<TargetConfiguration>>;
|
|
2159
|
+
/** The workspace configuration */
|
|
2160
|
+
workspace: WorkspaceConfiguration;
|
|
2161
|
+
}
|
|
2162
|
+
/**
|
|
2163
|
+
* Creates a unique task ID from a target.
|
|
2164
|
+
*/
|
|
2165
|
+
declare const getTaskId: (target: TaskTarget) => string;
|
|
2166
|
+
/**
|
|
2167
|
+
* Parses a task ID into its component parts.
|
|
2168
|
+
*/
|
|
2169
|
+
declare const parseTaskId: (taskId: string) => TaskTarget;
|
|
2170
|
+
/**
|
|
2171
|
+
* Creates a task graph from a list of tasks, resolving all dependencies.
|
|
2172
|
+
*/
|
|
2173
|
+
declare const createTaskGraph: (initialTasks: Task[], options: CreateTaskGraphOptions) => TaskGraph;
|
|
2174
|
+
/**
|
|
2175
|
+
* Finds a single cycle in the task graph, if one exists.
|
|
2176
|
+
* Returns the cycle as an array of task IDs, or null if no cycle exists.
|
|
2177
|
+
*/
|
|
2178
|
+
declare const findCycle: (taskGraph: TaskGraph) => string[] | undefined;
|
|
2179
|
+
/**
|
|
2180
|
+
* Finds all cycles in the task graph.
|
|
2181
|
+
*/
|
|
2182
|
+
declare const findCycles: (taskGraph: TaskGraph) => string[][];
|
|
2183
|
+
/**
|
|
2184
|
+
* Walks the task graph in topological order (dependencies before dependents),
|
|
2185
|
+
* calling the callback for each task.
|
|
2186
|
+
*
|
|
2187
|
+
* Note: If the graph contains cycles, tasks involved in cycles will not be visited.
|
|
2188
|
+
* Use `findCycle` to detect cycles before walking if complete traversal is required.
|
|
2189
|
+
*/
|
|
2190
|
+
declare const walkTaskGraph: (taskGraph: TaskGraph, callback: (taskId: string) => void) => void;
|
|
2191
|
+
/**
|
|
2192
|
+
* Returns a reversed copy of the task graph (edges point in the opposite direction).
|
|
2193
|
+
*/
|
|
2194
|
+
declare const reverseTaskGraph: (taskGraph: TaskGraph) => TaskGraph;
|
|
2195
|
+
/**
|
|
2196
|
+
* Returns the leaf tasks (tasks with no dependencies of their own).
|
|
2197
|
+
*/
|
|
2198
|
+
declare const getLeafTasks: (taskGraph: TaskGraph) => string[];
|
|
2199
|
+
/**
|
|
2200
|
+
* Removes edges that form cycles, making the graph acyclic.
|
|
2201
|
+
* Returns a new task graph without the cycle-forming edges.
|
|
2202
|
+
*/
|
|
2203
|
+
declare const makeAcyclic: (taskGraph: TaskGraph) => TaskGraph;
|
|
2204
|
+
/**
|
|
2205
|
+
* Gets all tasks that depend on the given task (directly or transitively).
|
|
2206
|
+
*/
|
|
2207
|
+
declare const getDependentTasks: (taskGraph: TaskGraph, taskId: string) => string[];
|
|
2208
|
+
/**
|
|
2209
|
+
* Gets all tasks that the given task depends on (directly or transitively).
|
|
2210
|
+
*/
|
|
2211
|
+
declare const getTransitiveDependencies: (taskGraph: TaskGraph, taskId: string) => string[];
|
|
2212
|
+
/**
|
|
2213
|
+
* Interface for task hashers.
|
|
2214
|
+
*/
|
|
2215
|
+
interface TaskHasher {
|
|
2216
|
+
hashTask: (task: Task) => Promise<TaskHashDetails>;
|
|
2217
|
+
/**
|
|
2218
|
+
* Rehashes a single file bypassing any in-memory cache. Optional to keep
|
|
2219
|
+
* external/custom hashers backward compatible; the orchestrator skips
|
|
2220
|
+
* self-modifying-task detection when the implementation is absent.
|
|
2221
|
+
*/
|
|
2222
|
+
rehashFile?: (filePath: string) => Promise<string | undefined>;
|
|
2223
|
+
}
|
|
2224
|
+
/**
|
|
2225
|
+
* Options for creating an InProcessTaskHasher.
|
|
2226
|
+
*/
|
|
2227
|
+
interface TaskHasherOptions {
|
|
2228
|
+
/**
|
|
2229
|
+
* When true, scan each task's resolved command for `$VAR`/`${VAR}`
|
|
2230
|
+
* references and auto-fingerprint them. Catches the common case of
|
|
2231
|
+
* a script reading `$VERCEL_URL` or `${NEXT_PUBLIC_API}` without
|
|
2232
|
+
* the user remembering to declare it in `envVars`/`globalEnv`.
|
|
2233
|
+
* @default false
|
|
2234
|
+
*/
|
|
2235
|
+
autoEnvVars?: boolean;
|
|
2236
|
+
/** Additional environment variables to include in hash */
|
|
2237
|
+
envVars?: string[];
|
|
2238
|
+
/**
|
|
2239
|
+
* Enable framework environment variable inference.
|
|
2240
|
+
* When true, auto-detects frameworks and includes their public
|
|
2241
|
+
* env var prefixes in the task hash.
|
|
2242
|
+
* @default false
|
|
2243
|
+
*/
|
|
2244
|
+
frameworkInference?: boolean;
|
|
2245
|
+
/**
|
|
2246
|
+
* Global environment variables that invalidate all task hashes.
|
|
2247
|
+
*/
|
|
2248
|
+
globalEnv?: string[];
|
|
2249
|
+
/**
|
|
2250
|
+
* Global input files that invalidate all task hashes when changed.
|
|
2251
|
+
* These are workspace-root-relative paths (e.g., "pnpm-lock.yaml").
|
|
2252
|
+
*/
|
|
2253
|
+
globalInputs?: string[];
|
|
2254
|
+
/**
|
|
2255
|
+
* Optional persistent mtime/size-indexed file snapshot. When set,
|
|
2256
|
+
* `#hashFile` consults the snapshot first and only re-reads file
|
|
2257
|
+
* contents when the file's mtime or size has changed since the
|
|
2258
|
+
* previous run. Cuts cold-cache fingerprint time dramatically on
|
|
2259
|
+
* large workspaces where most source files don't change run-to-run.
|
|
2260
|
+
*
|
|
2261
|
+
* The caller is responsible for `load()`ing the snapshot before
|
|
2262
|
+
* using the hasher and `save()`ing it after the run completes.
|
|
2263
|
+
*/
|
|
2264
|
+
incrementalHasher?: IncrementalFileHasher;
|
|
2265
|
+
/** Named input definitions */
|
|
2266
|
+
namedInputs?: NamedInputs;
|
|
2267
|
+
/** Project configurations keyed by project name */
|
|
2268
|
+
projects: Record<string, ProjectConfiguration>;
|
|
2269
|
+
/**
|
|
2270
|
+
* Enable smart lockfile hashing.
|
|
2271
|
+
* When true, instead of hashing the entire lockfile, only the resolved
|
|
2272
|
+
* versions of a package's actual dependencies are hashed.
|
|
2273
|
+
* This means changing the lockfile only busts cache for affected packages.
|
|
2274
|
+
*
|
|
2275
|
+
* Matches Turborepo's smart lockfile hashing behavior.
|
|
2276
|
+
* @default false
|
|
2277
|
+
*/
|
|
2278
|
+
smartLockfileHashing?: boolean;
|
|
2279
|
+
/** Target default configurations */
|
|
2280
|
+
targetDefaults?: Record<string, Partial<TargetConfiguration>>;
|
|
2281
|
+
/** The workspace root directory */
|
|
2282
|
+
workspaceRoot: string;
|
|
2283
|
+
}
|
|
2284
|
+
/**
|
|
2285
|
+
* Computes hashes for tasks based on their inputs.
|
|
2286
|
+
* Used to determine if a cached result can be reused.
|
|
2287
|
+
*/
|
|
2288
|
+
declare class InProcessTaskHasher implements TaskHasher {
|
|
2289
|
+
#private;
|
|
2290
|
+
constructor(options: TaskHasherOptions);
|
|
2291
|
+
hashTask(task: Task): Promise<TaskHashDetails>;
|
|
2292
|
+
clearCache(): void;
|
|
2293
|
+
/**
|
|
2294
|
+
* Reads `filePath` fresh and returns its content hash, bypassing the
|
|
2295
|
+
* in-memory cache used during the initial `hashTask` pass.
|
|
2296
|
+
*
|
|
2297
|
+
* Used to detect tasks that modify their own tracked inputs: compare
|
|
2298
|
+
* a pre-execution hash (from `task.hashDetails.nodes`) against the
|
|
2299
|
+
* post-execution result of this method.
|
|
2300
|
+
* @param filePath Absolute path to the file.
|
|
2301
|
+
* @returns The fresh xxh3 hash, or `undefined` if the file cannot be read.
|
|
2302
|
+
*/
|
|
2303
|
+
rehashFile(filePath: string): Promise<string | undefined>;
|
|
2304
|
+
}
|
|
2305
|
+
/**
|
|
2306
|
+
* Computes the final hash for a task from its hash details.
|
|
2307
|
+
* Uses native Rust xxh3-128 when available, otherwise pure TS xxh3-ts.
|
|
2308
|
+
* Both produce identical xxh3-128 hashes, ensuring cache compatibility
|
|
2309
|
+
* regardless of whether the native addon is loaded.
|
|
2310
|
+
*/
|
|
2311
|
+
declare const computeTaskHash: (hashDetails: TaskHashDetails) => string;
|
|
2312
|
+
/**
|
|
2313
|
+
* Options for partitioning tasks across CI runners.
|
|
2314
|
+
*/
|
|
2315
|
+
interface PartitionOptions {
|
|
2316
|
+
/** 1-based partition index (e.g., 1 for the first partition) */
|
|
2317
|
+
index: number;
|
|
2318
|
+
/** Total number of partitions */
|
|
2319
|
+
total: number;
|
|
2320
|
+
}
|
|
2321
|
+
/**
|
|
2322
|
+
* Parses a partition string like "1/4" into PartitionOptions.
|
|
2323
|
+
* Also supports the VIS_PARTITION environment variable as fallback.
|
|
2324
|
+
*/
|
|
2325
|
+
declare const parsePartition: (value?: string) => PartitionOptions | undefined;
|
|
2326
|
+
/**
|
|
2327
|
+
* Manages the scheduling order of tasks based on dependencies,
|
|
2328
|
+
* parallelism constraints, and estimated execution times.
|
|
2329
|
+
*/
|
|
2330
|
+
declare class TaskScheduler {
|
|
2331
|
+
#private;
|
|
2332
|
+
/**
|
|
2333
|
+
* Partitions a list of tasks for distributed CI execution.
|
|
2334
|
+
* Tasks are sorted by ID for deterministic distribution, then split
|
|
2335
|
+
* using ceiling division so partitions differ by at most one task.
|
|
2336
|
+
* @param tasks The full list of tasks to partition
|
|
2337
|
+
* @param partition The partition configuration (1-based index and total)
|
|
2338
|
+
* @returns The subset of tasks assigned to this partition
|
|
2339
|
+
*/
|
|
2340
|
+
static partitionTasks(tasks: Task[], partition: PartitionOptions): Task[];
|
|
2341
|
+
constructor(taskGraph: TaskGraph, projectGraph: ProjectGraph, maxParallel?: number);
|
|
2342
|
+
/**
|
|
2343
|
+
* Returns the next batch of tasks that are ready to execute.
|
|
2344
|
+
*/
|
|
2345
|
+
getNextBatch(): Task[];
|
|
2346
|
+
startTask(taskId: string): void;
|
|
2347
|
+
completeTask(taskId: string): void;
|
|
2348
|
+
isComplete(): boolean;
|
|
2349
|
+
get remainingCount(): number;
|
|
2350
|
+
get runningCount(): number;
|
|
2351
|
+
}
|
|
2352
|
+
/**
|
|
2353
|
+
* Options for the TaskOrchestrator.
|
|
2354
|
+
*/
|
|
2355
|
+
interface TaskOrchestratorOptions {
|
|
2356
|
+
/**
|
|
2357
|
+
* Tasks marked `always: true` to run after the main task graph
|
|
2358
|
+
* completes. Run sequentially, in declaration order, even if the
|
|
2359
|
+
* main run failed or was aborted (SIGINT skips them — that's an
|
|
2360
|
+
* explicit user request to stop). Skipped if their `when` clause
|
|
2361
|
+
* doesn't match.
|
|
2362
|
+
*/
|
|
2363
|
+
alwaysTasks?: Task[];
|
|
2364
|
+
autoFingerprint?: boolean;
|
|
2365
|
+
cache: Cache;
|
|
2366
|
+
cacheDiagnostics?: boolean;
|
|
2367
|
+
captureOutput?: boolean;
|
|
2368
|
+
dryRun?: boolean;
|
|
2369
|
+
fingerprintEnvPatterns?: string[];
|
|
2370
|
+
lifeCycle: LifeCycleInterface;
|
|
2371
|
+
remoteCache?: RemoteCache;
|
|
2372
|
+
resolveCommand?: (task: Task) => string | undefined;
|
|
2373
|
+
scheduler: TaskScheduler;
|
|
2374
|
+
skipCache?: boolean;
|
|
2375
|
+
summarize?: boolean;
|
|
2376
|
+
taskExecutor: TaskExecutor;
|
|
2377
|
+
taskGraph?: TaskGraph;
|
|
2378
|
+
taskHasher: TaskHasher;
|
|
2379
|
+
untrackedEnvVars?: string[];
|
|
2380
|
+
/**
|
|
2381
|
+
* Context used to evaluate per-task `when` conditions. Defaults
|
|
2382
|
+
* to the live process state — `process.env`, `process.platform`,
|
|
2383
|
+
* git branch read from `workspaceRoot`. Override in tests.
|
|
2384
|
+
*/
|
|
2385
|
+
whenContext?: WhenContext;
|
|
2386
|
+
workspaceRoot: string;
|
|
2387
|
+
}
|
|
2388
|
+
/**
|
|
2389
|
+
* Orchestrates the execution of tasks, handling caching,
|
|
2390
|
+
* scheduling, and lifecycle events.
|
|
2391
|
+
*/
|
|
2392
|
+
declare class TaskOrchestrator {
|
|
2393
|
+
#private;
|
|
2394
|
+
constructor(options: TaskOrchestratorOptions);
|
|
2395
|
+
run(): Promise<TaskResults>;
|
|
2396
|
+
}
|
|
2397
|
+
/**
|
|
2398
|
+
* Minimal virtual terminal buffer that processes ANSI escape sequences
|
|
2399
|
+
* for cursor movement and line erasure. This allows PTY output from
|
|
2400
|
+
* interactive tools (inquirer, etc.) to render correctly by updating
|
|
2401
|
+
* lines in place rather than always appending.
|
|
2402
|
+
*
|
|
2403
|
+
* Supported sequences:
|
|
2404
|
+
* - \r carriage return (cursor to column 0)
|
|
2405
|
+
* - \n line feed (new line)
|
|
2406
|
+
* - \x1b[nA cursor up n lines
|
|
2407
|
+
* - \x1b[nB cursor down n lines
|
|
2408
|
+
* - \x1b[nC cursor forward n columns
|
|
2409
|
+
* - \x1b[nD cursor back n columns
|
|
2410
|
+
* - \x1b[nG cursor to column n
|
|
2411
|
+
* - \x1b[r;cH cursor position
|
|
2412
|
+
* - \x1b[K erase from cursor to end of line (0K, 1K, 2K)
|
|
2413
|
+
* - \x1b[J erase from cursor to end of display (0J, 1J, 2J)
|
|
2414
|
+
* - \x1b[...m SGR (colors/styles) — passed through into output
|
|
2415
|
+
*/
|
|
2416
|
+
declare class TerminalBuffer {
|
|
2417
|
+
#private;
|
|
2418
|
+
constructor(maxBytes?: number);
|
|
2419
|
+
/**
|
|
2420
|
+
* Process raw PTY output data.
|
|
2421
|
+
*/
|
|
2422
|
+
write(data: string): void;
|
|
2423
|
+
/** Get the current buffer content as a string. */
|
|
2424
|
+
toString(): string;
|
|
2425
|
+
}
|
|
2426
|
+
/**
|
|
2427
|
+
* Result of a tracked task execution.
|
|
2428
|
+
*/
|
|
2429
|
+
interface TrackedExecutionResult {
|
|
2430
|
+
/** File accesses recorded during execution */
|
|
2431
|
+
accesses: FileAccess[];
|
|
2432
|
+
/** The command exit code */
|
|
2433
|
+
code: number;
|
|
2434
|
+
/** The command stdout + stderr output */
|
|
2435
|
+
terminalOutput: string;
|
|
2436
|
+
}
|
|
2437
|
+
/**
|
|
2438
|
+
* A task executor that tracks file accesses during command execution.
|
|
2439
|
+
*
|
|
2440
|
+
* Tracking strategies (in priority order):
|
|
2441
|
+
* 1. **Linux**: strace-based syscall interception (most complete)
|
|
2442
|
+
* 2. **macOS/Windows**: Node.js preload script that patches `fs` module
|
|
2443
|
+
* (works for Node.js processes, not native binaries)
|
|
2444
|
+
* 3. **Fallback**: No tracking (accesses array will be empty)
|
|
2445
|
+
*/
|
|
2446
|
+
declare class TrackedTaskExecutor {
|
|
2447
|
+
#private;
|
|
2448
|
+
constructor(workspaceRoot: string);
|
|
2449
|
+
/**
|
|
2450
|
+
* Returns true if file access tracking is supported on the current platform.
|
|
2451
|
+
* strace tracking (Linux) or preload script (any Node.js process).
|
|
2452
|
+
*/
|
|
2453
|
+
get isTrackingSupported(): boolean;
|
|
2454
|
+
/**
|
|
2455
|
+
* Returns true if the platform supports full syscall-level tracking (strace).
|
|
2456
|
+
*/
|
|
2457
|
+
get isStraceSupported(): boolean;
|
|
2458
|
+
/**
|
|
2459
|
+
* Executes a task command and tracks all file system accesses.
|
|
2460
|
+
*
|
|
2461
|
+
* On Linux, uses strace for comprehensive tracking.
|
|
2462
|
+
* On other platforms, uses a Node.js preload script (for Node processes).
|
|
2463
|
+
*/
|
|
2464
|
+
execute(task: Task, options: TaskExecutionOptions, command: string): Promise<TrackedExecutionResult>;
|
|
2465
|
+
/**
|
|
2466
|
+
* Kills all active child processes. Called on abort/signal to prevent orphans.
|
|
2467
|
+
*/
|
|
2468
|
+
killAll(): void;
|
|
2469
|
+
}
|
|
2470
|
+
/**
|
|
2471
|
+
* Hashes a file's content using xxh3-128.
|
|
2472
|
+
* Returns undefined if the file cannot be read.
|
|
2473
|
+
*/
|
|
2474
|
+
declare const hashFile: (filePath: string) => Promise<string | undefined>;
|
|
2475
|
+
/**
|
|
2476
|
+
* Hashes one or more string values using xxh3-128.
|
|
2477
|
+
*/
|
|
2478
|
+
declare const hashStrings: (...values: string[]) => string;
|
|
2479
|
+
/**
|
|
2480
|
+
* Sorts an object's keys for deterministic serialization.
|
|
2481
|
+
*/
|
|
2482
|
+
declare const sortObjectKeys: (object: Record<string, unknown>) => Record<string, unknown>;
|
|
2483
|
+
/**
|
|
2484
|
+
* Recursively collects all file paths in a directory,
|
|
2485
|
+
* skipping directories in the ignored set.
|
|
2486
|
+
*
|
|
2487
|
+
* Tracks visited real paths to prevent infinite loops from symlink cycles.
|
|
2488
|
+
*/
|
|
2489
|
+
declare const collectFiles: (directory: string, ignoredDirectories: Set<string>, visitedRealPaths?: Set<string>) => Promise<string[]>;
|
|
2490
|
+
/**
|
|
2491
|
+
* Resolves the working directory for a task.
|
|
2492
|
+
*/
|
|
2493
|
+
declare const resolveTaskCwd: (workspaceRoot: string, task: Task) => string;
|
|
2494
|
+
/**
|
|
2495
|
+
* Creates a failure TaskResult from an error.
|
|
2496
|
+
*/
|
|
2497
|
+
declare const createFailureResult: (task: Task, error: unknown, startTime: number) => TaskResult;
|
|
2498
|
+
declare const readPackageDeps: (packageJsonPath: string, options?: {
|
|
2499
|
+
optional?: boolean;
|
|
2500
|
+
peer?: boolean;
|
|
2501
|
+
}) => Promise<Set<string> | undefined>;
|
|
2502
|
+
/**
|
|
2503
|
+
* Generates a unique ID for temporary files/directories.
|
|
2504
|
+
* Not cryptographically secure — for cache entry naming only.
|
|
2505
|
+
*/
|
|
2506
|
+
declare const uniqueId: () => string;
|
|
2507
|
+
export { type AffectedOptions, type AffectedResult, type AffectedScope, Cache, type CacheMissReason, type CacheOptions, type CachedResult, type ChromeTraceEvent, CompositeLifeCycle, type ConcurrentCloseEvent, type ConcurrentCommandConfig, type ConcurrentCommandInput, type ConcurrentRunResult, type ConcurrentRunnerOptions, ConsoleLifeCycle, type ConstraintViolation, type ConstraintsConfig, DEFAULT_CACHE_DIRECTORY_NAME, type DependencyKindRules, type DependencyType, type DetectedFramework, EmptyLifeCycle, type EnvMatcher, type EnvironmentInput, type ExternalDependencyInput, type FileAccess, FileAccessTracker, type FileSetBase, type FileSetInput, type FileSetPattern, type FileSnapshot, FingerprintManager, type GraphFormat, type GraphJson, type GraphVisualizerOptions, InProcessTaskHasher, IncrementalFileHasher, type IncrementalHasherOptions, type InputDefinition, type InputHandlerOptions, type LifeCycleInterface, LockfileHasher, type LogMode, LogReporter, type NamedInputs, type NodePlatform, type OutputSpec, type PackageLockfileHash, type ParseCommandsOptions, type PartitionOptions, type ProcessEvent, type ProjectConfiguration, type ProjectGraph, type ProjectGraphDependency, type ProjectGraphProjectNode, RemoteCache, type RemoteCacheCompression, type RemoteCacheOptions, type RemoteCacheSigning, type ResolvedDependency, type RestartOptions, type RunSummary, type RuntimeInput, type TagRelationships, type TargetConfiguration, type TargetDependencyConfig, type Task, type TaskExecutionOptions, type TaskExecutor, type TaskFingerprint, type TaskGraph, type TaskHashDetails, type TaskHasher, type TaskHasherOptions, TaskOrchestrator, type TaskOrchestratorOptions, type TaskPriority, type TaskResult, type TaskResults, type TaskRunnerContext, type TaskRunnerOptions, TaskScheduler, type TaskStatus, type TaskSummary, type TaskTarget, type TasksRunner, type TeardownOptions, TerminalBuffer, type TokenContext, type TrackedExecutionResult, TrackedTaskExecutor, type TrackingResult, type TypeBoundaries, type WhenCondition, type WhenContext, type WorkspaceConfiguration, buildForwardDependencyMap, buildReverseDependencyMap, collectFiles, computeTaskHash, createFailureResult, createInputHandler, createLogReporter, createTaskGraph, defaultTaskRunner, detectFrameworks, detectScriptShell, enforceProjectConstraints, evaluateWhen, expandAffected, expandArguments, expandShortcut, expandTokens, expandTokensInString, expandWildcard, explainWhen, extractPackageName, filterAffectedTasks, findCycle, findCycles, formatCacheSize, formatTimingTable, generatePreloadScript, generateRunSummary, getAffectedProjects, getChangedFiles, getCurrentBranch, getDependentTasks, getFrameworkEnvVariables, getLastRunSummaryPath, getLeafTasks, getTaskId, getTransitiveDependencies, hashFile, hashStrings, inferFrameworkEnvPatterns, isNativeAvailable, loadNativeBindings, logTimings, makeAcyclic, parseCacheSize, parseCommands, parseNpmLockfile, parsePartition, parsePnpmLockfile, parseTaskId, parseYarnLockfile, projectGraphToDot, readLastRunSummary, readPackageDeps, resetBranchCache, resolveOutputs, resolveTaskCwd, reverseTaskGraph, runConcurrentFallback, runConcurrently, runTeardown, sortObjectKeys, stripQuotes, toChromeTrace, toGraphAscii, toGraphHtml, toGraphJson, toGraphvizDot, uniqueId, walkTaskGraph, withRestart, writeChromeTrace, writeLastRunSummary, writeRunSummary };
|