@vzn/vx 0.0.186 → 0.0.188
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/run.ts +3 -0
- package/src/cli/task-verb.ts +30 -10
- package/src/orchestrator/index.ts +1 -1
- package/src/orchestrator/run.ts +22 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vzn/vx",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.188",
|
|
4
4
|
"description": "A fast, correct task runner and build cache for JavaScript monorepos.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
"node": ">=18"
|
|
18
18
|
},
|
|
19
19
|
"optionalDependencies": {
|
|
20
|
-
"@vzn/vx-linux-x64": "0.0.
|
|
21
|
-
"@vzn/vx-linux-arm64": "0.0.
|
|
22
|
-
"@vzn/vx-darwin-x64": "0.0.
|
|
23
|
-
"@vzn/vx-darwin-arm64": "0.0.
|
|
20
|
+
"@vzn/vx-linux-x64": "0.0.188",
|
|
21
|
+
"@vzn/vx-linux-arm64": "0.0.188",
|
|
22
|
+
"@vzn/vx-darwin-x64": "0.0.188",
|
|
23
|
+
"@vzn/vx-darwin-arm64": "0.0.188"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@anthropic-ai/sandbox-runtime": "^0.0.76"
|
package/src/cli/run.ts
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
import type { ContinueMode } from '../graph/index.js'
|
|
17
17
|
import { type CachePolicy, FULL_CACHE_POLICY, parseCachePolicy } from '../cache/index.js'
|
|
18
18
|
import { findCwdProject, pickTask, resolveFilters } from './select.js'
|
|
19
|
+
import { nxTargetHint } from './task-verb.js'
|
|
19
20
|
import { MAX_TIMEOUT_MS, isUserError, parseDecimalInt, machineParallelism } from '../util/index.js'
|
|
20
21
|
import { formatGraphDot, formatPlanJson, formatPlanText } from './plan-format.js'
|
|
21
22
|
|
|
@@ -512,6 +513,8 @@ export async function resolveRunOptions(
|
|
|
512
513
|
} else {
|
|
513
514
|
const cwdProject = await findCwdProject(cwd)
|
|
514
515
|
if (!cwdProject) {
|
|
516
|
+
const nx = await nxTargetHint(tasks, cwd)
|
|
517
|
+
if (nx !== null) return { error: nx }
|
|
515
518
|
return {
|
|
516
519
|
error:
|
|
517
520
|
'not inside a project. Pass --all for every project, --filter <pattern> to filter, or run from within a project directory.',
|
package/src/cli/task-verb.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// does it. It stays a refusal: a verb that runs whatever task shares its
|
|
5
5
|
// name would change meaning the day a plugin declares that verb.
|
|
6
6
|
|
|
7
|
+
import { nxProjectTarget } from '../orchestrator/index.js'
|
|
7
8
|
import { findWorkspaceRoot, listProjects, loadWorkspace } from '../workspace/index.js'
|
|
8
9
|
import { findCwdProject } from './select.js'
|
|
9
10
|
import { loadCliProjects } from './workspace-config.js'
|
|
@@ -15,16 +16,8 @@ export async function taskVerbHint(
|
|
|
15
16
|
cwd: string,
|
|
16
17
|
): Promise<string | null> {
|
|
17
18
|
if (command.includes('#')) return `\`${command}\` is a task: vx run ${command}`
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const root = await findWorkspaceRoot(cwd)
|
|
21
|
-
projects = await loadCliProjects(root, await listProjects(await loadWorkspace(root)), 'all', {
|
|
22
|
-
noCreate: true,
|
|
23
|
-
})
|
|
24
|
-
} catch {
|
|
25
|
-
// No workspace, or a config that does not load: the plain unknown-command line stands.
|
|
26
|
-
return null
|
|
27
|
-
}
|
|
19
|
+
const projects = await workspaceProjects(cwd)
|
|
20
|
+
if (projects === null) return null
|
|
28
21
|
if (![...projects.values()].some((p) => p.config.tasks?.[command] !== undefined)) return null
|
|
29
22
|
// Nx's `nx build app`: the word after the target is its project.
|
|
30
23
|
const project = rest[0] !== undefined && projects.has(rest[0]) ? rest[0] : undefined
|
|
@@ -36,3 +29,30 @@ export async function taskVerbHint(
|
|
|
36
29
|
: `vx run ${command}`
|
|
37
30
|
return `\`${command}\` is a task here, not a command: ${run}`
|
|
38
31
|
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* `vx run web:build` outside a project, as `nx run web:build` is typed:
|
|
35
|
+
* the `vx run` of each name that is Nx's `project:target` here, or null.
|
|
36
|
+
*/
|
|
37
|
+
export async function nxTargetHint(tasks: readonly string[], cwd: string): Promise<string | null> {
|
|
38
|
+
if (!tasks.some((t) => t.includes(':'))) return null
|
|
39
|
+
const projects = await workspaceProjects(cwd)
|
|
40
|
+
if (projects === null) return null
|
|
41
|
+
const specs = tasks.map((t) => nxProjectTarget(t, projects))
|
|
42
|
+
if (specs.some((s) => s === undefined)) return null
|
|
43
|
+
return `\`${tasks.join(' ')}\` is Nx's project:target: vx run ${specs.join(' ')}`
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function workspaceProjects(
|
|
47
|
+
cwd: string,
|
|
48
|
+
): Promise<Awaited<ReturnType<typeof loadCliProjects>> | null> {
|
|
49
|
+
try {
|
|
50
|
+
const root = await findWorkspaceRoot(cwd)
|
|
51
|
+
return await loadCliProjects(root, await listProjects(await loadWorkspace(root)), 'all', {
|
|
52
|
+
noCreate: true,
|
|
53
|
+
})
|
|
54
|
+
} catch {
|
|
55
|
+
// No workspace, or a config that does not load: the caller's plain line stands.
|
|
56
|
+
return null
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Module contract for `orchestrator`. Cross-module imports must come
|
|
2
2
|
// through here (enforced by tests/module-boundaries.test.ts).
|
|
3
3
|
|
|
4
|
-
export { run, planRun } from './run.js'
|
|
4
|
+
export { run, planRun, nxProjectTarget } from './run.js'
|
|
5
5
|
export { prepareRun, type PreparedRun } from './prepare.js'
|
|
6
6
|
export {
|
|
7
7
|
loadProjects,
|
package/src/orchestrator/run.ts
CHANGED
|
@@ -1298,6 +1298,11 @@ function didYouMean(
|
|
|
1298
1298
|
const hints = new Set<string>()
|
|
1299
1299
|
for (const spec of unresolved) {
|
|
1300
1300
|
const at = spec.indexOf('#')
|
|
1301
|
+
const nx = nxProjectTarget(spec, projects)
|
|
1302
|
+
if (nx !== undefined) {
|
|
1303
|
+
hints.add(nx)
|
|
1304
|
+
continue
|
|
1305
|
+
}
|
|
1301
1306
|
if (at < 0) {
|
|
1302
1307
|
const t = nearest(spec, allTasks)
|
|
1303
1308
|
if (t !== undefined) hints.add(t)
|
|
@@ -1315,6 +1320,23 @@ function didYouMean(
|
|
|
1315
1320
|
return hints.size === 0 ? '' : ` Did you mean ${[...hints].join(', ')}?`
|
|
1316
1321
|
}
|
|
1317
1322
|
|
|
1323
|
+
/**
|
|
1324
|
+
* Nx's `project:target` (`nx run web:build`) as vx spells it, `web#build`,
|
|
1325
|
+
* when that project declares that task; a name with a colon is otherwise
|
|
1326
|
+
* a task of its own (`build:prod`).
|
|
1327
|
+
*/
|
|
1328
|
+
export function nxProjectTarget(
|
|
1329
|
+
spec: string,
|
|
1330
|
+
projects: ReadonlyMap<string, ProjectEntry>,
|
|
1331
|
+
): string | undefined {
|
|
1332
|
+
const colon = spec.indexOf(':')
|
|
1333
|
+
if (colon <= 0 || spec.includes('#')) return undefined
|
|
1334
|
+
const [project, task] = [spec.slice(0, colon), spec.slice(colon + 1)]
|
|
1335
|
+
return projects.get(project)?.config.tasks?.[task] === undefined
|
|
1336
|
+
? undefined
|
|
1337
|
+
: `${project}#${task}`
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1318
1340
|
/** The executed, keyed outcomes of a run — what flakiness is judged on. */
|
|
1319
1341
|
function flakyCandidates(outcomes: readonly TaskOutcome[]): FlakyCandidate[] {
|
|
1320
1342
|
const out: FlakyCandidate[] = []
|