@visulima/vis 1.0.0-alpha.5 → 1.0.0-alpha.7

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 (128) hide show
  1. package/CHANGELOG.md +157 -81
  2. package/README.md +144 -14
  3. package/dist/ai-analysis.d.ts +3 -17
  4. package/dist/ai-cache.d.ts +1 -1
  5. package/dist/ai-types.d.ts +16 -0
  6. package/dist/bin.js +352 -221
  7. package/dist/cache-directory.d.ts +73 -0
  8. package/dist/codeowners.d.ts +30 -0
  9. package/dist/commands/action-graph.d.ts +8 -0
  10. package/dist/commands/audit.d.ts +3 -3
  11. package/dist/commands/cache.d.ts +86 -0
  12. package/dist/commands/ci.d.ts +19 -0
  13. package/dist/commands/docker.d.ts +22 -0
  14. package/dist/commands/generate.d.ts +10 -0
  15. package/dist/commands/ignore-helpers.d.ts +157 -0
  16. package/dist/commands/ignore.d.ts +17 -0
  17. package/dist/commands/info.d.ts +3 -0
  18. package/dist/commands/list.d.ts +3 -0
  19. package/dist/commands/migrate/backup.d.ts +8 -0
  20. package/dist/commands/migrate/constants.d.ts +6 -2
  21. package/dist/commands/migrate/gitleaks.d.ts +29 -0
  22. package/dist/commands/migrate/json.d.ts +4 -2
  23. package/dist/commands/migrate/kingfisher.d.ts +14 -0
  24. package/dist/commands/migrate/moon.d.ts +5 -0
  25. package/dist/commands/migrate/nano-staged.d.ts +30 -0
  26. package/dist/commands/migrate/nx.d.ts +12 -0
  27. package/dist/commands/migrate/prompt.d.ts +2 -0
  28. package/dist/commands/migrate/secretlint.d.ts +14 -0
  29. package/dist/commands/migrate/shared.d.ts +29 -0
  30. package/dist/commands/migrate/turborepo.d.ts +11 -0
  31. package/dist/commands/migrate/types.d.ts +8 -1
  32. package/dist/commands/migrate/verify.d.ts +12 -0
  33. package/dist/commands/run.d.ts +13 -0
  34. package/dist/commands/sbom.d.ts +10 -0
  35. package/dist/commands/secrets.d.ts +3 -0
  36. package/dist/commands/staged.d.ts +7 -0
  37. package/dist/commands/status.d.ts +3 -0
  38. package/dist/commands/sync.d.ts +16 -0
  39. package/dist/commands/task-why.d.ts +3 -0
  40. package/dist/config.d.ts +17 -2
  41. package/dist/config.js +1 -1
  42. package/dist/docker.d.ts +73 -0
  43. package/dist/flakiness.d.ts +40 -0
  44. package/dist/generate/discover.d.ts +29 -0
  45. package/dist/generate/index.d.ts +32 -0
  46. package/dist/generate/index.js +1 -0
  47. package/dist/generate/loader.d.ts +15 -0
  48. package/dist/generate/moon-adapter/filename-interp.d.ts +42 -0
  49. package/dist/generate/moon-adapter/filters.d.ts +22 -0
  50. package/dist/generate/moon-adapter/frontmatter.d.ts +39 -0
  51. package/dist/generate/moon-adapter/index.d.ts +19 -0
  52. package/dist/generate/moon-adapter/tera-subset.d.ts +85 -0
  53. package/dist/generate/moon-adapter/util.d.ts +14 -0
  54. package/dist/generate/prompts.d.ts +25 -0
  55. package/dist/generate/remote.d.ts +43 -0
  56. package/dist/generate/runner.d.ts +37 -0
  57. package/dist/generate/types.d.ts +152 -0
  58. package/dist/hooks.d.ts +118 -0
  59. package/dist/native-binding.d.ts +8 -1
  60. package/dist/packem_chunks/index.js +7 -0
  61. package/dist/packem_chunks/loader.js +1 -0
  62. package/dist/packem_shared/otelPlugin-CJLkguJ8.js +1 -0
  63. package/dist/plugins/otel.d.ts +63 -0
  64. package/dist/pm-runner.d.ts +24 -3
  65. package/dist/run-report.d.ts +40 -0
  66. package/dist/runtime-check.d.ts +27 -0
  67. package/dist/sbom/cyclonedx.d.ts +39 -0
  68. package/dist/sbom/installed-package.d.ts +49 -0
  69. package/dist/sbom/license.d.ts +31 -0
  70. package/dist/sbom/lockfile.d.ts +34 -0
  71. package/dist/sbom/purl.d.ts +25 -0
  72. package/dist/sbom/resolve-specifier.d.ts +24 -0
  73. package/dist/sbom/types.d.ts +196 -0
  74. package/dist/secrets/baseline.d.ts +20 -0
  75. package/dist/secrets/format.d.ts +14 -0
  76. package/dist/secrets/git.d.ts +6 -0
  77. package/dist/secrets/spinner.d.ts +9 -0
  78. package/dist/selectors.d.ts +81 -0
  79. package/dist/shell-history.d.ts +16 -0
  80. package/dist/staged/cli-parse.d.ts +18 -0
  81. package/dist/staged/config.d.ts +14 -0
  82. package/dist/staged/errors/apply-empty-commit-error.d.ts +4 -0
  83. package/dist/staged/errors/config-error.d.ts +4 -0
  84. package/dist/staged/errors/get-backup-stash-error.d.ts +4 -0
  85. package/dist/staged/errors/git-error.d.ts +6 -0
  86. package/dist/staged/errors/index.d.ts +12 -0
  87. package/dist/staged/errors/restore-original-state-error.d.ts +4 -0
  88. package/dist/staged/errors/staged-error.d.ts +8 -0
  89. package/dist/staged/errors/task-error.d.ts +6 -0
  90. package/dist/staged/git/diff.d.ts +76 -0
  91. package/dist/staged/git/exec.d.ts +43 -0
  92. package/dist/staged/git/index.d.ts +77 -0
  93. package/dist/staged/git/stash.d.ts +37 -0
  94. package/dist/staged/index.d.ts +13 -0
  95. package/dist/staged/match.d.ts +12 -0
  96. package/dist/staged/renderer/index.d.ts +9 -0
  97. package/dist/staged/renderer/ink/index.d.ts +4 -0
  98. package/dist/staged/renderer/plain.d.ts +12 -0
  99. package/dist/staged/tasks/build.d.ts +13 -0
  100. package/dist/staged/tasks/exec.d.ts +56 -0
  101. package/dist/staged/tasks/run.d.ts +26 -0
  102. package/dist/staged/types.d.ts +173 -0
  103. package/dist/target-discovery.d.ts +59 -0
  104. package/dist/target-options.d.ts +261 -0
  105. package/dist/tui/components/OutputPanel.d.ts +2 -1
  106. package/dist/tui/components/TaskListPanel.d.ts +1 -1
  107. package/dist/tui/components/TaskStore.d.ts +1 -1
  108. package/dist/tui/components/devcontainer/DevcontainerStore.d.ts +1 -1
  109. package/dist/tui/components/devcontainer/catalogs/mount-suggestions.d.ts +1 -1
  110. package/dist/tui/components/devcontainer/sections/GeneralSection.d.ts +1 -1
  111. package/dist/tui/components/devcontainer/sections/PreviewPanel.d.ts +1 -1
  112. package/dist/tui/components/devcontainer/types.d.ts +4 -4
  113. package/dist/tui/components/graph/GraphStore.d.ts +1 -1
  114. package/dist/tui/components/graph/ProjectDetailPanel.d.ts +1 -1
  115. package/dist/tui/components/optimize/OptimizeDetailPanel.d.ts +1 -1
  116. package/dist/tui/components/optimize/OptimizeStore.d.ts +1 -1
  117. package/dist/tui/components/update/PackageDetailPanel.d.ts +1 -1
  118. package/dist/tui/components/update/PackageListPanel.d.ts +2 -2
  119. package/dist/tui/components/update/UpdateStore.d.ts +1 -1
  120. package/dist/tui/components/update/VisUpdateApp.d.ts +3 -3
  121. package/dist/tui/dynamic-life-cycle.d.ts +2 -1
  122. package/dist/tui/static-life-cycle.d.ts +7 -1
  123. package/dist/watch.d.ts +65 -0
  124. package/dist/workspace.d.ts +326 -6
  125. package/index.js +727 -554
  126. package/package.json +38 -32
  127. package/schemas/project.schema.json +344 -0
  128. package/schemas/vis-config.schema.json +331 -0
@@ -0,0 +1,261 @@
1
+ import type { TargetConfiguration } from "@visulima/task-runner";
2
+ /**
3
+ * Semantic classification for a target.
4
+ * - `build`: Generates one or more artifacts; cached by default.
5
+ * - `test`: Validation task (lint, typecheck, unit test). Default type.
6
+ * - `run`: One-off or long-running process. Not cached by default.
7
+ */
8
+ export type TargetType = "build" | "run" | "test";
9
+ /**
10
+ * Preset bundles of target options.
11
+ * - `server`: Long-running local dev server — caching off, not in CI,
12
+ * interactive, persistent.
13
+ * - `utility`: Short-lived helper — caching off, not in CI.
14
+ */
15
+ export type TargetPreset = "server" | "utility";
16
+ /**
17
+ * Controls whether a target runs in CI.
18
+ * - `true` (default): Always run.
19
+ * - `false`: Never run in CI (local-only).
20
+ * - `"affected"`: Only when the project is affected by the current change set.
21
+ * - `"always"`: Always run, even if unaffected.
22
+ */
23
+ export type RunInCI = "affected" | "always" | boolean;
24
+ /**
25
+ * Controls how affected files are forwarded to a task.
26
+ * - `false` (default): Do not forward.
27
+ * - `"args"`: Append affected paths as additional command arguments.
28
+ * - `"env"`: Expose them via `VIS_AFFECTED_FILES` environment variable.
29
+ * - `"both"`: Both of the above.
30
+ */
31
+ export type AffectedFilesMode = "args" | "both" | "env" | false;
32
+ /** Supported OS filters for target execution. */
33
+ export type TargetOsType = "linux" | "macos" | "windows";
34
+ /**
35
+ * Vis-specific target options that extend the task-runner's
36
+ * base `TargetConfiguration`. These live under `target.options` and are
37
+ * interpreted by vis before handing the task off to task-runner.
38
+ */
39
+ /**
40
+ * Object form of the `when` gate. Matches against process.env or
41
+ * process.platform — deliberately small surface area so conditions
42
+ * stay auditable and declarative.
43
+ */
44
+ export interface TargetConditionObject {
45
+ /** Env var name to compare against `equals` or `in`. */
46
+ env?: string;
47
+ /** Value that `env` must match exactly. */
48
+ equals?: string;
49
+ /** Any value in this list matches. Ignored when `equals` is set. */
50
+ in?: string[];
51
+ /** Run only on this platform (or one of these). */
52
+ platform?: NodeJS.Platform | NodeJS.Platform[];
53
+ }
54
+ /**
55
+ * Evaluates a `when` condition against the current process state.
56
+ * Returns `true` when the task should run, `false` when it should be
57
+ * skipped. Unknown shapes default to `true` — we'd rather over-run
58
+ * than silently hide tasks on malformed config.
59
+ */
60
+ export declare const evaluateWhen: (when: TargetConditionObject | string | undefined, environment?: Record<string, string | undefined>, platform?: NodeJS.Platform) => boolean;
61
+ export interface VisTargetOptions {
62
+ /**
63
+ * How to forward affected files to the task process.
64
+ * Only used when invoked via `vis affected &lt;target>`.
65
+ * @default false
66
+ */
67
+ affectedFiles?: AffectedFilesMode;
68
+ /**
69
+ * Load environment variables from dotenv file(s) before running.
70
+ * - `string`: a single file path (relative to project root).
71
+ * - `string[]`: multiple files — later entries override earlier ones,
72
+ * so put more-specific files last (e.g. `[".env", ".env.local"]`).
73
+ * - `true`: auto-cascade in the Next/Vite order:
74
+ * `.env` → `.env.{NODE_ENV}` → `.env.local` → `.env.{NODE_ENV}.local`.
75
+ * Skips `.env.local` when NODE_ENV is `test`, matching Next.js.
76
+ */
77
+ envFile?: boolean | string | string[];
78
+ /**
79
+ * When true, the task is serialized with respect to parallel execution
80
+ * and must be run on the main process (claims stdin). Used for commands
81
+ * that read from the terminal.
82
+ * @default false
83
+ */
84
+ interactive?: boolean;
85
+ /**
86
+ * When true, the task is hidden from CLI listings and can only be invoked
87
+ * as a dependency of another task.
88
+ * @default false
89
+ */
90
+ internal?: boolean;
91
+ /**
92
+ * Serializes all tasks that share the same mutex name. Useful for tasks
93
+ * that contend on a shared resource (e.g., a database migration).
94
+ */
95
+ mutex?: string;
96
+ /**
97
+ * Restricts execution to specific operating systems. Tasks run on
98
+ * unmatched platforms are skipped with a warning.
99
+ */
100
+ osType?: TargetOsType | TargetOsType[];
101
+ /**
102
+ * When true, the task is a long-running / never-ending process.
103
+ * Persistent tasks are scheduled last, execute after all cacheable
104
+ * tasks complete, and are never cached.
105
+ * @default false
106
+ */
107
+ persistent?: boolean;
108
+ /**
109
+ * A preset that pre-fills a common bundle of options.
110
+ * User-provided fields always take precedence over the preset.
111
+ */
112
+ preset?: TargetPreset;
113
+ /**
114
+ * Run the task through a pseudo-terminal so color-aware tools
115
+ * (vitest, eslint, biome, …) render as if attached to a real TTY
116
+ * instead of a pipe. Output is captured via task-runner's
117
+ * `TerminalBuffer` so ANSI escapes are normalized into the final
118
+ * rendered state before reaching the reporter.
119
+ *
120
+ * Forces cache to off — PTY output can include timing-dependent
121
+ * frames (spinners) that aren't safe to replay from a cache.
122
+ * @default false
123
+ */
124
+ pty?: boolean;
125
+ /**
126
+ * Number of times to retry the task on failure. Uses an exponential
127
+ * backoff by default (1s, 2s, 4s, ...).
128
+ * @default 0
129
+ */
130
+ retryCount?: number;
131
+ /**
132
+ * Delay between retry attempts in milliseconds, or `"exponential"`
133
+ * for 2^attempt * 1000 ms.
134
+ * @default "exponential"
135
+ */
136
+ retryDelay?: number | "exponential";
137
+ /**
138
+ * When true, the command executes with the workspace root as CWD
139
+ * instead of the project root.
140
+ * @default false
141
+ */
142
+ runFromWorkspaceRoot?: boolean;
143
+ /**
144
+ * Controls whether the task runs in CI environments.
145
+ * @default true
146
+ */
147
+ runInCI?: RunInCI;
148
+ /**
149
+ * Per-target shell override. When set, the command runs through this
150
+ * shell instead of the platform default.
151
+ */
152
+ shell?: string;
153
+ /**
154
+ * Maximum wall-clock milliseconds a single task run is allowed to
155
+ * take before being killed. `0` / `undefined` means no timeout.
156
+ *
157
+ * When the timeout fires the task is sent SIGTERM then SIGKILL
158
+ * (via the concurrent runner's `killSignal`/`killTimeout`
159
+ * semantics) and the task exits with a failure status carrying the
160
+ * `[timeout]` marker in `terminalOutput`. Retries count against
161
+ * this per-attempt, not cumulatively.
162
+ *
163
+ * Use this to prevent runaway tasks from eating CI wall-clock time
164
+ * up to the job-level cutoff.
165
+ */
166
+ timeout?: number;
167
+ /**
168
+ * Per-target unix shell override, used on Linux and macOS.
169
+ * Takes precedence over `shell` on unix-like systems.
170
+ */
171
+ unixShell?: string;
172
+ /**
173
+ * Conditional gate: the task is scheduled only when `when` evaluates
174
+ * truthy. Shapes:
175
+ * - `"$VAR"` — run only if the env var is non-empty
176
+ * - `"!VAR"` — run only if the env var is empty/unset
177
+ * - `{ env: "NAME", equals: "value" }` — run only if env equals
178
+ * - `{ env: "NAME", in: ["a", "b"] }` — run only if env is in set
179
+ * - `{ platform: "darwin" | "linux" | "win32" }` — OS gate
180
+ *
181
+ * Kept declarative on purpose — no dynamic code execution. For
182
+ * richer logic, use osType/runInCI or a pre-hook script.
183
+ */
184
+ when?: TargetConditionObject | string;
185
+ /**
186
+ * Per-target windows shell override, used on Windows.
187
+ * Takes precedence over `shell` on Windows.
188
+ */
189
+ windowsShell?: string;
190
+ }
191
+ /**
192
+ * An extended target configuration that adds the vis-specific options
193
+ * on top of task-runner's `TargetConfiguration`.
194
+ */
195
+ export interface VisTargetConfiguration extends Omit<TargetConfiguration, "options"> {
196
+ /**
197
+ * Alternate names that resolve to this target on the CLI. Useful
198
+ * for shortening long canonical names (`test` ↔ `t`) or for
199
+ * offering migration-friendly aliases when renaming targets.
200
+ * Aliases must be globally unique within the workspace.
201
+ */
202
+ aliases?: string[];
203
+ /**
204
+ * One-line description surfaced by `vis list` and (in future)
205
+ * per-task `--help`. Kept short — longer docs belong in project
206
+ * READMEs or vis.config.ts comments.
207
+ */
208
+ description?: string;
209
+ /** Vis-specific target options. */
210
+ options?: VisTargetOptions;
211
+ /** Preset applied before user-specified options. */
212
+ preset?: TargetPreset;
213
+ /**
214
+ * Semantic task type. Affects caching defaults and CI filtering.
215
+ * @default "test"
216
+ */
217
+ type?: TargetType;
218
+ }
219
+ /**
220
+ * Apply preset defaults to a target configuration. Returns a new
221
+ * object — never mutates its input.
222
+ */
223
+ export declare const applyPreset: (target: VisTargetConfiguration) => VisTargetConfiguration;
224
+ /** Detects the current operating system as a {@link TargetOsType}. */
225
+ export declare const detectCurrentOs: () => TargetOsType;
226
+ /**
227
+ * Returns `true` if the given OS matches the target's `osType` filter.
228
+ * Tasks without an `osType` option always match.
229
+ */
230
+ export declare const matchesOs: (options: VisTargetOptions | undefined, currentOs?: TargetOsType) => boolean;
231
+ /**
232
+ * Returns `true` if the task should run in the current environment based
233
+ * on its `runInCI` option. `affectedInCi` should indicate whether the
234
+ * project is in the current affected set (only relevant for `"affected"`).
235
+ */
236
+ export declare const shouldRunInCI: (options: VisTargetOptions | undefined, isCi: boolean, affectedInCi?: boolean) => boolean;
237
+ /**
238
+ * Resolves the `envFile` target option into a merged env map.
239
+ *
240
+ * - `string` → load that single file
241
+ * - `string[]` → load each in order; later entries win on key collision
242
+ * - `true` → load the Next/Vite cascade:
243
+ * `.env` → `.env.{NODE_ENV}` → `.env.local` → `.env.{NODE_ENV}.local`
244
+ * (`.env.local` skipped for NODE_ENV=test, matching Next.js)
245
+ *
246
+ * Silently skips files that don't exist. Returns `{}` when no file in
247
+ * the cascade is present — safe to merge directly into the child env.
248
+ */
249
+ export declare const loadEnvFile: (projectRoot: string, envFile: boolean | string | string[]) => Record<string, string>;
250
+ /**
251
+ * Pick the effective shell for a target on the current platform.
252
+ * Returns `undefined` if no per-target shell is configured.
253
+ */
254
+ export declare const resolveTargetShell: (options: VisTargetOptions | undefined, currentOs?: TargetOsType) => string | undefined;
255
+ /**
256
+ * Returns the default `cache` value implied by the target type.
257
+ * - `build`: cached by default.
258
+ * - `run`: never cached.
259
+ * - `test`: cached by default.
260
+ */
261
+ export declare const defaultCacheForType: (type: TargetType | undefined) => boolean | undefined;
@@ -1,3 +1,4 @@
1
+ import type { ScrollViewRef } from "@visulima/tui";
1
2
  import type { TaskRowData } from "./TaskRow.d.ts";
2
3
  interface OutputPanelProps {
3
4
  /** Duration in ms (for top-right border display). */
@@ -6,7 +7,7 @@ interface OutputPanelProps {
6
7
  /** Whether interactive input mode is active (keystrokes forwarded to PTY). */
7
8
  interactiveMode?: boolean;
8
9
  output: string;
9
- scrollRef?: React.RefObject<import("@visulima/tui").ScrollViewRef>;
10
+ scrollRef?: React.RefObject<ScrollViewRef | null>;
10
11
  /** Whether to show "&lt;enter> full screen" hint in bottom border. */
11
12
  showFullscreenHint?: boolean;
12
13
  status: TaskRowData["status"] | undefined;
@@ -11,7 +11,7 @@ interface TaskListPanelProps {
11
11
  parallelSlots?: number;
12
12
  pinnedTaskIds: [string | null, string | null];
13
13
  rows: TaskRowData[];
14
- scrollRef: React.RefObject<ScrollViewRef>;
14
+ scrollRef: React.RefObject<ScrollViewRef | null>;
15
15
  selectedIndex: number;
16
16
  title: string;
17
17
  }
@@ -47,7 +47,7 @@ export declare class TaskStore {
47
47
  #private;
48
48
  constructor(tasks: Task[]);
49
49
  getSnapshot: () => TaskState;
50
- subscribe: (listener: Listener) => () => void;
50
+ subscribe: (listener: Listener) => (() => void);
51
51
  startTasks(started: Task[]): void;
52
52
  endTasks(results: TaskResult[]): void;
53
53
  addOutput(taskId: string, output: string): void;
@@ -35,7 +35,7 @@ export declare class DevcontainerStore {
35
35
  #private;
36
36
  constructor(config: DevcontainerConfig | null, hadComments: boolean, detectedPm?: PackageManager | null);
37
37
  getSnapshot: () => DevcontainerState;
38
- subscribe: (listener: Listener) => () => void;
38
+ subscribe: (listener: Listener) => (() => void);
39
39
  setSection(section: SectionId): void;
40
40
  nextSection(): void;
41
41
  previousSection(): void;
@@ -16,4 +16,4 @@ export declare const FEATURE_MOUNTS: {
16
16
  * Get suggested mounts based on the package manager and enabled features.
17
17
  * Returns only mounts that are not already in the current config.
18
18
  */
19
- export declare const getSuggestedMounts: (pm: PackageManager | null, enabledFeatures: Record<string, Record<string, unknown> | string>, currentMounts: Array<MountEntry | string>) => MountEntry[];
19
+ export declare const getSuggestedMounts: (pm: PackageManager | null, enabledFeatures: Record<string, Record<string, unknown> | string>, currentMounts: (MountEntry | string)[]) => MountEntry[];
@@ -8,5 +8,5 @@ interface GeneralSectionProps {
8
8
  }
9
9
  declare const GeneralSection: ({ config, fieldEditing, fieldIndex, onUpdate }: GeneralSectionProps) => React.JSX.Element;
10
10
  export declare const GENERAL_FIELD_COUNT: number;
11
- export declare const GENERAL_BOOLEAN_FIELDS: readonly ("privileged" | "overrideCommand")[];
11
+ export declare const GENERAL_BOOLEAN_FIELDS: ReadonlyArray<"privileged" | "overrideCommand">;
12
12
  export default GeneralSection;
@@ -5,7 +5,7 @@ interface PreviewPanelProps {
5
5
  readonly hadComments: boolean;
6
6
  readonly jsonPreview: string;
7
7
  readonly mode: "create" | "edit";
8
- readonly scrollRef: React.RefObject<ScrollViewRef>;
8
+ readonly scrollRef: React.RefObject<ScrollViewRef | null>;
9
9
  }
10
10
  declare const PreviewPanel: ({ focused, hadComments, jsonPreview, mode, scrollRef }: PreviewPanelProps) => React.JSX.Element;
11
11
  export default PreviewPanel;
@@ -29,16 +29,16 @@ export interface DevcontainerConfig {
29
29
  };
30
30
  dockerComposeFile?: string | string[];
31
31
  features?: Record<string, Record<string, unknown> | string>;
32
- forwardPorts?: Array<number | string>;
32
+ forwardPorts?: (number | string)[];
33
33
  image?: string;
34
- mounts?: Array<MountEntry | string>;
34
+ mounts?: (MountEntry | string)[];
35
35
  name?: string;
36
36
  onCreateCommand?: string | string[];
37
37
  overrideCommand?: boolean;
38
+ portsAttributes?: Record<string, PortAttributes>;
38
39
  postAttachCommand?: string | string[];
39
40
  postCreateCommand?: string | string[];
40
41
  postStartCommand?: string | string[];
41
- portsAttributes?: Record<string, PortAttributes>;
42
42
  privileged?: boolean;
43
43
  remoteEnv?: Record<string, string>;
44
44
  remoteUser?: string;
@@ -50,4 +50,4 @@ export interface DevcontainerConfig {
50
50
  workspaceMount?: string;
51
51
  }
52
52
  export type SectionId = "compose" | "environment" | "extensions" | "features" | "general" | "lifecycle" | "mounts" | "ports";
53
- export declare const SECTION_ORDER: readonly SectionId[];
53
+ export declare const SECTION_ORDER: ReadonlyArray<SectionId>;
@@ -25,7 +25,7 @@ export declare class GraphStore {
25
25
  #private;
26
26
  constructor(projectGraph: ProjectGraph);
27
27
  getSnapshot: () => GraphState;
28
- subscribe: (listener: Listener) => () => void;
28
+ subscribe: (listener: Listener) => (() => void);
29
29
  getFilteredNodes(): GraphNode[];
30
30
  getStats(): {
31
31
  apps: number;
@@ -4,7 +4,7 @@ import type { GraphNode } from "./GraphStore.d.ts";
4
4
  interface ProjectDetailPanelProps {
5
5
  focused: boolean;
6
6
  node: GraphNode | null;
7
- scrollRef?: React.RefObject<ScrollViewRef>;
7
+ scrollRef?: React.RefObject<ScrollViewRef | null>;
8
8
  }
9
9
  declare const ProjectDetailPanel: ({ focused, node, scrollRef }: ProjectDetailPanelProps) => React.JSX.Element;
10
10
  export default ProjectDetailPanel;
@@ -3,7 +3,7 @@ import type { OptimizeEntry } from "./OptimizeStore.d.ts";
3
3
  interface OptimizeDetailPanelProps {
4
4
  entry: OptimizeEntry | null;
5
5
  focused: boolean;
6
- scrollRef?: React.RefObject<ScrollViewRef>;
6
+ scrollRef?: React.RefObject<ScrollViewRef | null>;
7
7
  }
8
8
  declare const OptimizeDetailPanel: ({ entry, focused, scrollRef }: OptimizeDetailPanelProps) => React.JSX.Element;
9
9
  export default OptimizeDetailPanel;
@@ -32,7 +32,7 @@ declare class OptimizeStore {
32
32
  #private;
33
33
  constructor(entries: OptimizeEntry[]);
34
34
  getSnapshot: () => OptimizeState;
35
- subscribe: (listener: Listener) => () => void;
35
+ subscribe: (listener: Listener) => (() => void);
36
36
  getFilteredEntries: () => OptimizeEntry[];
37
37
  select(index: number): void;
38
38
  toggleCheck(packageName: string): void;
@@ -6,7 +6,7 @@ interface PackageDetailPanelProps {
6
6
  entry: OutdatedEntry | null;
7
7
  focused: boolean;
8
8
  recommendation?: AiRecommendation;
9
- scrollRef?: React.RefObject<ScrollViewRef>;
9
+ scrollRef?: React.RefObject<ScrollViewRef | null>;
10
10
  }
11
11
  declare const PackageDetailPanel: ({ changelogUrl, entry, focused, recommendation, scrollRef }: PackageDetailPanelProps) => React.JSX.Element;
12
12
  export default PackageDetailPanel;
@@ -4,9 +4,9 @@ interface PackageListPanelProps {
4
4
  checkedEntries: Set<string>;
5
5
  entries: OutdatedEntry[];
6
6
  filterActive: boolean;
7
+ filteredOutCount: number;
7
8
  filterText: string;
8
9
  filterType: FilterType;
9
- filteredOutCount: number;
10
10
  focused: boolean;
11
11
  groupedByCatalog: Map<string, OutdatedEntry[]>;
12
12
  isDryRun: boolean;
@@ -17,5 +17,5 @@ interface PackageListPanelProps {
17
17
  totalEntries: number;
18
18
  viewportHeight: number;
19
19
  }
20
- declare const PackageListPanel: ({ checkedEntries, entries, filterActive, filterText, filterType, filteredOutCount, focused, groupedByCatalog, isDryRun, scrollOffset, selectedIndex, totalCatalogEntries, totalChecked, totalEntries, viewportHeight, }: PackageListPanelProps) => React.JSX.Element;
20
+ declare const PackageListPanel: ({ checkedEntries, entries, filterActive, filteredOutCount, filterText, filterType, focused, groupedByCatalog, isDryRun, scrollOffset, selectedIndex, totalCatalogEntries, totalChecked, totalEntries, viewportHeight, }: PackageListPanelProps) => React.JSX.Element;
21
21
  export default PackageListPanel;
@@ -38,7 +38,7 @@ export declare class UpdateStore {
38
38
  #private;
39
39
  constructor(entries: OutdatedEntry[], aiResult?: AiAnalysisResult | null);
40
40
  getSnapshot: () => UpdateState;
41
- subscribe: (listener: Listener) => () => void;
41
+ subscribe: (listener: Listener) => (() => void);
42
42
  /** Get the currently filtered + visible entries. */
43
43
  getFilteredEntries(): OutdatedEntry[];
44
44
  /** Get AI recommendation for a specific package. */
@@ -7,12 +7,12 @@ interface VisUpdateAppProps {
7
7
  changelogUrls?: Map<string, string>;
8
8
  /** Total unique packages checked by the registry. */
9
9
  checkedCount?: number;
10
- /** Total catalog entries (before deduplication). */
11
- totalCatalogEntries?: number;
12
10
  /** Packages that have newer versions but were filtered out by the target constraint. */
13
11
  filteredOutEntries?: OutdatedEntry[];
14
12
  isDryRun: boolean;
15
13
  store: UpdateStore;
14
+ /** Total catalog entries (before deduplication). */
15
+ totalCatalogEntries?: number;
16
16
  }
17
- declare const VisUpdateApp: ({ autoExitSeconds, changelogUrls, checkedCount, filteredOutEntries, isDryRun, store, totalCatalogEntries }: VisUpdateAppProps) => React.JSX.Element;
17
+ declare const VisUpdateApp: ({ autoExitSeconds, changelogUrls, checkedCount, filteredOutEntries, isDryRun, store, totalCatalogEntries, }: VisUpdateAppProps) => React.JSX.Element;
18
18
  export default VisUpdateApp;
@@ -1,5 +1,6 @@
1
1
  import type { LifeCycleInterface, Task } from "@visulima/task-runner";
2
2
  import { TaskStore } from "./components/TaskStore.d.ts";
3
+ import type { StdinEntry } from "./types.d.ts";
3
4
  interface DynamicOutputOptions {
4
5
  args: {
5
6
  parallel?: boolean | number;
@@ -9,7 +10,7 @@ interface DynamicOutputOptions {
9
10
  autoExit?: boolean | number;
10
11
  projectNames: string[];
11
12
  /** Registry of writable stdin entries keyed by task ID, for interactive input. */
12
- stdinRegistry?: Map<string, import("./types").StdinEntry>;
13
+ stdinRegistry?: Map<string, StdinEntry>;
13
14
  tasks: Task[];
14
15
  }
15
16
  interface DynamicOutputResult {
@@ -1,8 +1,14 @@
1
- import type { LifeCycleInterface, Task, TaskResult, TaskStatus } from "@visulima/task-runner";
1
+ import type { LifeCycleInterface, LogReporter, Task, TaskResult, TaskStatus } from "@visulima/task-runner";
2
2
  interface StaticOutputOptions {
3
3
  args: {
4
4
  targets: string[];
5
5
  };
6
+ /**
7
+ * Optional {@link LogReporter} that takes over `printTaskTerminalOutput`
8
+ * when the user picks a `--log` mode. Absent, the CI-style
9
+ * separator+status formatting is kept (vis's default).
10
+ */
11
+ logReporter?: LogReporter;
6
12
  projectNames: string[];
7
13
  tasks: Task[];
8
14
  }
@@ -0,0 +1,65 @@
1
+ import type { TaskResults } from "@visulima/task-runner";
2
+ /**
3
+ * Debounced multi-directory file watcher. Watches one or more project
4
+ * roots recursively and invokes `onChange` at most once per debounce
5
+ * window. Ignores edits inside `node_modules` and `.git`.
6
+ *
7
+ * `node:fs.watch({ recursive: true })` is supported on Linux, macOS,
8
+ * and Windows since Node 20+, so no additional dependency is needed.
9
+ */
10
+ export interface WatchHandle {
11
+ close: () => void;
12
+ }
13
+ export interface WatchOptions {
14
+ /** Debounce window in milliseconds. Defaults to 150 ms. */
15
+ debounceMs?: number;
16
+ /**
17
+ * Optional predicate invoked against every raw file event
18
+ * (relative path as provided by `node:fs.watch`). Used by
19
+ * tracked-access watch mode to drop changes to files the last
20
+ * run didn't actually read. Return `false` to discard the event.
21
+ */
22
+ filter?: (path: string) => boolean;
23
+ /** Fired when a watched file changes (after debounce). */
24
+ onChange: (changedPaths: string[]) => void | Promise<void>;
25
+ /** Project roots to watch, resolved to absolute paths. */
26
+ paths: string[];
27
+ }
28
+ /**
29
+ * The set of workspace-relative paths that a run actually read, plus
30
+ * the minimal set of directories that contain them. Used by
31
+ * tracked-access watch mode to only re-trigger runs when a file the
32
+ * previous run actually consumed changes — drops noise from unrelated
33
+ * edits under the project roots.
34
+ *
35
+ * `files` stays workspace-relative because `node:fs.watch` emits
36
+ * paths relative to the watched root.
37
+ */
38
+ export interface TrackedWatchTargets {
39
+ directories: string[];
40
+ files: Set<string>;
41
+ }
42
+ /**
43
+ * Extracts the set of files every task in `results` reported as an
44
+ * input. Returns empty sets when no task carries hash details — the
45
+ * caller falls back to watching project roots in that case.
46
+ *
47
+ * Directories are deduplicated and pruned so a parent dir shadows its
48
+ * descendants — watching both would double-fire events.
49
+ */
50
+ export declare const collectTrackedWatchTargets: (results: TaskResults, workspaceRoot: string) => TrackedWatchTargets;
51
+ /**
52
+ * Translates a set of workspace-relative tracked paths into a filter
53
+ * suitable for {@link startWatcher}. The watcher emits paths relative
54
+ * to its watched root — which, after pruning, may be any ancestor
55
+ * directory — so we match on the **suffix** of the tracked path
56
+ * instead of an exact comparison.
57
+ */
58
+ export declare const createTrackedFileFilter: (trackedFiles: Set<string>, workspaceRoot: string, watchedDirectories: string[]) => ((path: string) => boolean);
59
+ /**
60
+ * Starts recursive file watchers on the given paths and invokes
61
+ * {@link WatchOptions.onChange} after a debounce window.
62
+ * @param options Watcher configuration.
63
+ * @returns A handle to close all watchers.
64
+ */
65
+ export declare const startWatcher: (options: WatchOptions) => WatchHandle;