@gjsify/cli 0.14.0 → 0.15.1

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.
@@ -0,0 +1,157 @@
1
+ import { type Workspace } from '@gjsify/workspace';
2
+ /** Bump to invalidate every existing cache entry (schema/semantic changes). */
3
+ export declare const BUILD_CACHE_LAYOUT_VERSION = "v1";
4
+ /** Conventional per-package build output directories, checked in this order. */
5
+ export declare const OUTPUT_DIR_CANDIDATES: readonly ["lib", "dist", "dist-templates"];
6
+ /** Keep at most this many keys per package; evict the least recently stored/used. */
7
+ export declare const MAX_KEYS_PER_PACKAGE = 2;
8
+ /** Toolchain packages whose resolved versions salt every cache key. */
9
+ export declare const TOOLCHAIN_PACKAGES: readonly ["@gjsify/cli", "@gjsify/tsc", "rolldown", "typescript"];
10
+ export interface BuildCacheManifest {
11
+ version: 1;
12
+ layout: string;
13
+ package: string;
14
+ script: string;
15
+ key: string;
16
+ /** Output dirs (relative to the package dir) the build modified. */
17
+ dirs: string[];
18
+ /** Content hash of the stored output dirs (mtime-independent). */
19
+ outputsHash: string;
20
+ createdAt: string;
21
+ usedAt: string;
22
+ }
23
+ /** `true` when GJSIFY_BUILD_CACHE is set to a non-empty, non-"0"/"false" value. */
24
+ export declare function buildCacheEnabledByEnv(env?: Record<string, string | undefined>): boolean;
25
+ /** Cache root for a workspace: `<root>/node_modules/.cache/gjsify/build`. */
26
+ export declare function buildCacheRoot(workspaceRoot: string): string;
27
+ /**
28
+ * Directory-safe package name. Scoped names collapse (`@gjsify/cli` →
29
+ * `gjsify-cli`); an 8-hex sha256 suffix of the exact name rules out
30
+ * collisions between e.g. `@a/b-c` and `@a-b/c`.
31
+ */
32
+ export declare function sanitizePackageDirName(name: string): string;
33
+ /** Streamed sha256 of one file (bounded memory, real contents). */
34
+ export declare function hashFileStream(path: string): string;
35
+ /**
36
+ * Content hash of a package's build INPUTS: every file under `src/**`, plus
37
+ * `package.json`, plus root `tsconfig*.json`. Sorted, content-streamed —
38
+ * mtimes do not participate, so a `git checkout` with identical contents
39
+ * hashes identically across machines.
40
+ */
41
+ export declare function hashPackageInputs(location: string): string;
42
+ /**
43
+ * Mtime-independent content hash of a set of output dirs — used to skip the
44
+ * restore copy when the on-disk outputs already match the cached entry, and
45
+ * as an integrity stamp of what was stored.
46
+ */
47
+ export declare function hashOutputDirs(location: string, dirs: readonly string[]): string;
48
+ /**
49
+ * Cheap per-dir change signature (existence + file list + sizes + mtimes).
50
+ * Taken BEFORE running the script and compared AFTER, to detect which output
51
+ * dirs the build actually modified. Content hashing is deliberately avoided
52
+ * here — a build that rewrites identical bytes still bumps mtimes, and that
53
+ * is exactly the "this dir belongs to the build" signal we want.
54
+ */
55
+ export declare function snapshotOutputDirs(location: string): Record<string, string | null>;
56
+ /** Output dirs whose signature changed (or that newly appeared) since `before`. */
57
+ export declare function modifiedOutputDirs(location: string, before: Record<string, string | null>): string[];
58
+ export interface ComposeCacheKeyInput {
59
+ script: string;
60
+ /** Extra args forwarded to the script invocation (affect the outputs). */
61
+ args?: readonly string[];
62
+ /** Toolchain package → resolved version (or 'none'). */
63
+ toolchain: Record<string, string>;
64
+ /** The package's own input hash. */
65
+ ownHash: string;
66
+ /** dep name → input hash for the FULL transitive workspace-dep closure. */
67
+ depHashes: ReadonlyMap<string, string> | Record<string, string>;
68
+ }
69
+ /** Deterministic cache key (32 hex chars) from all invalidation ingredients. */
70
+ export declare function composeCacheKey(input: ComposeCacheKeyInput): string;
71
+ /**
72
+ * Resolve the toolchain versions that salt every key from the workspace's
73
+ * OWN resolution (`<root>/node_modules/<pkg>/package.json`). In the gjsify
74
+ * monorepo these are symlinks into the workspace itself, so a CLI/tsc bump
75
+ * invalidates immediately. A package that isn't resolvable maps to 'none'
76
+ * (deterministic). `@gjsify/cli` additionally falls back to the RUNNING
77
+ * CLI's own version so globally-installed CLIs still salt correctly.
78
+ */
79
+ export declare function resolveToolchainVersions(workspaceRoot: string): Record<string, string>;
80
+ /** Directory of one cache entry: `<cacheRoot>/<pkg-sanitized>/<key>`. */
81
+ export declare function buildCacheEntryDir(cacheRoot: string, pkgName: string, key: string): string;
82
+ /** Read + validate a cache entry's manifest; any mismatch is a MISS (null). */
83
+ export declare function readCacheEntry(cacheRoot: string, pkgName: string, key: string): BuildCacheManifest | null;
84
+ /**
85
+ * Store the given output dirs of a package under `key`. Atomic: builds a
86
+ * `.tmp-<pid>` sibling then renames into place, so concurrent readers never
87
+ * observe a partial entry. Best-effort — failures are swallowed (the build
88
+ * itself already succeeded).
89
+ */
90
+ export declare function storeCacheEntry(cacheRoot: string, pkg: {
91
+ name: string;
92
+ location: string;
93
+ }, key: string, script: string, dirs: readonly string[]): BuildCacheManifest | null;
94
+ /**
95
+ * Restore a validated entry into the package. Replaces EXACTLY the dirs the
96
+ * manifest records (delete-then-copy within the package); skips the copy
97
+ * when the on-disk outputs already content-match the entry. Returns how the
98
+ * hit was satisfied, or null when restoration failed (treat as MISS).
99
+ */
100
+ export declare function restoreCacheEntry(cacheRoot: string, pkg: {
101
+ name: string;
102
+ location: string;
103
+ }, manifest: BuildCacheManifest): 'restored' | 'up-to-date' | null;
104
+ /** Evict the oldest entries (by last store/use) beyond `keep` per package. */
105
+ export declare function pruneCacheEntries(cacheRoot: string, pkgName: string, keep?: number): void;
106
+ export interface BuildCacheRunnerOptions {
107
+ /** Workspace (monorepo) root — owns node_modules/.cache. */
108
+ root: string;
109
+ /** ALL discovered workspaces (not just the selected set) for dep closure. */
110
+ workspaces: readonly Workspace[];
111
+ /** Script name being run (part of every key). */
112
+ script: string;
113
+ /** Extra args forwarded to every invocation (part of every key). */
114
+ args?: readonly string[];
115
+ /**
116
+ * Workspace names that will be run. Their input hashes (plus their
117
+ * closures') are computed EAGERLY at construction so every key reflects
118
+ * the tree state at RUN START — a build that mutates its own `src/`
119
+ * (adwaita-web's generated stylesheet module) must not make a sibling's
120
+ * key depend on scheduling order within the same run.
121
+ */
122
+ targets?: readonly string[];
123
+ /** Log sink (default: stderr, keeping stdout clean for script output). */
124
+ log?: (line: string) => void;
125
+ }
126
+ export declare function buildCacheOptedOut(ws: Workspace): boolean;
127
+ /**
128
+ * Per-run orchestrator used by `gjsify workspace` / `gjsify foreach`:
129
+ * memoizes input hashes + keys across packages, restores on hit, snapshots +
130
+ * stores on miss. All entry points are fail-soft — any internal error logs a
131
+ * warning and reports a MISS so the script runs normally.
132
+ */
133
+ export declare class BuildCacheRunner {
134
+ private readonly options;
135
+ private readonly cacheRoot;
136
+ private readonly graph;
137
+ private readonly toolchain;
138
+ private readonly ownHashes;
139
+ private readonly closures;
140
+ private readonly keys;
141
+ private readonly log;
142
+ constructor(options: BuildCacheRunnerOptions);
143
+ private ownHashOf;
144
+ /** BFS transitive workspace-dep closure (cycle-safe), excluding `name` itself. */
145
+ private closureOf;
146
+ /** Content-hash cache key for one workspace (memoized per run). */
147
+ keyFor(ws: Workspace): string;
148
+ /**
149
+ * Try to satisfy the script from the cache. Returns `true` on a hit
150
+ * (outputs restored / already current — the caller SKIPS the script).
151
+ */
152
+ tryRestore(ws: Workspace): boolean;
153
+ /** Snapshot the candidate output dirs BEFORE running the script. */
154
+ snapshotOutputs(ws: Workspace): Record<string, string | null>;
155
+ /** After a SUCCESSFUL script run: store the dirs the build modified. */
156
+ storeAfterSuccess(ws: Workspace, before: Record<string, string | null>): void;
157
+ }