@kici-dev/shared 0.1.3 → 0.1.5
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/dist/db-admin.d.ts +25 -3
- package/dist/db-admin.js +20 -11
- package/dist/db-collation.d.ts +60 -0
- package/dist/db-collation.js +52 -0
- package/dist/db-collation.test.d.ts +2 -0
- package/dist/env/allowlist.d.ts +6 -6
- package/dist/env/allowlist.js +7 -7
- package/dist/env/logger-env.d.ts +6 -1
- package/dist/env/logger-env.js +21 -0
- package/dist/idempotency-env-diff.d.ts +83 -0
- package/dist/idempotency-env-diff.js +163 -0
- package/dist/idempotency-env-diff.test.d.ts +2 -0
- package/dist/idempotency-files.d.ts +71 -0
- package/dist/idempotency-files.js +73 -6
- package/dist/idempotency-yaml-diff.d.ts +74 -0
- package/dist/idempotency-yaml-diff.js +241 -0
- package/dist/idempotency-yaml-diff.test.d.ts +2 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/logger.d.ts +4 -1
- package/dist/logger.js +23 -17
- package/dist/telemetry/index.d.ts +1 -1
- package/dist/telemetry/index.js +2 -2
- package/dist/telemetry/init.d.ts +10 -0
- package/dist/telemetry/init.js +32 -1
- package/dist/tool-check.js +31 -11
- package/package.json +14 -1
- package/sbom.spdx.json +10 -5
|
@@ -29,6 +29,16 @@
|
|
|
29
29
|
*/
|
|
30
30
|
export type FileChangeCategory = 'new' | 'content' | 'mode' | 'time-only';
|
|
31
31
|
export type ContentSkipReason = 'binary' | 'too-large' | 'read-failed' | 'sensitive';
|
|
32
|
+
/**
|
|
33
|
+
* Renderer hint for the diff body. The default `'unified-text'` produces
|
|
34
|
+
* a `createTwoFilesPatch`-style block (the v1 shape). `'env-semantic'`
|
|
35
|
+
* routes through the env-file diff renderer (keys + classification, with
|
|
36
|
+
* value masking by default). `'yaml-semantic'` routes through the yaml
|
|
37
|
+
* deep-diff renderer (dotted-path leaf entries, with masking on sensitive
|
|
38
|
+
* paths). `'suppressed'` hides the body and prints a skip-reason marker —
|
|
39
|
+
* used for genuinely-opaque content the caller refuses to capture.
|
|
40
|
+
*/
|
|
41
|
+
export type FileDiffMode = 'unified-text' | 'env-semantic' | 'yaml-semantic' | 'suppressed';
|
|
32
42
|
/**
|
|
33
43
|
* Per-file drift entry as carried inside a phase's Drift value.
|
|
34
44
|
* `localPath` and `remotePath` are filled in by the caller that owns the
|
|
@@ -53,7 +63,23 @@ export interface FileDriftEntry {
|
|
|
53
63
|
remoteContent?: string;
|
|
54
64
|
/** Set when content capture was intentionally skipped — used by the renderer to explain the gap. */
|
|
55
65
|
contentSkipped?: ContentSkipReason;
|
|
66
|
+
/**
|
|
67
|
+
* Renderer hint. When omitted, the renderer auto-detects from
|
|
68
|
+
* `remotePath`: `.env` → `'env-semantic'`, `.yaml` / `.yml` →
|
|
69
|
+
* `'yaml-semantic'`, otherwise → `'unified-text'`. Explicit values
|
|
70
|
+
* override the auto-detect. Set to `'suppressed'` to opt out of any
|
|
71
|
+
* inline body and rely on `contentSkipped` for the explanation row.
|
|
72
|
+
*/
|
|
73
|
+
diffMode?: FileDiffMode;
|
|
56
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Auto-detect the diff mode for a given entry. Explicit `entry.diffMode`
|
|
77
|
+
* always wins. Otherwise the suffix of `remotePath` is the only signal —
|
|
78
|
+
* we deliberately do NOT sniff `localContent` bytes because the goal of
|
|
79
|
+
* the helper is to produce a deterministic, callsite-readable hint that
|
|
80
|
+
* matches the caller's intent.
|
|
81
|
+
*/
|
|
82
|
+
export declare function resolveDiffMode(entry: FileDriftEntry): FileDiffMode;
|
|
57
83
|
/** Low-level parse output: category + the relative path rsync printed. */
|
|
58
84
|
export interface ItemizeRecord {
|
|
59
85
|
itemizeCode: string;
|
|
@@ -80,6 +106,21 @@ export interface RenderDriftOpts {
|
|
|
80
106
|
color?: boolean;
|
|
81
107
|
/** Cap on diff body lines per entry (excluding header). Default 200. */
|
|
82
108
|
maxLines?: number;
|
|
109
|
+
/**
|
|
110
|
+
* When true, env-semantic and yaml-semantic renderers will print the
|
|
111
|
+
* actual values instead of masking them. Off by default so the confirm
|
|
112
|
+
* prompt and the tee'd log file never carry plaintext credentials
|
|
113
|
+
* without an explicit operator opt-in.
|
|
114
|
+
*/
|
|
115
|
+
revealEnvValues?: boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Restrict which categories get a diff body rendered. Entries whose
|
|
118
|
+
* category is NOT in this set show only the per-file row, no diff.
|
|
119
|
+
* Default: `['new', 'content']` (every visible drift body). Useful for
|
|
120
|
+
* `--diff-only=content` operator workflows that want to suppress the
|
|
121
|
+
* potentially-huge full-file body of newly-introduced files.
|
|
122
|
+
*/
|
|
123
|
+
diffOnlyCategories?: FileChangeCategory[];
|
|
83
124
|
}
|
|
84
125
|
/**
|
|
85
126
|
* Render the unified-diff block for a single FileDriftEntry. Returns an
|
|
@@ -92,8 +133,37 @@ export interface RenderDriftOpts {
|
|
|
92
133
|
* skip reason. Entries with no content captured (older callers that
|
|
93
134
|
* didn't fill the fields) also return empty — the caller falls back to
|
|
94
135
|
* the label-only row.
|
|
136
|
+
*
|
|
137
|
+
* This function ALWAYS renders the unified-text shape regardless of the
|
|
138
|
+
* entry's `diffMode` — it's the v1 path. The renderer dispatch in
|
|
139
|
+
* `renderFileDrifts` decides which shape to invoke per entry; this
|
|
140
|
+
* helper stays the unified-text branch for callers that want to render
|
|
141
|
+
* a single entry in unified shape.
|
|
95
142
|
*/
|
|
96
143
|
export declare function renderFileDriftWithDiff(entry: FileDriftEntry, opts?: Pick<RenderDriftOpts, 'color' | 'maxLines'>): string[];
|
|
144
|
+
/**
|
|
145
|
+
* Dispatch helper: given a single entry and the render opts, pick the
|
|
146
|
+
* right renderer based on `resolveDiffMode(entry)`. Returns the diff body
|
|
147
|
+
* lines (no surrounding indent applied) — same shape as
|
|
148
|
+
* `renderFileDriftWithDiff` so the caller can nest each line identically
|
|
149
|
+
* regardless of which renderer fired.
|
|
150
|
+
*
|
|
151
|
+
* The placeholder `yaml-semantic` branch deliberately falls back to the
|
|
152
|
+
* unified-text rendering when this entry hasn't been routed through a
|
|
153
|
+
* yaml-aware caller. The dedicated `renderYamlDiff` lives in
|
|
154
|
+
* `idempotency-yaml-diff.ts`; the dispatch wire-up happens here once it's
|
|
155
|
+
* imported.
|
|
156
|
+
*/
|
|
157
|
+
export declare function renderFileDriftBody(entry: FileDriftEntry, opts?: RenderDriftOpts): string[];
|
|
158
|
+
/**
|
|
159
|
+
* Yaml renderer registration. The yaml module (`idempotency-yaml-diff.ts`)
|
|
160
|
+
* calls `setYamlDiffRenderer` at its own load time so the file-drift
|
|
161
|
+
* renderer can dispatch to it without taking a static dependency on the
|
|
162
|
+
* `yaml` npm package. Callers that never import the yaml module fall
|
|
163
|
+
* through to unified-text rendering, which is the safe default.
|
|
164
|
+
*/
|
|
165
|
+
type YamlDiffRenderer = (entry: FileDriftEntry, opts: RenderDriftOpts) => string[];
|
|
166
|
+
export declare function setYamlDiffRenderer(renderer: YamlDiffRenderer | null): void;
|
|
97
167
|
/**
|
|
98
168
|
* Render a FileDriftEntry[] as an aligned multi-line block suitable for
|
|
99
169
|
* inclusion in a confirm-prompt summary.
|
|
@@ -110,4 +180,5 @@ export declare function renderFileDriftWithDiff(entry: FileDriftEntry, opts?: Pi
|
|
|
110
180
|
* decides how to nest the block in a wider prompt.
|
|
111
181
|
*/
|
|
112
182
|
export declare function renderFileDrifts(entries: FileDriftEntry[], opts?: RenderDriftOpts): string[];
|
|
183
|
+
export {};
|
|
113
184
|
//# sourceMappingURL=idempotency-files.d.ts.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import "./chunk-gOLHoazu.js";
|
|
2
|
+
import { diffEnvFiles, renderEnvDiff } from "./idempotency-env-diff.js";
|
|
2
3
|
import { createTwoFilesPatch } from "diff";
|
|
3
4
|
//#region src/idempotency-files.ts
|
|
4
5
|
/**
|
|
@@ -36,6 +37,20 @@ const ANSI_CYAN = "\x1B[36m";
|
|
|
36
37
|
const ANSI_BOLD = "\x1B[1m";
|
|
37
38
|
const ANSI_RESET = "\x1B[0m";
|
|
38
39
|
/**
|
|
40
|
+
* Auto-detect the diff mode for a given entry. Explicit `entry.diffMode`
|
|
41
|
+
* always wins. Otherwise the suffix of `remotePath` is the only signal —
|
|
42
|
+
* we deliberately do NOT sniff `localContent` bytes because the goal of
|
|
43
|
+
* the helper is to produce a deterministic, callsite-readable hint that
|
|
44
|
+
* matches the caller's intent.
|
|
45
|
+
*/
|
|
46
|
+
function resolveDiffMode(entry) {
|
|
47
|
+
if (entry.diffMode) return entry.diffMode;
|
|
48
|
+
const remote = entry.remotePath.toLowerCase();
|
|
49
|
+
if (remote.endsWith(".env")) return "env-semantic";
|
|
50
|
+
if (remote.endsWith(".yaml") || remote.endsWith(".yml")) return "yaml-semantic";
|
|
51
|
+
return "unified-text";
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
39
54
|
* Parse one line of `rsync --itemize-changes` output. Returns null for
|
|
40
55
|
* lines that are not actionable file drift entries:
|
|
41
56
|
* - "sending incremental file list" header line
|
|
@@ -118,6 +133,12 @@ const SKIP_REASON_DISPLAY = {
|
|
|
118
133
|
* skip reason. Entries with no content captured (older callers that
|
|
119
134
|
* didn't fill the fields) also return empty — the caller falls back to
|
|
120
135
|
* the label-only row.
|
|
136
|
+
*
|
|
137
|
+
* This function ALWAYS renders the unified-text shape regardless of the
|
|
138
|
+
* entry's `diffMode` — it's the v1 path. The renderer dispatch in
|
|
139
|
+
* `renderFileDrifts` decides which shape to invoke per entry; this
|
|
140
|
+
* helper stays the unified-text branch for callers that want to render
|
|
141
|
+
* a single entry in unified shape.
|
|
121
142
|
*/
|
|
122
143
|
function renderFileDriftWithDiff(entry, opts = {}) {
|
|
123
144
|
if (entry.category === "mode" || entry.category === "time-only") return [];
|
|
@@ -135,6 +156,54 @@ function renderFileDriftWithDiff(entry, opts = {}) {
|
|
|
135
156
|
if (truncated) lines.push(`… (${body.length - maxLines} more lines truncated; raw patch in log file)`);
|
|
136
157
|
return lines;
|
|
137
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Dispatch helper: given a single entry and the render opts, pick the
|
|
161
|
+
* right renderer based on `resolveDiffMode(entry)`. Returns the diff body
|
|
162
|
+
* lines (no surrounding indent applied) — same shape as
|
|
163
|
+
* `renderFileDriftWithDiff` so the caller can nest each line identically
|
|
164
|
+
* regardless of which renderer fired.
|
|
165
|
+
*
|
|
166
|
+
* The placeholder `yaml-semantic` branch deliberately falls back to the
|
|
167
|
+
* unified-text rendering when this entry hasn't been routed through a
|
|
168
|
+
* yaml-aware caller. The dedicated `renderYamlDiff` lives in
|
|
169
|
+
* `idempotency-yaml-diff.ts`; the dispatch wire-up happens here once it's
|
|
170
|
+
* imported.
|
|
171
|
+
*/
|
|
172
|
+
function renderFileDriftBody(entry, opts = {}) {
|
|
173
|
+
if (entry.category === "mode" || entry.category === "time-only") return [];
|
|
174
|
+
const mode = resolveDiffMode(entry);
|
|
175
|
+
if (mode === "suppressed") return [SKIP_REASON_DISPLAY[entry.contentSkipped ?? "sensitive"]];
|
|
176
|
+
if (entry.contentSkipped) return [SKIP_REASON_DISPLAY[entry.contentSkipped]];
|
|
177
|
+
if (mode === "env-semantic") return renderEnvDiffBody(entry, opts);
|
|
178
|
+
if (mode === "yaml-semantic") {
|
|
179
|
+
if (yamlDiffRenderer) return yamlDiffRenderer(entry, opts);
|
|
180
|
+
}
|
|
181
|
+
return renderFileDriftWithDiff(entry, {
|
|
182
|
+
color: opts.color,
|
|
183
|
+
maxLines: opts.maxLines
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Bridge between the env-diff module and the file-drift renderer. Reads
|
|
188
|
+
* `localContent` + `remoteContent` from the entry and delegates to
|
|
189
|
+
* `diffEnvFiles` + `renderEnvDiff` from `idempotency-env-diff.ts`.
|
|
190
|
+
*
|
|
191
|
+
* NEW entries (no `remoteContent`) treat the remote side as an empty file
|
|
192
|
+
* — every local key becomes an `added` entry.
|
|
193
|
+
*/
|
|
194
|
+
function renderEnvDiffBody(entry, opts) {
|
|
195
|
+
const local = entry.localContent ?? "";
|
|
196
|
+
const remote = entry.category === "new" ? "" : entry.remoteContent ?? "";
|
|
197
|
+
if (local === "" && remote === "" && entry.category !== "new") return [];
|
|
198
|
+
return renderEnvDiff(diffEnvFiles(local, remote), {
|
|
199
|
+
reveal: opts.revealEnvValues ?? false,
|
|
200
|
+
color: opts.color ?? false
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
let yamlDiffRenderer = null;
|
|
204
|
+
function setYamlDiffRenderer(renderer) {
|
|
205
|
+
yamlDiffRenderer = renderer;
|
|
206
|
+
}
|
|
138
207
|
function colorize(line, color) {
|
|
139
208
|
if (!color) return line;
|
|
140
209
|
if (line.startsWith("+++") || line.startsWith("---")) return `${ANSI_BOLD}${line}${ANSI_RESET}`;
|
|
@@ -170,21 +239,19 @@ function renderFileDrifts(entries, opts = {}) {
|
|
|
170
239
|
if (ai !== bi) return ai - bi;
|
|
171
240
|
return a.localPath.localeCompare(b.localPath);
|
|
172
241
|
});
|
|
242
|
+
const diffOnly = new Set(opts.diffOnlyCategories ?? ["new", "content"]);
|
|
173
243
|
const lines = [`${entries.length} file(s) drifted: ${summary}`];
|
|
174
244
|
for (const e of sorted) {
|
|
175
245
|
const label = CATEGORY_DISPLAY[e.category].padEnd(widest);
|
|
176
246
|
lines.push(` ${label} ${e.localPath}`);
|
|
177
|
-
if (opts.withContent) {
|
|
178
|
-
const diff =
|
|
179
|
-
color: opts.color,
|
|
180
|
-
maxLines: opts.maxLines
|
|
181
|
-
});
|
|
247
|
+
if (opts.withContent && diffOnly.has(e.category)) {
|
|
248
|
+
const diff = renderFileDriftBody(e, opts);
|
|
182
249
|
for (const dl of diff) lines.push(` ${dl}`);
|
|
183
250
|
}
|
|
184
251
|
}
|
|
185
252
|
return lines;
|
|
186
253
|
}
|
|
187
254
|
//#endregion
|
|
188
|
-
export { parseItemizeLine, renderFileDriftWithDiff, renderFileDrifts };
|
|
255
|
+
export { parseItemizeLine, renderFileDriftBody, renderFileDriftWithDiff, renderFileDrifts, resolveDiffMode, setYamlDiffRenderer };
|
|
189
256
|
|
|
190
257
|
//# sourceMappingURL=idempotency-files.js.map
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* YAML-file semantic diff for the idempotent-step preview path. Parses
|
|
3
|
+
* both sides with the `yaml` npm package, deep-walks the resulting JS
|
|
4
|
+
* trees, and emits one `YamlDiffEntry` per leaf-level path that differs.
|
|
5
|
+
*
|
|
6
|
+
* "Leaf" means the smallest scalar inside the tree: a string, number,
|
|
7
|
+
* boolean, or null. Arrays compare element-by-element by index; objects
|
|
8
|
+
* recurse into their fields. The dotted path follows the JS-property
|
|
9
|
+
* convention (`Database.postgres.User.Password`, `clients[2].name`).
|
|
10
|
+
*
|
|
11
|
+
* The renderer masks every entry whose path contains a sensitive
|
|
12
|
+
* segment (`/password|passwd|secret|api[_-]?key|token|credentials?/i`)
|
|
13
|
+
* unless the operator passes `reveal: true` via the
|
|
14
|
+
* `--reveal-env-values` CLI flag. Non-sensitive entries print their
|
|
15
|
+
* values inline so the operator can see config drift at a glance.
|
|
16
|
+
*/
|
|
17
|
+
export type YamlDiffKind = 'added' | 'removed' | 'changed';
|
|
18
|
+
export interface YamlDiffEntry {
|
|
19
|
+
/** Dotted path to the leaf, e.g. "Database.postgres.User.Password" or "auth.clients[0].secret". */
|
|
20
|
+
path: string;
|
|
21
|
+
kind: YamlDiffKind;
|
|
22
|
+
/** Populated for `changed` / `removed`. Scalar leaf value. */
|
|
23
|
+
oldValue?: unknown;
|
|
24
|
+
/** Populated for `added` / `changed`. Scalar leaf value. */
|
|
25
|
+
newValue?: unknown;
|
|
26
|
+
/** True when any segment in `path` matches the sensitive-keyword heuristic. */
|
|
27
|
+
sensitive: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Returns true when any segment of the dotted path matches the
|
|
31
|
+
* sensitive-keyword heuristic. Numeric array indices (`[0]`) are
|
|
32
|
+
* stripped before the match so a path like `clients[3].token` still
|
|
33
|
+
* matches via the `token` segment.
|
|
34
|
+
*/
|
|
35
|
+
export declare function isPathSensitive(dottedPath: string): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Deep-diff two YAML bodies. Both sides are parsed with the `yaml`
|
|
38
|
+
* package, then a recursive walk emits one entry per leaf that differs.
|
|
39
|
+
* Returns an empty array when the documents are structurally equivalent.
|
|
40
|
+
*
|
|
41
|
+
* Throws when either side fails to parse — the caller (the renderer
|
|
42
|
+
* dispatch) catches and falls back to unified-text rendering on a parse
|
|
43
|
+
* failure so a stray template tag in a yaml-by-suffix file doesn't lose
|
|
44
|
+
* the operator's diff.
|
|
45
|
+
*/
|
|
46
|
+
export declare function diffYamlContent(local: string, remote: string): YamlDiffEntry[];
|
|
47
|
+
export interface YamlDiffRenderOpts {
|
|
48
|
+
/** When true, sensitive paths show their values inline; otherwise masked. */
|
|
49
|
+
reveal?: boolean;
|
|
50
|
+
/** When true, color the kind label + values via ANSI escapes. */
|
|
51
|
+
color?: boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Render the yaml-semantic diff body. Returns one entry's worth of
|
|
55
|
+
* lines per `YamlDiffEntry`, plus an empty-state fallback line when
|
|
56
|
+
* there's nothing to show. No surrounding indent applied — the caller
|
|
57
|
+
* decides nesting.
|
|
58
|
+
*
|
|
59
|
+
* Layout:
|
|
60
|
+
*
|
|
61
|
+
* Database.postgres.User.Password: changed (masked — pass --reveal-env-values to show)
|
|
62
|
+
* server.listen: changed
|
|
63
|
+
* - old=80
|
|
64
|
+
* + new=8080
|
|
65
|
+
* features.beta: added
|
|
66
|
+
* + new=true
|
|
67
|
+
*
|
|
68
|
+
* The CLI flag is named `--reveal-env-values` because the same flag
|
|
69
|
+
* governs env-semantic + yaml-semantic value reveals; calling the flag
|
|
70
|
+
* "env-values" reflects the most common case (sops-derived env files)
|
|
71
|
+
* but it activates yaml-side reveal too.
|
|
72
|
+
*/
|
|
73
|
+
export declare function renderYamlDiff(entries: YamlDiffEntry[], opts?: YamlDiffRenderOpts): string[];
|
|
74
|
+
//# sourceMappingURL=idempotency-yaml-diff.d.ts.map
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import "./chunk-gOLHoazu.js";
|
|
2
|
+
import { setYamlDiffRenderer } from "./idempotency-files.js";
|
|
3
|
+
import { parse } from "yaml";
|
|
4
|
+
//#region src/idempotency-yaml-diff.ts
|
|
5
|
+
/**
|
|
6
|
+
* YAML-file semantic diff for the idempotent-step preview path. Parses
|
|
7
|
+
* both sides with the `yaml` npm package, deep-walks the resulting JS
|
|
8
|
+
* trees, and emits one `YamlDiffEntry` per leaf-level path that differs.
|
|
9
|
+
*
|
|
10
|
+
* "Leaf" means the smallest scalar inside the tree: a string, number,
|
|
11
|
+
* boolean, or null. Arrays compare element-by-element by index; objects
|
|
12
|
+
* recurse into their fields. The dotted path follows the JS-property
|
|
13
|
+
* convention (`Database.postgres.User.Password`, `clients[2].name`).
|
|
14
|
+
*
|
|
15
|
+
* The renderer masks every entry whose path contains a sensitive
|
|
16
|
+
* segment (`/password|passwd|secret|api[_-]?key|token|credentials?/i`)
|
|
17
|
+
* unless the operator passes `reveal: true` via the
|
|
18
|
+
* `--reveal-env-values` CLI flag. Non-sensitive entries print their
|
|
19
|
+
* values inline so the operator can see config drift at a glance.
|
|
20
|
+
*/
|
|
21
|
+
const ANSI_RED = "\x1B[31m";
|
|
22
|
+
const ANSI_GREEN = "\x1B[32m";
|
|
23
|
+
const ANSI_CYAN = "\x1B[36m";
|
|
24
|
+
const ANSI_RESET = "\x1B[0m";
|
|
25
|
+
const SENSITIVE_SEGMENT_RE = /^(password|passwd|secret|secrets|api[_-]?key|token|credentials?)$/i;
|
|
26
|
+
/**
|
|
27
|
+
* Returns true when any segment of the dotted path matches the
|
|
28
|
+
* sensitive-keyword heuristic. Numeric array indices (`[0]`) are
|
|
29
|
+
* stripped before the match so a path like `clients[3].token` still
|
|
30
|
+
* matches via the `token` segment.
|
|
31
|
+
*/
|
|
32
|
+
function isPathSensitive(dottedPath) {
|
|
33
|
+
return dottedPath.split(/[.[\]]+/).filter((s) => s !== "").filter((s) => !/^\d+$/.test(s)).some((s) => SENSITIVE_SEGMENT_RE.test(s));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Deep-diff two YAML bodies. Both sides are parsed with the `yaml`
|
|
37
|
+
* package, then a recursive walk emits one entry per leaf that differs.
|
|
38
|
+
* Returns an empty array when the documents are structurally equivalent.
|
|
39
|
+
*
|
|
40
|
+
* Throws when either side fails to parse — the caller (the renderer
|
|
41
|
+
* dispatch) catches and falls back to unified-text rendering on a parse
|
|
42
|
+
* failure so a stray template tag in a yaml-by-suffix file doesn't lose
|
|
43
|
+
* the operator's diff.
|
|
44
|
+
*/
|
|
45
|
+
function diffYamlContent(local, remote) {
|
|
46
|
+
const localTree = local === "" ? void 0 : parse(local);
|
|
47
|
+
const remoteTree = remote === "" ? void 0 : parse(remote);
|
|
48
|
+
const entries = [];
|
|
49
|
+
walkDiff("", localTree, remoteTree, entries);
|
|
50
|
+
entries.sort((a, b) => {
|
|
51
|
+
if (a.kind !== b.kind) {
|
|
52
|
+
const ORDER = {
|
|
53
|
+
added: 0,
|
|
54
|
+
changed: 1,
|
|
55
|
+
removed: 2
|
|
56
|
+
};
|
|
57
|
+
return ORDER[a.kind] - ORDER[b.kind];
|
|
58
|
+
}
|
|
59
|
+
return a.path.localeCompare(b.path);
|
|
60
|
+
});
|
|
61
|
+
return entries;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Recursive walk over `local` and `remote`. For each pair of values at
|
|
65
|
+
* `path`:
|
|
66
|
+
* - Both undefined → emit nothing (key missing in both).
|
|
67
|
+
* - Only local defined → recurse / emit `added`.
|
|
68
|
+
* - Only remote defined → recurse / emit `removed`.
|
|
69
|
+
* - Both defined, structurally compatible (both objects / both arrays)
|
|
70
|
+
* → recurse into children.
|
|
71
|
+
* - Both defined, scalar or shape-mismatched → emit `changed`.
|
|
72
|
+
*/
|
|
73
|
+
function walkDiff(path, local, remote, out) {
|
|
74
|
+
const lDefined = local !== void 0;
|
|
75
|
+
const rDefined = remote !== void 0;
|
|
76
|
+
if (!lDefined && !rDefined) return;
|
|
77
|
+
if (lDefined && !rDefined) {
|
|
78
|
+
emitLeafOrTree(path, local, "added", out);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (!lDefined && rDefined) {
|
|
82
|
+
emitLeafOrTree(path, remote, "removed", out);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const lObj = isPlainObject(local);
|
|
86
|
+
const rObj = isPlainObject(remote);
|
|
87
|
+
const lArr = Array.isArray(local);
|
|
88
|
+
const rArr = Array.isArray(remote);
|
|
89
|
+
if (lObj && rObj) {
|
|
90
|
+
const lRec = local;
|
|
91
|
+
const rRec = remote;
|
|
92
|
+
const keys = new Set([...Object.keys(lRec), ...Object.keys(rRec)]);
|
|
93
|
+
for (const key of keys) walkDiff(path === "" ? key : `${path}.${key}`, lRec[key], rRec[key], out);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (lArr && rArr) {
|
|
97
|
+
const lArrTyped = local;
|
|
98
|
+
const rArrTyped = remote;
|
|
99
|
+
const len = Math.max(lArrTyped.length, rArrTyped.length);
|
|
100
|
+
for (let i = 0; i < len; i++) walkDiff(`${path}[${i}]`, lArrTyped[i], rArrTyped[i], out);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (deepEqual(local, remote)) return;
|
|
104
|
+
out.push({
|
|
105
|
+
path,
|
|
106
|
+
kind: "changed",
|
|
107
|
+
oldValue: remote,
|
|
108
|
+
newValue: local,
|
|
109
|
+
sensitive: isPathSensitive(path)
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* When a whole subtree is added or removed, we collapse it into a
|
|
114
|
+
* single entry rather than emitting one per descendant leaf. The
|
|
115
|
+
* value is the entire subtree; the renderer prints it inline (masked
|
|
116
|
+
* when the path is sensitive) or via a JSON one-liner.
|
|
117
|
+
*/
|
|
118
|
+
function emitLeafOrTree(path, value, kind, out) {
|
|
119
|
+
const reportedPath = path === "" ? "<root>" : path;
|
|
120
|
+
if (kind === "added") out.push({
|
|
121
|
+
path: reportedPath,
|
|
122
|
+
kind,
|
|
123
|
+
newValue: value,
|
|
124
|
+
sensitive: isPathSensitive(path)
|
|
125
|
+
});
|
|
126
|
+
else out.push({
|
|
127
|
+
path: reportedPath,
|
|
128
|
+
kind,
|
|
129
|
+
oldValue: value,
|
|
130
|
+
sensitive: isPathSensitive(path)
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function isPlainObject(value) {
|
|
134
|
+
if (value === null || typeof value !== "object") return false;
|
|
135
|
+
if (Array.isArray(value)) return false;
|
|
136
|
+
const proto = Object.getPrototypeOf(value);
|
|
137
|
+
return proto === Object.prototype || proto === null;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Cheap structural equality check. Only used as a tie-breaker for the
|
|
141
|
+
* "neither object nor array" branch — scalar leaves go through
|
|
142
|
+
* `===` after a JSON-stringify-equiv comparison. Functions / Dates /
|
|
143
|
+
* other class instances fall back to `Object.is`, which is fine
|
|
144
|
+
* because the `yaml` package only emits plain values for the tag set
|
|
145
|
+
* we use (scalar, sequence, mapping).
|
|
146
|
+
*/
|
|
147
|
+
function deepEqual(a, b) {
|
|
148
|
+
if (Object.is(a, b)) return true;
|
|
149
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Render the yaml-semantic diff body. Returns one entry's worth of
|
|
153
|
+
* lines per `YamlDiffEntry`, plus an empty-state fallback line when
|
|
154
|
+
* there's nothing to show. No surrounding indent applied — the caller
|
|
155
|
+
* decides nesting.
|
|
156
|
+
*
|
|
157
|
+
* Layout:
|
|
158
|
+
*
|
|
159
|
+
* Database.postgres.User.Password: changed (masked — pass --reveal-env-values to show)
|
|
160
|
+
* server.listen: changed
|
|
161
|
+
* - old=80
|
|
162
|
+
* + new=8080
|
|
163
|
+
* features.beta: added
|
|
164
|
+
* + new=true
|
|
165
|
+
*
|
|
166
|
+
* The CLI flag is named `--reveal-env-values` because the same flag
|
|
167
|
+
* governs env-semantic + yaml-semantic value reveals; calling the flag
|
|
168
|
+
* "env-values" reflects the most common case (sops-derived env files)
|
|
169
|
+
* but it activates yaml-side reveal too.
|
|
170
|
+
*/
|
|
171
|
+
function renderYamlDiff(entries, opts = {}) {
|
|
172
|
+
const reveal = opts.reveal ?? false;
|
|
173
|
+
const color = opts.color ?? false;
|
|
174
|
+
if (entries.length === 0) return ["0 yaml leaf(s) drifted (structure matches)"];
|
|
175
|
+
const lines = [];
|
|
176
|
+
for (const entry of entries) {
|
|
177
|
+
const mask = entry.sensitive && !reveal;
|
|
178
|
+
const headTail = mask ? " (masked — pass --reveal-env-values to show)" : "";
|
|
179
|
+
lines.push(`${entry.path}: ${colorizeKind(entry.kind, color)}${headTail}`);
|
|
180
|
+
if (mask) continue;
|
|
181
|
+
if (entry.kind === "changed" || entry.kind === "removed") lines.push(` ${colorize("- old=" + formatValue(entry.oldValue), "old", color)}`);
|
|
182
|
+
if (entry.kind === "changed" || entry.kind === "added") lines.push(` ${colorize("+ new=" + formatValue(entry.newValue), "new", color)}`);
|
|
183
|
+
}
|
|
184
|
+
return lines;
|
|
185
|
+
}
|
|
186
|
+
function formatValue(value) {
|
|
187
|
+
if (value === null) return "null";
|
|
188
|
+
if (value === void 0) return "undefined";
|
|
189
|
+
if (typeof value === "string") return value;
|
|
190
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
191
|
+
try {
|
|
192
|
+
const json = JSON.stringify(value);
|
|
193
|
+
if (json.length <= 240) return json;
|
|
194
|
+
return json.slice(0, 240) + `… (${json.length - 240} more bytes)`;
|
|
195
|
+
} catch {
|
|
196
|
+
return String(value);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
function colorizeKind(kind, color) {
|
|
200
|
+
if (!color) return kind;
|
|
201
|
+
switch (kind) {
|
|
202
|
+
case "added": return `${ANSI_GREEN}${kind}${ANSI_RESET}`;
|
|
203
|
+
case "removed": return `${ANSI_RED}${kind}${ANSI_RESET}`;
|
|
204
|
+
case "changed": return `${ANSI_CYAN}${kind}${ANSI_RESET}`;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function colorize(text, side, color) {
|
|
208
|
+
if (!color) return text;
|
|
209
|
+
return side === "new" ? `${ANSI_GREEN}${text}${ANSI_RESET}` : `${ANSI_RED}${text}${ANSI_RESET}`;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Bridge between the FileDriftEntry / RenderDriftOpts API surface and
|
|
213
|
+
* the yaml diff renderer. Registered at module load time via
|
|
214
|
+
* `setYamlDiffRenderer` so `renderFileDriftBody` can dispatch yaml
|
|
215
|
+
* entries without a hard dependency on the `yaml` package in
|
|
216
|
+
* `idempotency-files.ts`.
|
|
217
|
+
*
|
|
218
|
+
* On a yaml-parse failure, the renderer returns a single explanatory
|
|
219
|
+
* line and the dispatch falls through (caller-side) to the unified-text
|
|
220
|
+
* body so the operator still sees something useful.
|
|
221
|
+
*/
|
|
222
|
+
function renderYamlDiffEntry(entry, opts) {
|
|
223
|
+
const local = entry.localContent ?? "";
|
|
224
|
+
const remote = entry.category === "new" ? "" : entry.remoteContent ?? "";
|
|
225
|
+
if (local === "" && remote === "" && entry.category !== "new") return [];
|
|
226
|
+
let diffs;
|
|
227
|
+
try {
|
|
228
|
+
diffs = diffYamlContent(local, remote);
|
|
229
|
+
} catch (err) {
|
|
230
|
+
return [`(yaml parse failed — ${err.message})`];
|
|
231
|
+
}
|
|
232
|
+
return renderYamlDiff(diffs, {
|
|
233
|
+
reveal: opts.revealEnvValues ?? false,
|
|
234
|
+
color: opts.color ?? false
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
setYamlDiffRenderer(renderYamlDiffEntry);
|
|
238
|
+
//#endregion
|
|
239
|
+
export { diffYamlContent, isPathSensitive, renderYamlDiff };
|
|
240
|
+
|
|
241
|
+
//# sourceMappingURL=idempotency-yaml-diff.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { RingBuffer } from './ring-buffer.js';
|
|
2
2
|
export { toErrorMessage, serializeError } from './error.js';
|
|
3
3
|
export { createPool, createDb } from './db.js';
|
|
4
|
-
export { parseDatabaseUrl, maskDatabaseUrl, dropAndCreateDatabase, dropDatabaseDirect, ensureDatabase, createDbRole, createReadOnlyDbUser, computeMigrationsHash, storeMigrationContentHash, readStoredMigrationContentHash, isSchemaCurrent, clearDispatchQueueDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, purgeScopedSecretsDirect, seedEnvironmentDirect, seedEnvironmentBindingDirect, setEnvironmentPolicyDirect, listEnvironmentsDirect, showEnvironmentDirect, createEnvironmentTemplateDirect, setEnvironmentSecretDirect, listQueueDirect, showQueueEntryDirect, listExecutionRunsDirect, showExecutionRunDirect, listExecutionJobsDirect, listRegistrationsDirect, showRegistrationDirect, registerWorkflowManualDirect, resetRaftStateDirect, emitKiciEventDirect, seedGenericWebhookSourceDirect, purgeSecretBackendsDirect, apiKeyExistsDirect, seedApiKeyInlineDirect, platformConnectionExistsDirect, countWebhookSourcesByConnectionIdDirect, findAnyUserApiKeyIdDirect, seedSyntheticGithubSourceDirect, seedWebhookSecretDirect, seedSourcePrivateKeyDirect, bumpRegistryVersionDirect, pollKiciEventsDirect, waitForPostgresDirect, waitForRunCompletionDirect, cleanupExecutionRowsDirect, isSchemaCurrentFromFilesDirect, storeMigrationContentHashInTableDirect, createJoinTokenDirect, updateSourceRoutingKeyDirect, prunePeerCredentialsDirect, waitForPlatformRegistrationsDirect, seedUniversalGitSourceDirect, seedCiSecurityFixturesDirect, waitForExecutionRunStatusSinceDirect, latestExecutionRunByStatusDirect, waitForLatestExecutionJobStatusDirect, describeTableColumnsDirect, tableExistsDirect, insertKiciEventRawDirect, showKiciEventDirect, listKiciEventsDirect, deleteKiciEventsDirect, verifyKiciEventNotifyDirect, seedCrossRepoTrustDirect, listCrossRepoTrustBySourceRoutingKeyDirect, deleteCrossRepoTrustDirect, insertCrossRepoTrustStrictDirect, deleteWorkflowRegistrationsDirect, getWorkflowRegistrationByIdDirect, listRegistrationsByRoutingKeyDirect, waitForRegistrationsByRoutingKeyDirect, waitForRegistrationsUpdatedAtAdvanceDirect, updateWorkflowRegistrationCommitShaDirect, insertWorkflowRegistrationRawDirect, insertWorkflowRegistrationStrictDirect, getRegistryVersionDirect, bumpRegistryVersionSimpleDirect, upsertCronLastFiredDirect, countCronLastFiredDirect, insertCronLastFiredNowDirect, deleteCronLastFiredDirect, deleteExecutionRunsByWorkflowNameDirect, getGenericWebhookSourceByRoutingKeyDirect, listActiveGenericWebhookSourcesDirect, updateGenericWebhookVerificationConfigDirect, deleteGenericWebhookSourcesByNameDirect, restoreSoftDeletedGenericWebhookSourceDirect, upsertOrgSettingsGlobalWorkflowsDirect, updateOrgSettingsDeniedReposDirect, deleteOrgSettingsByCustomerIdDirect, getExecutionRunSecurityDirect, getHeldRunByIdDirect, countHeldRunsByRunIdDirect, waitForPlatformExecutionRunStatusDirect, waitForPlatformEventLogDistinctRoutedDirect, waitForEventLogRowByDeliveryIdDirect, resolvePlatformWebhookSourceRoutingKeyDirect, ensureOrgOwnerMemberDirect, deletePeerCredentialsByInstanceIdLikeDirect, insertPeerCredentialExpiredDirect, getPeerCredentialRevokedAtDirect, listActivePeerCredentialsExcludingDirect, clearPeerCredentialsRevokedAtByIdsDirect, countActivePeerCredentialsByInstanceDirect, type ColumnInfo, type KiciEventRow, type CrossRepoTrustRow, type WorkflowRegistrationFullRow, type RegistrationsScopedResult, type LatestExecutionRunResult, type WaitForLatestJobResult, type ExecutionRunSecurityRow, type HeldRunSecurityRow, type EventLogRow as PlatformEventLogRow, type UpsertOrgSettingsOpts, type OrgSettingsRepoPatternEntry, type InsertKiciEventRawOpts, type EmitKiciEventOpts, type SeedGenericWebhookSourceOpts, REGISTERABLE_TRIGGER_TYPES, MIGRATION_HASH_TABLE, type PurgeStaleExecutionResult, type PurgeStaleSourcesResult, type SeedEnvironmentOpts, type SeedEnvironmentResult, type SeedEnvironmentBindingOpts, type SetEnvironmentPolicyOpts, type EnvironmentRow, type EnvironmentVariableRow, type EnvironmentBindingRow, type ShowEnvironmentResult, type CreateEnvironmentTemplateOpts, type SetEnvironmentSecretOpts, type DispatchQueueRow, type ListQueueOpts, type ExecutionRunRow, type ExecutionJobRow, type ListExecutionRunsOpts, type WorkflowRegistrationRow, type ListRegistrationsOpts, type ListRegistrationsResult, type ShowRegistrationResult, type RegisterWorkflowManualOpts, type RegisterWorkflowManualResult, } from './db-admin.js';
|
|
4
|
+
export { parseDatabaseUrl, maskDatabaseUrl, dropAndCreateDatabase, dropDatabaseDirect, ensureDatabase, type EnsureDatabaseOpts, createDbRole, createReadOnlyDbUser, computeMigrationsHash, storeMigrationContentHash, readStoredMigrationContentHash, isSchemaCurrent, clearDispatchQueueDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, purgeScopedSecretsDirect, seedEnvironmentDirect, seedEnvironmentBindingDirect, setEnvironmentPolicyDirect, listEnvironmentsDirect, showEnvironmentDirect, createEnvironmentTemplateDirect, setEnvironmentSecretDirect, listQueueDirect, showQueueEntryDirect, listExecutionRunsDirect, showExecutionRunDirect, listExecutionJobsDirect, listRegistrationsDirect, showRegistrationDirect, registerWorkflowManualDirect, resetRaftStateDirect, emitKiciEventDirect, seedGenericWebhookSourceDirect, purgeSecretBackendsDirect, apiKeyExistsDirect, seedApiKeyInlineDirect, platformConnectionExistsDirect, countWebhookSourcesByConnectionIdDirect, findAnyUserApiKeyIdDirect, seedSyntheticGithubSourceDirect, seedWebhookSecretDirect, seedSourcePrivateKeyDirect, bumpRegistryVersionDirect, pollKiciEventsDirect, waitForPostgresDirect, waitForRunCompletionDirect, cleanupExecutionRowsDirect, isSchemaCurrentFromFilesDirect, storeMigrationContentHashInTableDirect, createJoinTokenDirect, updateSourceRoutingKeyDirect, prunePeerCredentialsDirect, waitForPlatformRegistrationsDirect, seedUniversalGitSourceDirect, seedCiSecurityFixturesDirect, waitForExecutionRunStatusSinceDirect, latestExecutionRunByStatusDirect, waitForLatestExecutionJobStatusDirect, describeTableColumnsDirect, tableExistsDirect, insertKiciEventRawDirect, showKiciEventDirect, listKiciEventsDirect, deleteKiciEventsDirect, verifyKiciEventNotifyDirect, seedCrossRepoTrustDirect, listCrossRepoTrustBySourceRoutingKeyDirect, deleteCrossRepoTrustDirect, insertCrossRepoTrustStrictDirect, deleteWorkflowRegistrationsDirect, getWorkflowRegistrationByIdDirect, listRegistrationsByRoutingKeyDirect, waitForRegistrationsByRoutingKeyDirect, waitForRegistrationsUpdatedAtAdvanceDirect, updateWorkflowRegistrationCommitShaDirect, insertWorkflowRegistrationRawDirect, insertWorkflowRegistrationStrictDirect, getRegistryVersionDirect, bumpRegistryVersionSimpleDirect, upsertCronLastFiredDirect, countCronLastFiredDirect, insertCronLastFiredNowDirect, deleteCronLastFiredDirect, deleteExecutionRunsByWorkflowNameDirect, getGenericWebhookSourceByRoutingKeyDirect, listActiveGenericWebhookSourcesDirect, updateGenericWebhookVerificationConfigDirect, deleteGenericWebhookSourcesByNameDirect, restoreSoftDeletedGenericWebhookSourceDirect, upsertOrgSettingsGlobalWorkflowsDirect, updateOrgSettingsDeniedReposDirect, deleteOrgSettingsByCustomerIdDirect, getExecutionRunSecurityDirect, getHeldRunByIdDirect, countHeldRunsByRunIdDirect, waitForPlatformExecutionRunStatusDirect, waitForPlatformEventLogDistinctRoutedDirect, waitForEventLogRowByDeliveryIdDirect, resolvePlatformWebhookSourceRoutingKeyDirect, ensureOrgOwnerMemberDirect, deletePeerCredentialsByInstanceIdLikeDirect, insertPeerCredentialExpiredDirect, getPeerCredentialRevokedAtDirect, listActivePeerCredentialsExcludingDirect, clearPeerCredentialsRevokedAtByIdsDirect, countActivePeerCredentialsByInstanceDirect, type ColumnInfo, type KiciEventRow, type CrossRepoTrustRow, type WorkflowRegistrationFullRow, type RegistrationsScopedResult, type LatestExecutionRunResult, type WaitForLatestJobResult, type ExecutionRunSecurityRow, type HeldRunSecurityRow, type EventLogRow as PlatformEventLogRow, type UpsertOrgSettingsOpts, type OrgSettingsRepoPatternEntry, type InsertKiciEventRawOpts, type EmitKiciEventOpts, type SeedGenericWebhookSourceOpts, REGISTERABLE_TRIGGER_TYPES, MIGRATION_HASH_TABLE, type PurgeStaleExecutionResult, type PurgeStaleSourcesResult, type SeedEnvironmentOpts, type SeedEnvironmentResult, type SeedEnvironmentBindingOpts, type SetEnvironmentPolicyOpts, type EnvironmentRow, type EnvironmentVariableRow, type EnvironmentBindingRow, type ShowEnvironmentResult, type CreateEnvironmentTemplateOpts, type SetEnvironmentSecretOpts, type DispatchQueueRow, type ListQueueOpts, type ExecutionRunRow, type ExecutionJobRow, type ListExecutionRunsOpts, type WorkflowRegistrationRow, type ListRegistrationsOpts, type ListRegistrationsResult, type ShowRegistrationResult, type RegisterWorkflowManualOpts, type RegisterWorkflowManualResult, } from './db-admin.js';
|
|
5
5
|
export { createMetricsRoutes, type MetricsRoutesDeps } from './routes/metrics.js';
|
|
6
6
|
export { createHealthRoutes, type HealthRoutesDeps } from './routes/health.js';
|
|
7
7
|
export { initZx } from './zx.js';
|
|
@@ -11,7 +11,7 @@ export { getReconnectDelay } from './reconnect-delay.js';
|
|
|
11
11
|
export { formatBytes } from './format-bytes.js';
|
|
12
12
|
export { formatDuration, formatUptime } from './format-duration.js';
|
|
13
13
|
export { sha256, sha256File, deriveSharedSecret, normalizeLineEndings } from './crypto.js';
|
|
14
|
-
export { initTelemetry, getPrometheusExporter, createMeter, type TelemetryConfig, } from './telemetry/index.js';
|
|
14
|
+
export { initTelemetry, getPrometheusExporter, collectRuntimeMetricNames, createMeter, type TelemetryConfig, } from './telemetry/index.js';
|
|
15
15
|
export { setupGracefulShutdown, type ShutdownStep, type ShutdownLogger, type ShutdownHandle, type GracefulShutdownOptions, } from './graceful-shutdown.js';
|
|
16
16
|
export { validateRequiredTools, type ToolRequirement } from './tool-check.js';
|
|
17
17
|
export { createS3Client, type CreateS3ClientOptions, type SharedS3Config } from './s3-client.js';
|
package/dist/index.js
CHANGED
|
@@ -13,7 +13,7 @@ import { initZx } from "./zx.js";
|
|
|
13
13
|
import { enrichRequestContext, getRequestContext, requestContext } from "./request-context.js";
|
|
14
14
|
import { createLogger, guardStartup, logger, setServiceName } from "./logger.js";
|
|
15
15
|
import { getReconnectDelay } from "./reconnect-delay.js";
|
|
16
|
-
import { getPrometheusExporter, initTelemetry } from "./telemetry/init.js";
|
|
16
|
+
import { collectRuntimeMetricNames, getPrometheusExporter, initTelemetry } from "./telemetry/init.js";
|
|
17
17
|
import { createMeter } from "./telemetry/metrics.js";
|
|
18
18
|
import "./telemetry/index.js";
|
|
19
19
|
import { validateRequiredTools } from "./tool-check.js";
|
|
@@ -28,4 +28,4 @@ import { BaseColdStore } from "./cold-store/cold-store.js";
|
|
|
28
28
|
import { ChunkLru } from "./cold-store/lru.js";
|
|
29
29
|
import { DEFAULT_TABLE_CONFIG, resolveTableConfig } from "./cold-store/config.js";
|
|
30
30
|
import "./cold-store/index.js";
|
|
31
|
-
export { BaseColdStore, COLD_BUCKET_NAMES, ChunkLru, DEFAULT_TABLE_CONFIG, MIGRATION_HASH_TABLE, REGISTERABLE_TRIGGER_TYPES, RingBuffer, apiKeyExistsDirect, bumpRegistryVersionDirect, bumpRegistryVersionSimpleDirect, chunkObjectKey, cleanupExecutionRowsDirect, clearDispatchQueueDirect, clearPeerCredentialsRevokedAtByIdsDirect, coldDaysToBucket, coldStoreArchiveBytesTotal, coldStoreArchiveCyclesTotal, coldStoreArchiveDurationSeconds, coldStoreArchiveRowsTotal, coldStorePurgeBytesTotal, coldStorePurgeChunksTotal, coldStorePurgeDurationSeconds, coldStoreRehydrateBytesTotal, coldStoreRehydrateDurationSeconds, coldStoreRehydrateRequestsTotal, coldStoreReplayDurationSeconds, coldStoreReplayRowsTotal, coldStoreVerifyFailuresTotal, computeChunkId, computeMigrationsHash, countActivePeerCredentialsByInstanceDirect, countCronLastFiredDirect, countHeldRunsByRunIdDirect, countWebhookSourcesByConnectionIdDirect, createDb, createDbRole, createEnvironmentTemplateDirect, createHealthRoutes, createJoinTokenDirect, createLogger, createMeter, createMetricsRoutes, createPool, createReadOnlyDbUser, createS3Client, decodeChunk, deleteCronLastFiredDirect, deleteCrossRepoTrustDirect, deleteExecutionRunsByWorkflowNameDirect, deleteGenericWebhookSourcesByNameDirect, deleteKiciEventsDirect, deleteOrgSettingsByCustomerIdDirect, deletePeerCredentialsByInstanceIdLikeDirect, deleteWorkflowRegistrationsDirect, deriveSharedSecret, describeTableColumnsDirect, dropAndCreateDatabase, dropDatabaseDirect, emitKiciEventDirect, encodeChunk, encodeKeySegment, enrichRequestContext, ensureDatabase, ensureOrgOwnerMemberDirect, findAnyUserApiKeyIdDirect, formatBytes, formatDuration, formatUptime, getExecutionRunSecurityDirect, getGenericWebhookSourceByRoutingKeyDirect, getHeldRunByIdDirect, getPeerCredentialRevokedAtDirect, getPrometheusExporter, getReconnectDelay, getRegistryVersionDirect, getRequestContext, getWorkflowRegistrationByIdDirect, guardStartup, initTelemetry, initZx, insertCronLastFiredNowDirect, insertCrossRepoTrustStrictDirect, insertKiciEventRawDirect, insertPeerCredentialExpiredDirect, insertWorkflowRegistrationRawDirect, insertWorkflowRegistrationStrictDirect, isLongerColdRetention, isSchemaCurrent, isSchemaCurrentFromFilesDirect, latestExecutionRunByStatusDirect, listActiveGenericWebhookSourcesDirect, listActivePeerCredentialsExcludingDirect, listCrossRepoTrustBySourceRoutingKeyDirect, listEnvironmentsDirect, listExecutionJobsDirect, listExecutionRunsDirect, listKiciEventsDirect, listQueueDirect, listRegistrationsByRoutingKeyDirect, listRegistrationsDirect, logger, maskDatabaseUrl, normalizeLineEndings, parseDatabaseUrl, parseManifest, platformConnectionExistsDirect, pollKiciEventsDirect, prunePeerCredentialsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, readStoredMigrationContentHash, registerWorkflowManualDirect, requestContext, resetRaftStateDirect, resolvePlatformWebhookSourceRoutingKeyDirect, resolveTableConfig, restoreSoftDeletedGenericWebhookSourceDirect, seedApiKeyInlineDirect, seedCiSecurityFixturesDirect, seedCrossRepoTrustDirect, seedEnvironmentBindingDirect, seedEnvironmentDirect, seedGenericWebhookSourceDirect, seedSourcePrivateKeyDirect, seedSyntheticGithubSourceDirect, seedUniversalGitSourceDirect, seedWebhookSecretDirect, serializeError, serializeManifest, setEnvironmentPolicyDirect, setEnvironmentSecretDirect, setServiceName, setupGracefulShutdown, sha256, sha256File, showEnvironmentDirect, showExecutionRunDirect, showKiciEventDirect, showQueueEntryDirect, showRegistrationDirect, storeMigrationContentHash, storeMigrationContentHashInTableDirect, tableExistsDirect, tablePrefix, tenantDayBucketPrefix, tenantDayPrefix, toErrorMessage, updateGenericWebhookVerificationConfigDirect, updateOrgSettingsDeniedReposDirect, updateSourceRoutingKeyDirect, updateWorkflowRegistrationCommitShaDirect, upsertCronLastFiredDirect, upsertOrgSettingsGlobalWorkflowsDirect, validateRequiredTools, verifyKiciEventNotifyDirect, waitForEventLogRowByDeliveryIdDirect, waitForExecutionRunStatusSinceDirect, waitForLatestExecutionJobStatusDirect, waitForPlatformEventLogDistinctRoutedDirect, waitForPlatformExecutionRunStatusDirect, waitForPlatformRegistrationsDirect, waitForPostgresDirect, waitForRegistrationsByRoutingKeyDirect, waitForRegistrationsUpdatedAtAdvanceDirect, waitForRunCompletionDirect };
|
|
31
|
+
export { BaseColdStore, COLD_BUCKET_NAMES, ChunkLru, DEFAULT_TABLE_CONFIG, MIGRATION_HASH_TABLE, REGISTERABLE_TRIGGER_TYPES, RingBuffer, apiKeyExistsDirect, bumpRegistryVersionDirect, bumpRegistryVersionSimpleDirect, chunkObjectKey, cleanupExecutionRowsDirect, clearDispatchQueueDirect, clearPeerCredentialsRevokedAtByIdsDirect, coldDaysToBucket, coldStoreArchiveBytesTotal, coldStoreArchiveCyclesTotal, coldStoreArchiveDurationSeconds, coldStoreArchiveRowsTotal, coldStorePurgeBytesTotal, coldStorePurgeChunksTotal, coldStorePurgeDurationSeconds, coldStoreRehydrateBytesTotal, coldStoreRehydrateDurationSeconds, coldStoreRehydrateRequestsTotal, coldStoreReplayDurationSeconds, coldStoreReplayRowsTotal, coldStoreVerifyFailuresTotal, collectRuntimeMetricNames, computeChunkId, computeMigrationsHash, countActivePeerCredentialsByInstanceDirect, countCronLastFiredDirect, countHeldRunsByRunIdDirect, countWebhookSourcesByConnectionIdDirect, createDb, createDbRole, createEnvironmentTemplateDirect, createHealthRoutes, createJoinTokenDirect, createLogger, createMeter, createMetricsRoutes, createPool, createReadOnlyDbUser, createS3Client, decodeChunk, deleteCronLastFiredDirect, deleteCrossRepoTrustDirect, deleteExecutionRunsByWorkflowNameDirect, deleteGenericWebhookSourcesByNameDirect, deleteKiciEventsDirect, deleteOrgSettingsByCustomerIdDirect, deletePeerCredentialsByInstanceIdLikeDirect, deleteWorkflowRegistrationsDirect, deriveSharedSecret, describeTableColumnsDirect, dropAndCreateDatabase, dropDatabaseDirect, emitKiciEventDirect, encodeChunk, encodeKeySegment, enrichRequestContext, ensureDatabase, ensureOrgOwnerMemberDirect, findAnyUserApiKeyIdDirect, formatBytes, formatDuration, formatUptime, getExecutionRunSecurityDirect, getGenericWebhookSourceByRoutingKeyDirect, getHeldRunByIdDirect, getPeerCredentialRevokedAtDirect, getPrometheusExporter, getReconnectDelay, getRegistryVersionDirect, getRequestContext, getWorkflowRegistrationByIdDirect, guardStartup, initTelemetry, initZx, insertCronLastFiredNowDirect, insertCrossRepoTrustStrictDirect, insertKiciEventRawDirect, insertPeerCredentialExpiredDirect, insertWorkflowRegistrationRawDirect, insertWorkflowRegistrationStrictDirect, isLongerColdRetention, isSchemaCurrent, isSchemaCurrentFromFilesDirect, latestExecutionRunByStatusDirect, listActiveGenericWebhookSourcesDirect, listActivePeerCredentialsExcludingDirect, listCrossRepoTrustBySourceRoutingKeyDirect, listEnvironmentsDirect, listExecutionJobsDirect, listExecutionRunsDirect, listKiciEventsDirect, listQueueDirect, listRegistrationsByRoutingKeyDirect, listRegistrationsDirect, logger, maskDatabaseUrl, normalizeLineEndings, parseDatabaseUrl, parseManifest, platformConnectionExistsDirect, pollKiciEventsDirect, prunePeerCredentialsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, readStoredMigrationContentHash, registerWorkflowManualDirect, requestContext, resetRaftStateDirect, resolvePlatformWebhookSourceRoutingKeyDirect, resolveTableConfig, restoreSoftDeletedGenericWebhookSourceDirect, seedApiKeyInlineDirect, seedCiSecurityFixturesDirect, seedCrossRepoTrustDirect, seedEnvironmentBindingDirect, seedEnvironmentDirect, seedGenericWebhookSourceDirect, seedSourcePrivateKeyDirect, seedSyntheticGithubSourceDirect, seedUniversalGitSourceDirect, seedWebhookSecretDirect, serializeError, serializeManifest, setEnvironmentPolicyDirect, setEnvironmentSecretDirect, setServiceName, setupGracefulShutdown, sha256, sha256File, showEnvironmentDirect, showExecutionRunDirect, showKiciEventDirect, showQueueEntryDirect, showRegistrationDirect, storeMigrationContentHash, storeMigrationContentHashInTableDirect, tableExistsDirect, tablePrefix, tenantDayBucketPrefix, tenantDayPrefix, toErrorMessage, updateGenericWebhookVerificationConfigDirect, updateOrgSettingsDeniedReposDirect, updateSourceRoutingKeyDirect, updateWorkflowRegistrationCommitShaDirect, upsertCronLastFiredDirect, upsertOrgSettingsGlobalWorkflowsDirect, validateRequiredTools, verifyKiciEventNotifyDirect, waitForEventLogRowByDeliveryIdDirect, waitForExecutionRunStatusSinceDirect, waitForLatestExecutionJobStatusDirect, waitForPlatformEventLogDistinctRoutedDirect, waitForPlatformExecutionRunStatusDirect, waitForPlatformRegistrationsDirect, waitForPostgresDirect, waitForRegistrationsByRoutingKeyDirect, waitForRegistrationsUpdatedAtAdvanceDirect, waitForRunCompletionDirect };
|
package/dist/logger.d.ts
CHANGED
|
@@ -23,7 +23,10 @@ export interface Logger {
|
|
|
23
23
|
}
|
|
24
24
|
/** Logger creation options */
|
|
25
25
|
interface LoggerOptions {
|
|
26
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Use JSON format (default: auto-detected from KICI_LOG_FORMAT env var, with
|
|
28
|
+
* a TTY fallback). Passing an explicit boolean wins over the env var.
|
|
29
|
+
*/
|
|
27
30
|
json?: boolean;
|
|
28
31
|
/** Log level (default: 'info') */
|
|
29
32
|
level?: LogLevel;
|