@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,29 @@
1
+ import type { MigrateLogger, MigrationReport } from "./types.d.ts";
2
+ /**
3
+ * Serialises a config object to a pretty-printed TypeScript string with
4
+ * unquoted keys (idiomatic TS style).
5
+ * @param obj The configuration object to serialise.
6
+ * @returns A JSON string with keys unquoted for TS readability.
7
+ */
8
+ export declare const serializeConfigObject: (obj: Record<string, unknown>) => string;
9
+ /**
10
+ * Writes (or previews) a rendered `vis.config.ts`. Guards against
11
+ * overwriting an existing file and logs the outcome.
12
+ * @param workspaceRoot Absolute workspace root path.
13
+ * @param rendered The full file content to write.
14
+ * @param options Migration options (`dryRun` controls preview mode).
15
+ * @param logger Logger for user feedback.
16
+ * @param report Migration report to append warnings to.
17
+ * @returns `true` if written (or previewed in dry-run), `false` if skipped.
18
+ */
19
+ export declare const writeVisConfig: (workspaceRoot: string, rendered: string, options: {
20
+ dryRun?: boolean;
21
+ }, logger: MigrateLogger, report: MigrationReport) => boolean;
22
+ /**
23
+ * Reads and parses a JSON config file from the workspace root.
24
+ * @param workspaceRoot Absolute workspace root path.
25
+ * @param fileName File name relative to the workspace root.
26
+ * @returns The parsed object, or `undefined` if the file doesn't exist.
27
+ * @throws On JSON parse errors.
28
+ */
29
+ export declare const readJsonConfig: <T>(workspaceRoot: string, fileName: string) => T | undefined;
@@ -0,0 +1,11 @@
1
+ import type { MigrateLogger, MigrationReport } from "./types.d.ts";
2
+ /**
3
+ * Translates a `turbo.json` into a `vis.config.ts`.
4
+ * @param workspaceRoot Absolute workspace root path.
5
+ * @param options Migration options.
6
+ * @param logger Logger for user feedback.
7
+ * @param report Migration report to append manual steps and warnings.
8
+ */
9
+ export declare const migrateTurborepo: (workspaceRoot: string, options: {
10
+ dryRun?: boolean;
11
+ }, logger: MigrateLogger, report: MigrationReport) => void;
@@ -3,10 +3,16 @@ interface MigrateLogger {
3
3
  warn: (message: string) => void;
4
4
  }
5
5
  interface MigrationReport {
6
+ backupsCreated: string[];
6
7
  gitHooksConfigured: boolean;
7
8
  inlinedLintStagedConfigCount: number;
8
9
  manualSteps: string[];
9
10
  mergedStagedConfigCount: number;
11
+ perMigration: Record<string, {
12
+ removedConfigCount: number;
13
+ removedPackageCount: number;
14
+ rewrittenScriptCount: number;
15
+ }>;
10
16
  removedConfigCount: number;
11
17
  removedPackageCount: number;
12
18
  rewrittenScriptCount: number;
@@ -15,6 +21,7 @@ interface MigrationReport {
15
21
  declare const createMigrationReport: () => MigrationReport;
16
22
  declare const addMigrationWarning: (report: MigrationReport | undefined, warning: string) => void;
17
23
  declare const addManualStep: (report: MigrationReport | undefined, step: string) => void;
24
+ declare const bumpPerMigration: (report: MigrationReport, migration: string, field: "removedConfigCount" | "removedPackageCount" | "rewrittenScriptCount", delta?: number) => void;
18
25
  type PackageManagerType = "bun" | "npm" | "pnpm" | "yarn";
19
26
  export type { MigrateLogger, MigrationReport, PackageManagerType };
20
- export { addManualStep, addMigrationWarning, createMigrationReport };
27
+ export { addManualStep, addMigrationWarning, bumpPerMigration, createMigrationReport };
@@ -0,0 +1,12 @@
1
+ import type { MigrateLogger } from "./types.d.ts";
2
+ export interface VerificationIssue {
3
+ detail: string;
4
+ kind: "config" | "script" | "hook" | "devDep";
5
+ location: string;
6
+ }
7
+ /**
8
+ * Check that a prior `vis migrate gitleaks` / `secretlint` run was complete:
9
+ * no stray scripts, devDependencies, hooks, or configs referencing the old
10
+ * tools. Safe to run repeatedly — purely read-only.
11
+ */
12
+ export declare const verifyMigration: (root: string, logger: MigrateLogger) => VerificationIssue[];
@@ -1,3 +1,16 @@
1
1
  import type { Command } from "@visulima/cerebro";
2
+ /**
3
+ * Shared counter for the global `--retry-budget` flag. Tasks consult
4
+ * `claim(requested)` at launch to grab up to `requested` retries; the
5
+ * budget is decremented conservatively by the claim (not by actual
6
+ * retries consumed) to keep the bound simple to reason about. Once
7
+ * the budget is exhausted, subsequent tasks run with no retries —
8
+ * surfacing flakiness instead of silently burning CI time.
9
+ */
10
+ export interface RetryBudget {
11
+ claim: (requested: number) => number;
12
+ readonly remaining: number;
13
+ }
14
+ export declare const createRetryBudget: (limit: number) => RetryBudget;
2
15
  declare const run: Command;
3
16
  export default run;
@@ -0,0 +1,10 @@
1
+ import type { Command } from "@visulima/cerebro";
2
+ /**
3
+ * `vis sbom` — CycloneDX 1.6 Software Bill of Materials generator.
4
+ *
5
+ * Mirrors `vis docker scaffold` in shape: accepts an optional `--focus`
6
+ * list, walks the workspace graph, and writes the result to disk
7
+ * (or stdout).
8
+ */
9
+ declare const sbom: Command;
10
+ export default sbom;
@@ -0,0 +1,3 @@
1
+ import type { Command } from "@visulima/cerebro";
2
+ declare const secrets: Command;
3
+ export default secrets;
@@ -1,3 +1,10 @@
1
1
  import type { Command } from "@visulima/cerebro";
2
+ import type { RunOptions, StagedConfig } from "../index.d.ts";
3
+ /**
4
+ * Translates the cerebro-parsed CLI options (kebab-case keys, string/boolean values)
5
+ * into a strongly-typed `RunOptions` object. Only the flags the user passed are
6
+ * forwarded — the rest fall through to `runStaged`'s own defaults.
7
+ */
8
+ export declare const buildRunOptions: (raw: Record<string, unknown>, stagedConfig: StagedConfig | undefined) => RunOptions;
2
9
  declare const staged: Command;
3
10
  export default staged;
@@ -0,0 +1,3 @@
1
+ import type { Command } from "@visulima/cerebro";
2
+ declare const status: Command;
3
+ export default status;
@@ -0,0 +1,16 @@
1
+ import type { Command } from "@visulima/cerebro";
2
+ /**
3
+ * `vis sync &lt;kind>` performs workspace-wide synchronisations that
4
+ * cannot be derived from a task graph alone.
5
+ *
6
+ * Currently supported kinds:
7
+ *
8
+ * - `codeowners`: aggregates `owners` entries from every project's
9
+ * project.json into a single CODEOWNERS file at the repo root
10
+ * (or `.github/CODEOWNERS` when the target flag is set).
11
+ *
12
+ * Additional kinds will land alongside their features (for example:
13
+ * `tsconfig-references`, `package-json` sort, `hooks`).
14
+ */
15
+ declare const sync: Command;
16
+ export default sync;
@@ -0,0 +1,3 @@
1
+ import type { Command } from "@visulima/cerebro";
2
+ declare const taskWhy: Command;
3
+ export default taskWhy;
package/dist/config.d.ts CHANGED
@@ -1,5 +1,6 @@
1
+ import type { VisPlugin } from "./hooks.d.ts";
1
2
  import type { VisConfig } from "./workspace.d.ts";
2
- /** Supported config file names, checked in order. */
3
+ /** Supported config file names, checked in priority order. */
3
4
  declare const CONFIG_FILES: string[];
4
5
  /**
5
6
  * Secure-by-default security settings based on npm supply chain best practices.
@@ -16,6 +17,11 @@ declare const SECURITY_DEFAULTS: Required<Pick<NonNullable<VisConfig["security"]
16
17
  declare const applyDefaults: (config: VisConfig) => VisConfig;
17
18
  /**
18
19
  * Find the vis config file in a directory.
20
+ *
21
+ * Reads the directory listing once and intersects it with the known
22
+ * config filenames rather than `stat`-ing each candidate — one syscall
23
+ * instead of up to six. Priority order is preserved via
24
+ * `CONFIG_FILES` so `.ts` still wins over `.mjs` when both exist.
19
25
  * @param directory The directory to search in.
20
26
  * @returns The absolute path to the config file, or `undefined` if not found.
21
27
  */
@@ -64,4 +70,13 @@ declare const loadVisConfig: (workspaceRoot: string) => Promise<VisConfig>;
64
70
  * ```
65
71
  */
66
72
  declare const defineConfig: (config: VisConfig) => VisConfig;
67
- export { applyDefaults, CONFIG_FILES, defineConfig, findVisConfigFile, loadVisConfig, SECURITY_DEFAULTS };
73
+ /**
74
+ * Type-safe helper for defining a vis plugin. Pure identity — exists
75
+ * only so plugin authors get inference from the `VisPlugin` contract
76
+ * without needing a `satisfies` annotation.
77
+ */
78
+ declare const definePlugin: (plugin: VisPlugin) => VisPlugin;
79
+ export type { VisHooks, VisPlugin } from "./hooks.d.ts";
80
+ export type { OtelPluginOptions, OtelSpan, OtelTracer } from "./plugins/otel.d.ts";
81
+ export { otelPlugin } from "./plugins/otel.d.ts";
82
+ export { applyDefaults, CONFIG_FILES, defineConfig, definePlugin, findVisConfigFile, loadVisConfig, SECURITY_DEFAULTS };
package/dist/config.js CHANGED
@@ -1 +1 @@
1
- var m=Object.defineProperty;var u=(e,t)=>m(e,"name",{value:t,configurable:!0});import{createRequire as C}from"node:module";import{findCacheDirSync as w}from"@visulima/find-cache-dir";import{ensureDirSync as p,isAccessibleSync as D,readJsonSync as x,writeJsonSync as E}from"@visulima/fs";import{join as o,dirname as I}from"@visulima/path";import{createJiti as P}from"jiti";const v=C(import.meta.url),r=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,d=u(e=>{if(typeof r<"u"&&r.versions&&r.versions.node){const[t,s]=r.versions.node.split(".").map(Number);if(t>22||t===22&&s>=3||t===20&&s>=16)return r.getBuiltinModule(e)}return v(e)},"__cjs_getBuiltinModule"),{createHash:_}=d("node:crypto"),{existsSync:y,readFileSync:S,copyFileSync:j,unlinkSync:b}=d("node:fs"),{tmpdir:F}=d("node:os");var T=Object.defineProperty,n=u((e,t)=>T(e,"name",{value:t,configurable:!0}),"e");const A=["vis.config.ts","vis.config.mts","vis.config.cts","vis.config.js","vis.config.mjs","vis.config.cjs"],J={blockExoticSubdeps:!0,strictDepBuilds:!0,trustPolicy:"no-downgrade",trustPolicyIgnoreAfter:43200},V=n(e=>({...J,...e}),"mergeSecurityDefaults"),l=n(e=>({...e,security:V(e.security),update:{security:!0,target:"minor",...e.update}}),"applyDefaults"),k=n(e=>{for(const t of A){const s=o(e,t);if(y(s))return s}},"findVisConfigFile"),q=n(e=>_("sha256").update(S(e)).digest("hex"),"hashFileContents"),B=n(e=>{const t=o(e,"node_modules");if(y(t)){const i=o(t,".cache","vis");return p(i),o(i,"vis-config-cache.json")}const s=w("vis",{create:!0,cwd:e});return s?o(s,"vis-config-cache.json"):void 0},"getConfigCachePath"),N=n((e,t)=>{if(D(e))try{const s=x(e);if(s.hash===t)return s.config}catch{}},"readConfigCache"),O=n((e,t,s)=>{try{p(I(e)),E(e,{config:s,hash:t})}catch{}},"writeConfigCache"),H=n(async e=>{const t=k(e);if(!t)return l({});const s=q(t),i=B(e);if(i){const g=N(i,s);if(g)return g}const h=t.slice(t.lastIndexOf(".")),a=o(F(),`vis-config-${s}${h}`);j(t,a);let c;try{c=await P(e,{fsCache:!1,moduleCache:!1}).import(a,{default:!0,try:!0})??{}}finally{try{b(a)}catch{}}let f;return f=l(typeof c=="function"?await c()??{}:c),i&&O(i,s,f),f},"loadVisConfig"),Y=n(e=>l(e),"defineConfig");export{A as CONFIG_FILES,J as SECURITY_DEFAULTS,l as applyDefaults,Y as defineConfig,k as findVisConfigFile,H as loadVisConfig};
1
+ var b=Object.defineProperty;var l=(e,t)=>b(e,"name",{value:t,configurable:!0});import{createRequire as k}from"node:module";import{findCacheDirSync as D}from"@visulima/find-cache-dir";import{isAccessibleSync as y,ensureDirSync as m,readJsonSync as T,writeJsonSync as x}from"@visulima/fs";import{join as f,dirname as E}from"@visulima/path";import{createJiti as I}from"jiti";const _=k(import.meta.url),d=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,v=l(e=>{if(typeof d<"u"&&d.versions&&d.versions.node){const[t,n]=d.versions.node.split(".").map(Number);if(t>22||t===22&&n>=3||t===20&&n>=16)return d.getBuiltinModule(e)}return _(e)},"__cjs_getBuiltinModule"),{createHash:C}=v("node:crypto"),{readdirSync:j,copyFileSync:w,unlinkSync:P,readFileSync:A}=v("node:fs"),{tmpdir:F}=v("node:os");var O=Object.defineProperty,u=l((e,t)=>O(e,"name",{value:t,configurable:!0}),"a");const $=1,g=2,X=u(e=>{const{renameSpan:t,tracer:n}=e;let s;const a=new Map;return z({hooks:{"run:after":u(r=>{if(!s)return;const i=[...r.values()].filter(o=>o.status==="failure").length;s.setAttribute?.("vis.run.tasks_total",r.size),s.setAttribute?.("vis.run.tasks_failed",i),i>0?s.setStatus?.({code:g,message:`${String(i)} task(s) failed`}):s.setStatus?.({code:$}),s.end(),s=void 0;for(const o of a.values())o.end();a.clear()},"run:after"),"run:before":u(r=>{s&&(s.setStatus?.({code:g,message:"run:before fired while previous run was still active"}),s.end());for(const i of a.values())i.end();a.clear(),s=n.startSpan("vis.run",{attributes:{"vis.run.task_count":r.tasks.length,"vis.workspace_root":r.workspaceRoot}})},"run:before"),"task:after":u((r,i)=>{const o=a.get(r.id);o&&(o.setAttribute?.("vis.task.exit_code",i.code??0),o.setAttribute?.("vis.task.cache_status",i.status),o.end(),a.delete(r.id))},"task:after"),"task:before":u(r=>{const i=a.get(r.id);i&&(i.setStatus?.({code:g,message:"retried — superseded by new attempt"}),i.end());const o=n.startSpan(t?t(r):r.id,{attributes:{"vis.task.id":r.id,"vis.task.project":r.target.project,"vis.task.target":r.target.target}});a.set(r.id,o)},"task:before"),"task:failure":u((r,i)=>{const o=a.get(r.id);o&&o.setStatus?.({code:g,message:`Task failed with exit code ${String(i.code??-1)}`})},"task:failure")},name:"otel"})},"otelPlugin");var J=Object.defineProperty,c=l((e,t)=>J(e,"name",{value:t,configurable:!0}),"s");const S=["vis.config.ts","vis.config.mts","vis.config.cts","vis.config.js","vis.config.mjs","vis.config.cjs"],R=new Set(S),V={blockExoticSubdeps:!0,strictDepBuilds:!0,trustPolicy:"no-downgrade",trustPolicyIgnoreAfter:43200},q=c(e=>({...V,...e}),"mergeSecurityDefaults"),p=c(e=>({...e,security:q(e.security),update:{security:!0,target:"minor",...e.update}}),"applyDefaults"),B=c(e=>{let t;try{t=j(e)}catch{return}const n=new Set(t.filter(s=>R.has(s)));for(const s of S)if(n.has(s))return f(e,s)},"findVisConfigFile"),M=c(e=>C("sha256").update(A(e)).digest("hex"),"hashFileContents"),N=c(e=>{const t=f(e,"node_modules");if(y(t)){const s=f(t,".cache","vis");return m(s),f(s,"vis-config-cache.json")}const n=D("vis",{create:!0,cwd:e});return n?f(n,"vis-config-cache.json"):void 0},"getConfigCachePath"),L=c((e,t)=>{if(y(e))try{const n=T(e);if(n.hash===t)return n.config}catch{}},"readConfigCache"),U=c((e,t,n)=>{try{m(E(e)),x(e,{config:n,hash:t})}catch{}},"writeConfigCache"),Z=c(async e=>{const t=B(e);if(!t)return p({});const n=M(t),s=N(e);if(s){const h=L(s,n);if(h)return h}const a=t.slice(t.lastIndexOf(".")),r=f(F(),`vis-config-${n}${a}`);w(t,r);let i;try{i=await I(e,{fsCache:!1,moduleCache:!1}).import(r,{default:!0,try:!0})??{}}finally{try{P(r)}catch{}}let o;return o=p(typeof i=="function"?await i()??{}:i),s&&U(s,n,o),o},"loadVisConfig"),ee=c(e=>p(e),"defineConfig"),z=c(e=>e,"definePlugin");export{S as CONFIG_FILES,V as SECURITY_DEFAULTS,p as applyDefaults,ee as defineConfig,z as definePlugin,B as findVisConfigFile,Z as loadVisConfig,X as otelPlugin};
@@ -0,0 +1,73 @@
1
+ import type { ProjectGraph, WorkspaceConfiguration } from "@visulima/task-runner";
2
+ /**
3
+ * Minimal Docker scaffold: copies the set of files Docker's layer
4
+ * cache benefits from keeping stable (manifests + lockfiles) so an
5
+ * image build can `COPY` them first and install dependencies before
6
+ * source code arrives.
7
+ *
8
+ * Computes the set of projects a focus project depends on and copies
9
+ * only their `package.json` + `project.json` + root manifests, not
10
+ * the whole source tree. Compare with moon's `moon docker scaffold`.
11
+ */
12
+ /** Name of the manifest file written by scaffold and read by prune. */
13
+ export declare const DOCKER_MANIFEST_FILENAME = "vis-docker-manifest.json";
14
+ export interface ScaffoldOptions {
15
+ /** Project names to focus on — transitive deps are pulled in automatically. */
16
+ focus: string[];
17
+ /**
18
+ * Include the full source tree for the focus project(s). Used for the
19
+ * `sources` stage so the build can actually compile code after deps
20
+ * are installed.
21
+ */
22
+ includeSources?: boolean;
23
+ /** Output directory, typically `.vis/docker/workspace`. */
24
+ outDir: string;
25
+ /** Project graph used to compute the transitive dependency closure. */
26
+ projectGraph: ProjectGraph;
27
+ /** Workspace configuration with resolved project roots. */
28
+ workspace: WorkspaceConfiguration;
29
+ /** Workspace root on disk. */
30
+ workspaceRoot: string;
31
+ }
32
+ /**
33
+ * Computes the full set of projects that must exist in the Docker context
34
+ * to build a given focus set: the focus projects themselves plus every
35
+ * project reachable from them in the workspace dependency graph.
36
+ * @param focus Project names to focus on.
37
+ * @param projectGraph The workspace project graph.
38
+ * @returns A set containing every project in the transitive closure.
39
+ */
40
+ export declare const resolveFocusProjects: (focus: string[], projectGraph: ProjectGraph) => Set<string>;
41
+ /**
42
+ * Build a minimal Docker context at {@link ScaffoldOptions.outDir}.
43
+ *
44
+ * Creates two directories:
45
+ * - `&lt;outDir>/workspace/` — root manifests + per-project manifests for the
46
+ * focus closure. `COPY` this BEFORE `pnpm install` for layer caching.
47
+ * - `&lt;outDir>/sources/` — full source trees for the focus projects (only
48
+ * when {@link ScaffoldOptions.includeSources} is true).
49
+ * @param options Scaffold configuration.
50
+ * @returns The list of project names included in the scaffold.
51
+ */
52
+ export declare const scaffoldDockerContext: (options: ScaffoldOptions) => {
53
+ projects: string[];
54
+ };
55
+ export interface PruneOptions {
56
+ /** Root of the scaffolded context (containing `vis-docker-manifest.json`). */
57
+ contextRoot: string;
58
+ workspace: WorkspaceConfiguration;
59
+ workspaceRoot: string;
60
+ }
61
+ /**
62
+ * Removes every workspace project that is not in the focus closure.
63
+ *
64
+ * Intended to run inside a Docker build stage after installing
65
+ * dependencies, so unfocused workspace symlinks are stripped from
66
+ * the final image.
67
+ * @param options Prune configuration.
68
+ * @returns The list of project root paths that were removed.
69
+ * @throws If no `vis-docker-manifest.json` exists at the context root.
70
+ */
71
+ export declare const pruneDockerContext: (options: PruneOptions) => {
72
+ removed: string[];
73
+ };
@@ -0,0 +1,40 @@
1
+ import type { LoadedRunSummary } from "./run-report.d.ts";
2
+ /**
3
+ * Per-task flakiness statistics aggregated across multiple run summaries.
4
+ */
5
+ export interface TaskFlakiness {
6
+ /** Number of runs where this task failed (exitCode !== 0). */
7
+ failures: number;
8
+ /** Flakiness rate: failures / totalRuns. */
9
+ flakinessRate: number;
10
+ /** Most recent failure time (ISO 8601), if any. */
11
+ lastFailure?: string;
12
+ project: string;
13
+ /** Number of runs where this task succeeded. */
14
+ successes: number;
15
+ target: string;
16
+ taskId: string;
17
+ /** Total number of times this task appeared in runs. */
18
+ totalRuns: number;
19
+ }
20
+ /**
21
+ * Reads all run summary files from `.task-runner/runs/` and computes
22
+ * per-task flakiness statistics.
23
+ *
24
+ * Pass `summaries` (from {@link loadRunSummaries}) when the caller
25
+ * already loaded the history — avoids re-reading every JSON off disk
26
+ * just to get the same data.
27
+ * @param workspaceRoot Absolute path to the workspace root.
28
+ * @param options Filtering options.
29
+ * @returns Flakiness stats sorted by rate (most flaky first).
30
+ */
31
+ export declare const analyzeFlakiness: (workspaceRoot: string, options?: {
32
+ minRuns?: number;
33
+ since?: string;
34
+ }, summaries?: LoadedRunSummary[]) => TaskFlakiness[];
35
+ /**
36
+ * Formats flakiness stats as an ASCII table.
37
+ * @param stats Flakiness statistics to format.
38
+ * @returns Lines of formatted output (including header).
39
+ */
40
+ export declare const formatFlakinessTable: (stats: TaskFlakiness[]) => string[];
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Template discovery for `vis generate`.
3
+ *
4
+ * Discovery sources, in priority order:
5
+ * 1. Native templates in `&lt;workspace>/.vis/templates/&lt;name>.{ts,js,mjs}`.
6
+ * 2. Moon-format directories in `&lt;workspace>/.vis/templates/&lt;name>/`
7
+ * (any directory with a `template.yml`).
8
+ * 3. Moon-format directories in `&lt;workspace>/.moon/templates/&lt;name>/`
9
+ * (zero-config import for users mid-migration from moon).
10
+ * 4. Extra directories listed in `vis.config.ts` `generator.templates`.
11
+ *
12
+ * Native templates win over moon templates with the same name; a
13
+ * warning is printed at discovery time so the conflict is visible.
14
+ */
15
+ import type { DiscoveredTemplate } from "./types.d.ts";
16
+ interface DiscoverOptions {
17
+ /** Extra template directories from `vis.config.ts` `generator.templates`. */
18
+ extraDirectories?: string[];
19
+ /** Logger callback for conflict warnings. */
20
+ onWarning?: (message: string) => void;
21
+ /** Workspace root — `.vis/templates/` and `.moon/templates/` are resolved against this. */
22
+ workspaceRoot: string;
23
+ }
24
+ /**
25
+ * Discover templates across the workspace. Returns a deduplicated list
26
+ * with native sources winning over moon when names collide.
27
+ */
28
+ export declare const discoverTemplates: (options: DiscoverOptions) => DiscoveredTemplate[];
29
+ export {};
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Public surface for `vis generate` template authors.
3
+ *
4
+ * Native templates live at `&lt;workspace>/.vis/templates/&lt;name>.{ts,js,mjs}`
5
+ * and import `createTemplate` from this module.
6
+ * @example
7
+ * ```typescript
8
+ * import { createTemplate } from "@visulima/vis/generate";
9
+ *
10
+ * export default createTemplate({
11
+ * about: { name: "package", description: "Scaffold a new package" },
12
+ * options: {
13
+ * name: { type: "string", required: true, prompt: "Package name?" },
14
+ * },
15
+ * async produce({ options }) {
16
+ * return {
17
+ * files: {
18
+ * [`packages/${options.name}/package.json`]: JSON.stringify({ name: options.name }, null, 2),
19
+ * [`packages/${options.name}/src/index.ts`]: "export {};\n",
20
+ * },
21
+ * };
22
+ * },
23
+ * });
24
+ * ```
25
+ */
26
+ import type { Template } from "./types.d.ts";
27
+ /**
28
+ * Identity helper for type inference. Authors get autocomplete + checks
29
+ * without having to annotate the export.
30
+ */
31
+ export declare const createTemplate: (template: Template) => Template;
32
+ export type { ArrayVariable, BooleanVariable, BuiltinVars, Creation, CreationDirectory, CreationFile, DiscoveredTemplate, EnumVariable, FileMeta, NumberVariable, Options, Script, ScriptObject, StringVariable, Template, TemplateAbout, TemplateContext, Variable, VariableMap, VariableType, } from "./types.d.ts";
@@ -0,0 +1 @@
1
+ var t=Object.defineProperty;var r=(e,a)=>t(e,"name",{value:a,configurable:!0});var c=Object.defineProperty,l=r((e,a)=>c(e,"name",{value:a,configurable:!0}),"a");const o=l(e=>e,"createTemplate");export{o as createTemplate};
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Native template loader.
3
+ *
4
+ * Native templates live as `.ts`/`.js`/`.mjs` modules under
5
+ * `&lt;workspace>/.vis/templates/&lt;name>.&lt;ext>` and export a `Template` as
6
+ * their default export. We use jiti so TypeScript and ESM/CJS
7
+ * interop both work without a separate build step.
8
+ */
9
+ import type { Template } from "./types.d.ts";
10
+ /**
11
+ * Load a native template module from disk and return its default export.
12
+ * The directory containing the file is used as jiti's working dir so
13
+ * relative imports inside the template resolve as the author expects.
14
+ */
15
+ export declare const loadNativeTemplate: (path: string) => Promise<Template>;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Filename interpolation for moon-format templates.
3
+ *
4
+ * Bracket syntax inside any path segment:
5
+ * `[var]` → value of `var` from the variable map
6
+ * `[var | filter]` → filter applied to the value
7
+ * `[var | filter(arg)]` → filter with a string argument
8
+ *
9
+ * Suffixes `.tera` and `.twig` are stripped from the final segment
10
+ * (they exist only for editor syntax highlighting).
11
+ */
12
+ /**
13
+ * Interpolate a single path segment or an entire path. Variables are
14
+ * looked up in `vars`; missing keys raise an error so typos surface
15
+ * during render rather than producing surprising filenames.
16
+ *
17
+ * `.tera` / `.twig` extensions are stripped from the result.
18
+ */
19
+ export declare const interpolateFilename: (filename: string, vars: Record<string, unknown>) => string;
20
+ /**
21
+ * Strip the trailing `.tera` / `.twig` marker from **every** path
22
+ * segment. moon strips them per segment (not just the final one) so a
23
+ * template at `src/.tera/file.ts.tera` renders to `src/file.ts`, not
24
+ * `src/.tera/file.ts`.
25
+ */
26
+ export declare const stripTeraSuffix: (filename: string) => string;
27
+ /**
28
+ * Strip the trailing `.raw` extension. moon adopters ship binary or
29
+ * Tera-conflicting files with `.raw` suffix; renderers must skip them
30
+ * but the suffix itself is removed on write.
31
+ */
32
+ export declare const stripRawSuffix: (filename: string) => string;
33
+ /**
34
+ * True when the file is a partial — matched by *either* a basename
35
+ * starting with `_` (moon's primary convention) or a path segment
36
+ * equal to `partials` (moon's "folder of partials" convention).
37
+ *
38
+ * The earlier substring match on `"partial"` swallowed any file whose
39
+ * name contained those letters (e.g. `PartialResult.ts`,
40
+ * `partially-applied.ts`), silently dropping them from the output.
41
+ */
42
+ export declare const isPartialPath: (path: string) => boolean;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Built-in filter functions used by the Tera-subset renderer and
3
+ * the filename interpolator. Names match moon's filter set.
4
+ *
5
+ * Case helpers come from `@visulima/string/case` (better Unicode and
6
+ * acronym handling than the bare `change-case` package; same package
7
+ * powers the rest of the visulima toolchain). Path filters use
8
+ * `@visulima/path` so behaviour matches the rest of vis.
9
+ */
10
+ export type FilterFn = (value: unknown, ...args: unknown[]) => unknown;
11
+ /**
12
+ * Map of filter name → function. Unknown filter names raise an error
13
+ * at render time so typos in templates don't silently no-op.
14
+ */
15
+ export declare const FILTERS: Record<string, FilterFn>;
16
+ export declare const isKnownFilter: (name: string) => boolean;
17
+ /**
18
+ * Apply a filter by name with optional arguments. Throws when the
19
+ * filter name is unknown — callers should phrase the error with a
20
+ * file:line reference.
21
+ */
22
+ export declare const applyFilter: (name: string, value: unknown, args?: unknown[]) => unknown;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Per-file YAML frontmatter splitter for moon-format templates.
3
+ *
4
+ * Frontmatter is a YAML block delimited by `---` on its own line at
5
+ * the very top of a file. Recognised keys (moon parity):
6
+ * - `to`: override the destination path (interpolation supported)
7
+ * - `force`: overwrite without prompting (default false)
8
+ * - `if`: include the file only when the condition is truthy
9
+ * - `skip`: skip rendering entirely when truthy
10
+ *
11
+ * Frontmatter is parsed via `@visulima/fs` `readYaml`-compatible YAML
12
+ * dialect. The parser is exposed as a callback to keep this module
13
+ * dependency-free for unit tests.
14
+ */
15
+ export interface Frontmatter {
16
+ /** Allow extra keys without losing them on round-trip. */
17
+ [key: string]: unknown;
18
+ /** Overwrite an existing file at the destination without prompting. */
19
+ force?: boolean;
20
+ /** Truthy expression / value gate — file is emitted only when truthy. */
21
+ if?: unknown;
22
+ /** Truthy expression / value gate — file is skipped when truthy. */
23
+ skip?: unknown;
24
+ /** Override destination path; supports `{{ var }}` interpolation. */
25
+ to?: string;
26
+ }
27
+ export interface SplitResult {
28
+ /** File body with the frontmatter block removed. */
29
+ body: string;
30
+ /** Parsed frontmatter, or `undefined` when the file has no `---` block. */
31
+ frontmatter?: Frontmatter;
32
+ }
33
+ /**
34
+ * Split the frontmatter block from the file body.
35
+ * @param source The file contents.
36
+ * @param parseYaml YAML parser callback; pass `(s) => parseYaml(s)` from
37
+ * `@visulima/fs/yaml` at the call site to avoid a runtime dep here.
38
+ */
39
+ export declare const splitFrontmatter: (source: string, parseYaml: (yaml: string) => unknown) => SplitResult;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Moon-format template adapter.
3
+ *
4
+ * Loads a directory matching moon's template layout
5
+ * (`template.yml` + a tree of files / partials / assets) and synthesises
6
+ * a `Template` (the same shape native vis templates export).
7
+ *
8
+ * The adapter pre-reads every template file at load time and parses
9
+ * the AST once. Per-run the renderer evaluates the AST against the
10
+ * resolved options scope — no further disk I/O.
11
+ */
12
+ import type { Template } from "../types.d.ts";
13
+ /**
14
+ * Load a moon-format template directory into a `Template`.
15
+ * @param templateDir Absolute path to the directory containing `template.yml`.
16
+ * @param name Stable name used by `vis generate &lt;name>` (used as a fallback
17
+ * when `template.yml` omits `title`).
18
+ */
19
+ export declare const loadMoonTemplate: (templateDir: string, name: string) => Template;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Tera-subset renderer for moon-format template content.
3
+ *
4
+ * Supported constructs (intersection of moon's most-used features):
5
+ * - `{{ var }}` and `{{ var | filter }}` and `{{ var | filter(arg) }}`
6
+ * with chained filters: `{{ var | snake_case | upper_case }}`
7
+ * - `{% if expr %} ... {% else %} ... {% endif %}`
8
+ * where `expr` is `var`, `not var`, `var == "lit"`, `var != "lit"`
9
+ * - `{% for x in collection %} ... {% endfor %}`
10
+ * where `collection` is a variable holding an array
11
+ * - `{% include "name" %}` — pulls the rendered output of a partial
12
+ *
13
+ * Explicitly UNSUPPORTED, with a clear `file:line` error message:
14
+ * - `{% set x = ... %}`
15
+ * - `{% extends "..." %}`
16
+ * - `{% block ... %}` / `{% endblock %}`
17
+ * - `{% macro ... %}` / `{% endmacro %}`
18
+ * - Custom whitespace control (`{%- -%}`)
19
+ *
20
+ * The parser is a single-pass tokenizer feeding a tree-walking
21
+ * evaluator. Errors carry the original 1-based line number for the
22
+ * source file, threaded through from the moon adapter via `filename`.
23
+ */
24
+ type Node = {
25
+ type: "text";
26
+ value: string;
27
+ } | {
28
+ expression: string;
29
+ line: number;
30
+ type: "expr";
31
+ } | {
32
+ alternate?: Node[];
33
+ condition: string;
34
+ consequent: Node[];
35
+ line: number;
36
+ type: "if";
37
+ } | {
38
+ binding: string;
39
+ body: Node[];
40
+ collection: string;
41
+ line: number;
42
+ type: "for";
43
+ } | {
44
+ line: number;
45
+ name: string;
46
+ type: "include";
47
+ };
48
+ /**
49
+ * Recursive-descent condition evaluator with precedence:
50
+ * `or` (lowest) → `and` → `not` → comparison (`==` / `!=`) → primary.
51
+ * Parentheses override precedence.
52
+ *
53
+ * Exported so the moon adapter can reuse the same grammar on
54
+ * frontmatter `if:` / `skip:` strings.
55
+ */
56
+ export declare const evaluateConditionExpression: (condition: string, scope: Record<string, unknown>, filename: string, line: number) => boolean;
57
+ interface RenderOptions {
58
+ /** Source filename — used in error messages. */
59
+ filename: string;
60
+ /**
61
+ * Internal: set of partial names currently on the include stack.
62
+ * Used to detect cycles — if an include re-enters a partial that's
63
+ * already resolving, we throw instead of stack-overflowing.
64
+ */
65
+ includeStack?: Set<string>;
66
+ /** Map of partial name → already-resolved AST. */
67
+ partials?: Map<string, Node[]>;
68
+ /** Variable scope (built-in vars merged with user options). */
69
+ scope: Record<string, unknown>;
70
+ }
71
+ /**
72
+ * Parse a template source into an AST. Used by the moon adapter to
73
+ * pre-parse partials once and reuse them across files.
74
+ */
75
+ export declare const parseTemplate: (source: string, filename: string) => Node[];
76
+ /**
77
+ * Render a parsed AST with the given scope.
78
+ */
79
+ export declare const renderAst: (nodes: Node[], options: RenderOptions) => string;
80
+ /**
81
+ * Convenience: parse + render in one call. Prefer `parseTemplate` +
82
+ * `renderAst` when a template is rendered repeatedly (e.g. in loops).
83
+ */
84
+ export declare const renderTemplate: (source: string, options: RenderOptions) => string;
85
+ export type { Node };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Split on `,` at the top level — outside quotes and parentheses.
3
+ *
4
+ * Used by both `parseFilterCall` in `filename-interp.ts` and
5
+ * `tera-subset.ts` so `path_join("a,b", "c")` and
6
+ * `[var | path_join("a,b", "c")]` produce the same two args.
7
+ */
8
+ export declare const splitCommaOutsideQuotes: (input: string) => string[];
9
+ /**
10
+ * Strip matching single- or double-quote wrappers. Returns `undefined`
11
+ * when the input isn't a quoted literal so callers can fall through to
12
+ * variable lookup or number parsing.
13
+ */
14
+ export declare const stripQuotes: (input: string) => string | undefined;