@vzn/vx 0.0.183 → 0.0.185

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 (2) hide show
  1. package/package.json +5 -5
  2. package/src/config.ts +33 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vzn/vx",
3
- "version": "0.0.183",
3
+ "version": "0.0.185",
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.183",
21
- "@vzn/vx-linux-arm64": "0.0.183",
22
- "@vzn/vx-darwin-x64": "0.0.183",
23
- "@vzn/vx-darwin-arm64": "0.0.183"
20
+ "@vzn/vx-linux-x64": "0.0.185",
21
+ "@vzn/vx-linux-arm64": "0.0.185",
22
+ "@vzn/vx-darwin-x64": "0.0.185",
23
+ "@vzn/vx-darwin-arm64": "0.0.185"
24
24
  },
25
25
  "dependencies": {
26
26
  "@anthropic-ai/sandbox-runtime": "^0.0.76"
package/src/config.ts CHANGED
@@ -530,6 +530,18 @@ type DependsOnEntry<K extends string> =
530
530
  | `${string}#${string}`
531
531
  | `${string}*${string}`
532
532
 
533
+ /**
534
+ * The keys of `T` that `Shape` does not declare, typed `never`. A generic
535
+ * argument skips TypeScript's excess-property check, so a Turbo-shaped
536
+ * `outputs` on a task, or `cwd` in `exec`, type-checked and failed only
537
+ * when vx loaded the config (D-69), as did a typo beside a known key in
538
+ * `defineWorkspace` (D-70); `never` puts the error on that line.
539
+ */
540
+ type Known<T, Shape> = { [P in keyof T]: P extends keyof Shape ? unknown : never }
541
+
542
+ /** `T[P]` when `T` has it; `unknown` (no keys to check) when it does not. */
543
+ type At<T, P extends PropertyKey> = T extends { readonly [Q in P]?: infer V } ? V : unknown
544
+
533
545
  /**
534
546
  * Identity function — exists only so TypeScript narrows literal types
535
547
  * and, crucially, **validates `dependsOn` against this project's own
@@ -538,17 +550,31 @@ type DependsOnEntry<K extends string> =
538
550
  * free strings. Runtime behavior is unchanged (it returns its input).
539
551
  */
540
552
  export function defineProject<const T extends ProjectConfig>(
541
- config: T & {
542
- tasks?: {
543
- [K in keyof NonNullable<T['tasks']>]?: {
544
- dependsOn?: readonly DependsOnEntry<Extract<keyof NonNullable<T['tasks']>, string>>[]
553
+ config: T &
554
+ Known<T, ProjectConfig> & {
555
+ tasks?: {
556
+ [K in keyof NonNullable<T['tasks']>]?: Known<NonNullable<T['tasks']>[K], TaskConfig> & {
557
+ dependsOn?: readonly DependsOnEntry<Extract<keyof NonNullable<T['tasks']>, string>>[]
558
+ exec?: Known<At<NonNullable<T['tasks']>[K], 'exec'>, ExecConfig>
559
+ cache?: Known<At<NonNullable<T['tasks']>[K], 'cache'>, CacheConfig> & {
560
+ inputs?: Known<At<At<NonNullable<T['tasks']>[K], 'cache'>, 'inputs'>, CacheInputs>
561
+ outputs?: Known<At<At<NonNullable<T['tasks']>[K], 'cache'>, 'outputs'>, CacheOutputs>
562
+ }
563
+ }
545
564
  }
546
- }
547
- },
565
+ },
548
566
  ): T {
549
567
  return config as T
550
568
  }
551
569
 
552
- export function defineWorkspace<T extends WorkspaceConfig>(config: T): T {
570
+ export function defineWorkspace<T extends WorkspaceConfig>(
571
+ config: T &
572
+ Known<T, WorkspaceConfig> & {
573
+ cacheRetention?: Known<
574
+ At<T, 'cacheRetention'>,
575
+ NonNullable<WorkspaceConfig['cacheRetention']>
576
+ >
577
+ },
578
+ ): T {
553
579
  return config
554
580
  }