@visulima/vis 1.0.0-alpha.4 → 1.0.0-alpha.6
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/CHANGELOG.md +164 -75
- package/README.md +144 -14
- package/dist/ai-analysis.d.ts +3 -17
- package/dist/ai-cache.d.ts +1 -1
- package/dist/ai-types.d.ts +16 -0
- package/dist/bin.js +353 -215
- package/dist/cache-directory.d.ts +73 -0
- package/dist/catalog.d.ts +22 -4
- package/dist/codeowners.d.ts +30 -0
- package/dist/commands/action-graph.d.ts +8 -0
- package/dist/commands/audit.d.ts +3 -3
- package/dist/commands/cache.d.ts +86 -0
- package/dist/commands/ci.d.ts +19 -0
- package/dist/commands/docker.d.ts +22 -0
- package/dist/commands/generate.d.ts +10 -0
- package/dist/commands/ignore-helpers.d.ts +157 -0
- package/dist/commands/ignore.d.ts +17 -0
- package/dist/commands/info.d.ts +3 -0
- package/dist/commands/list.d.ts +3 -0
- package/dist/commands/migrate/backup.d.ts +8 -0
- package/dist/commands/migrate/constants.d.ts +6 -2
- package/dist/commands/migrate/gitleaks.d.ts +29 -0
- package/dist/commands/migrate/json.d.ts +4 -2
- package/dist/commands/migrate/kingfisher.d.ts +14 -0
- package/dist/commands/migrate/moon.d.ts +5 -0
- package/dist/commands/migrate/nano-staged.d.ts +30 -0
- package/dist/commands/migrate/nx.d.ts +12 -0
- package/dist/commands/migrate/prompt.d.ts +2 -0
- package/dist/commands/migrate/secretlint.d.ts +14 -0
- package/dist/commands/migrate/shared.d.ts +29 -0
- package/dist/commands/migrate/turborepo.d.ts +11 -0
- package/dist/commands/migrate/types.d.ts +8 -1
- package/dist/commands/migrate/verify.d.ts +12 -0
- package/dist/commands/run.d.ts +13 -0
- package/dist/commands/sbom.d.ts +10 -0
- package/dist/commands/secrets.d.ts +3 -0
- package/dist/commands/staged.d.ts +7 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/sync.d.ts +16 -0
- package/dist/commands/task-why.d.ts +3 -0
- package/dist/config.d.ts +18 -3
- package/dist/config.js +1 -1
- package/dist/docker.d.ts +73 -0
- package/dist/flakiness.d.ts +40 -0
- package/dist/generate/discover.d.ts +29 -0
- package/dist/generate/index.d.ts +32 -0
- package/dist/generate/index.js +1 -0
- package/dist/generate/loader.d.ts +15 -0
- package/dist/generate/moon-adapter/filename-interp.d.ts +42 -0
- package/dist/generate/moon-adapter/filters.d.ts +22 -0
- package/dist/generate/moon-adapter/frontmatter.d.ts +39 -0
- package/dist/generate/moon-adapter/index.d.ts +19 -0
- package/dist/generate/moon-adapter/tera-subset.d.ts +85 -0
- package/dist/generate/moon-adapter/util.d.ts +14 -0
- package/dist/generate/prompts.d.ts +25 -0
- package/dist/generate/remote.d.ts +43 -0
- package/dist/generate/runner.d.ts +37 -0
- package/dist/generate/types.d.ts +152 -0
- package/dist/hooks.d.ts +118 -0
- package/dist/native-binding.d.ts +8 -1
- package/dist/packem_chunks/index.js +7 -0
- package/dist/packem_chunks/loader.js +1 -0
- package/dist/packem_shared/otelPlugin-CJLkguJ8.js +1 -0
- package/dist/plugins/otel.d.ts +63 -0
- package/dist/pm-runner.d.ts +24 -3
- package/dist/run-report.d.ts +40 -0
- package/dist/runtime-check.d.ts +27 -0
- package/dist/sbom/cyclonedx.d.ts +39 -0
- package/dist/sbom/installed-package.d.ts +49 -0
- package/dist/sbom/license.d.ts +31 -0
- package/dist/sbom/lockfile.d.ts +34 -0
- package/dist/sbom/purl.d.ts +25 -0
- package/dist/sbom/resolve-specifier.d.ts +24 -0
- package/dist/sbom/types.d.ts +196 -0
- package/dist/secrets/baseline.d.ts +20 -0
- package/dist/secrets/format.d.ts +14 -0
- package/dist/secrets/git.d.ts +6 -0
- package/dist/secrets/spinner.d.ts +9 -0
- package/dist/selectors.d.ts +81 -0
- package/dist/shell-history.d.ts +16 -0
- package/dist/staged/cli-parse.d.ts +18 -0
- package/dist/staged/config.d.ts +14 -0
- package/dist/staged/errors/apply-empty-commit-error.d.ts +4 -0
- package/dist/staged/errors/config-error.d.ts +4 -0
- package/dist/staged/errors/get-backup-stash-error.d.ts +4 -0
- package/dist/staged/errors/git-error.d.ts +6 -0
- package/dist/staged/errors/index.d.ts +12 -0
- package/dist/staged/errors/restore-original-state-error.d.ts +4 -0
- package/dist/staged/errors/staged-error.d.ts +8 -0
- package/dist/staged/errors/task-error.d.ts +6 -0
- package/dist/staged/git/diff.d.ts +76 -0
- package/dist/staged/git/exec.d.ts +43 -0
- package/dist/staged/git/index.d.ts +77 -0
- package/dist/staged/git/stash.d.ts +37 -0
- package/dist/staged/index.d.ts +13 -0
- package/dist/staged/match.d.ts +12 -0
- package/dist/staged/renderer/index.d.ts +9 -0
- package/dist/staged/renderer/ink/index.d.ts +4 -0
- package/dist/staged/renderer/plain.d.ts +12 -0
- package/dist/staged/tasks/build.d.ts +13 -0
- package/dist/staged/tasks/exec.d.ts +56 -0
- package/dist/staged/tasks/run.d.ts +26 -0
- package/dist/staged/types.d.ts +173 -0
- package/dist/target-discovery.d.ts +59 -0
- package/dist/target-options.d.ts +261 -0
- package/dist/tui/components/OutputPanel.d.ts +2 -1
- package/dist/tui/components/TaskListPanel.d.ts +1 -1
- package/dist/tui/components/TaskStore.d.ts +1 -1
- package/dist/tui/components/devcontainer/DevcontainerStore.d.ts +1 -1
- package/dist/tui/components/devcontainer/catalogs/mount-suggestions.d.ts +1 -1
- package/dist/tui/components/devcontainer/sections/GeneralSection.d.ts +1 -1
- package/dist/tui/components/devcontainer/sections/PreviewPanel.d.ts +1 -1
- package/dist/tui/components/devcontainer/types.d.ts +4 -4
- package/dist/tui/components/graph/GraphStore.d.ts +1 -1
- package/dist/tui/components/graph/ProjectDetailPanel.d.ts +1 -1
- package/dist/tui/components/optimize/OptimizeDetailPanel.d.ts +1 -1
- package/dist/tui/components/optimize/OptimizeStore.d.ts +1 -1
- package/dist/tui/components/update/PackageDetailPanel.d.ts +1 -1
- package/dist/tui/components/update/PackageListPanel.d.ts +4 -1
- package/dist/tui/components/update/UpdateStore.d.ts +1 -1
- package/dist/tui/components/update/VisUpdateApp.d.ts +8 -1
- package/dist/tui/dynamic-life-cycle.d.ts +2 -1
- package/dist/tui/static-life-cycle.d.ts +7 -1
- package/dist/watch.d.ts +65 -0
- package/dist/workspace.d.ts +366 -6
- package/index.js +727 -554
- package/package.json +38 -33
- package/schemas/project.schema.json +344 -0
- package/schemas/vis-config.schema.json +331 -0
|
@@ -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;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Variable-schema → interactive prompts.
|
|
3
|
+
*
|
|
4
|
+
* Builds on the same `node:readline` helpers `vis create` uses (see
|
|
5
|
+
* src/commands/create/prompts.ts). The implementation is minimal — no
|
|
6
|
+
* fancy multi-line UI, no spinner, no terminal control codes — to
|
|
7
|
+
* stay consistent with the rest of the vis CLI surface.
|
|
8
|
+
*/
|
|
9
|
+
import type { Options, VariableMap } from "./types.d.ts";
|
|
10
|
+
interface CollectOptions {
|
|
11
|
+
/** When true, skip prompts and use defaults / overrides only. */
|
|
12
|
+
defaults: boolean;
|
|
13
|
+
/** When false, never prompt — error on missing required values. */
|
|
14
|
+
interactive: boolean;
|
|
15
|
+
/** CLI overrides — variable name → unparsed string from `--name=value`. */
|
|
16
|
+
overrides: Record<string, string>;
|
|
17
|
+
/** Variable schema. */
|
|
18
|
+
variables: VariableMap;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Collect option values from prompts + CLI overrides + defaults, then
|
|
22
|
+
* validate them.
|
|
23
|
+
*/
|
|
24
|
+
export declare const collectOptions: (collectOptionsArguments: CollectOptions) => Promise<Options>;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote template fetching for `vis generate`.
|
|
3
|
+
*
|
|
4
|
+
* Reuses giget (already a vis dep, used by `vis create`) to fetch
|
|
5
|
+
* `git://`, `npm://`, and `https://` archive sources into a cache
|
|
6
|
+
* directory before discover/load runs against them.
|
|
7
|
+
*
|
|
8
|
+
* Sources are normalized via the same patterns vis create uses; see
|
|
9
|
+
* `src/commands/create/templates/remote.ts` for the underlying
|
|
10
|
+
* downloadTemplate call.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* True when the input looks like a remote source giget can resolve.
|
|
14
|
+
*/
|
|
15
|
+
export declare const isRemoteSource: (input: string) => boolean;
|
|
16
|
+
interface FetchOptions {
|
|
17
|
+
/** Auth token forwarded to giget for private repos. */
|
|
18
|
+
auth?: string;
|
|
19
|
+
/** Prefer cached templates over re-download. */
|
|
20
|
+
preferOffline?: boolean;
|
|
21
|
+
/** Override the cache/work directory (defaults to a fresh tmp). */
|
|
22
|
+
targetDirectory?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface FetchResult {
|
|
25
|
+
/**
|
|
26
|
+
* Release the tmp directory once the caller has finished loading
|
|
27
|
+
* the template into memory. No-op when the directory was supplied
|
|
28
|
+
* externally via `targetDirectory`.
|
|
29
|
+
*/
|
|
30
|
+
cleanup: () => void;
|
|
31
|
+
/** Absolute directory containing the downloaded template. */
|
|
32
|
+
directory: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Download a remote template and return the directory it lives in.
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const { directory } = await fetchRemoteTemplate("git://github.com/org/template#main");
|
|
39
|
+
* const template = await loadMoonTemplate(directory, "from-git");
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare const fetchRemoteTemplate: (source: string, options?: FetchOptions) => Promise<FetchResult>;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template runner — applies a `Creation` to disk.
|
|
3
|
+
*
|
|
4
|
+
* Walks the recursive `files` tree, prompts for overwrites unless
|
|
5
|
+
* `--force` was passed, runs scripts in phase order, and prints
|
|
6
|
+
* suggestions at the end. `--dry-run` prints the planned writes
|
|
7
|
+
* without touching the filesystem.
|
|
8
|
+
*
|
|
9
|
+
* Every write target is checked against the destination directory to
|
|
10
|
+
* reject `..`-escapes and absolute paths coming from rendered
|
|
11
|
+
* frontmatter `to:` fields or filename interpolation — template
|
|
12
|
+
* authors (or remote templates) must not be able to scribble
|
|
13
|
+
* outside the caller's chosen destination.
|
|
14
|
+
*/
|
|
15
|
+
import type { Template } from "./types.d.ts";
|
|
16
|
+
interface RunnerOptions {
|
|
17
|
+
/** Caller's CWD for `working_dir`. */
|
|
18
|
+
cwd: string;
|
|
19
|
+
/** Destination directory (absolute). */
|
|
20
|
+
destination: string;
|
|
21
|
+
/** When true, print but don't write. */
|
|
22
|
+
dryRun?: boolean;
|
|
23
|
+
/** When true, overwrite existing files without prompting. */
|
|
24
|
+
force?: boolean;
|
|
25
|
+
/** Resolved option values from `collectOptions`. */
|
|
26
|
+
options: Record<string, unknown>;
|
|
27
|
+
/** When true, don't run scripts. */
|
|
28
|
+
skipScripts?: boolean;
|
|
29
|
+
/** Workspace root for `dest_rel_dir`. */
|
|
30
|
+
workspaceRoot: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Run a template end-to-end: invoke `produce`, write files, run scripts,
|
|
34
|
+
* print suggestions.
|
|
35
|
+
*/
|
|
36
|
+
export declare const runTemplate: (template: Template, options: RunnerOptions) => Promise<void>;
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the `vis generate` template runtime.
|
|
3
|
+
*
|
|
4
|
+
* The shape intentionally echoes Bingo's `Template` so a future Bingo
|
|
5
|
+
* adapter (re-exporting `bingo` Templates through this runtime) is a
|
|
6
|
+
* one-pager. Authors do not depend on Bingo to write a vis generator.
|
|
7
|
+
*/
|
|
8
|
+
export type VariableType = "array" | "boolean" | "enum" | "number" | "string";
|
|
9
|
+
/** Common variable fields (all types). */
|
|
10
|
+
interface VariableBase {
|
|
11
|
+
/**
|
|
12
|
+
* Default value when the user accepts the prompt without typing.
|
|
13
|
+
* For `boolean` this is `true|false`; for `enum` it must match `values`.
|
|
14
|
+
*/
|
|
15
|
+
default?: boolean | number | string | string[];
|
|
16
|
+
/** Hide from prompts; can still be set via CLI or `--defaults`. */
|
|
17
|
+
internal?: boolean;
|
|
18
|
+
/** Sort order in prompts (lower first). Defaults to declaration order. */
|
|
19
|
+
order?: number;
|
|
20
|
+
/** Override the prompt text. Defaults to the variable name. */
|
|
21
|
+
prompt?: string;
|
|
22
|
+
/** When true, the user must provide a non-empty value. */
|
|
23
|
+
required?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export type StringVariable = VariableBase & {
|
|
26
|
+
type: "string";
|
|
27
|
+
};
|
|
28
|
+
export type NumberVariable = VariableBase & {
|
|
29
|
+
type: "number";
|
|
30
|
+
};
|
|
31
|
+
export type BooleanVariable = VariableBase & {
|
|
32
|
+
default?: boolean;
|
|
33
|
+
type: "boolean";
|
|
34
|
+
};
|
|
35
|
+
export type ArrayVariable = VariableBase & {
|
|
36
|
+
type: "array";
|
|
37
|
+
};
|
|
38
|
+
export interface EnumVariable extends VariableBase {
|
|
39
|
+
/** Allow multiple selections (returns `string[]`). */
|
|
40
|
+
multiple?: boolean;
|
|
41
|
+
type: "enum";
|
|
42
|
+
/** Selectable values. */
|
|
43
|
+
values: string[];
|
|
44
|
+
}
|
|
45
|
+
export type Variable = ArrayVariable | BooleanVariable | EnumVariable | NumberVariable | StringVariable;
|
|
46
|
+
/** Map of variable name → spec, as authors declare them. */
|
|
47
|
+
export type VariableMap = Record<string, Variable>;
|
|
48
|
+
/** Resolved option values passed to `produce()`. */
|
|
49
|
+
export type Options = Record<string, unknown>;
|
|
50
|
+
/** A file in a Creation can be a string, a Buffer (binary asset), or a nested directory. */
|
|
51
|
+
export type CreationFile = Buffer | string;
|
|
52
|
+
export interface CreationDirectory {
|
|
53
|
+
[key: string]: CreationDirectory | CreationFile;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Script entry produced by `produce()`.
|
|
57
|
+
* - `string`: shell command, runs in the destination directory.
|
|
58
|
+
* - `object`: shell commands with optional phase ordering.
|
|
59
|
+
*/
|
|
60
|
+
export type Script = ScriptObject | string;
|
|
61
|
+
export interface ScriptObject {
|
|
62
|
+
/** Shell command(s) to run sequentially. */
|
|
63
|
+
commands: string[];
|
|
64
|
+
/**
|
|
65
|
+
* Phase ordering. Phases run in ascending order; scripts within
|
|
66
|
+
* the same phase are dispatched concurrently. Default: 0.
|
|
67
|
+
*/
|
|
68
|
+
phase?: number;
|
|
69
|
+
/** Suppress command output. Default: false. */
|
|
70
|
+
silent?: boolean;
|
|
71
|
+
}
|
|
72
|
+
/** Object returned by a template's `produce()` function. */
|
|
73
|
+
export interface Creation {
|
|
74
|
+
/** Recursive directory tree. Keys with `/` are auto-split. */
|
|
75
|
+
files?: CreationDirectory;
|
|
76
|
+
/**
|
|
77
|
+
* Per-file metadata keyed by the *flattened* destination path
|
|
78
|
+
* (e.g. `src/foo.ts`). Optional — native templates usually omit
|
|
79
|
+
* this; the moon adapter populates it from per-file frontmatter
|
|
80
|
+
* so `force: true` survives the trip to the runner without
|
|
81
|
+
* changing the shape of `files`.
|
|
82
|
+
*/
|
|
83
|
+
filesMeta?: Record<string, FileMeta>;
|
|
84
|
+
/** Shell scripts to run after files are written. */
|
|
85
|
+
scripts?: Script[];
|
|
86
|
+
/** User-facing tips printed after the run. */
|
|
87
|
+
suggestions?: string[];
|
|
88
|
+
}
|
|
89
|
+
export interface FileMeta {
|
|
90
|
+
/**
|
|
91
|
+
* Overwrite an existing file at this path without prompting or
|
|
92
|
+
* consulting the global `--force` flag.
|
|
93
|
+
*/
|
|
94
|
+
force?: boolean;
|
|
95
|
+
}
|
|
96
|
+
/** Context object passed to `produce()`. */
|
|
97
|
+
export interface TemplateContext {
|
|
98
|
+
/** Built-in variables: `dest_dir`, `dest_rel_dir`, `working_dir`, `workspace_root`. */
|
|
99
|
+
builtins: BuiltinVars;
|
|
100
|
+
/** Resolved option values (after prompts + CLI overrides + defaults). */
|
|
101
|
+
options: Options;
|
|
102
|
+
}
|
|
103
|
+
export interface BuiltinVars {
|
|
104
|
+
/** Absolute destination directory. */
|
|
105
|
+
dest_dir: string;
|
|
106
|
+
/** Destination relative to the workspace root. */
|
|
107
|
+
dest_rel_dir: string;
|
|
108
|
+
/** Caller's current working directory. */
|
|
109
|
+
working_dir: string;
|
|
110
|
+
/** Absolute workspace root (from `findMonorepoRootSync`, fallback to `working_dir`). */
|
|
111
|
+
workspace_root: string;
|
|
112
|
+
}
|
|
113
|
+
/** Top-level "About" metadata for a template. */
|
|
114
|
+
export interface TemplateAbout {
|
|
115
|
+
/** One-line description. */
|
|
116
|
+
description: string;
|
|
117
|
+
/** Short identifier shown in `vis generate --list` and prompts. */
|
|
118
|
+
name: string;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* The author-facing template shape.
|
|
122
|
+
* Both native (`.vis/templates/<name>.ts`) and moon-adapter outputs
|
|
123
|
+
* normalize to this.
|
|
124
|
+
*/
|
|
125
|
+
export interface Template {
|
|
126
|
+
about: TemplateAbout;
|
|
127
|
+
/**
|
|
128
|
+
* Default destination directory (relative to workspace root unless
|
|
129
|
+
* absolute or starting with `./`). Honored when the user does not
|
|
130
|
+
* pass `--to`. Maps to moon's `template.yml` `destination`.
|
|
131
|
+
*/
|
|
132
|
+
destination?: string;
|
|
133
|
+
/** Variable schema for prompts. */
|
|
134
|
+
options?: VariableMap;
|
|
135
|
+
/** Build the Creation given resolved options and built-in vars. */
|
|
136
|
+
produce: (context: TemplateContext) => Creation | Promise<Creation>;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Discovery record: a Template plus where it came from.
|
|
140
|
+
* Surfaced by `vis generate --list`.
|
|
141
|
+
*/
|
|
142
|
+
export interface DiscoveredTemplate {
|
|
143
|
+
/** Lazy loader — invoke to materialize the Template. */
|
|
144
|
+
load: () => Promise<Template>;
|
|
145
|
+
/** Stable name used by `vis generate <name>`. */
|
|
146
|
+
name: string;
|
|
147
|
+
/** Absolute path on disk (file for native, directory for moon). */
|
|
148
|
+
path: string;
|
|
149
|
+
/** Source classification — affects load + listing. */
|
|
150
|
+
source: "config" | "moon" | "native" | "remote";
|
|
151
|
+
}
|
|
152
|
+
export {};
|
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { LifeCycleInterface, Task, TaskResult } from "@visulima/task-runner";
|
|
2
|
+
import type { Hookable } from "hookable";
|
|
3
|
+
/**
|
|
4
|
+
* Typed hook surface exposed to vis plugins.
|
|
5
|
+
*
|
|
6
|
+
* Plugins subscribe via `hooks.hook(name, handler)` — handlers are
|
|
7
|
+
* awaited sequentially in registration order. Returning a promise
|
|
8
|
+
* delays the next hook firing until it resolves, so plugins can
|
|
9
|
+
* safely perform async setup/teardown.
|
|
10
|
+
*
|
|
11
|
+
* Naming deliberately mirrors vite-task / webpack-style verbs:
|
|
12
|
+
* before/after for boundaries, on<Event> for passive observation.
|
|
13
|
+
*/
|
|
14
|
+
export interface VisHooks {
|
|
15
|
+
/**
|
|
16
|
+
* Fired after the entire task graph completes (including any
|
|
17
|
+
* failures). `results` maps task ID → {@link TaskResult}.
|
|
18
|
+
*/
|
|
19
|
+
"run:after": (results: Map<string, TaskResult>) => Promise<void> | void;
|
|
20
|
+
/**
|
|
21
|
+
* Fired once before any task in the graph starts, after workspace
|
|
22
|
+
* discovery and graph construction. Throwing aborts the run.
|
|
23
|
+
*/
|
|
24
|
+
"run:before": (context: {
|
|
25
|
+
tasks: Task[];
|
|
26
|
+
workspaceRoot: string;
|
|
27
|
+
}) => Promise<void> | void;
|
|
28
|
+
/**
|
|
29
|
+
* Fired after a task completes (success, failure, or cache hit).
|
|
30
|
+
* Receives the final {@link TaskResult}.
|
|
31
|
+
*/
|
|
32
|
+
"task:after": (task: Task, result: TaskResult) => Promise<void> | void;
|
|
33
|
+
/**
|
|
34
|
+
* Fired before each task begins execution — after scheduling, before
|
|
35
|
+
* the executor runs the command. Throwing aborts that single task.
|
|
36
|
+
*/
|
|
37
|
+
"task:before": (task: Task) => Promise<void> | void;
|
|
38
|
+
/** Fired when a task hit the local or remote cache. */
|
|
39
|
+
"task:cacheHit": (task: Task, result: TaskResult) => Promise<void> | void;
|
|
40
|
+
/**
|
|
41
|
+
* Fired when auto-fingerprint cache diagnostics reports a miss,
|
|
42
|
+
* carrying the human-readable reason string.
|
|
43
|
+
*/
|
|
44
|
+
"task:cacheMiss": (task: Task, reasons: string) => Promise<void> | void;
|
|
45
|
+
/** Fired when a task exits non-zero. */
|
|
46
|
+
"task:failure": (task: Task, result: TaskResult) => Promise<void> | void;
|
|
47
|
+
/**
|
|
48
|
+
* Fired with a stderr chunk as a running task emits it. Plugins
|
|
49
|
+
* that ship logs live (Slack, Datadog) should prefer this over
|
|
50
|
+
* `task:after` so they don't wait for the full buffer.
|
|
51
|
+
*/
|
|
52
|
+
"task:stderr": (task: Task, chunk: string) => Promise<void> | void;
|
|
53
|
+
/**
|
|
54
|
+
* Fired with a stdout chunk as a running task emits it. See
|
|
55
|
+
* `task:stderr` for semantics.
|
|
56
|
+
*/
|
|
57
|
+
"task:stdout": (task: Task, chunk: string) => Promise<void> | void;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Public plugin contract. Implementations register handlers by
|
|
61
|
+
* returning a partial {@link VisHooks} map from `hooks`, or by
|
|
62
|
+
* mutating the Hookable instance directly via `setup(hooks)` for
|
|
63
|
+
* advanced cases (dynamic registration, removeHook, etc.).
|
|
64
|
+
*
|
|
65
|
+
* Plugins are loaded in the order they appear in `visConfig.plugins`.
|
|
66
|
+
* Handler execution order within a hook follows registration order,
|
|
67
|
+
* so earlier plugins see events first.
|
|
68
|
+
*/
|
|
69
|
+
export interface VisPlugin {
|
|
70
|
+
/**
|
|
71
|
+
* Declarative handlers — the common shape. One entry per hook
|
|
72
|
+
* name; pass a function or an array of functions (all run serially
|
|
73
|
+
* in order).
|
|
74
|
+
*/
|
|
75
|
+
hooks?: Partial<{
|
|
76
|
+
[K in keyof VisHooks]: VisHooks[K] | VisHooks[K][];
|
|
77
|
+
}>;
|
|
78
|
+
/** Plugin name — surfaced in debug logs. */
|
|
79
|
+
name: string;
|
|
80
|
+
/**
|
|
81
|
+
* Imperative setup — receives the shared Hookable instance so the
|
|
82
|
+
* plugin can register hooks conditionally, unregister later, or
|
|
83
|
+
* use advanced APIs like `hookOnce`/`beforeEach`/`afterEach`.
|
|
84
|
+
*/
|
|
85
|
+
setup?: (hooks: Hookable<VisHooks>) => Promise<void> | void;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Optional callback invoked whenever a plugin handler throws. Lets
|
|
89
|
+
* callers surface buggy plugins without crashing the run — pass a
|
|
90
|
+
* logger or re-throw to promote plugin errors to fatals.
|
|
91
|
+
*/
|
|
92
|
+
export type HookErrorHandler = (hookName: keyof VisHooks, error: unknown) => void;
|
|
93
|
+
/**
|
|
94
|
+
* Creates a fresh typed hook registry. One instance is created per
|
|
95
|
+
* `vis run` invocation and passed to every plugin's `setup()`.
|
|
96
|
+
*/
|
|
97
|
+
export declare const createVisHooks: () => Hookable<VisHooks>;
|
|
98
|
+
/**
|
|
99
|
+
* Registers each plugin's handlers against the shared hook instance.
|
|
100
|
+
* Synchronous failures in `setup()` abort plugin loading and propagate.
|
|
101
|
+
*/
|
|
102
|
+
export declare const registerPlugins: (hooks: Hookable<VisHooks>, plugins: VisPlugin[] | undefined) => Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* Bridges `LifeCycleInterface` (the task-runner contract) into
|
|
105
|
+
* `VisHooks` events. Register this as a lifecycle alongside the
|
|
106
|
+
* existing UI renderers so plugin authors see the same events the
|
|
107
|
+
* TUI/static output do, without having to understand task-runner's
|
|
108
|
+
* lower-level `LifeCycleInterface` shape.
|
|
109
|
+
*/
|
|
110
|
+
export declare class HookableLifeCycle implements LifeCycleInterface {
|
|
111
|
+
#private;
|
|
112
|
+
constructor(hooks: Hookable<VisHooks>, onError?: HookErrorHandler);
|
|
113
|
+
startTasks(tasks: Task[]): void;
|
|
114
|
+
endTasks(results: TaskResult[]): void;
|
|
115
|
+
printCacheMiss(task: Task, reasons: string): void;
|
|
116
|
+
onTaskStdout(task: Task, chunk: string): void;
|
|
117
|
+
onTaskStderr(task: Task, chunk: string): void;
|
|
118
|
+
}
|
package/dist/native-binding.d.ts
CHANGED
|
@@ -121,12 +121,19 @@ interface NativeBindings {
|
|
|
121
121
|
detectPackageManager: (cwd: string) => DetectedPackageManager;
|
|
122
122
|
execPmCommand: (bin: string, args: string[], cwd: string) => ExecResult;
|
|
123
123
|
execPmCommandInteractive: (bin: string, args: string[], cwd: string) => number;
|
|
124
|
+
/**
|
|
125
|
+
* ABI compatibility version exported from the Rust binding. The TypeScript
|
|
126
|
+
* loader compares this against {@link EXPECTED_NATIVE_BINDING_VERSION} and
|
|
127
|
+
* rejects mismatched addons so a stale `.node` file from before a
|
|
128
|
+
* signature change is not used silently.
|
|
129
|
+
*/
|
|
130
|
+
NATIVE_BINDING_VERSION: number;
|
|
124
131
|
resolveAdd: (pm: string, version: string, options: AddOptions) => ResolvedCommand;
|
|
125
132
|
resolveDedupe: (pm: string, version: string, check: boolean) => ResolvedCommand;
|
|
126
133
|
resolveDlx: (pm: string, version: string, options: DlxOptions) => ResolvedCommand;
|
|
127
134
|
resolveExec: (pm: string, version: string, options: ExecOptions) => ResolvedCommand;
|
|
128
135
|
resolveInstall: (pm: string, version: string, options: InstallOptions) => ResolvedCommand;
|
|
129
|
-
resolveLink: (pm: string, target: string | null) => ResolvedCommand;
|
|
136
|
+
resolveLink: (pm: string, version: string, target: string | null) => ResolvedCommand;
|
|
130
137
|
resolveOutdated: (pm: string, version: string, options: OutdatedOptions) => ResolvedCommand;
|
|
131
138
|
resolvePmCommand: (pm: string, version: string, subcommand: string, extraArgs: string[]) => ResolvedCommand;
|
|
132
139
|
resolveRemove: (pm: string, version: string, options: RemoveOptions) => ResolvedCommand;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
var H=Object.defineProperty;var v=(e,t)=>H(e,"name",{value:t,configurable:!0});import{walkSync as J,readFileSync as k}from"@visulima/fs";import{readYamlSync as X}from"@visulima/fs/yaml";import{relative as M,join as R}from"@visulima/path";import{parse as Z}from"yaml";import{constantCase as ee,trainCase as te,snakeCase as ne,pascalCase as re,kebabCase as ie,camelCase as se}from"@visulima/string/case";var ae=Object.defineProperty,d=v((e,t)=>ae(e,"name",{value:t,configurable:!0}),"e");const h=d(e=>e==null?"":typeof e=="string"?e:String(e),"stringify"),S={camel_case:d(e=>se(h(e)),"camel_case"),kebab_case:d(e=>ie(h(e)),"kebab_case"),lower_case:d(e=>h(e).toLowerCase(),"lower_case"),pascal_case:d(e=>re(h(e)),"pascal_case"),path_join:d((e,...t)=>{const r=[h(e),...t.map(h)];return R(...r)},"path_join"),path_relative:d((e,t)=>M(h(t),h(e)),"path_relative"),snake_case:d(e=>ne(h(e)),"snake_case"),upper_case:d(e=>h(e).toUpperCase(),"upper_case"),upper_kebab_case:d(e=>te(h(e)),"upper_kebab_case"),upper_snake_case:d(e=>ee(h(e)),"upper_snake_case")};d(e=>Object.hasOwn(S,e),"isKnownFilter");const I=d((e,t,r=[])=>{const n=S[e];if(!n)throw new Error(`Unknown filter "${e}". Known filters: ${Object.keys(S).sort().join(", ")}.`);return n(t,...r)},"applyFilter");var oe=Object.defineProperty,N=v((e,t)=>oe(e,"name",{value:t,configurable:!0}),"d$1");const L=N(e=>{const t=[];let r=0,n=0,i,s=-1;for(const a of e){if(s+=1,i){a===i&&(i=void 0);continue}if(a==='"'||a==="'"){i=a;continue}a==="("?r+=1:a===")"?r-=1:a===","&&r===0&&(t.push(e.slice(n,s)),n=s+1)}return t.push(e.slice(n)),t},"splitCommaOutsideQuotes"),le=N(e=>{if(e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1)},"stripQuotes");var ce=Object.defineProperty,$=v((e,t)=>ce(e,"name",{value:t,configurable:!0}),"i$1");const fe=/\[([^\]]+)\]/g,ue=$(e=>{const t=e.trim(),r=t.indexOf("(");if(r===-1)return{args:[],name:t};if(!t.endsWith(")"))throw new Error(`Filter call "${e}" missing closing ")"`);const n=t.slice(0,r).trim(),i=t.slice(r+1,-1).trim();return i===""?{args:[],name:n}:{args:L(i).map(s=>{const a=s.trim();return le(a)??a}),name:n}},"parseFilterCall"),pe=$(e=>{const t=e.split("|").map(n=>n.trim()),r=t[0]??"";if(!r)throw new Error(`Empty variable name in expression "${e}"`);return{filters:t.slice(1).map(ue),name:r}},"parsePipe"),me=$(e=>e==null?"":typeof e=="string"?e:String(e),"stringify"),de=$((e,t)=>{const r=e.replaceAll(fe,(n,i)=>{const{filters:s,name:a}=pe(i);if(!Object.hasOwn(t,a))throw new Error(`Variable "${a}" used in filename "${e}" but not defined`);let o=t[a];for(const l of s)o=I(l.name,o,l.args);return me(o)});return q(r)},"interpolateFilename"),q=$(e=>e.split("/").map(t=>t.endsWith(".tera")||t.endsWith(".twig")?t.slice(0,-5):t).join("/"),"stripTeraSuffix"),he=$(e=>e.endsWith(".raw")?e.slice(0,-4):e,"stripRawSuffix"),ye=$(e=>{const t=e.split("/");return(t.at(-1)??"").startsWith("_")?!0:t.slice(0,-1).includes("partials")},"isPartialPath");var ge=Object.defineProperty,be=v((e,t)=>ge(e,"name",{value:t,configurable:!0}),"i");const we=be((e,t)=>{if(!e.startsWith(`---
|
|
2
|
+
`)&&!e.startsWith(`---\r
|
|
3
|
+
`))return{body:e};const r=e.indexOf(`
|
|
4
|
+
---`,3);if(r===-1)return{body:e};let n=r+1+3;e[n]==="\r"&&(n+=1),e[n]===`
|
|
5
|
+
`&&(n+=1);const i=e.startsWith(`---\r
|
|
6
|
+
`)?5:4,s=e.slice(i,r).replaceAll("\r","");let a;try{a=t(s)}catch(o){const l=o instanceof Error?o.message:String(o);throw new Error(`Failed to parse frontmatter YAML: ${l}`)}if(a==null)return{body:e.slice(n)};if(typeof a!="object"||Array.isArray(a))throw new TypeError(`Frontmatter must be a YAML mapping, got ${Array.isArray(a)?"array":typeof a}`);return{body:e.slice(n),frontmatter:a}},"splitFrontmatter");var ve=Object.defineProperty,f=v((e,t)=>ve(e,"name",{value:t,configurable:!0}),"c");const $e=/\{\{-?(.+?)-?\}\}|\{%-?(.+?)-?%\}/gs,U=f(e=>{const t=[];let r=0,n=1;const i=f(s=>{for(const a of s)a===`
|
|
7
|
+
`&&(n+=1)},"advanceLine");for(const s of e.matchAll($e)){const a=s.index??0;if(a>r){const c=e.slice(r,a);t.push({line:n,type:"text",value:c}),i(c)}const o=n,l=s[0];l.startsWith("{{")?t.push({line:o,type:"expr",value:(s[1]??"").trim()}):t.push({line:o,type:"stmt",value:(s[2]??"").trim()}),i(l),r=a+l.length}if(r<e.length){const s=e.slice(r);t.push({line:n,type:"text",value:s})}return t},"tokenize"),xe=new Set(["block","endblock","endfilter","endmacro","extends","filter","import","macro","set"]),G=f((e,t)=>{let r=0;const n=f((s,a)=>{throw new Error(`${t}:${s}: ${a}`)},"error"),i=f(s=>{const a=[];for(;r<e.length;){const o=e[r];if(o.type==="text"){a.push({type:"text",value:o.value}),r+=1;continue}if(o.type==="expr"){a.push({expression:o.value,line:o.line,type:"expr"}),r+=1;continue}const l=o.value.split(/\s+/)[0]??"";if(s.includes(l))return a;if(xe.has(l)&&n(o.line,`Tera feature "{% ${l} %}" is not supported. Supported: if/else/endif, for/endfor, include. Rewrite the template to avoid macros, set, extends, block, and import.`),l==="if"){r+=1;const c=o.value.slice(2).trim(),m=i(["else","endif"]);let u;r<e.length&&e[r].type==="stmt"&&e[r].value.split(/\s+/)[0]==="else"&&(r+=1,u=i(["endif"])),(r>=e.length||e[r].type!=="stmt"||e[r].value.split(/\s+/)[0]!=="endif")&&n(o.line,"Unterminated {% if %} — missing {% endif %}"),r+=1,a.push({alternate:u,condition:c,consequent:m,line:o.line,type:"if"});continue}if(l==="for"){r+=1;const c=o.value.slice(3).trim(),m=c.indexOf(" in ");m===-1&&n(o.line,"Malformed {% for %} — expected `for <name> in <collection>`");const u=c.slice(0,m).trim(),g=c.slice(m+4).trim();(!u||!g)&&n(o.line,"Malformed {% for %} — missing binding or collection");const p=i(["endfor"]);(r>=e.length||e[r].type!=="stmt"||e[r].value.split(/\s+/)[0]!=="endfor")&&n(o.line,"Unterminated {% for %} — missing {% endfor %}"),r+=1,a.push({binding:u,body:p,collection:g,line:o.line,type:"for"});continue}if(l==="include"){r+=1;const c=o.value.slice(7).trim(),m=Q(c);m===void 0&&n(o.line,"Malformed {% include %} — expected a quoted partial name"),a.push({line:o.line,name:m,type:"include"});continue}n(o.line,`Unknown tag "{% ${l} %}". Supported: if, for, include.`)}return a},"parseBlock");return i([])},"parse"),Q=f(e=>{if(e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1)},"stripQuotes"),Ee=f(e=>e==null?"":typeof e=="boolean"||typeof e=="number"?String(e):typeof e=="string"?e:JSON.stringify(e),"stringify"),Oe=f(e=>e==null||e===!1||e===0||e===""?!1:Array.isArray(e)?e.length>0:!0,"isTruthy"),V=f((e,t,r,n,i=!0)=>{const s=e.split(".");if(i&&s.length>0&&!Object.hasOwn(t,s[0]))throw new Error(`${n}:${r}: Variable "${e}" is not defined`);let a=t;for(const o of s){if(a==null)return;if(typeof a!="object")throw new TypeError(`${n}:${r}: Cannot read "${o}" on non-object value`);a=a[o]}return a},"lookupVariable"),ke=f(e=>{const t=[];let r=0,n=0,i;for(let s=0;s<e.length;s+=1){const a=e[s];if(i){a===i&&(i=void 0);continue}if(a==='"'||a==="'"){i=a;continue}a==="("?r+=1:a===")"?r-=1:a==="|"&&r===0&&(t.push(e.slice(n,s)),n=s+1)}return t.push(e.slice(n)),t},"splitFilterPipe"),je=f(e=>{const t=e.trim(),r=t.indexOf("(");if(r===-1)return{args:[],name:t};if(!t.endsWith(")"))throw new Error(`Filter call "${e}" missing closing ")"`);const n=t.slice(0,r).trim(),i=t.slice(r+1,-1).trim();return i?{args:L(i).map(s=>s.trim()),name:n}:{args:[],name:n}},"parseFilterCall"),j=f((e,t,r,n,i=!0)=>{const s=e.trim();if(s==="true")return!0;if(s==="false")return!1;if(s==="null"||s==="none")return null;const a=Q(s);return a!==void 0?a:/^-?\d+(\.\d+)?$/.test(s)?Number(s):V(s,t,r,n,i)},"evaluatePrimary"),B=f((e,t,r,n,i=!0)=>{const s=ke(e),a=s[0].trim();let o=j(a,t,r,n,i);for(let l=1;l<s.length;l+=1){const c=s[l].trim(),{args:m,name:u}=je(c),g=m.map(p=>j(p,t,r,n,i));try{o=I(u,o,g)}catch(p){const w=p instanceof Error?p.message:String(p);throw new Error(`${n}:${r}: ${w}`)}}return o},"evaluateExpression"),D=f((e,t)=>{let r,n=0;for(let i=0;i<=e.length-t.length;i+=1){const s=e[i];if(r){s===r&&(r=void 0);continue}if(s==='"'||s==="'"){r=s;continue}if(s==="("){n+=1;continue}if(s===")"){n-=1;continue}if(n===0&&e.slice(i,i+t.length)===t)return i}return-1},"findOperatorOutsideQuotes"),A=f((e,t)=>{const r=[];let n=0,i=0;for(;i<=e.length-t.length;){const s=D(e.slice(i),t);if(s===-1)break;r.push(e.slice(n,i+s)),i+=s+t.length,n=i}return r.push(e.slice(n)),r},"splitLogical"),x=f((e,t,r,n)=>{const i=e.trim();if(i==="")return!1;if(i.startsWith("(")&&i.endsWith(")")&&Se(i)===i.length-1)return x(i.slice(1,-1),t,r,n);const s=A(i," or ");if(s.length>1)return s.some(o=>x(o,t,r,n));const a=A(i," and ");if(a.length>1)return a.every(o=>x(o,t,r,n));if(i.startsWith("not "))return!x(i.slice(4),t,r,n);for(const o of["==","!="]){const l=D(i,o);if(l!==-1){const c=j(i.slice(0,l),t,n,r,!1),m=j(i.slice(l+o.length),t,n,r,!1),u=c===m;return o==="=="?u:!u}}return Oe(B(i,t,n,r,!1))},"evaluateConditionExpression"),Se=f(e=>{if(e[0]!=="(")return-1;let t=0,r,n=-1;for(const i of e){if(n+=1,r){i===r&&(r=void 0);continue}if(i==='"'||i==="'"){r=i;continue}if(i==="(")t+=1;else if(i===")"&&(t-=1,t===0))return n}return-1},"matchingParen"),E=f((e,t)=>{let r="";for(const n of e){if(n.type==="text"){r+=n.value;continue}if(n.type==="expr"){r+=Ee(B(n.expression,t.scope,n.line,t.filename));continue}if(n.type==="if"){const i=x(n.condition,t.scope,t.filename,n.line)?n.consequent:n.alternate??[];r+=E(i,t);continue}if(n.type==="for"){const i=V(n.collection,t.scope,n.line,t.filename,!1);if(i==null)continue;if(!Array.isArray(i))throw new TypeError(`${t.filename}:${n.line}: {% for %} expected an array, got ${typeof i}`);for(const s of i){const a={...t.scope,[n.binding]:s};r+=E(n.body,{...t,scope:a})}continue}if(n.type==="include"){const i=t.partials?.get(n.name);if(!i)throw new Error(`${t.filename}:${n.line}: Partial "${n.name}" not found. Available: ${[...t.partials?.keys()??[]].join(", ")||"(none)"}`);const s=t.includeStack??new Set;if(s.has(n.name)){const a=[...s,n.name].join(" → ");throw new Error(`${t.filename}:${n.line}: Circular partial include detected: ${a}`)}s.add(n.name);try{r+=E(i,{...t,filename:`<partial:${n.name}>`,includeStack:s})}finally{s.delete(n.name)}}}return r},"renderNodes"),_e=f((e,t)=>G(U(e),t),"parseTemplate");f((e,t)=>E(e,t),"renderAst");const _=f((e,t)=>E(G(U(e),t.filename),t),"renderTemplate");var Ce=Object.defineProperty,y=v((e,t)=>Ce(e,"name",{value:t,configurable:!0}),"s");const P="template.yml",Te=".raw",We=new Set([".cjs",".css",".env",".gitattributes",".gitignore",".graphql",".html",".ini",".js",".json",".json5",".jsonc",".jsx",".lock",".md",".mdx",".mjs",".prettierrc",".raw",".rs",".scss",".sh",".sql",".svg",".tera",".toml",".ts",".tsx",".twig",".txt",".vue",".xml",".yaml",".yml"]),Ae=new Set(["Brewfile","CHANGELOG","CODEOWNERS","CONTRIBUTING","COPYING","Dockerfile","Gemfile","LICENCE","LICENSE","Makefile","NOTICE","Procfile","Rakefile","README","VERSION"]),Pe=y(e=>{const t=Math.max(e.lastIndexOf("/"),e.lastIndexOf("\\")),r=t===-1?e:e.slice(t+1),n=r.lastIndexOf(".");return n===-1||n===0?"":r.slice(n).toLowerCase()},"lastDot"),Y=y(e=>{const t=Math.max(e.lastIndexOf("/"),e.lastIndexOf("\\"));return t===-1?e:e.slice(t+1)},"basename"),Fe=y(e=>{const t=Pe(e);if(t!=="")return We.has(t);const r=Y(e);return!!Ae.has(r)},"isLikelyText"),Me=y(e=>{const t={default:e.default,internal:e.internal,order:e.order,prompt:e.prompt,required:e.required};switch(e.type){case"array":return{...t,type:"array"};case"boolean":return{...t,default:typeof t.default=="boolean"?t.default:void 0,type:"boolean"};case"enum":return{...t,multiple:e.multiple,type:"enum",values:e.values??[]};case"number":return{...t,type:"number"};case"string":return{...t,type:"string"};default:throw new Error(`Unsupported variable type "${String(e.type)}"`)}},"yamlVariableToVariable"),Re=y(e=>e.replaceAll("\\","/").replace(/^\.\//,"").replaceAll(/\/+/g,"/"),"normalizeDestinationPath"),Ie=y((e,t,r)=>{const n=t.split("/").filter(Boolean);if(n.length===0)throw new Error("Empty destination path for value");let i=e;for(let s=0;s<n.length-1;s+=1){const a=n[s],o=i[a];if(o===void 0){const l={};i[a]=l,i=l}else if(typeof o=="object"&&!Buffer.isBuffer(o))i=o;else throw new TypeError(`Path conflict: "${n.slice(0,s+1).join("/")}" is both a file and a directory`)}i[n.at(-1)]=r},"flattenFiles"),F=y((e,t,r)=>{if(typeof e!="string")return Ne(e);const n=e.includes("{{")||e.includes("{%")?_(e,{filename:`${r}#frontmatter`,scope:t}):e;return x(n,t,`${r}#frontmatter`,1)},"evaluateGate"),Ne=y(e=>e==null||e===!1||e===0||e===""?!1:Array.isArray(e)?e.length>0:typeof e=="string"?e!=="false"&&e!=="0":!0,"truthyValue"),De=y((e,t)=>{const r=R(e,P),n=X(r);if(!n||typeof n!="object")throw new Error(`${r}: must contain a YAML mapping`);const i={};if(n.variables)for(const[l,c]of Object.entries(n.variables))i[l]=Me(c);const s=new Map,a=[];for(const l of J(e,{includeDirs:!1,includeSymlinks:!1})){if(l.path===r)continue;const c=M(e,l.path).replaceAll("\\","/");if(c===P)continue;if(ye(c)){const u=k(l.path),g=_e(u,c);for(const p of Le(c))s.has(p)&&s.get(p)!==g&&console.warn(`warn: partial name "${p}" is declared by multiple files — last one wins. Use distinct names or fully-qualified includes.`),s.set(p,g);continue}if(c.endsWith(Te)){const u=k(l.path);a.push({binary:null,isRaw:!0,rawText:u,relativePath:c});continue}if(Fe(c)){const u=k(l.path);a.push({binary:null,isRaw:!1,rawText:u,relativePath:c});continue}const m=k(l.path,{buffer:!0});a.push({binary:m,isRaw:!1,rawText:null,relativePath:c})}const o=y(l=>{const c={...l.builtins,...l.options},m={},u={};for(const p of a){const w=p.relativePath;let O,C,T=!1;if(p.binary)O=p.binary;else if(p.isRaw)O=p.rawText??"";else{const K=p.rawText??"",b=we(K,z=>Z(z));if(b.frontmatter){if(b.frontmatter.skip!==void 0&&F(b.frontmatter.skip,c,w)||b.frontmatter.if!==void 0&&!F(b.frontmatter.if,c,w))continue;typeof b.frontmatter.to=="string"&&(C=_(b.frontmatter.to,{filename:`${w}#frontmatter.to`,partials:s,scope:c})),b.frontmatter.force===!0&&(T=!0)}O=_(b.body,{filename:w,partials:s,scope:c})}const W=Re(C??de(he(w),c));Ie(m,W,O),T&&(u[W]={force:!0})}const g={files:m};return Object.keys(u).length>0&&(g.filesMeta=u),g},"produce");return{about:{description:n.description??`Moon-format template at ${e}`,name:n.title??t},destination:n.destination,options:i,produce:o}},"loadMoonTemplate"),Le=y(e=>{const t=q(e),r=new Set;r.add(t);const n=Y(t);if(r.add(n),n.startsWith("_")){r.add(n.replace(/^_+/,""));const i=t.slice(0,t.length-n.length);r.add(`${i}${n.replace(/^_+/,"")}`)}return[...r]},"partialKeys");export{De as loadMoonTemplate};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var n=Object.defineProperty;var o=(t,e)=>n(t,"name",{value:e,configurable:!0});import{dirname as u}from"@visulima/path";import{createJiti as l}from"jiti";var i=Object.defineProperty,a=o((t,e)=>i(t,"name",{value:e,configurable:!0}),"r");const p=a((t,e)=>{if(!e||typeof e!="object")throw new TypeError(`${t}: default export must be an object (got ${e===null?"null":typeof e}). Use createTemplate({ ... }).`);const r=e;if(typeof r.about!="object"||r.about===null)throw new TypeError(`${t}: default export missing required "about" object`);if(typeof r.produce!="function")throw new TypeError(`${t}: default export missing required "produce" function`);return e},"validateTemplateExport"),d=a(async t=>{const e=await l(u(t),{fsCache:!1,moduleCache:!1}).import(t,{default:!0,try:!0})??null;return p(t,e)},"loadNativeTemplate");export{d as loadNativeTemplate};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{otelPlugin as l}from"../config.js";export{l as otelPlugin};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Task } from "@visulima/task-runner";
|
|
2
|
+
import type { VisPlugin } from "../hooks.d.ts";
|
|
3
|
+
/**
|
|
4
|
+
* Minimal OTel-shaped span. Deliberately structural so users can pass
|
|
5
|
+
* an `@opentelemetry/api` Tracer, an `@opentelemetry/sdk-node` one, or
|
|
6
|
+
* a custom implementation without the plugin depending on any
|
|
7
|
+
* particular OTel package.
|
|
8
|
+
*/
|
|
9
|
+
export interface OtelSpan {
|
|
10
|
+
end: () => void;
|
|
11
|
+
recordException?: (error: unknown) => void;
|
|
12
|
+
setAttribute?: (key: string, value: boolean | number | string) => void;
|
|
13
|
+
setStatus?: (status: {
|
|
14
|
+
code: number;
|
|
15
|
+
message?: string;
|
|
16
|
+
}) => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Minimal Tracer contract. Accepts the real
|
|
20
|
+
* `@opentelemetry/api`'s `Tracer.startSpan(name, options?)` shape —
|
|
21
|
+
* the plugin only calls the two methods it strictly needs.
|
|
22
|
+
*/
|
|
23
|
+
export interface OtelTracer {
|
|
24
|
+
startSpan: (name: string, options?: {
|
|
25
|
+
attributes?: Record<string, string | number | boolean>;
|
|
26
|
+
}) => OtelSpan;
|
|
27
|
+
}
|
|
28
|
+
export interface OtelPluginOptions {
|
|
29
|
+
/**
|
|
30
|
+
* Rename incoming `project:target` IDs before they become OTel
|
|
31
|
+
* span names. Defaults to passing the id through unchanged.
|
|
32
|
+
*/
|
|
33
|
+
renameSpan?: (task: Task) => string;
|
|
34
|
+
/** Tracer used to emit spans. Required — pass the one from `@opentelemetry/api`'s `trace.getTracer("vis")`. */
|
|
35
|
+
tracer: OtelTracer;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Reference plugin that maps vis hook lifecycle events to OTel spans.
|
|
39
|
+
*
|
|
40
|
+
* Emits:
|
|
41
|
+
* - one **root span** named `vis.run` spanning `run:before` → `run:after`
|
|
42
|
+
* - one **child span** per task spanning `task:before` → `task:after`
|
|
43
|
+
* with attributes `vis.task.id`, `vis.task.project`, `vis.task.target`,
|
|
44
|
+
* `vis.task.cache_status`, `vis.task.exit_code`
|
|
45
|
+
* - `task:failure` sets span status to ERROR and records the exit code
|
|
46
|
+
*
|
|
47
|
+
* Streaming stdout/stderr events are intentionally **not** emitted as
|
|
48
|
+
* span events — high-frequency chunks would blow up OTel backends. Use
|
|
49
|
+
* a log exporter if you need stream-level visibility.
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* import { trace } from "@opentelemetry/api";
|
|
53
|
+
* import { defineConfig } from "@visulima/vis/config";
|
|
54
|
+
* import { otelPlugin } from "@visulima/vis/plugins/otel";
|
|
55
|
+
*
|
|
56
|
+
* const tracer = trace.getTracer("vis", "1.0.0");
|
|
57
|
+
*
|
|
58
|
+
* export default defineConfig({
|
|
59
|
+
* plugins: [otelPlugin({ tracer })],
|
|
60
|
+
* });
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare const otelPlugin: (options: OtelPluginOptions) => VisPlugin;
|
package/dist/pm-runner.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Shared helper for executing package manager commands via native Rust bindings.
|
|
3
3
|
* Falls back to JS-based detection when native bindings are unavailable.
|
|
4
4
|
*/
|
|
5
|
-
import type { AddOptions, DlxOptions, ExecOptions, InstallOptions, OutdatedOptions, RemoveOptions, WhyOptions } from "./native-binding.d.ts";
|
|
5
|
+
import type { AddOptions, DlxOptions, ExecOptions, InstallOptions, OutdatedOptions, RemoveOptions, ResolvedCommand, WhyOptions } from "./native-binding.d.ts";
|
|
6
6
|
interface PmInfo {
|
|
7
7
|
name: "bun" | "npm" | "pnpm" | "yarn";
|
|
8
8
|
version: string;
|
|
@@ -14,10 +14,31 @@ declare const runRemove: (pm: PmInfo, options: RemoveOptions, cwd: string, logge
|
|
|
14
14
|
declare const runDedupe: (pm: PmInfo, check: boolean, cwd: string, logger: Console) => number;
|
|
15
15
|
declare const runWhy: (pm: PmInfo, options: WhyOptions, cwd: string, logger: Console) => number;
|
|
16
16
|
declare const runOutdated: (pm: PmInfo, options: OutdatedOptions, cwd: string, logger: Console) => number;
|
|
17
|
+
interface InfoOptions {
|
|
18
|
+
fields: string[];
|
|
19
|
+
json: boolean;
|
|
20
|
+
package: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Resolves a registry metadata lookup to a runnable command. Built in TS
|
|
24
|
+
* rather than the Rust resolver because bun needs `pm view` (two-word
|
|
25
|
+
* subcommand) and yarn berry needs `yarn npm info` — both shapes the existing
|
|
26
|
+
* `resolve_pm_command` view branch gets wrong.
|
|
27
|
+
*
|
|
28
|
+
* Pure function — exported for unit testing.
|
|
29
|
+
*/
|
|
30
|
+
declare const resolveInfo: (pm: PmInfo, options: InfoOptions) => ResolvedCommand;
|
|
31
|
+
declare const runInfo: (pm: PmInfo, options: InfoOptions, cwd: string, logger: Console) => number;
|
|
32
|
+
/**
|
|
33
|
+
* Resolves and runs a PM `link` operation. Passes `pm.version` to the native
|
|
34
|
+
* resolver so it can warn about pnpm v11 restrictions (arg-less link and
|
|
35
|
+
* global-store name resolution were removed). `target` is `null` for arg-less
|
|
36
|
+
* link, or a package name / path string.
|
|
37
|
+
*/
|
|
17
38
|
declare const runLink: (pm: PmInfo, target: string | null, cwd: string, logger: Console) => number;
|
|
18
39
|
declare const runUnlink: (pm: PmInfo, packages: string[], recursive: boolean, cwd: string, logger: Console) => number;
|
|
19
40
|
declare const runDlx: (pm: PmInfo, options: DlxOptions, cwd: string, logger: Console) => number;
|
|
20
41
|
declare const runExec: (pm: PmInfo, options: ExecOptions, cwd: string, logger: Console) => number;
|
|
21
42
|
declare const runPmSubcommand: (pm: PmInfo, subcommand: string, args: string[], cwd: string, logger: Console) => number;
|
|
22
|
-
export type { PmInfo };
|
|
23
|
-
export { detectPm, runAdd, runDedupe, runDlx, runExec, runInstall, runLink, runOutdated, runPmSubcommand, runRemove, runUnlink, runWhy };
|
|
43
|
+
export type { InfoOptions, PmInfo };
|
|
44
|
+
export { detectPm, resolveInfo, runAdd, runDedupe, runDlx, runExec, runInfo, runInstall, runLink, runOutdated, runPmSubcommand, runRemove, runUnlink, runWhy };
|