@vzn/vx 0.0.590 → 0.0.591

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.590",
3
+ "version": "0.0.591",
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.590",
25
- "@vzn/vx-linux-arm64": "0.0.590",
26
- "@vzn/vx-darwin-x64": "0.0.590",
27
- "@vzn/vx-darwin-arm64": "0.0.590"
24
+ "@vzn/vx-linux-x64": "0.0.591",
25
+ "@vzn/vx-linux-arm64": "0.0.591",
26
+ "@vzn/vx-darwin-x64": "0.0.591",
27
+ "@vzn/vx-darwin-arm64": "0.0.591"
28
28
  },
29
29
  "dependencies": {
30
30
  "@anthropic-ai/sandbox-runtime": "^0.0.76"
@@ -663,6 +663,7 @@ export function validateProjectConfig(config: ProjectConfig, configPath: string)
663
663
  `let cleanOutputs delete files outside it)`,
664
664
  )
665
665
  }
666
+ assertPosixGlob(g, `${where}.cache.outputs.files`, 'project')
666
667
  assertNoForeignToken(g, `${where}.cache.outputs.files`)
667
668
  if (namesDirItself(g)) {
668
669
  throw new UserError(
@@ -714,6 +715,7 @@ export function validateProjectConfig(config: ProjectConfig, configPath: string)
714
715
  `use cache.inputs.workspaceFiles for workspace-root-relative inputs)`,
715
716
  )
716
717
  }
718
+ assertPosixGlob(g, `${where}.cache.inputs.files`, 'project')
717
719
  assertNoForeignToken(g, `${where}.cache.inputs.files`)
718
720
  if (namesDirItself(g)) {
719
721
  throw new UserError(
@@ -1196,6 +1198,39 @@ function isAbsoluteGlob(glob: string): boolean {
1196
1198
  return g.startsWith('/') || (g.includes('{') && /[{,]\//.test(g))
1197
1199
  }
1198
1200
 
1201
+ const DRIVE = /(^|[{,])[A-Za-z]:[\\/]+/g
1202
+
1203
+ /**
1204
+ * True when a backslash in the glob is a Windows separator. One before a
1205
+ * bracket, a brace, a `!` or a backslash is an escape (`app/\[id\]`,
1206
+ * `\{b\}`); one before anything else is a separator — `a\*b` reads as
1207
+ * `a/*b` on Windows far more often than as a file named with a star, which
1208
+ * `a?b` still selects.
1209
+ */
1210
+ function hasBackslashSeparator(body: string): boolean {
1211
+ for (let i = body.indexOf('\\'); i !== -1; i = body.indexOf('\\', i + 2)) {
1212
+ if (!'[]{}!\\'.includes(body[i + 1] ?? '/')) return true
1213
+ }
1214
+ return false
1215
+ }
1216
+
1217
+ /**
1218
+ * A Windows spelling (`src\**`, `C:/src/**`) loaded with only a "matched no
1219
+ * files" warning, and a task keyed on it never saw its source (X-67).
1220
+ */
1221
+ function assertPosixGlob(glob: string, where: string, base: string): void {
1222
+ const neg = glob.startsWith('!') ? '!' : ''
1223
+ const body = glob.slice(neg.length)
1224
+ DRIVE.lastIndex = 0
1225
+ const drive = DRIVE.test(body)
1226
+ if (!drive && !hasBackslashSeparator(body)) return
1227
+ const write = neg + body.replace(DRIVE, '$1').replace(/\\(?![[\]{}!\\])/g, '/')
1228
+ throw new UserError(
1229
+ `${where}: "${glob}" ${drive ? 'starts with a Windows drive' : 'uses a backslash as a path separator'} — ` +
1230
+ `task globs are ${base}-relative with forward slashes: write "${write}"`,
1231
+ )
1232
+ }
1233
+
1199
1234
  /**
1200
1235
  * `!!x` INVERTS the input set instead of double-negating it.
1201
1236
  *
@@ -1405,6 +1440,7 @@ function validateWorkspaceGlobs(v: unknown, where: string, negation: boolean): v
1405
1440
  `entries are workspace-root-relative and must stay within the workspace root`,
1406
1441
  )
1407
1442
  }
1443
+ assertPosixGlob(g, where, 'workspace-root')
1408
1444
  assertNoForeignToken(g, where)
1409
1445
  if (namesDirItself(g)) {
1410
1446
  throw new UserError(