@vzn/vx 0.0.415 → 0.0.417
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/package.json +5 -5
- package/src/cli/watch.ts +2 -0
- package/src/util/index.ts +1 -1
- package/src/util/timing.ts +13 -1
- package/src/workspace/migrate-scripts.ts +26 -5
- package/src/workspace/workspace.ts +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vzn/vx",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.417",
|
|
4
4
|
"description": "The fastest task runner and build cache for JavaScript monorepos.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -21,10 +21,10 @@
|
|
|
21
21
|
"node": ">=18"
|
|
22
22
|
},
|
|
23
23
|
"optionalDependencies": {
|
|
24
|
-
"@vzn/vx-linux-x64": "0.0.
|
|
25
|
-
"@vzn/vx-linux-arm64": "0.0.
|
|
26
|
-
"@vzn/vx-darwin-x64": "0.0.
|
|
27
|
-
"@vzn/vx-darwin-arm64": "0.0.
|
|
24
|
+
"@vzn/vx-linux-x64": "0.0.417",
|
|
25
|
+
"@vzn/vx-linux-arm64": "0.0.417",
|
|
26
|
+
"@vzn/vx-darwin-x64": "0.0.417",
|
|
27
|
+
"@vzn/vx-darwin-arm64": "0.0.417"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@anthropic-ai/sandbox-runtime": "^0.0.76"
|
package/src/cli/watch.ts
CHANGED
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
} from './watch-filter.js'
|
|
43
43
|
import { CLOSED, fsClockNow, type WatchHandle, WatcherPool } from './watch-fs.js'
|
|
44
44
|
import { ChangeJudge } from './watch-judge.js'
|
|
45
|
+
import { restartTimings } from '../util/index.js'
|
|
45
46
|
import { memberEntries, sameMembers, sweepConfigs, watchedProjects } from './watch-set.js'
|
|
46
47
|
|
|
47
48
|
/** One line for a watcher or re-read the OS refused; the loop goes on without it. */
|
|
@@ -357,6 +358,7 @@ async function runWatchLoop(args: WatchLoopArgs): Promise<number> {
|
|
|
357
358
|
try {
|
|
358
359
|
await held?.stop()
|
|
359
360
|
held = undefined
|
|
361
|
+
restartTimings()
|
|
360
362
|
const start = Date.now()
|
|
361
363
|
held = (await runOrchestrator(opts)).persistent
|
|
362
364
|
changes.lastCycle = { start, end: Date.now() }
|
package/src/util/index.ts
CHANGED
|
@@ -18,7 +18,7 @@ export {
|
|
|
18
18
|
OUT_OF_FDS_HINT,
|
|
19
19
|
} from './errors.js'
|
|
20
20
|
export { xxh3, xxh3hex } from './hash.js'
|
|
21
|
-
export { mark, printTimings, span } from './timing.js'
|
|
21
|
+
export { mark, printTimings, restartTimings, span } from './timing.js'
|
|
22
22
|
export { clampInt, formatElapsed, MAX_TIMEOUT_MS, parseDecimalInt } from './num.js'
|
|
23
23
|
export {
|
|
24
24
|
asTrees,
|
package/src/util/timing.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// of it sit outside the table; the table shows each stage's own share.
|
|
8
8
|
|
|
9
9
|
const enabled = process.env.VX_TIMING !== undefined && process.env.VX_TIMING !== ''
|
|
10
|
-
|
|
10
|
+
let t0 = Bun.nanoseconds()
|
|
11
11
|
const marks: Array<[label: string, ns: number]> = []
|
|
12
12
|
|
|
13
13
|
/** Record the end of a stage. No-op unless `VX_TIMING` is set. */
|
|
@@ -19,6 +19,18 @@ export function mark(label: string): void {
|
|
|
19
19
|
const spans = new Map<string, [count: number, ns: number]>()
|
|
20
20
|
const noop = (): void => {}
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Start a new table: `vx watch` runs one per cycle in one process, and
|
|
24
|
+
* without this a cycle's table reprinted every earlier cycle's rows and
|
|
25
|
+
* its first stage counted the idle wait before it.
|
|
26
|
+
*/
|
|
27
|
+
export function restartTimings(): void {
|
|
28
|
+
if (!enabled) return
|
|
29
|
+
t0 = Bun.nanoseconds()
|
|
30
|
+
marks.length = 0
|
|
31
|
+
spans.clear()
|
|
32
|
+
}
|
|
33
|
+
|
|
22
34
|
/**
|
|
23
35
|
* Time one occurrence of a repeated operation (a per-task probe, a restore):
|
|
24
36
|
* `const end = span('probe'); …; end()`. Accumulated by label and printed
|
|
@@ -557,6 +557,9 @@ function usesPnp(dir: string): boolean {
|
|
|
557
557
|
const PNP_NOTE =
|
|
558
558
|
"Yarn Plug'n'Play installs this repo: a package's bins live in `.pnp.cjs`, not `node_modules/.bin`, so a task's `tsc` is not found under vx — set `nodeLinker: node-modules` in `.yarnrc.yml` and run `yarn install`, or write each command as `yarn exec '<command>'`"
|
|
559
559
|
|
|
560
|
+
/** A runner of this package's scripts by name: `run-p build:*`. */
|
|
561
|
+
const RUNS_OWN = /(?:^|\s)(?:run-s|run-p|npm-run-all)(?:\s|$)/
|
|
562
|
+
|
|
560
563
|
/** A package manager running a script by name: `pnpm build`, `npm run x`, `bun run x`. */
|
|
561
564
|
const RUNS_SCRIPT =
|
|
562
565
|
/(?:^|[\s;&|(])(?:pnpm|pn|npm|yarn|bun)\s+(?:run(?:-script)?\s+)?([^\s;&|()'"-][^\s;&|()'"]*)/g
|
|
@@ -835,6 +838,9 @@ export function migrateScripts(
|
|
|
835
838
|
}
|
|
836
839
|
const tasks: GeneratedTask[] = []
|
|
837
840
|
let readsManifest = false
|
|
841
|
+
const text = Object.entries(scripts).filter(
|
|
842
|
+
(e): e is [string, string] => typeof e[1] === 'string',
|
|
843
|
+
)
|
|
838
844
|
for (const name of names) {
|
|
839
845
|
if (!isTask(name)) continue
|
|
840
846
|
|
|
@@ -886,19 +892,34 @@ export function migrateScripts(
|
|
|
886
892
|
// pnpm run lint`) ran each again inside the command, beside the task
|
|
887
893
|
// of that name: `vx run check` built twice. The chain's order may
|
|
888
894
|
// matter, so it is named rather than turned into a group.
|
|
895
|
+
// Through `run-s` / `run-p` / `npm-run-all` too (`build: run-p
|
|
896
|
+
// build:*`), each segment naming every task it runs (M-48). A
|
|
897
|
+
// persistent one has PERSISTENT_TODO.
|
|
898
|
+
const persistent = isPersistent(name, scripts)
|
|
899
|
+
let ranTasks = 0
|
|
889
900
|
const ownRuns = own
|
|
890
901
|
.split(/&&|\|\||;/)
|
|
891
902
|
.map((part) => part.trim())
|
|
892
903
|
.filter((part) => {
|
|
893
904
|
const d = delegatedScript(part)
|
|
894
|
-
|
|
905
|
+
if (d !== null) {
|
|
906
|
+
if (d === name || !isTask(d)) return false
|
|
907
|
+
ranTasks++
|
|
908
|
+
return true
|
|
909
|
+
}
|
|
910
|
+
if (persistent || !RUNS_OWN.test(part)) return false
|
|
911
|
+
const refs = new Set(scriptRefs(part, text).filter((r) => r !== name && isTask(r)))
|
|
912
|
+
ranTasks += refs.size
|
|
913
|
+
return refs.size > 0
|
|
895
914
|
})
|
|
896
915
|
if (ownRuns.length > 0) {
|
|
897
916
|
const list = ownRuns.map((r) => `\`${r}\``).join(', ')
|
|
898
917
|
todos.push(
|
|
899
|
-
ownRuns.length === 1
|
|
900
|
-
|
|
901
|
-
|
|
918
|
+
`${list} ${ownRuns.length === 1 ? 'runs' : 'run'} this package's own ${
|
|
919
|
+
ranTasks === 1
|
|
920
|
+
? 'task again inside the command, beside that task: name it'
|
|
921
|
+
: 'tasks again inside the command, beside those tasks: name them'
|
|
922
|
+
} under dependsOn and drop ${ownRuns.length === 1 ? 'it' : 'them'} from the command`,
|
|
902
923
|
)
|
|
903
924
|
}
|
|
904
925
|
const exec: Record<string, unknown> = { command }
|
|
@@ -911,7 +932,7 @@ export function migrateScripts(
|
|
|
911
932
|
)
|
|
912
933
|
}
|
|
913
934
|
const task: Record<string, unknown> = { exec }
|
|
914
|
-
if (
|
|
935
|
+
if (persistent) {
|
|
915
936
|
exec['persistent'] = {}
|
|
916
937
|
todos.push(PERSISTENT_TODO)
|
|
917
938
|
}
|
|
@@ -290,6 +290,11 @@ function parsePackageJson(text: string, file: string): PackageJson {
|
|
|
290
290
|
if (name !== undefined && (typeof name !== 'string' || name.trim() !== name)) {
|
|
291
291
|
throw new UserError(`${file}: "name" must be a string with no surrounding whitespace`)
|
|
292
292
|
}
|
|
293
|
+
// A task is `<project>#<task>` split at the first `#`: `"a#b"` planned
|
|
294
|
+
// under `--all` but no run spec or dependsOn could reach it (D-130).
|
|
295
|
+
if (typeof name === 'string' && name.includes('#')) {
|
|
296
|
+
throw new UserError(`${file}: "name" cannot hold "#" — vx addresses a task as <name>#<task>`)
|
|
297
|
+
}
|
|
293
298
|
return pkg as PackageJson
|
|
294
299
|
}
|
|
295
300
|
|