@vzn/vx 0.0.525 → 0.0.526
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vzn/vx",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.526",
|
|
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.526",
|
|
25
|
+
"@vzn/vx-linux-arm64": "0.0.526",
|
|
26
|
+
"@vzn/vx-darwin-x64": "0.0.526",
|
|
27
|
+
"@vzn/vx-darwin-arm64": "0.0.526"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@anthropic-ai/sandbox-runtime": "^0.0.76"
|
package/src/exec/runner.ts
CHANGED
|
@@ -158,13 +158,20 @@ function trailingCommentStart(command: string): number {
|
|
|
158
158
|
/**
|
|
159
159
|
* The command a task runs with the args after `--` appended, shell-quoted.
|
|
160
160
|
* They go before a trailing comment: appended after it, `echo args: # show`
|
|
161
|
-
* ran without them and said nothing (item 1060).
|
|
161
|
+
* ran without them and said nothing (item 1060). Trailing blanks go first.
|
|
162
162
|
*/
|
|
163
163
|
export function withForwardArgs(command: string, args: readonly string[] | undefined): string {
|
|
164
164
|
if (!args || args.length === 0) return command
|
|
165
165
|
const quoted = args.map(shellQuote).join(' ')
|
|
166
166
|
let comment = trailingCommentStart(command)
|
|
167
|
-
if (comment < 0)
|
|
167
|
+
if (comment < 0) {
|
|
168
|
+
// A command that ends in a newline (a template literal's closing line)
|
|
169
|
+
// ran the args as a command of their own: `--watch: not found`. Kept
|
|
170
|
+
// when an odd run of backslashes ends it: that escapes what follows.
|
|
171
|
+
const body = command.trimEnd()
|
|
172
|
+
const escaped = (/\\+$/.exec(body)?.[0].length ?? 0) % 2 === 1
|
|
173
|
+
return `${escaped ? command : body} ${quoted}`
|
|
174
|
+
}
|
|
168
175
|
// A comment-only last line after a commented line: the args go before
|
|
169
176
|
// the earliest comment, or they land inside it (`echo one # c\n# two`).
|
|
170
177
|
for (let c = comment; c >= 0; c = trailingCommentStart(command.slice(0, c).trimEnd())) comment = c
|
|
@@ -169,17 +169,21 @@ export async function applyProjectHooks(
|
|
|
169
169
|
* deleting each other's outputs). A violation is reported
|
|
170
170
|
* against the LAST plugin that ran: usually the one whose edit made it so,
|
|
171
171
|
* but an earlier plugin's edit that a later one left in place is blamed on
|
|
172
|
-
* the later one, since
|
|
172
|
+
* the later one, since the structure is not checked between plugins.
|
|
173
|
+
* Each node's task config is (`afterEach`), like the `project` stage's.
|
|
173
174
|
*/
|
|
174
175
|
export async function applyGraphHooks(
|
|
175
176
|
plugins: readonly VxPlugin[],
|
|
176
177
|
nodes: Map<string, TaskNode>,
|
|
177
178
|
ctx: GraphHookContext,
|
|
179
|
+
/** Runs after EACH plugin's edit, so a refused task config names the plugin that wrote it. */
|
|
180
|
+
afterEach?: (plugin: VxPlugin) => void,
|
|
178
181
|
): Promise<void> {
|
|
179
182
|
let last: VxPlugin | undefined
|
|
180
183
|
for (const plugin of plugins) {
|
|
181
184
|
if (plugin.graph === undefined) continue
|
|
182
185
|
await safe(plugin, 'graph', () => plugin.graph!(nodes, ctx))
|
|
186
|
+
afterEach?.(plugin)
|
|
183
187
|
last = plugin
|
|
184
188
|
}
|
|
185
189
|
if (last === undefined) return
|
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
resolveCacheDir,
|
|
40
40
|
resolveStoreRoot,
|
|
41
41
|
type ProjectEntry,
|
|
42
|
+
validateProjectConfig,
|
|
42
43
|
} from '../workspace/index.js'
|
|
43
44
|
import {
|
|
44
45
|
buildTaskGraph,
|
|
@@ -61,6 +62,7 @@ import {
|
|
|
61
62
|
discoverProjects,
|
|
62
63
|
gitOfDiscovery,
|
|
63
64
|
graphOfDiscovery,
|
|
65
|
+
isDefaultBuild,
|
|
64
66
|
loadProjects,
|
|
65
67
|
loadWorkspacePlugins,
|
|
66
68
|
type LoadedProjects,
|
|
@@ -597,12 +599,30 @@ export async function prepareRun(options: RunOptions, log: Logger): Promise<Prep
|
|
|
597
599
|
)
|
|
598
600
|
mark('git enumeration')
|
|
599
601
|
if (hasHook(plugins, 'graph')) {
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
602
|
+
// A hook edits each node's config in place, as `project` does, so the
|
|
603
|
+
// edit is held to what the loader accepts from a user: a misspelled
|
|
604
|
+
// `exec` field ran as an empty command and failed with no reason.
|
|
605
|
+
const configPaths = new Map(projectMetas.map((m) => [m.name, m.configPath]))
|
|
606
|
+
await applyGraphHooks(
|
|
607
|
+
plugins,
|
|
608
|
+
nodes,
|
|
609
|
+
{
|
|
610
|
+
workspaceRoot,
|
|
611
|
+
cacheDir,
|
|
612
|
+
warn: (m) => log.status(m),
|
|
613
|
+
requested: [...nodes.values()].filter((n) => n.requested).map((n) => n.id),
|
|
614
|
+
},
|
|
615
|
+
(plugin) => {
|
|
616
|
+
for (const n of nodes.values()) {
|
|
617
|
+
if (isDefaultBuild(n.config)) continue
|
|
618
|
+
const where = configPaths.get(n.projectName) ?? `${n.projectName} (no config file)`
|
|
619
|
+
validateProjectConfig(
|
|
620
|
+
{ tasks: { [n.taskName]: n.config } },
|
|
621
|
+
`${where} (after plugin '${plugin.name}')`,
|
|
622
|
+
)
|
|
623
|
+
}
|
|
624
|
+
},
|
|
625
|
+
)
|
|
606
626
|
}
|
|
607
627
|
if (hasHook(plugins, 'key')) {
|
|
608
628
|
await applyKeyHooks(plugins, nodes, { workspaceRoot, cacheDir, warn: (m) => log.status(m) })
|