@oh-my-pi/hashline 17.2.9 → 17.2.11
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 +16 -0
- package/dist/types/apply.d.ts +1 -1
- package/dist/types/clipboard.d.ts +6 -3
- package/dist/types/messages.d.ts +2 -2
- package/dist/types/prefixes.d.ts +9 -9
- package/dist/types/snapshots.d.ts +1 -1
- package/package.json +3 -3
- package/src/apply.ts +4 -2
- package/src/clipboard.ts +13 -7
- package/src/messages.ts +3 -3
- package/src/parser.ts +6 -6
- package/src/prefixes.ts +10 -10
- package/src/snapshots.ts +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [17.2.11] - 2026-08-07
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Pasting an empty named register (`PUT … @name` with no matching capture) now surfaces a warning listing available registers and removes the span target instead of throwing an error.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Fixed an issue where pipe-numbered `read`/`search` rows copied into top-level and bare-body patch payloads were not properly recovered (#7905).
|
|
14
|
+
|
|
15
|
+
## [17.2.10] - 2026-08-06
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Updated internal caching dependency to use `@oh-my-pi/pi-utils/lru`.
|
|
20
|
+
|
|
5
21
|
## [17.2.2] - 2026-07-31
|
|
6
22
|
|
|
7
23
|
### Breaking Changes
|
package/dist/types/apply.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export interface ApplyEditsOptions {
|
|
|
18
18
|
* across files; omitted, the call gets a private register.
|
|
19
19
|
*/
|
|
20
20
|
clipboard?: Clipboard;
|
|
21
|
-
/** `PASTE` with an empty register: `throw` (default) or `drop` (streaming previews). */
|
|
21
|
+
/** Anonymous `PASTE` with an empty register: `throw` (default) or `drop` (streaming previews). An empty named-register paste never throws — it warns and pastes nothing. */
|
|
22
22
|
onEmptyPaste?: "throw" | "drop";
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
@@ -3,8 +3,10 @@ import type { Clipboard, Edit } from "./types.js";
|
|
|
3
3
|
export declare function hasClipboardEdit(edits: readonly Edit[]): boolean;
|
|
4
4
|
/** Optional knobs for {@link resolveClipboardEdits}. */
|
|
5
5
|
export interface ResolveClipboardEditsOptions {
|
|
6
|
-
/** `PUT` with an empty register: `throw` (default) or `drop` (streaming previews). */
|
|
6
|
+
/** `PUT` with an empty register: `throw` (default) or `drop` (streaming previews). Named registers never throw — an empty named paste warns and pastes nothing. */
|
|
7
7
|
onEmptyPaste?: "throw" | "drop";
|
|
8
|
+
/** Receives non-fatal diagnostics (e.g. an empty named-register paste). */
|
|
9
|
+
onWarning?: (message: string) => void;
|
|
8
10
|
}
|
|
9
11
|
/**
|
|
10
12
|
* Resolve clipboard edits against the original file lines in authored order.
|
|
@@ -18,7 +20,8 @@ export declare function forkClipboard(source?: Clipboard): Clipboard;
|
|
|
18
20
|
/** Publish a clipboard fork back to its source register (only named registers persist across batches). */
|
|
19
21
|
export declare function commitClipboard(fork: Clipboard, target: Clipboard): void;
|
|
20
22
|
/**
|
|
21
|
-
* Validate
|
|
22
|
-
* mutating the register or reading file content.
|
|
23
|
+
* Validate anonymous clipboard sequencing (empty or ambiguous unlabeled paste)
|
|
24
|
+
* without mutating the register or reading file content. Empty named-register
|
|
25
|
+
* pastes are non-fatal — they surface as apply-time warnings instead.
|
|
23
26
|
*/
|
|
24
27
|
export declare function validateClipboardSequence(edits: readonly Edit[], clipboard: Clipboard): void;
|
package/dist/types/messages.d.ts
CHANGED
|
@@ -109,8 +109,8 @@ export declare const COLONLESS_PUT_TAKES_NO_BODY = "`PUT` without `:` is clipboa
|
|
|
109
109
|
export declare const COLONLESS_SPAN_PUT = "Colonless `PUT` is clipboard-backed, and span targets need a named register (`PUT 5.=9 @name`); the anonymous register pastes only at gaps (`PUT >40`). To write literal content, add `:` and `+TEXT` body rows.";
|
|
110
110
|
/** Anonymous paste ran with an empty anonymous register. */
|
|
111
111
|
export declare const EMPTY_PASTE = "Nothing to paste: no unlabeled `CUT` precedes this `PUT` in this call, and the anonymous register never carries across calls. Put `CUT N.=M` / `CUT N*` above it, or use named registers (`CUT \u2026 @name` \u2192 `PUT \u2026 @name`) for cross-call moves.";
|
|
112
|
-
/** Named paste read a register that holds nothing. */
|
|
113
|
-
export declare function
|
|
112
|
+
/** Named paste read a register that holds nothing; the paste applied as empty (span targets are still removed). */
|
|
113
|
+
export declare function emptyRegisterPasteWarning(name: string, known: readonly string[]): string;
|
|
114
114
|
/** Unlabeled paste with two or more unlabeled cuts pending. */
|
|
115
115
|
export declare function ambiguousAnonymousPasteMessage(pending: readonly string[]): string;
|
|
116
116
|
/**
|
package/dist/types/prefixes.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* When a
|
|
3
|
-
*
|
|
4
|
-
* diff-style echoes, a leading `+`. These helpers detect
|
|
5
|
-
* the raw text. Two strip modes are exposed:
|
|
2
|
+
* When a payload is authored against `read`/`search` output, each line is
|
|
3
|
+
* prefixed with either a line number (`123:` in hashline mode or `123|`
|
|
4
|
+
* otherwise) or, for diff-style echoes, a leading `+`. These helpers detect
|
|
5
|
+
* that and recover the raw text. Two strip modes are exposed:
|
|
6
6
|
*
|
|
7
7
|
* - {@link stripNewLinePrefixes} — opportunistic: strips when the input
|
|
8
8
|
* clearly carries hashline or diff prefixes, leaves it alone otherwise.
|
|
@@ -17,15 +17,15 @@
|
|
|
17
17
|
export declare function isReadMetadataLine(line: string): boolean;
|
|
18
18
|
/**
|
|
19
19
|
* Single-pass variant of {@link stripLeadingHashlinePrefixes} that strips at
|
|
20
|
-
* most one leading
|
|
21
|
-
* loop. Use this when the input carries at most one snapshot prefix
|
|
22
|
-
* bare body row paste from `read` output) — recursive stripping would
|
|
23
|
-
* content whose own text starts with
|
|
20
|
+
* most one leading line-number prefix (`N:`, `N|`, `>>>N:`, `+N:` etc.) and
|
|
21
|
+
* does NOT loop. Use this when the input carries at most one snapshot prefix
|
|
22
|
+
* (e.g. a bare body row paste from `read` output) — recursive stripping would
|
|
23
|
+
* corrupt content whose own text starts with a line-number prefix.
|
|
24
24
|
*/
|
|
25
25
|
export declare function stripOneLeadingHashlinePrefix(line: string): string;
|
|
26
26
|
/**
|
|
27
27
|
* Strip whichever prefix scheme the lines appear to be carrying:
|
|
28
|
-
* -
|
|
28
|
+
* - line-number prefixes (`123:` or `123|`) when every content line has one
|
|
29
29
|
* - leading `+` (diff style) when at least half the lines have one
|
|
30
30
|
* - mixed `+<n>:` form when present
|
|
31
31
|
*
|
|
@@ -88,7 +88,7 @@ export interface InMemorySnapshotStoreOptions {
|
|
|
88
88
|
maxTotalBytes?: number;
|
|
89
89
|
}
|
|
90
90
|
/**
|
|
91
|
-
* In-memory {@link SnapshotStore} backed by
|
|
91
|
+
* In-memory {@link SnapshotStore} backed by a bounded LRU. Per-path history is a
|
|
92
92
|
* short ring of full-file versions (oldest dropped first); per-session path
|
|
93
93
|
* tracking is LRU-bounded so cold paths age out automatically.
|
|
94
94
|
*
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/hashline",
|
|
4
|
-
"version": "17.2.
|
|
4
|
+
"version": "17.2.11",
|
|
5
5
|
"description": "Hashline: a compact, line-anchored patch language and applier. Pluggable FS/IO so it works over disk, in-memory, or any custom backend.",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"fmt": "biome format --write ."
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@oh-my-pi/pi-natives": "17.2.
|
|
37
|
-
"
|
|
36
|
+
"@oh-my-pi/pi-natives": "17.2.11",
|
|
37
|
+
"@oh-my-pi/pi-utils": "17.2.11"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/bun": "^1.3.14"
|
package/src/apply.ts
CHANGED
|
@@ -1301,7 +1301,7 @@ export interface ApplyEditsOptions {
|
|
|
1301
1301
|
* across files; omitted, the call gets a private register.
|
|
1302
1302
|
*/
|
|
1303
1303
|
clipboard?: Clipboard;
|
|
1304
|
-
/** `PASTE` with an empty register: `throw` (default) or `drop` (streaming previews). */
|
|
1304
|
+
/** Anonymous `PASTE` with an empty register: `throw` (default) or `drop` (streaming previews). An empty named-register paste never throws — it warns and pastes nothing. */
|
|
1305
1305
|
onEmptyPaste?: "throw" | "drop";
|
|
1306
1306
|
}
|
|
1307
1307
|
|
|
@@ -1318,8 +1318,10 @@ export function applyEdits(text: string, edits: readonly Edit[], options: ApplyE
|
|
|
1318
1318
|
|
|
1319
1319
|
// Clipboard pre-pass: capture `cut` ranges from the original lines and
|
|
1320
1320
|
// expand `paste` edits into plain inserts in authored order.
|
|
1321
|
+
const clipboardWarnings: string[] = [];
|
|
1321
1322
|
const concrete = resolveClipboardEdits(edits, fileLines, options.clipboard ?? {}, {
|
|
1322
1323
|
...(options.onEmptyPaste === undefined ? {} : { onEmptyPaste: options.onEmptyPaste }),
|
|
1324
|
+
onWarning: message => clipboardWarnings.push(message),
|
|
1323
1325
|
});
|
|
1324
1326
|
|
|
1325
1327
|
// Block edits are deferred until `resolveBlockEdits` expands them into
|
|
@@ -1345,7 +1347,7 @@ export function applyEdits(text: string, edits: readonly Edit[], options: ApplyE
|
|
|
1345
1347
|
const indentationWarnings = repairReplacementIndentation(targetEdits, fileLines);
|
|
1346
1348
|
const { edits: repaired, warnings: boundaryWarnings } = repairReplacementBoundaries(targetEdits, fileLines);
|
|
1347
1349
|
const { edits: landed, warnings: landingWarnings } = repairAfterInsertLandings(repaired, fileLines);
|
|
1348
|
-
const warnings = [...indentationWarnings, ...boundaryWarnings, ...landingWarnings];
|
|
1350
|
+
const warnings = [...clipboardWarnings, ...indentationWarnings, ...boundaryWarnings, ...landingWarnings];
|
|
1349
1351
|
|
|
1350
1352
|
// Partition edits into bof, eof, and anchor-targeted buckets.
|
|
1351
1353
|
const bofLines: string[] = [];
|
package/src/clipboard.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* (`lines`) is batch-local and resets between calls.
|
|
9
9
|
*/
|
|
10
10
|
import { HL_CUT_KEYWORD, HL_PUT_KEYWORD, HL_RANGE_SEP } from "./format";
|
|
11
|
-
import { ambiguousAnonymousPasteMessage, EMPTY_PASTE,
|
|
11
|
+
import { ambiguousAnonymousPasteMessage, EMPTY_PASTE, emptyRegisterPasteWarning } from "./messages";
|
|
12
12
|
import { cloneCursor } from "./tokenizer";
|
|
13
13
|
import type { Clipboard, Edit } from "./types";
|
|
14
14
|
|
|
@@ -33,25 +33,30 @@ export function hasClipboardEdit(edits: readonly Edit[]): boolean {
|
|
|
33
33
|
|
|
34
34
|
/** Optional knobs for {@link resolveClipboardEdits}. */
|
|
35
35
|
export interface ResolveClipboardEditsOptions {
|
|
36
|
-
/** `PUT` with an empty register: `throw` (default) or `drop` (streaming previews). */
|
|
36
|
+
/** `PUT` with an empty register: `throw` (default) or `drop` (streaming previews). Named registers never throw — an empty named paste warns and pastes nothing. */
|
|
37
37
|
onEmptyPaste?: "throw" | "drop";
|
|
38
|
+
/** Receives non-fatal diagnostics (e.g. an empty named-register paste). */
|
|
39
|
+
onWarning?: (message: string) => void;
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
/**
|
|
41
|
-
* Read lines from a register.
|
|
43
|
+
* Read lines from a register. A missing named register warns and reads as
|
|
44
|
+
* empty; anonymous misuse throws unless `onEmptyPaste === "drop"`.
|
|
42
45
|
*/
|
|
43
46
|
function readRegister(
|
|
44
47
|
register: string | undefined,
|
|
45
48
|
clipboard: Clipboard,
|
|
46
49
|
lineNum: number,
|
|
47
50
|
onEmptyPaste: "throw" | "drop",
|
|
51
|
+
onWarning?: (message: string) => void,
|
|
48
52
|
): readonly string[] | null {
|
|
49
53
|
if (register !== undefined) {
|
|
50
54
|
const lines = clipboard.named?.get(register);
|
|
51
55
|
if (lines !== undefined) return lines;
|
|
52
56
|
if (onEmptyPaste === "drop") return null;
|
|
53
57
|
const known = clipboard.named ? [...clipboard.named.keys()] : [];
|
|
54
|
-
|
|
58
|
+
onWarning?.(`line ${lineNum}: ${emptyRegisterPasteWarning(register, known)}`);
|
|
59
|
+
return [];
|
|
55
60
|
}
|
|
56
61
|
|
|
57
62
|
const pending = clipboard.pendingAnonCuts ?? [];
|
|
@@ -112,7 +117,7 @@ export function resolveClipboardEdits(
|
|
|
112
117
|
continue;
|
|
113
118
|
}
|
|
114
119
|
if (edit.kind === "paste") {
|
|
115
|
-
const lines = readRegister(edit.register, clipboard, edit.lineNum, onEmptyPaste);
|
|
120
|
+
const lines = readRegister(edit.register, clipboard, edit.lineNum, onEmptyPaste, options.onWarning);
|
|
116
121
|
if (lines === null) continue;
|
|
117
122
|
|
|
118
123
|
if (edit.at.kind === "gap") {
|
|
@@ -187,8 +192,9 @@ export function commitClipboard(fork: Clipboard, target: Clipboard): void {
|
|
|
187
192
|
}
|
|
188
193
|
|
|
189
194
|
/**
|
|
190
|
-
* Validate
|
|
191
|
-
* mutating the register or reading file content.
|
|
195
|
+
* Validate anonymous clipboard sequencing (empty or ambiguous unlabeled paste)
|
|
196
|
+
* without mutating the register or reading file content. Empty named-register
|
|
197
|
+
* pastes are non-fatal — they surface as apply-time warnings instead.
|
|
192
198
|
*/
|
|
193
199
|
export function validateClipboardSequence(edits: readonly Edit[], clipboard: Clipboard): void {
|
|
194
200
|
const fork = forkClipboard(clipboard);
|
package/src/messages.ts
CHANGED
|
@@ -331,9 +331,9 @@ export const COLONLESS_SPAN_PUT = `Colonless \`PUT\` is clipboard-backed, and sp
|
|
|
331
331
|
/** Anonymous paste ran with an empty anonymous register. */
|
|
332
332
|
export const EMPTY_PASTE = `Nothing to paste: no unlabeled \`CUT\` precedes this \`PUT\` in this call, and the anonymous register never carries across calls. Put \`CUT N${HL_RANGE_SEP}M\` / \`CUT N*\` above it, or use named registers (\`CUT … @name\` → \`PUT … @name\`) for cross-call moves.`;
|
|
333
333
|
|
|
334
|
-
/** Named paste read a register that holds nothing. */
|
|
335
|
-
export function
|
|
336
|
-
const base = `\`@${name}\`
|
|
334
|
+
/** Named paste read a register that holds nothing; the paste applied as empty (span targets are still removed). */
|
|
335
|
+
export function emptyRegisterPasteWarning(name: string, known: readonly string[]): string {
|
|
336
|
+
const base = `\`@${name}\` was empty — no \`CUT … @${name}\` precedes this op in this call and no persisted register has that name — so nothing was pasted (a span target is still removed).`;
|
|
337
337
|
return known.length === 0 ? base : `${base} Available registers: ${known.map(k => `\`@${k}\``).join(", ")}.`;
|
|
338
338
|
}
|
|
339
339
|
|
package/src/parser.ts
CHANGED
|
@@ -112,7 +112,7 @@ function bodylessTargetMessage(target: BlockTarget, hadColon: boolean): string |
|
|
|
112
112
|
*/
|
|
113
113
|
const BARE_LITERAL_VALUE_RE = /^\s*(?:"[^"]*"|'[^']*'|[-+]?\d+(?:\.\d+)?)\s*,?\s*$/;
|
|
114
114
|
|
|
115
|
-
const TOP_LEVEL_SNAPSHOT_ROW_RE = /^\s*([1-9]\d*)
|
|
115
|
+
const TOP_LEVEL_SNAPSHOT_ROW_RE = /^\s*([1-9]\d*)[:|](.*)$/;
|
|
116
116
|
|
|
117
117
|
function parseTopLevelSnapshotRow(text: string): { line: number; text: string } | null {
|
|
118
118
|
const match = TOP_LEVEL_SNAPSHOT_ROW_RE.exec(text);
|
|
@@ -595,11 +595,11 @@ export class Executor {
|
|
|
595
595
|
}
|
|
596
596
|
|
|
597
597
|
/**
|
|
598
|
-
* Strip a single read-output line-number prefix (`N:`) from every
|
|
599
|
-
* row, but only when *all* bare rows carry one. A uniform set of
|
|
600
|
-
* the signature of content pasted straight from `read`/`search`
|
|
601
|
-
* mixed set means the
|
|
602
|
-
* authored with an explicit `+` are not bare and are never touched.
|
|
598
|
+
* Strip a single read-output line-number prefix (`N:` or `N|`) from every
|
|
599
|
+
* bare body row, but only when *all* bare rows carry one. A uniform set of
|
|
600
|
+
* prefixes is the signature of content pasted straight from `read`/`search`
|
|
601
|
+
* output; a mixed set means the prefix is genuine payload content and must
|
|
602
|
+
* stay. Rows authored with an explicit `+` are not bare and are never touched.
|
|
603
603
|
*/
|
|
604
604
|
#stripBarePrefixesIfUniform(payloads: PayloadRow[]): void {
|
|
605
605
|
let sawBare = false;
|
package/src/prefixes.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* When a
|
|
3
|
-
*
|
|
4
|
-
* diff-style echoes, a leading `+`. These helpers detect
|
|
5
|
-
* the raw text. Two strip modes are exposed:
|
|
2
|
+
* When a payload is authored against `read`/`search` output, each line is
|
|
3
|
+
* prefixed with either a line number (`123:` in hashline mode or `123|`
|
|
4
|
+
* otherwise) or, for diff-style echoes, a leading `+`. These helpers detect
|
|
5
|
+
* that and recover the raw text. Two strip modes are exposed:
|
|
6
6
|
*
|
|
7
7
|
* - {@link stripNewLinePrefixes} — opportunistic: strips when the input
|
|
8
8
|
* clearly carries hashline or diff prefixes, leaves it alone otherwise.
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import { HL_FILE_HASH_LENGTH } from "./format";
|
|
18
18
|
|
|
19
|
-
const HL_PREFIX_RE = /^\s*(?:>>>|>>)?\s*(?:[+*-]\s*)?\d
|
|
19
|
+
const HL_PREFIX_RE = /^\s*(?:>>>|>>)?\s*(?:[+*-]\s*)?\d+[:|]/;
|
|
20
20
|
const HL_PREFIX_PLUS_RE = /^\s*(?:>>>|>>)?\s*\+\s*\d+:/;
|
|
21
21
|
const HL_HEADER_RE = new RegExp(`^\\s*\\[[^#\\r\\n]+#[0-9a-fA-F]{${HL_FILE_HASH_LENGTH}}\\]\\s*$`);
|
|
22
22
|
const DIFF_PLUS_RE = /^[+](?![+])/;
|
|
@@ -41,10 +41,10 @@ function stripLeadingHashlinePrefixes(line: string): string {
|
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
43
|
* Single-pass variant of {@link stripLeadingHashlinePrefixes} that strips at
|
|
44
|
-
* most one leading
|
|
45
|
-
* loop. Use this when the input carries at most one snapshot prefix
|
|
46
|
-
* bare body row paste from `read` output) — recursive stripping would
|
|
47
|
-
* content whose own text starts with
|
|
44
|
+
* most one leading line-number prefix (`N:`, `N|`, `>>>N:`, `+N:` etc.) and
|
|
45
|
+
* does NOT loop. Use this when the input carries at most one snapshot prefix
|
|
46
|
+
* (e.g. a bare body row paste from `read` output) — recursive stripping would
|
|
47
|
+
* corrupt content whose own text starts with a line-number prefix.
|
|
48
48
|
*/
|
|
49
49
|
export function stripOneLeadingHashlinePrefix(line: string): string {
|
|
50
50
|
return line.replace(HL_PREFIX_RE, "");
|
|
@@ -90,7 +90,7 @@ function collectLinePrefixStats(lines: string[]): LinePrefixStats {
|
|
|
90
90
|
|
|
91
91
|
/**
|
|
92
92
|
* Strip whichever prefix scheme the lines appear to be carrying:
|
|
93
|
-
* -
|
|
93
|
+
* - line-number prefixes (`123:` or `123|`) when every content line has one
|
|
94
94
|
* - leading `+` (diff style) when at least half the lines have one
|
|
95
95
|
* - mixed `+<n>:` form when present
|
|
96
96
|
*
|
package/src/snapshots.ts
CHANGED
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
*
|
|
16
16
|
* The abstract base class lets callers plug in whatever storage they like
|
|
17
17
|
* (LRU, persistent SQLite, etc.). {@link InMemorySnapshotStore} ships as a
|
|
18
|
-
* sensible default backed by
|
|
18
|
+
* sensible default backed by a bounded LRU: a limited set of paths, each with a
|
|
19
19
|
* short history of full-file versions so in-session edit chains can still
|
|
20
20
|
* recover against the version a stale tag names.
|
|
21
21
|
*/
|
|
22
|
-
import { LRUCache } from "
|
|
22
|
+
import { LRUCache } from "@oh-my-pi/pi-utils/lru";
|
|
23
23
|
import { computeFileHash } from "./format";
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -137,7 +137,7 @@ export interface InMemorySnapshotStoreOptions {
|
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
/**
|
|
140
|
-
* In-memory {@link SnapshotStore} backed by
|
|
140
|
+
* In-memory {@link SnapshotStore} backed by a bounded LRU. Per-path history is a
|
|
141
141
|
* short ring of full-file versions (oldest dropped first); per-session path
|
|
142
142
|
* tracking is LRU-bounded so cold paths age out automatically.
|
|
143
143
|
*
|