@ankurhalder/codebase-snapshot 0.0.0-stage → 2.1.0
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/LICENSE +21 -0
- package/README.md +331 -2
- package/dist/bin.js +5688 -0
- package/dist/chunk-QEIOXPMU.js +5093 -0
- package/dist/cli.cjs +5674 -0
- package/dist/cli.d.cts +48 -0
- package/dist/cli.d.ts +48 -0
- package/dist/cli.js +568 -0
- package/dist/index.cjs +5182 -0
- package/dist/index.d.cts +541 -0
- package/dist/index.d.ts +541 -0
- package/dist/index.js +3 -0
- package/dist/types-CJqkePM4.d.cts +391 -0
- package/dist/types-CJqkePM4.d.ts +391 -0
- package/docs/configuration.md +340 -0
- package/docs/install.md +136 -0
- package/package.json +94 -4
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
import { J as JsonSummary, M as MarkdownSummary, S as SourceSummary, R as ResolvedSnapshotConfig, a as SnapshotConfig, B as ByteSize, C as CliOptions, F as FileEntry, P as PartMetadata, L as LayerRule, K as KindRule, b as SecretRule, c as SecretFinding, V as ValidationResult, d as Manifest, A as ArtifactSelection, e as SkipRecord } from './types-CJqkePM4.js';
|
|
2
|
+
export { f as BudgetConfig, H as HooksConfig, I as InclusionMode, g as ManifestArtifact, h as ManifestConfigSnapshot, i as ManifestIndexes, j as ManifestTotals, k as Mode, O as OutputFormat, l as PartFileEntry, m as ResolvedArtifacts, n as ResolvedBudgets, o as SecretRuleInput, p as SkipReason, q as SummaryQuality, r as ValidationDrift } from './types-CJqkePM4.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Strips `//` and block comments the way JSONC does, without touching anything
|
|
6
|
+
* inside a string literal. `JSON.parse` alone made every `.jsonc` file report
|
|
7
|
+
* `invalid-json`, losing its key shape entirely.
|
|
8
|
+
*/
|
|
9
|
+
declare function stripJsonComments(content: string): string;
|
|
10
|
+
declare function summarizeJson(content: string): JsonSummary;
|
|
11
|
+
declare function summarizeMarkdown(content: string): MarkdownSummary;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Extracts a structural summary from a JS/TS source file.
|
|
15
|
+
*
|
|
16
|
+
* The traversal is an explicit stack, not recursion: a generated file with a
|
|
17
|
+
* long `a && b && …` chain used to overflow the call stack inside our own
|
|
18
|
+
* visitor and abort the entire snapshot. Callers should still treat a throw as
|
|
19
|
+
* possible (TypeScript's own parser recurses), so wrap the call.
|
|
20
|
+
*/
|
|
21
|
+
declare function summarizeTypeScriptSource(relativePath: string, content: string): SourceSummary;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Brands a resolved config so consumers can distinguish it from a user
|
|
25
|
+
* `SnapshotConfig` structurally, instead of guessing from the presence of a
|
|
26
|
+
* single field (`"secretRules" in input`), which misfired for hand-built configs
|
|
27
|
+
* and for user configs that happened to carry an extra key.
|
|
28
|
+
*/
|
|
29
|
+
declare function markResolvedConfig<T extends ResolvedSnapshotConfig>(config: T): T;
|
|
30
|
+
/**
|
|
31
|
+
* Detects a resolved config.
|
|
32
|
+
*
|
|
33
|
+
* The brand is a non-enumerable symbol, so it survives `structuredClone` but NOT
|
|
34
|
+
* `{ ...resolvedConfig, override }`. Relying on the brand alone caused a real
|
|
35
|
+
* regression: a spread config was re-resolved as a user config, which silently
|
|
36
|
+
* dropped custom `secretRules` and let matching secrets through in clear text.
|
|
37
|
+
* The structural fallback therefore accepts any object carrying the complete
|
|
38
|
+
* resolved-only shape.
|
|
39
|
+
*/
|
|
40
|
+
declare function isResolvedConfig(value: unknown): value is ResolvedSnapshotConfig;
|
|
41
|
+
/**
|
|
42
|
+
* Re-validates a resolved config taken from an untrusted path (e.g. a spread
|
|
43
|
+
* copy), recompiling secret rules so string patterns and stray `g`/`y` flags are
|
|
44
|
+
* normalised even when the object did not come from `resolveConfig`.
|
|
45
|
+
*/
|
|
46
|
+
declare function normalizeResolvedConfig(config: ResolvedSnapshotConfig): ResolvedSnapshotConfig;
|
|
47
|
+
/**
|
|
48
|
+
* Guards against a silently lossy config round-trip.
|
|
49
|
+
*
|
|
50
|
+
* A `RegExp` cannot survive `JSON.stringify`/`JSON.parse`: the pattern comes
|
|
51
|
+
* back as `{}`. Such an object no longer satisfies `isResolvedConfig`, so it
|
|
52
|
+
* would be re-resolved as a user config and its custom `secretRules` would be
|
|
53
|
+
* dropped without a word — a silent security regression. Fail loudly instead.
|
|
54
|
+
*/
|
|
55
|
+
declare function assertUsableConfigInput(value: unknown): void;
|
|
56
|
+
interface ConfigLoadResult {
|
|
57
|
+
config: SnapshotConfig | null;
|
|
58
|
+
/** Absolute path of the file the config came from, if any. */
|
|
59
|
+
file: string | null;
|
|
60
|
+
/** Why a candidate config file was ignored. Never silently discarded. */
|
|
61
|
+
warnings: string[];
|
|
62
|
+
/**
|
|
63
|
+
* Config files that exist but could not be read.
|
|
64
|
+
*
|
|
65
|
+
* These are fatal: a config that fails to parse used to be skipped in favour of
|
|
66
|
+
* the defaults, which meant a typo silently produced a snapshot with none of the
|
|
67
|
+
* developer's settings applied. A config that is merely unsupported on this Node
|
|
68
|
+
* version (a `.ts` file below Node 22.6) stays a warning — nothing is wrong with
|
|
69
|
+
* the file, and the message already says what to do.
|
|
70
|
+
*/
|
|
71
|
+
errors: string[];
|
|
72
|
+
}
|
|
73
|
+
/** True when this Node can `import()` a `.ts` file natively (type stripping). */
|
|
74
|
+
declare function supportsTypeScriptImports(): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Loads the first usable config file from `cwd`.
|
|
77
|
+
*
|
|
78
|
+
* Every failure is reported through `warnings` instead of being swallowed by an
|
|
79
|
+
* empty `catch`: a syntax error in a user's config used to be indistinguishable
|
|
80
|
+
* from having no config at all.
|
|
81
|
+
*/
|
|
82
|
+
declare function loadConfigFileDetailed(cwd: string): Promise<ConfigLoadResult>;
|
|
83
|
+
declare function loadConfigFile(cwd: string): Promise<SnapshotConfig | null>;
|
|
84
|
+
/** Smallest usable part budget: a part header plus one section must fit. */
|
|
85
|
+
declare const MIN_MAX_PART_BYTES = 4096;
|
|
86
|
+
/** Every artifact this package can write, in the order it is written. */
|
|
87
|
+
declare const ARTIFACT_NAMES: readonly ["readme", "manifest", "parts", "navigation", "projectTree", "audit", "monolith"];
|
|
88
|
+
/**
|
|
89
|
+
* Parses a byte budget.
|
|
90
|
+
*
|
|
91
|
+
* Accepts a plain number (`122880`), a numeric string (`"122880"`), or a
|
|
92
|
+
* human-readable size (`"120k"`, `"1.5mb"`, `"2 GB"`). Returns `undefined` for
|
|
93
|
+
* anything it cannot read, so callers can decide whether that is an error or a
|
|
94
|
+
* fallback — a typo'd budget must not silently become the default.
|
|
95
|
+
*/
|
|
96
|
+
declare function parseByteSize(value: ByteSize | null | undefined): number | undefined;
|
|
97
|
+
/**
|
|
98
|
+
* Merges user config, preset defaults and CLI overrides.
|
|
99
|
+
*
|
|
100
|
+
* `baseDir` is the directory the config was loaded from. Without it the natural
|
|
101
|
+
* library flow (`loadConfigFile(dir)` then `resolveConfig(config)`) silently
|
|
102
|
+
* fell back to `process.cwd()` and generated into the caller's directory.
|
|
103
|
+
*/
|
|
104
|
+
declare function resolveConfig(userConfig: SnapshotConfig | null, cliOptions?: Partial<CliOptions>, baseDir?: string): ResolvedSnapshotConfig;
|
|
105
|
+
/**
|
|
106
|
+
* Matches a path against a layer/kind rule.
|
|
107
|
+
*
|
|
108
|
+
* `"src/app/**"` now means "exactly `src/app` or below": the previous
|
|
109
|
+
* implementation stripped `**` **and** the trailing slash, so the pattern also
|
|
110
|
+
* matched `src/apple/` and `src/application/`.
|
|
111
|
+
*/
|
|
112
|
+
declare function matchRule(filePath: string, matcher: string | RegExp | ((filePath: string) => boolean)): boolean;
|
|
113
|
+
|
|
114
|
+
declare function defineConfig(config: SnapshotConfig): SnapshotConfig;
|
|
115
|
+
|
|
116
|
+
declare function generateProjectTree(filePaths: string[]): string;
|
|
117
|
+
|
|
118
|
+
interface PartitionedPart {
|
|
119
|
+
filename: string;
|
|
120
|
+
markdown: string;
|
|
121
|
+
metadata: PartMetadata;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Partitions rendered file sections into byte-bounded parts.
|
|
125
|
+
*
|
|
126
|
+
* The budget is a hard bound: a section that cannot fit into a part on its own
|
|
127
|
+
* is byte-truncated (and marked `isPreviewTruncated`) rather than emitted whole.
|
|
128
|
+
* The previous implementation skipped the flush check for an empty chunk, so one
|
|
129
|
+
* large file produced a part 13.5x over the configured budget.
|
|
130
|
+
*/
|
|
131
|
+
declare function partitionFiles(files: FileEntry[], maxPartBytes: number, contentFingerprint?: string): PartitionedPart[];
|
|
132
|
+
/**
|
|
133
|
+
* Re-numbers a set of parts as one sequence and rewrites their headers.
|
|
134
|
+
*
|
|
135
|
+
* Needed when parts are produced by more than one partition pass (per-layer
|
|
136
|
+
* budgets): each pass numbers from `part-001`, so the merged set would otherwise
|
|
137
|
+
* contain duplicate filenames and every `Previous:`/`Next:` link would lie.
|
|
138
|
+
*/
|
|
139
|
+
declare function renumberParts(parts: PartitionedPart[], contentFingerprint?: string): PartitionedPart[];
|
|
140
|
+
/**
|
|
141
|
+
* Chooses a fence longer than any backtick run in `content`, so a file that
|
|
142
|
+
* contains a fenced block cannot break out of its own code block.
|
|
143
|
+
*/
|
|
144
|
+
declare function fenceForContent(content: string): string;
|
|
145
|
+
/**
|
|
146
|
+
* Stable, injective anchor for a file path.
|
|
147
|
+
*
|
|
148
|
+
* The previous slug was not injective (`src/a-b.ts` and `src/a/b.ts` produced the
|
|
149
|
+
* same anchor) and, more importantly, no part file ever emitted the anchors that
|
|
150
|
+
* `reports/navigation.md` linked to — every file link was dead.
|
|
151
|
+
*/
|
|
152
|
+
declare function anchorForPath(filePath: string): string;
|
|
153
|
+
|
|
154
|
+
interface PreviewResult {
|
|
155
|
+
content: string;
|
|
156
|
+
isTruncated: boolean;
|
|
157
|
+
originalLines: number;
|
|
158
|
+
includedLines: number;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Line count with one consistent convention: a trailing newline does not start
|
|
162
|
+
* a new line, and an empty string has zero lines.
|
|
163
|
+
*
|
|
164
|
+
* Previously `index.ts` recorded 0 for an empty file while `preview.ts` recorded
|
|
165
|
+
* 1, and every newline-terminated file was over-counted by one.
|
|
166
|
+
*/
|
|
167
|
+
declare function countLines(content: string): number;
|
|
168
|
+
/**
|
|
169
|
+
* Truncates to a UTF-8 byte budget without splitting a multi-byte character.
|
|
170
|
+
*/
|
|
171
|
+
declare function truncateToBytes(content: string, maxBytes: number): {
|
|
172
|
+
content: string;
|
|
173
|
+
isTruncated: boolean;
|
|
174
|
+
};
|
|
175
|
+
declare function truncatePreview(content: string, headLines: number, tailLines: number): PreviewResult;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Everything preset detection is allowed to look at.
|
|
179
|
+
*
|
|
180
|
+
* Built once per run: the previous implementation re-read `package.json` inside
|
|
181
|
+
* every detector, which was both slow and incapable of seeing anything outside
|
|
182
|
+
* the JavaScript ecosystem.
|
|
183
|
+
*/
|
|
184
|
+
interface PresetContext {
|
|
185
|
+
cwd: string;
|
|
186
|
+
/** Top-level file names, e.g. `next.config.ts`. */
|
|
187
|
+
files: ReadonlySet<string>;
|
|
188
|
+
/** Top-level directory names. */
|
|
189
|
+
dirs: ReadonlySet<string>;
|
|
190
|
+
/** `dependencies` + `devDependencies` + `peerDependencies` names. */
|
|
191
|
+
dependencies: ReadonlySet<string>;
|
|
192
|
+
/** Small snapshots of well-known manifests, for keyword detection. */
|
|
193
|
+
manifests: Readonly<Record<string, string>>;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
interface PresetDefinition {
|
|
197
|
+
readonly name: string;
|
|
198
|
+
/** Higher wins. Framework presets outrank repository shapes. */
|
|
199
|
+
readonly priority: number;
|
|
200
|
+
detect(context: PresetContext): boolean;
|
|
201
|
+
readonly layers: LayerRule[];
|
|
202
|
+
readonly kinds: KindRule[];
|
|
203
|
+
/** Ecosystem-specific ignores, merged with the user's `excludePatterns`. */
|
|
204
|
+
readonly exclude?: string[];
|
|
205
|
+
/** Advice for the setup wizard. Never applied automatically. */
|
|
206
|
+
readonly recommendedBudget?: ByteSize;
|
|
207
|
+
}
|
|
208
|
+
interface DetectedPreset {
|
|
209
|
+
presetName: string;
|
|
210
|
+
layers: LayerRule[];
|
|
211
|
+
kinds: KindRule[];
|
|
212
|
+
/** Ecosystem ignores the scanner should apply in addition to the user's. */
|
|
213
|
+
exclude: string[];
|
|
214
|
+
recommendedBudget: ByteSize | null;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Every preset, ordered by priority.
|
|
218
|
+
*
|
|
219
|
+
* Ordering is the whole detection model: the first definition whose `detect`
|
|
220
|
+
* returns true wins, so the list is sorted once at module load rather than being
|
|
221
|
+
* hand-maintained in the right order.
|
|
222
|
+
*/
|
|
223
|
+
declare const PRESETS: readonly PresetDefinition[];
|
|
224
|
+
/** Every preset name, in priority order — used by the CLI and the wizard. */
|
|
225
|
+
declare function listPresetNames(): string[];
|
|
226
|
+
declare function getPreset(name: string): PresetDefinition | undefined;
|
|
227
|
+
/** Detects the preset for `cwd`, reading the repository once. */
|
|
228
|
+
declare function detectPreset(cwd: string, forced?: string): DetectedPreset;
|
|
229
|
+
|
|
230
|
+
declare function isBinaryExtension(filePath: string): boolean;
|
|
231
|
+
declare function isBinaryBuffer(buffer: Buffer): boolean;
|
|
232
|
+
declare function isBinaryFile(absolutePath: string): boolean;
|
|
233
|
+
|
|
234
|
+
declare function detectLanguage(filePath: string): string;
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Redacts secrets from `content`.
|
|
238
|
+
*
|
|
239
|
+
* - Replaces only the matched span, so unrelated code sharing the line survives
|
|
240
|
+
* (the previous implementation discarded the whole line).
|
|
241
|
+
* - Masks PEM private-key blocks as a unit; per-line rules can only see the
|
|
242
|
+
* `BEGIN` header, which left every body line of a real key in the output.
|
|
243
|
+
* - Records `{ rule, line, path }` only. No excerpt of the source is retained,
|
|
244
|
+
* because that excerpt was being written verbatim into `reports/audit.md`.
|
|
245
|
+
*/
|
|
246
|
+
declare function scanAndRedactSecrets(content: string, rules: SecretRule[], filePath?: string): {
|
|
247
|
+
redacted: string;
|
|
248
|
+
findings: SecretFinding[];
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Validates a generated snapshot against the working tree and against the
|
|
253
|
+
* recorded configuration.
|
|
254
|
+
*
|
|
255
|
+
* Beyond source-file hashes this now also:
|
|
256
|
+
* - refuses a manifest that does not have the expected shape (previously threw
|
|
257
|
+
* an uncaught `TypeError`),
|
|
258
|
+
* - verifies every emitted `parts/*.md` against its recorded `byteSize`/`sha256`
|
|
259
|
+
* (previously a deleted or corrupted part still reported `valid: true`),
|
|
260
|
+
* - re-checks the effective configuration and the part/file bookkeeping,
|
|
261
|
+
* - verifies monolith artefact digests when present.
|
|
262
|
+
*/
|
|
263
|
+
declare function validateSnapshot(configInput: ResolvedSnapshotConfig | SnapshotConfig): ValidationResult;
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Default secret rules.
|
|
267
|
+
*
|
|
268
|
+
* Design notes:
|
|
269
|
+
* - Every quantifier is bounded. An unbounded `[A-Za-z0-9_-]{10,}` followed by
|
|
270
|
+
* `\.` backtracks to the end of the line at every start position, which made
|
|
271
|
+
* `jwt-token` quadratic (measured: 1.22 s for a 200 KB line). JWT segments are
|
|
272
|
+
* never longer than a few KB, so bounding at 1024 keeps the match linear in
|
|
273
|
+
* practice while still matching every realistic token.
|
|
274
|
+
* - Rules are line-oriented; the whole-block private-key scan lives in
|
|
275
|
+
* `redact.ts` because it spans lines.
|
|
276
|
+
* - Names are matched case-insensitively only where a value is anchored by
|
|
277
|
+
* quotes or a length, to keep false positives at zero on ordinary source.
|
|
278
|
+
*/
|
|
279
|
+
declare const DEFAULT_SECRET_PATTERNS: SecretRule[];
|
|
280
|
+
|
|
281
|
+
interface ExplainResult {
|
|
282
|
+
/** Path relative to the configured cwd, POSIX separators. */
|
|
283
|
+
path: string;
|
|
284
|
+
/** Whether the path exists on disk. */
|
|
285
|
+
exists: boolean;
|
|
286
|
+
/** Whether the scanner would include it in the next snapshot. */
|
|
287
|
+
included: boolean;
|
|
288
|
+
/** Why it is excluded, when it is. Mirrors `SkipRecord.reason`. */
|
|
289
|
+
reason?: string;
|
|
290
|
+
detail?: string;
|
|
291
|
+
layer?: string;
|
|
292
|
+
layerMatch?: string;
|
|
293
|
+
kind?: string;
|
|
294
|
+
kindMatch?: string;
|
|
295
|
+
language?: string;
|
|
296
|
+
/** Part filename from the last written manifest, when one is available. */
|
|
297
|
+
part?: string | null;
|
|
298
|
+
inclusionMode?: string;
|
|
299
|
+
lines?: number;
|
|
300
|
+
bytes?: number;
|
|
301
|
+
secretCount?: number;
|
|
302
|
+
secrets?: Array<{
|
|
303
|
+
rule: string;
|
|
304
|
+
line: number;
|
|
305
|
+
}>;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Explains what the scanner would do with one path.
|
|
309
|
+
*
|
|
310
|
+
* The whole point is that every decision is visible: which layer and kind rule
|
|
311
|
+
* matched, why a file was skipped, which part it landed in, and whether any
|
|
312
|
+
* secret rule fires. Re-running the real scanner is what keeps it honest.
|
|
313
|
+
*/
|
|
314
|
+
declare function explainPath(config: ResolvedSnapshotConfig, target: string): ExplainResult;
|
|
315
|
+
/** Renders an explanation for a terminal. */
|
|
316
|
+
declare function renderExplainText(result: ExplainResult): string;
|
|
317
|
+
|
|
318
|
+
interface ManifestDiff {
|
|
319
|
+
before: DiffSide;
|
|
320
|
+
after: DiffSide;
|
|
321
|
+
added: string[];
|
|
322
|
+
removed: string[];
|
|
323
|
+
changed: string[];
|
|
324
|
+
unchanged: number;
|
|
325
|
+
}
|
|
326
|
+
interface DiffSide {
|
|
327
|
+
generatedAt: string;
|
|
328
|
+
fingerprint: string;
|
|
329
|
+
fileCount: number;
|
|
330
|
+
partsCount: number;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Compares two manifests file by file.
|
|
334
|
+
*
|
|
335
|
+
* The per-file hashes and the content fingerprint already make this exact, so
|
|
336
|
+
* nothing is inferred: a path is added, removed or changed, never "maybe".
|
|
337
|
+
*/
|
|
338
|
+
declare function compareManifests(before: Manifest, after: Manifest): ManifestDiff;
|
|
339
|
+
/** Loads a manifest from a snapshot directory or a `manifest.json` path. */
|
|
340
|
+
declare function loadManifest(target: string): Manifest;
|
|
341
|
+
/** Renders a diff for a terminal. */
|
|
342
|
+
declare function renderDiffText(diff: ManifestDiff): string;
|
|
343
|
+
|
|
344
|
+
interface PromptIO {
|
|
345
|
+
input: NodeJS.ReadStream;
|
|
346
|
+
output: NodeJS.WriteStream;
|
|
347
|
+
}
|
|
348
|
+
/** Thrown when the developer presses Ctrl+C or Ctrl+D mid-prompt. */
|
|
349
|
+
declare class PromptCancelled extends Error {
|
|
350
|
+
constructor();
|
|
351
|
+
}
|
|
352
|
+
/** Both ends must be a TTY before anything interactive is attempted. */
|
|
353
|
+
declare function isInteractive(io: PromptIO): boolean;
|
|
354
|
+
|
|
355
|
+
interface InitOptions {
|
|
356
|
+
cwd: string;
|
|
357
|
+
/** Force a preset instead of detecting one. */
|
|
358
|
+
preset?: string;
|
|
359
|
+
maxPartBytes?: ByteSize;
|
|
360
|
+
include?: string[];
|
|
361
|
+
exclude?: string[];
|
|
362
|
+
skipArtifacts?: string[];
|
|
363
|
+
onlyArtifacts?: string[];
|
|
364
|
+
includeSensitiveFiles?: boolean;
|
|
365
|
+
/** Accept every default without prompting. */
|
|
366
|
+
yes?: boolean;
|
|
367
|
+
/** Write only the settings that differ from the defaults. */
|
|
368
|
+
minimal?: boolean;
|
|
369
|
+
/** Overwrite an existing config. */
|
|
370
|
+
force?: boolean;
|
|
371
|
+
/** Render the config without writing anything. */
|
|
372
|
+
dryRun?: boolean;
|
|
373
|
+
outDir?: string;
|
|
374
|
+
io?: PromptIO;
|
|
375
|
+
}
|
|
376
|
+
interface InitResult {
|
|
377
|
+
configPath: string;
|
|
378
|
+
configText: string;
|
|
379
|
+
written: boolean;
|
|
380
|
+
preset: string;
|
|
381
|
+
scripts: string[];
|
|
382
|
+
gitignoreEntries: string[];
|
|
383
|
+
/** Human-readable notes about anything that was skipped or could not be done. */
|
|
384
|
+
notes: string[];
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Runs the interactive setup, or writes a config from flags.
|
|
388
|
+
*
|
|
389
|
+
* Interactive only when both ends are a TTY and `--yes` was not passed; every
|
|
390
|
+
* other path uses the flag values and the detected preset, and prints what it
|
|
391
|
+
* decided rather than prompting.
|
|
392
|
+
*/
|
|
393
|
+
declare function runInit(options: InitOptions): Promise<InitResult>;
|
|
394
|
+
|
|
395
|
+
/** What the wizard decided, after prompts or flags. */
|
|
396
|
+
interface WizardAnswers {
|
|
397
|
+
preset: string;
|
|
398
|
+
maxPartBytes: ByteSize;
|
|
399
|
+
largeFileBytes: ByteSize;
|
|
400
|
+
include: string[];
|
|
401
|
+
excludePatterns: string[];
|
|
402
|
+
artifacts: Required<ArtifactSelection>;
|
|
403
|
+
includeSensitiveFiles: boolean;
|
|
404
|
+
outDir: string;
|
|
405
|
+
}
|
|
406
|
+
declare const DEFAULT_ANSWERS: WizardAnswers;
|
|
407
|
+
/**
|
|
408
|
+
* Renders the full, self-documenting config.
|
|
409
|
+
*
|
|
410
|
+
* Every setting appears at its current value, commented and grouped, because
|
|
411
|
+
* most developers never open the documentation — a file that lists only their
|
|
412
|
+
* changes cannot tell them what else exists. Deleting any line is safe: the
|
|
413
|
+
* defaults are real.
|
|
414
|
+
*/
|
|
415
|
+
declare function renderConfig(answers: WizardAnswers): string;
|
|
416
|
+
/**
|
|
417
|
+
* The terse variant: only what differs from the defaults.
|
|
418
|
+
*
|
|
419
|
+
* `--minimal` exists for people who prefer a short file and will read the docs.
|
|
420
|
+
*/
|
|
421
|
+
declare function renderMinimalConfig(answers: WizardAnswers): string;
|
|
422
|
+
|
|
423
|
+
interface HeuristicResult {
|
|
424
|
+
summary: SourceSummary;
|
|
425
|
+
/**
|
|
426
|
+
* `ast` only when a real parser produced this (TypeScript, and the script
|
|
427
|
+
* block of a Vue/Svelte/Astro component). Everything else is `heuristic`, and
|
|
428
|
+
* the manifest says so — a line-scan is not a parse.
|
|
429
|
+
*/
|
|
430
|
+
quality: "ast" | "heuristic";
|
|
431
|
+
}
|
|
432
|
+
interface LanguageProfile {
|
|
433
|
+
readonly id: string;
|
|
434
|
+
readonly extensions: readonly string[];
|
|
435
|
+
summarize(path: string, content: string): HeuristicResult;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Every heuristic profile, in no particular order — lookup is by extension.
|
|
440
|
+
*
|
|
441
|
+
* Adding a language is one file exporting a `LanguageProfile` plus one line
|
|
442
|
+
* here; nothing else in the pipeline changes.
|
|
443
|
+
*/
|
|
444
|
+
declare const LANGUAGE_PROFILES: readonly LanguageProfile[];
|
|
445
|
+
/** The profile that owns `path`, or `null` when no profile claims it. */
|
|
446
|
+
declare function profileForPath(path: string): LanguageProfile | null;
|
|
447
|
+
/**
|
|
448
|
+
* Summarizes `path` with whichever profile claims it.
|
|
449
|
+
*
|
|
450
|
+
* Returns `null` for files no profile handles — those still enter the snapshot,
|
|
451
|
+
* they just carry no structural summary.
|
|
452
|
+
*/
|
|
453
|
+
declare function summarizeWithProfile(path: string, content: string): HeuristicResult | null;
|
|
454
|
+
|
|
455
|
+
interface CollectOptions {
|
|
456
|
+
/**
|
|
457
|
+
* When non-empty, only files matching at least one pattern are candidates.
|
|
458
|
+
* Applied before `excludePatterns`, which then narrows the result further.
|
|
459
|
+
*/
|
|
460
|
+
includePatterns?: string[];
|
|
461
|
+
excludePatterns?: string[];
|
|
462
|
+
/**
|
|
463
|
+
* Emit credential-bearing files (`.env`, `*.pem`, `.npmrc`, `id_rsa`, …).
|
|
464
|
+
* Default `false`: they are skipped with `reason: "sensitive-file"`.
|
|
465
|
+
*/
|
|
466
|
+
includeSensitiveFiles?: boolean;
|
|
467
|
+
}
|
|
468
|
+
interface CollectResult {
|
|
469
|
+
files: string[];
|
|
470
|
+
skipped: SkipRecord[];
|
|
471
|
+
}
|
|
472
|
+
declare function isSensitivePath(relativePath: string): boolean;
|
|
473
|
+
/**
|
|
474
|
+
* Translates a glob (`**`, `*`, `?`, `{a,b}`, `[abc]`) into a RegExp. A pattern
|
|
475
|
+
* without a leading `/` matches at any depth, mirroring `.gitignore` semantics.
|
|
476
|
+
*
|
|
477
|
+
* Brace groups and character classes are supported because they are what people
|
|
478
|
+
* actually write: `*.{ts,tsx}` previously matched nothing at all, since `{` and
|
|
479
|
+
* `}` were escaped as literals.
|
|
480
|
+
*/
|
|
481
|
+
declare function globToRegExp(glob: string): RegExp;
|
|
482
|
+
/**
|
|
483
|
+
* Path exclusion with proper segment semantics.
|
|
484
|
+
*
|
|
485
|
+
* A plain (non-glob) pattern matches a whole path segment sequence, so
|
|
486
|
+
* `"test"` matches `test/a.ts` and `src/test/b.ts` but **not** `contest/entry.ts`
|
|
487
|
+
* (the previous implementation was a raw `String.includes`).
|
|
488
|
+
*/
|
|
489
|
+
declare function matchesExclude(relativePath: string, pattern: string): boolean;
|
|
490
|
+
/**
|
|
491
|
+
* Collects candidate file paths.
|
|
492
|
+
*
|
|
493
|
+
* Uses `git ls-files -z` when git is available: `-z` is required because the
|
|
494
|
+
* default output C-quotes paths containing non-ASCII characters, which silently
|
|
495
|
+
* mangled `src/café.ts` into a path that never existed and dropped the file.
|
|
496
|
+
*/
|
|
497
|
+
declare function collectFiles(cwd: string, options?: CollectOptions): CollectResult;
|
|
498
|
+
|
|
499
|
+
declare const GENERATOR_NAME = "@ankurhalder/codebase-snapshot";
|
|
500
|
+
declare const GENERATOR_VERSION = "2.1.0";
|
|
501
|
+
declare const SCHEMA_VERSION = "3.0.0";
|
|
502
|
+
interface GenerateOptions {
|
|
503
|
+
/** Compute the full manifest but write nothing to disk. */
|
|
504
|
+
dryRun?: boolean;
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Resolves and validates the output directories.
|
|
508
|
+
*
|
|
509
|
+
* `outDir` was previously deleted with `rmSync` before the replacement was
|
|
510
|
+
* renamed into place, so `outDir: "."` erased the whole repository and a
|
|
511
|
+
* nested `tmpDir` erased its own parent. These guards make that impossible.
|
|
512
|
+
*/
|
|
513
|
+
declare function resolveSafeOutputDirs(config: {
|
|
514
|
+
cwd: string;
|
|
515
|
+
outDir: string;
|
|
516
|
+
tmpDir: string;
|
|
517
|
+
}): {
|
|
518
|
+
outDir: string;
|
|
519
|
+
tmpDir: string;
|
|
520
|
+
};
|
|
521
|
+
/**
|
|
522
|
+
* Refuses to replace a directory that this generator did not write.
|
|
523
|
+
*
|
|
524
|
+
* `swapIntoPlace` renames the previous output aside and deletes it, and the
|
|
525
|
+
* scratch directory is deleted outright before every run. Path checks alone
|
|
526
|
+
* cannot make that safe: `outDir: "src"` is a plausible typo, and it used to
|
|
527
|
+
* delete the developer's entire source tree and exit 0.
|
|
528
|
+
*/
|
|
529
|
+
declare function assertReplaceable(target: string, label: "outDir" | "tmpDir"): void;
|
|
530
|
+
/**
|
|
531
|
+
* Generates the snapshot.
|
|
532
|
+
*
|
|
533
|
+
* Synchronous by design: it previously carried an `async` signature while doing
|
|
534
|
+
* only blocking I/O, which promised concurrency that did not exist. Existing
|
|
535
|
+
* `await generateSnapshot(...)` call sites continue to work.
|
|
536
|
+
*/
|
|
537
|
+
declare function generateSnapshot(configInput?: SnapshotConfig | ResolvedSnapshotConfig | null, options?: GenerateOptions): Manifest;
|
|
538
|
+
/** Promise-returning wrapper for consumers that prefer an async call site. */
|
|
539
|
+
declare function generateSnapshotAsync(configInput?: SnapshotConfig | ResolvedSnapshotConfig | null, options?: GenerateOptions): Promise<Manifest>;
|
|
540
|
+
|
|
541
|
+
export { ARTIFACT_NAMES, ArtifactSelection, ByteSize, CliOptions, DEFAULT_ANSWERS, DEFAULT_SECRET_PATTERNS, type ExplainResult, FileEntry, GENERATOR_NAME, GENERATOR_VERSION, type GenerateOptions, type HeuristicResult, type InitOptions, type InitResult, JsonSummary, KindRule, LANGUAGE_PROFILES, type LanguageProfile, LayerRule, MIN_MAX_PART_BYTES, Manifest, type ManifestDiff, MarkdownSummary, PRESETS, PartMetadata, PromptCancelled, ResolvedSnapshotConfig, SCHEMA_VERSION, SecretFinding, SecretRule, SkipRecord, SnapshotConfig, SourceSummary, ValidationResult, type WizardAnswers, anchorForPath, assertReplaceable, assertUsableConfigInput, collectFiles, compareManifests, countLines, defineConfig, detectLanguage, detectPreset, explainPath, fenceForContent, generateProjectTree, generateSnapshot, generateSnapshotAsync, getPreset, globToRegExp, isBinaryBuffer, isBinaryExtension, isBinaryFile, isInteractive, isResolvedConfig, isSensitivePath, listPresetNames, loadConfigFile, loadConfigFileDetailed, loadManifest, markResolvedConfig, matchRule, matchesExclude, normalizeResolvedConfig, parseByteSize, partitionFiles, profileForPath, renderConfig, renderDiffText, renderExplainText, renderMinimalConfig, renumberParts, resolveConfig, resolveSafeOutputDirs, runInit, scanAndRedactSecrets, stripJsonComments, summarizeJson, summarizeMarkdown, summarizeTypeScriptSource, summarizeWithProfile, supportsTypeScriptImports, truncatePreview, truncateToBytes, validateSnapshot };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { ARTIFACT_NAMES, DEFAULT_ANSWERS, DEFAULT_SECRET_PATTERNS, GENERATOR_NAME, GENERATOR_VERSION, LANGUAGE_PROFILES, MIN_MAX_PART_BYTES, PRESETS, PromptCancelled, SCHEMA_VERSION, anchorForPath, assertReplaceable, assertUsableConfigInput, collectFiles, compareManifests, countLines, defineConfig, detectLanguage, detectPreset, explainPath, fenceForContent, generateProjectTree, generateSnapshot, generateSnapshotAsync, getPreset, globToRegExp, isBinaryBuffer, isBinaryExtension, isBinaryFile, isInteractive, isResolvedConfig, isSensitivePath, listPresetNames, loadConfigFile, loadConfigFileDetailed, loadManifest, markResolvedConfig, matchRule, matchesExclude, normalizeResolvedConfig, parseByteSize, partitionFiles, profileForPath, renderConfig, renderDiffText, renderExplainText, renderMinimalConfig, renumberParts, resolveConfig, resolveSafeOutputDirs, runInit, scanAndRedactSecrets, stripJsonComments, summarizeJson, summarizeMarkdown, summarizeTypeScriptSource, summarizeWithProfile, supportsTypeScriptImports, truncatePreview, truncateToBytes, validateSnapshot } from './chunk-QEIOXPMU.js';
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
3
|
+
//# sourceMappingURL=index.js.map
|