@visulima/task-runner 1.0.0-alpha.8 → 1.0.0-alpha.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +3 -1
  3. package/dist/index.d.ts +791 -205
  4. package/dist/index.js +28 -20
  5. package/dist/packem_chunks/index.js +5593 -0
  6. package/dist/packem_shared/{Cache-CWaX_c8U.js → Cache-CbhoA268.js} +151 -10
  7. package/dist/packem_shared/{FileAccessTracker-CQ5Ot7Hd.js → FileAccessTracker-D8zIURPU.js} +1 -1
  8. package/dist/packem_shared/{FingerprintManager-CV7U4f4f.js → FingerprintManager-78DjwWQ4.js} +1 -1
  9. package/dist/packem_shared/HttpRemoteCache-BTXUBH7t.js +290 -0
  10. package/dist/packem_shared/INPUT_URI_SCHEMES-DRm76YI5.js +69 -0
  11. package/dist/packem_shared/{IncrementalFileHasher-BRS76-mb.js → IncrementalFileHasher-BBhVK491.js} +1 -1
  12. package/dist/packem_shared/ReapiRemoteCache-vgRxDMmu.js +1012 -0
  13. package/dist/packem_shared/{TaskOrchestrator-UCMHCx8c.js → TaskOrchestrator-CdRaQhTO.js} +34 -11
  14. package/dist/packem_shared/{TrackedTaskExecutor-CFPpQfXF.js → TrackedTaskExecutor-CWSMfHAW.js} +2 -2
  15. package/dist/packem_shared/V2_ROOT-DKBLxKo4.js +14 -0
  16. package/dist/packem_shared/actionDigestForTaskHash-BRE-9MT6.js +121 -0
  17. package/dist/packem_shared/archive-CnggHWb-.js +152 -0
  18. package/dist/packem_shared/{collectFiles-ClXHnHhg.js → collectFiles-cc1gokGU.js} +2 -1
  19. package/dist/packem_shared/{computeTaskHash-B5APHW7e.js → computeTaskHash-DHoBJ_-V.js} +10 -4
  20. package/dist/packem_shared/containsBlob-CwGB0a_q.js +125 -0
  21. package/dist/packem_shared/{createTaskGraph-B5YrfAMx.js → createTaskGraph-Bwl4hwAf.js} +17 -0
  22. package/dist/packem_shared/{defaultTaskRunner-DzR0ld8F.js → defaultTaskRunner-BaX4ZbFv.js} +24 -13
  23. package/dist/packem_shared/{detectFrameworks-CeFzKE6J.js → detectFrameworks-D7nyTc-o.js} +1 -1
  24. package/dist/packem_shared/{detectScriptShell-CR-xXKA4.js → detectScriptShell-CzxCM9-t.js} +1 -1
  25. package/dist/packem_shared/digestBuffer-CPdI2E1d.js +48 -0
  26. package/dist/packem_shared/{expandArguments-0AwD2BIA.js → expandArguments-Ba-hHYff.js} +2 -1
  27. package/dist/packem_shared/{expandTokensInString-C03AGAjh.js → expandTokensInString-Bb7nYehP.js} +2 -1
  28. package/dist/packem_shared/{extractPackageName-CbVNW-dr.js → extractPackageName-CMHjqGj_.js} +1 -1
  29. package/dist/packem_shared/{generateRunSummary-BE1jnQ3H.js → generateRunSummary-Bah7CFay.js} +1 -1
  30. package/dist/packem_shared/{getCurrentBranch-DsKPDoVj.js → getCurrentBranch-DVNikt0P.js} +11 -8
  31. package/dist/packem_shared/getMainWorktreeRoot-iBqToQJ4.js +114 -0
  32. package/dist/packem_shared/{parseCommands-CJ16ohOB.js → parseCommands-DDdIxaH5.js} +3 -3
  33. package/dist/packem_shared/resolveCacheMode-CsmHT_0o.js +21 -0
  34. package/dist/packem_shared/{runConcurrently-CmfC4r-f.js → runConcurrently-BCGQ9fJl.js} +1 -1
  35. package/dist/packem_shared/shell-quote-DWJJbt21.js +3 -0
  36. package/dist/packem_shared/{utils-zO0ZRgtf.js → utils-Bmnj-H2J.js} +4 -1
  37. package/index.js +52 -52
  38. package/package.json +23 -10
  39. package/dist/packem_shared/RemoteCache-DSU3lc87.js +0 -219
  40. package/dist/packem_shared/archive-UQHAnZUa.js +0 -102
@@ -1,10 +1,11 @@
1
- import { d as resolveTaskCwd, a as createFailureResult, e as createXxh3Hasher } from './utils-zO0ZRgtf.js';
1
+ import { d as resolveTaskCwd, a as createFailureResult, e as createXxh3Hasher } from './utils-Bmnj-H2J.js';
2
2
  import { resolve, join } from '@visulima/path';
3
- import { FingerprintManager } from './FingerprintManager-CV7U4f4f.js';
4
- import { generateRunSummary, writeLastRunSummary, writeRunSummary } from './generateRunSummary-BE1jnQ3H.js';
5
- import { computeTaskHash } from './computeTaskHash-B5APHW7e.js';
6
- import { TrackedTaskExecutor } from './TrackedTaskExecutor-CFPpQfXF.js';
7
- import { getCurrentBranch, evaluateWhen, explainWhen } from './getCurrentBranch-DsKPDoVj.js';
3
+ import { retrieveByTaskHash, storeByTaskHash } from './actionDigestForTaskHash-BRE-9MT6.js';
4
+ import { FingerprintManager } from './FingerprintManager-78DjwWQ4.js';
5
+ import { generateRunSummary, writeLastRunSummary, writeRunSummary } from './generateRunSummary-Bah7CFay.js';
6
+ import { computeTaskHash } from './computeTaskHash-DHoBJ_-V.js';
7
+ import { TrackedTaskExecutor } from './TrackedTaskExecutor-CWSMfHAW.js';
8
+ import { getCurrentBranch, evaluateWhen, explainWhen } from './getCurrentBranch-DVNikt0P.js';
8
9
 
9
10
  const hashFingerprint = (fingerprint) => {
10
11
  const hash = createXxh3Hasher();
@@ -26,6 +27,20 @@ const hashFingerprint = (fingerprint) => {
26
27
  }
27
28
  return hash.digest();
28
29
  };
30
+ const detectWarnings = (patterns, output) => {
31
+ if (!patterns || patterns.length === 0 || !output) {
32
+ return false;
33
+ }
34
+ for (const source of patterns) {
35
+ try {
36
+ if (new RegExp(source).test(output)) {
37
+ return true;
38
+ }
39
+ } catch {
40
+ }
41
+ }
42
+ return false;
43
+ };
29
44
  const createDeferred = () => {
30
45
  let resolve2;
31
46
  const promise = new Promise((r) => {
@@ -50,6 +65,7 @@ class TaskOrchestrator {
50
65
  #cacheDiagnostics;
51
66
  #resolveCommand;
52
67
  #remoteCache;
68
+ #onRemoteUploadError;
53
69
  #dryRun;
54
70
  #summarize;
55
71
  #taskGraph;
@@ -77,6 +93,7 @@ class TaskOrchestrator {
77
93
  this.#cacheDiagnostics = options.cacheDiagnostics ?? false;
78
94
  this.#resolveCommand = options.resolveCommand ?? void 0;
79
95
  this.#remoteCache = options.remoteCache ?? void 0;
96
+ this.#onRemoteUploadError = options.onRemoteUploadError ?? void 0;
80
97
  this.#dryRun = options.dryRun ?? false;
81
98
  this.#summarize = options.summarize ?? false;
82
99
  this.#taskGraph = options.taskGraph ?? void 0;
@@ -214,7 +231,7 @@ class TaskOrchestrator {
214
231
  return this.#applyCachedResult(task, cachedResult, startTime);
215
232
  }
216
233
  if (this.#remoteCache) {
217
- const retrieved = await this.#remoteCache.retrieve(hash, this.#cache.cacheDirectory);
234
+ const retrieved = await retrieveByTaskHash(this.#remoteCache, hash, this.#cache.cacheDirectory);
218
235
  if (retrieved) {
219
236
  const remoteCached = await this.#cache.get(hash);
220
237
  if (remoteCached) {
@@ -227,7 +244,7 @@ class TaskOrchestrator {
227
244
  }
228
245
  const result = await this.#executeTask(task, startTime);
229
246
  if (result.code === 0 && task.cache !== false && task.hash && this.#remoteCache) {
230
- this.#remoteCache.store(task.hash, this.#cache.cacheDirectory).catch(() => {
247
+ storeByTaskHash(this.#remoteCache, task.hash, this.#cache.cacheDirectory, this.#onRemoteUploadError).catch(() => {
231
248
  });
232
249
  }
233
250
  return result;
@@ -262,7 +279,7 @@ class TaskOrchestrator {
262
279
  return this.#executeTaskWithTracking(task, startTime);
263
280
  }
264
281
  async #applyCachedResult(task, cachedResult, startTime) {
265
- const restored = await this.#cache.restoreOutputs(cachedResult.hash, task.outputs);
282
+ const restored = await this.#cache.restoreOutputs(cachedResult.hash, task.outputs, task.cacheRestore);
266
283
  const status = restored ? "local-cache" : "local-cache-kept-existing";
267
284
  const result = {
268
285
  code: cachedResult.code,
@@ -281,16 +298,19 @@ class TaskOrchestrator {
281
298
  captureOutput: this.#captureOutput,
282
299
  cwd: resolveTaskCwd(this.#workspaceRoot, task)
283
300
  });
301
+ const hadWarnings = code === 0 && detectWarnings(task.warningPattern, terminalOutput);
284
302
  const result = {
285
303
  code,
286
304
  endTime: Date.now(),
305
+ hadWarnings: hadWarnings || void 0,
287
306
  startTime,
288
307
  status: code === 0 ? "success" : "failure",
289
308
  task,
290
309
  terminalOutput
291
310
  };
292
311
  this.#results.set(task.id, result);
293
- if (code === 0 && task.cache !== false && task.hash) {
312
+ const skipCacheOnWarning = hadWarnings && task.cacheOnWarning === false;
313
+ if (code === 0 && task.cache !== false && task.hash && !skipCacheOnWarning) {
294
314
  const modified = await this.#detectSelfModifiedInputs(task);
295
315
  if (modified.length > 0) {
296
316
  result.selfModified = true;
@@ -381,16 +401,19 @@ class TaskOrchestrator {
381
401
  this.#untrackedEnvVars
382
402
  );
383
403
  }
404
+ const hadWarnings = code === 0 && detectWarnings(task.warningPattern, terminalOutput);
384
405
  const result = {
385
406
  code,
386
407
  endTime: Date.now(),
408
+ hadWarnings: hadWarnings || void 0,
387
409
  startTime,
388
410
  status: code === 0 ? "success" : "failure",
389
411
  task,
390
412
  terminalOutput
391
413
  };
392
414
  this.#results.set(task.id, result);
393
- if (code === 0 && task.cache !== false && fingerprint) {
415
+ const skipCacheOnWarning = hadWarnings && task.cacheOnWarning === false;
416
+ if (code === 0 && task.cache !== false && fingerprint && !skipCacheOnWarning) {
394
417
  const modified = this.#detectSelfModifiedFingerprint(fingerprint);
395
418
  const emptyFingerprintReason = this.#describeEmptyFingerprint(fingerprint, usedRealTracker, trackerAccessCount);
396
419
  if (modified.length > 0) {
@@ -27,8 +27,8 @@ const {
27
27
  rm
28
28
  } = __cjs_getBuiltinModule("node:fs/promises");
29
29
  import { join } from '@visulima/path';
30
- import { FileAccessTracker, generatePreloadScript } from './FileAccessTracker-CQ5Ot7Hd.js';
31
- import { u as uniqueId } from './utils-zO0ZRgtf.js';
30
+ import { FileAccessTracker, generatePreloadScript } from './FileAccessTracker-D8zIURPU.js';
31
+ import { u as uniqueId } from './utils-Bmnj-H2J.js';
32
32
 
33
33
  class TrackedTaskExecutor {
34
34
  #tracker;
@@ -0,0 +1,14 @@
1
+ import { join } from '@visulima/path';
2
+
3
+ const V2_ROOT = "v2";
4
+ const V2_CAS = "cas";
5
+ const V2_AC = "ac";
6
+ const V2_INDEX = "task-hash-index";
7
+ const V2_TMP = "tmp";
8
+ const shard = (hash) => hash.slice(0, 2);
9
+ const casBlobPath = (root, hash) => join(root, V2_ROOT, V2_CAS, shard(hash), hash);
10
+ const acEntryPath = (root, actionHash) => join(root, V2_ROOT, V2_AC, shard(actionHash), `${actionHash}.json`);
11
+ const taskHashIndexPath = (root, taskHash) => join(root, V2_ROOT, V2_INDEX, shard(taskHash), taskHash);
12
+ const tmpDirectory = (root) => join(root, V2_ROOT, V2_TMP);
13
+
14
+ export { V2_AC, V2_CAS, V2_INDEX, V2_ROOT, V2_TMP, acEntryPath, casBlobPath, shard, taskHashIndexPath, tmpDirectory };
@@ -0,0 +1,121 @@
1
+ import { createRequire as __cjs_createRequire } from "node:module";
2
+
3
+ const __cjs_require = __cjs_createRequire(import.meta.url);
4
+
5
+ const __cjs_getProcess = typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" ? globalThis.process : process;
6
+
7
+ const __cjs_getBuiltinModule = (module) => {
8
+ // Check if we're in Node.js and version supports getBuiltinModule
9
+ if (typeof __cjs_getProcess !== "undefined" && __cjs_getProcess.versions && __cjs_getProcess.versions.node) {
10
+ const [major, minor] = __cjs_getProcess.versions.node.split(".").map(Number);
11
+ // Node.js 20.16.0+ and 22.3.0+
12
+ if (major > 22 || (major === 22 && minor >= 3) || (major === 20 && minor >= 16)) {
13
+ return __cjs_getProcess.getBuiltinModule(module);
14
+ }
15
+ }
16
+ // Fallback to createRequire
17
+ return __cjs_require(module);
18
+ };
19
+
20
+ const {
21
+ createHash,
22
+ randomUUID
23
+ } = __cjs_getBuiltinModule("node:crypto");
24
+ const {
25
+ createReadStream
26
+ } = __cjs_getBuiltinModule("node:fs");
27
+ const {
28
+ mkdir,
29
+ rm,
30
+ stat
31
+ } = __cjs_getBuiltinModule("node:fs/promises");
32
+ import { join } from '@visulima/path';
33
+ import { e as extractTarGz, c as createTarGz } from './archive-CnggHWb-.js';
34
+
35
+ const TARBALL_OUTPUT_PATH = "vis-entry.tar.gz";
36
+ const actionDigestForTaskHash = (taskHash) => {
37
+ const key = `vis-task:${taskHash}`;
38
+ return {
39
+ hash: createHash("sha256").update(Buffer.from(key, "utf8")).digest("hex"),
40
+ sizeBytes: 0
41
+ };
42
+ };
43
+ const containsByTaskHash = async (backend, taskHash) => {
44
+ try {
45
+ return await backend.containsAction(actionDigestForTaskHash(taskHash));
46
+ } catch {
47
+ return false;
48
+ }
49
+ };
50
+ const retrieveByTaskHash = async (backend, taskHash, localCacheDirectory) => {
51
+ const action = await backend.retrieveAction(actionDigestForTaskHash(taskHash));
52
+ if (action === null || action.outputFiles.length === 0) {
53
+ return false;
54
+ }
55
+ const tarballEntry = action.outputFiles[0];
56
+ if (!tarballEntry) {
57
+ return false;
58
+ }
59
+ const entryDirectory = join(localCacheDirectory, taskHash);
60
+ const archivePath = join(localCacheDirectory, `.download-${taskHash}-${randomUUID()}.tar.gz`);
61
+ try {
62
+ await mkdir(localCacheDirectory, { recursive: true });
63
+ const fetched = await backend.fetchBlob(tarballEntry.digest, archivePath);
64
+ if (!fetched) {
65
+ return false;
66
+ }
67
+ await mkdir(entryDirectory, { recursive: true });
68
+ await extractTarGz(archivePath, entryDirectory);
69
+ return true;
70
+ } catch {
71
+ await rm(entryDirectory, { force: true, recursive: true }).catch(() => {
72
+ });
73
+ return false;
74
+ } finally {
75
+ await rm(archivePath, { force: true }).catch(() => {
76
+ });
77
+ }
78
+ };
79
+ const storeByTaskHash = async (backend, taskHash, localCacheDirectory, onUploadError) => {
80
+ const entryDirectory = join(localCacheDirectory, taskHash);
81
+ const archivePath = join(localCacheDirectory, `.upload-${taskHash}-${randomUUID()}.tar.gz`);
82
+ try {
83
+ try {
84
+ await stat(join(entryDirectory, ".commit"));
85
+ } catch {
86
+ return false;
87
+ }
88
+ try {
89
+ await createTarGz(entryDirectory, archivePath);
90
+ const blobDigest = await digestFile(archivePath);
91
+ const result = {
92
+ exitCode: 0,
93
+ outputDirectories: [],
94
+ outputFiles: [{ digest: blobDigest, isExecutable: false, path: TARBALL_OUTPUT_PATH }]
95
+ };
96
+ const blob = {
97
+ digest: blobDigest,
98
+ open: () => Promise.resolve(createReadStream(archivePath))
99
+ };
100
+ return await backend.storeAction(actionDigestForTaskHash(taskHash), result, [blob]);
101
+ } catch (error) {
102
+ onUploadError?.(taskHash, error);
103
+ return false;
104
+ }
105
+ } finally {
106
+ await rm(archivePath, { force: true }).catch(() => {
107
+ });
108
+ }
109
+ };
110
+ const digestFile = async (path) => {
111
+ const hash = createHash("sha256");
112
+ let sizeBytes = 0;
113
+ for await (const chunk of createReadStream(path)) {
114
+ const buffer = chunk;
115
+ hash.update(buffer);
116
+ sizeBytes += buffer.byteLength;
117
+ }
118
+ return { hash: hash.digest("hex"), sizeBytes };
119
+ };
120
+
121
+ export { actionDigestForTaskHash, containsByTaskHash, retrieveByTaskHash, storeByTaskHash };
@@ -0,0 +1,152 @@
1
+ import { createRequire as __cjs_createRequire } from "node:module";
2
+
3
+ const __cjs_require = __cjs_createRequire(import.meta.url);
4
+
5
+ const __cjs_getProcess = typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" ? globalThis.process : process;
6
+
7
+ const __cjs_getBuiltinModule = (module) => {
8
+ // Check if we're in Node.js and version supports getBuiltinModule
9
+ if (typeof __cjs_getProcess !== "undefined" && __cjs_getProcess.versions && __cjs_getProcess.versions.node) {
10
+ const [major, minor] = __cjs_getProcess.versions.node.split(".").map(Number);
11
+ // Node.js 20.16.0+ and 22.3.0+
12
+ if (major > 22 || (major === 22 && minor >= 3) || (major === 20 && minor >= 16)) {
13
+ return __cjs_getProcess.getBuiltinModule(module);
14
+ }
15
+ }
16
+ // Fallback to createRequire
17
+ return __cjs_require(module);
18
+ };
19
+
20
+ const {
21
+ mkdir,
22
+ writeFile,
23
+ utimes,
24
+ readdir,
25
+ readFile,
26
+ stat
27
+ } = __cjs_getBuiltinModule("node:fs/promises");
28
+ const {
29
+ Readable
30
+ } = __cjs_getBuiltinModule("node:stream");
31
+ const {
32
+ pipeline
33
+ } = __cjs_getBuiltinModule("node:stream/promises");
34
+ const {
35
+ createGunzip,
36
+ createGzip,
37
+ createBrotliDecompress,
38
+ createBrotliCompress,
39
+ constants
40
+ } = __cjs_getBuiltinModule("node:zlib");
41
+ import { join, resolve, sep } from '@visulima/path';
42
+ import { parseTar, createTar } from 'nanotar';
43
+
44
+ const BROTLI_COMPRESS_OPTIONS = {
45
+ params: {
46
+ [constants.BROTLI_PARAM_MODE]: constants.BROTLI_MODE_TEXT,
47
+ [constants.BROTLI_PARAM_QUALITY]: 4
48
+ }
49
+ };
50
+ const collectEntries = async (sourceDirectory) => {
51
+ const entries = [];
52
+ const root = resolve(sourceDirectory);
53
+ const walk = async (absolute, relative) => {
54
+ const items = await readdir(absolute, { withFileTypes: true });
55
+ items.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
56
+ for (const item of items) {
57
+ const childAbsolute = join(absolute, item.name);
58
+ const childRelative = relative === "" ? item.name : `${relative}/${item.name}`;
59
+ if (item.isDirectory()) {
60
+ await walk(childAbsolute, childRelative);
61
+ continue;
62
+ }
63
+ if (!item.isFile()) {
64
+ continue;
65
+ }
66
+ const [data, info] = await Promise.all([readFile(childAbsolute), stat(childAbsolute)]);
67
+ entries.push({
68
+ attrs: {
69
+ // eslint-disable-next-line no-bitwise -- POSIX file modes encode the rwx triplet in the low 12 bits; bitmask is the canonical extraction
70
+ mode: (info.mode & 4095).toString(8),
71
+ mtime: Math.floor(info.mtimeMs)
72
+ },
73
+ data,
74
+ name: childRelative
75
+ });
76
+ }
77
+ };
78
+ await walk(root, "");
79
+ return entries;
80
+ };
81
+ const safeJoinForExtract = (destinationDirectory, entryName) => {
82
+ if (entryName === "" || entryName === "." || entryName === "./") {
83
+ return null;
84
+ }
85
+ if (entryName.startsWith("/") || entryName.startsWith("\\") || /^[a-z]:[\\/]/i.test(entryName)) {
86
+ return null;
87
+ }
88
+ const resolvedDestination = resolve(destinationDirectory);
89
+ const resolvedEntry = resolve(resolvedDestination, entryName);
90
+ const prefix = resolvedDestination.endsWith(sep) ? resolvedDestination : `${resolvedDestination}${sep}`;
91
+ if (resolvedEntry !== resolvedDestination && !resolvedEntry.startsWith(prefix)) {
92
+ return null;
93
+ }
94
+ return resolvedEntry;
95
+ };
96
+ const writeTarEntries = async (entries, destinationDirectory, options = {}) => {
97
+ const preserveMtime = options.preserveMtime ?? true;
98
+ const preservePerms = options.preservePerms ?? true;
99
+ await mkdir(destinationDirectory, { recursive: true });
100
+ for (const entry of entries) {
101
+ if (entry.data === void 0) {
102
+ continue;
103
+ }
104
+ const writePath = safeJoinForExtract(destinationDirectory, entry.name);
105
+ if (writePath === null) {
106
+ throw new Error(`[task-runner] refusing to extract tar entry with unsafe path: ${entry.name}`);
107
+ }
108
+ await mkdir(join(writePath, ".."), { recursive: true });
109
+ const mode = preservePerms && entry.attrs?.mode !== void 0 ? Number.parseInt(entry.attrs.mode, 8) : void 0;
110
+ await writeFile(writePath, entry.data, mode === void 0 ? void 0 : { mode });
111
+ if (preserveMtime && entry.attrs?.mtime !== void 0) {
112
+ const mtime = new Date(entry.attrs.mtime * 1e3);
113
+ await utimes(writePath, mtime, mtime);
114
+ }
115
+ }
116
+ };
117
+ const compressBuffer = async (buffer, transform, outputPath) => {
118
+ const { createWriteStream } = await import('node:fs');
119
+ await pipeline(Readable.from(Buffer.from(buffer)), transform, createWriteStream(outputPath));
120
+ };
121
+ const decompressBuffer = async (sourcePath, transform) => {
122
+ const { createReadStream } = await import('node:fs');
123
+ const chunks = [];
124
+ await pipeline(createReadStream(sourcePath), transform, async (source) => {
125
+ for await (const chunk of source) {
126
+ chunks.push(chunk);
127
+ }
128
+ });
129
+ return Buffer.concat(chunks);
130
+ };
131
+ const createTarGz = async (sourceDirectory, outputPath) => {
132
+ const entries = await collectEntries(sourceDirectory);
133
+ const tarBytes = createTar(entries);
134
+ await compressBuffer(tarBytes, createGzip(), outputPath);
135
+ };
136
+ const extractTarGz = async (archivePath, destinationDirectory, options) => {
137
+ const tarBuffer = await decompressBuffer(archivePath, createGunzip());
138
+ const entries = parseTar(tarBuffer);
139
+ await writeTarEntries(entries, destinationDirectory, options);
140
+ };
141
+ const createTarBrotli = async (sourceDirectory, outputPath) => {
142
+ const entries = await collectEntries(sourceDirectory);
143
+ const tarBytes = createTar(entries);
144
+ await compressBuffer(tarBytes, createBrotliCompress(BROTLI_COMPRESS_OPTIONS), outputPath);
145
+ };
146
+ const extractTarBrotli = async (archivePath, destinationDirectory, options) => {
147
+ const tarBuffer = await decompressBuffer(archivePath, createBrotliDecompress());
148
+ const entries = parseTar(tarBuffer);
149
+ await writeTarEntries(entries, destinationDirectory, options);
150
+ };
151
+
152
+ export { extractTarBrotli as a, createTarBrotli as b, createTarGz as c, extractTarGz as e };
@@ -18,5 +18,6 @@ const __cjs_getBuiltinModule = (module) => {
18
18
  };
19
19
 
20
20
 
21
- export { c as collectFiles, a as createFailureResult, h as hashFile, b as hashStrings, r as readPackageDeps, d as resolveTaskCwd, s as sortObjectKeys, u as uniqueId } from './utils-zO0ZRgtf.js';
21
+
22
+ export { c as collectFiles, a as createFailureResult, h as hashFile, b as hashStrings, r as readPackageDeps, d as resolveTaskCwd, s as sortObjectKeys, u as uniqueId } from './utils-Bmnj-H2J.js';
22
23
  import '@visulima/path';
@@ -24,11 +24,12 @@ const {
24
24
  stat,
25
25
  readFile
26
26
  } = __cjs_getBuiltinModule("node:fs/promises");
27
- import { b as hashStrings, s as sortObjectKeys, c as collectFiles, x as xxh3Hash, e as createXxh3Hasher } from './utils-zO0ZRgtf.js';
27
+ import { b as hashStrings, s as sortObjectKeys, c as collectFiles, x as xxh3Hash, e as createXxh3Hasher } from './utils-Bmnj-H2J.js';
28
28
  import { join, resolve, relative } from '@visulima/path';
29
- import { getFrameworkEnvVariables } from './detectFrameworks-CeFzKE6J.js';
30
- import { LockfileHasher } from './extractPackageName-CbVNW-dr.js';
29
+ import { getFrameworkEnvVariables } from './detectFrameworks-D7nyTc-o.js';
30
+ import { LockfileHasher } from './extractPackageName-CMHjqGj_.js';
31
31
  import { loadNativeBindings } from './isNativeAvailable-BpD28A6Z.js';
32
+ import { looksLikeInputUri, parseInputUri } from './INPUT_URI_SCHEMES-DRm76YI5.js';
32
33
 
33
34
  const DEFAULT_GLOBAL_INPUTS = ["package-lock.json", "pnpm-lock.yaml", "yarn.lock", "tsconfig.base.json", "tsconfig.json", ".env"];
34
35
  const IGNORED_DIRS = /* @__PURE__ */ new Set([".git", "coverage", "dist", "node_modules"]);
@@ -254,7 +255,12 @@ class InProcessTaskHasher {
254
255
  const seen = /* @__PURE__ */ new Set();
255
256
  for (const input of inputs) {
256
257
  if (typeof input === "string") {
257
- if (input.startsWith("{") || input.startsWith("!{")) {
258
+ if (looksLikeInputUri(input)) {
259
+ const parsed = parseInputUri(input);
260
+ if (parsed) {
261
+ result.push(parsed);
262
+ }
263
+ } else if (input.startsWith("{") || input.startsWith("!{")) {
258
264
  result.push({ fileset: input });
259
265
  } else if (input.startsWith("^")) {
260
266
  continue;
@@ -0,0 +1,125 @@
1
+ import { createRequire as __cjs_createRequire } from "node:module";
2
+
3
+ const __cjs_require = __cjs_createRequire(import.meta.url);
4
+
5
+ const __cjs_getProcess = typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" ? globalThis.process : process;
6
+
7
+ const __cjs_getBuiltinModule = (module) => {
8
+ // Check if we're in Node.js and version supports getBuiltinModule
9
+ if (typeof __cjs_getProcess !== "undefined" && __cjs_getProcess.versions && __cjs_getProcess.versions.node) {
10
+ const [major, minor] = __cjs_getProcess.versions.node.split(".").map(Number);
11
+ // Node.js 20.16.0+ and 22.3.0+
12
+ if (major > 22 || (major === 22 && minor >= 3) || (major === 20 && minor >= 16)) {
13
+ return __cjs_getProcess.getBuiltinModule(module);
14
+ }
15
+ }
16
+ // Fallback to createRequire
17
+ return __cjs_require(module);
18
+ };
19
+
20
+ const {
21
+ createReadStream,
22
+ createWriteStream
23
+ } = __cjs_getBuiltinModule("node:fs");
24
+ const {
25
+ stat,
26
+ mkdir,
27
+ writeFile,
28
+ rename,
29
+ rm,
30
+ utimes
31
+ } = __cjs_getBuiltinModule("node:fs/promises");
32
+ const {
33
+ pipeline
34
+ } = __cjs_getBuiltinModule("node:stream/promises");
35
+ import { dirname } from '@visulima/path';
36
+ import { u as uniqueId } from './utils-Bmnj-H2J.js';
37
+ import { digestFile } from './digestBuffer-CPdI2E1d.js';
38
+ import { casBlobPath, tmpDirectory } from './V2_ROOT-DKBLxKo4.js';
39
+
40
+ const containsBlob = async (root, digest) => {
41
+ try {
42
+ const stats = await stat(casBlobPath(root, digest.hash));
43
+ return stats.isFile() && stats.size === digest.sizeBytes;
44
+ } catch {
45
+ return false;
46
+ }
47
+ };
48
+ const putBlobFromFile = async (root, digest, sourcePath) => {
49
+ const finalPath = casBlobPath(root, digest.hash);
50
+ if (await containsBlob(root, digest)) {
51
+ await touchBlob(root, digest).catch(() => {
52
+ });
53
+ return;
54
+ }
55
+ const stagingPath = await stageBlob(root, sourcePath);
56
+ try {
57
+ await mkdir(dirname(finalPath), { recursive: true });
58
+ await rename(stagingPath, finalPath);
59
+ } catch (error) {
60
+ await rm(stagingPath, { force: true }).catch(() => {
61
+ });
62
+ if (!isAlreadyExistsError(error)) {
63
+ throw error;
64
+ }
65
+ }
66
+ };
67
+ const putBlobFromBytes = async (root, digest, bytes) => {
68
+ const finalPath = casBlobPath(root, digest.hash);
69
+ if (await containsBlob(root, digest)) {
70
+ await touchBlob(root, digest).catch(() => {
71
+ });
72
+ return;
73
+ }
74
+ const tmpDirectoryPath = tmpDirectory(root);
75
+ const stagingPath = `${tmpDirectoryPath}/${uniqueId()}`;
76
+ await mkdir(tmpDirectoryPath, { recursive: true });
77
+ await writeFile(stagingPath, bytes);
78
+ try {
79
+ await mkdir(dirname(finalPath), { recursive: true });
80
+ await rename(stagingPath, finalPath);
81
+ } catch (error) {
82
+ await rm(stagingPath, { force: true }).catch(() => {
83
+ });
84
+ if (!isAlreadyExistsError(error)) {
85
+ throw error;
86
+ }
87
+ }
88
+ };
89
+ const fetchBlobToFile = async (root, digest, destinationPath) => {
90
+ const sourcePath = casBlobPath(root, digest.hash);
91
+ try {
92
+ await stat(sourcePath);
93
+ } catch {
94
+ return false;
95
+ }
96
+ await mkdir(dirname(destinationPath), { recursive: true });
97
+ await pipeline(createReadStream(sourcePath), createWriteStream(destinationPath));
98
+ await touchBlob(root, digest).catch(() => {
99
+ });
100
+ return true;
101
+ };
102
+ const verifyBlob = async (filePath, expected) => {
103
+ const computed = await digestFile(filePath);
104
+ return computed?.hash === expected.hash && computed.sizeBytes === expected.sizeBytes;
105
+ };
106
+ const touchBlob = async (root, digest) => {
107
+ const now = /* @__PURE__ */ new Date();
108
+ await utimes(casBlobPath(root, digest.hash), now, now);
109
+ };
110
+ const stageBlob = async (root, sourcePath) => {
111
+ const tmpDirectoryPath = tmpDirectory(root);
112
+ const stagingPath = `${tmpDirectoryPath}/${uniqueId()}`;
113
+ await mkdir(tmpDirectoryPath, { recursive: true });
114
+ await pipeline(createReadStream(sourcePath), createWriteStream(stagingPath));
115
+ return stagingPath;
116
+ };
117
+ const isAlreadyExistsError = (error) => {
118
+ if (typeof error !== "object" || error === null) {
119
+ return false;
120
+ }
121
+ const { code } = error;
122
+ return code === "EEXIST" || code === "ENOTEMPTY";
123
+ };
124
+
125
+ export { containsBlob, fetchBlobToFile, putBlobFromBytes, putBlobFromFile, touchBlob, verifyBlob };
@@ -16,6 +16,13 @@ const parseTaskId = (taskId) => {
16
16
  target: parts[1]
17
17
  };
18
18
  };
19
+ const normalizeWarningPattern = (value) => {
20
+ if (value === void 0) {
21
+ return void 0;
22
+ }
23
+ const list = typeof value === "string" ? [value] : value;
24
+ return list.length === 0 ? void 0 : list;
25
+ };
19
26
  const getTaskOutputs = (projectName, targetName, workspace, targetDefaults) => {
20
27
  const project = workspace.projects[projectName];
21
28
  const targetConfig = project?.targets?.[targetName];
@@ -40,12 +47,17 @@ const getSameProjectTask = (projectName, targetName, overrides, workspace, targe
40
47
  {
41
48
  always: project.targets?.[targetName]?.always ?? targetDefaults?.[targetName]?.always,
42
49
  cache: project.targets?.[targetName]?.cache ?? targetDefaults?.[targetName]?.cache,
50
+ cacheOnWarning: project.targets?.[targetName]?.cacheOnWarning ?? targetDefaults?.[targetName]?.cacheOnWarning,
51
+ cacheRestore: project.targets?.[targetName]?.cacheRestore ?? targetDefaults?.[targetName]?.cacheRestore,
43
52
  id: getTaskId(target),
44
53
  outputs: getTaskOutputs(projectName, targetName, workspace, targetDefaults),
45
54
  overrides,
46
55
  parallelism: project.targets?.[targetName]?.parallelism ?? targetDefaults?.[targetName]?.parallelism,
47
56
  projectRoot: project.root,
48
57
  target,
58
+ warningPattern: normalizeWarningPattern(
59
+ project.targets?.[targetName]?.warningPattern ?? targetDefaults?.[targetName]?.warningPattern
60
+ ),
49
61
  when: project.targets?.[targetName]?.when ?? targetDefaults?.[targetName]?.when
50
62
  }
51
63
  ];
@@ -67,12 +79,17 @@ const getDependencyProjectTasks = (projectName, targetName, overrides, workspace
67
79
  tasks.push({
68
80
  always: depProject.targets?.[targetName]?.always ?? targetDefaults?.[targetName]?.always,
69
81
  cache: depProject.targets?.[targetName]?.cache ?? targetDefaults?.[targetName]?.cache,
82
+ cacheOnWarning: depProject.targets?.[targetName]?.cacheOnWarning ?? targetDefaults?.[targetName]?.cacheOnWarning,
83
+ cacheRestore: depProject.targets?.[targetName]?.cacheRestore ?? targetDefaults?.[targetName]?.cacheRestore,
70
84
  id: getTaskId(target),
71
85
  outputs: getTaskOutputs(dep.target, targetName, workspace, targetDefaults),
72
86
  overrides,
73
87
  parallelism: depProject.targets?.[targetName]?.parallelism ?? targetDefaults?.[targetName]?.parallelism,
74
88
  projectRoot: depProject.root,
75
89
  target,
90
+ warningPattern: normalizeWarningPattern(
91
+ depProject.targets?.[targetName]?.warningPattern ?? targetDefaults?.[targetName]?.warningPattern
92
+ ),
76
93
  when: depProject.targets?.[targetName]?.when ?? targetDefaults?.[targetName]?.when
77
94
  });
78
95
  }