@bendyline/docblocks 2.6.1 → 2.7.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.
Files changed (62) hide show
  1. package/THIRD_PARTY_NOTICES.txt +33 -33
  2. package/dist/capabilities-CdQAc745.d.ts +1233 -0
  3. package/dist/catalog-BQK05tne.d.ts +122 -0
  4. package/dist/chunk-245W57QP.js +31 -0
  5. package/dist/{chunk-2WDJ27EH.js → chunk-46AGYHDY.js} +8 -0
  6. package/dist/{chunk-4437YWLE.js → chunk-6UPO2GE6.js} +4 -2
  7. package/dist/{chunk-UMWCTEXW.js → chunk-7SN7YQL4.js} +211 -40
  8. package/dist/{chunk-OQCPBOQA.js → chunk-DAPFSEKY.js} +35 -0
  9. package/dist/{chunk-M62ZGJ5I.js → chunk-HABG2JM3.js} +0 -17
  10. package/dist/{chunk-YM7O3PWO.js → chunk-HKOOHM67.js} +20 -12
  11. package/dist/chunk-IDYE73TU.js +77 -0
  12. package/dist/{chunk-KLQKU74Q.js → chunk-IGB2VSRE.js} +124 -330
  13. package/dist/{chunk-BVY7GGNV.js → chunk-L6PRMR7T.js} +137 -95
  14. package/dist/chunk-LPIJ6HKL.js +19 -0
  15. package/dist/{chunk-SJBB5OD7.js → chunk-QS5WTLUZ.js} +10 -8
  16. package/dist/chunk-R2JX5N3F.js +382 -0
  17. package/dist/{chunk-ZO7G53QP.js → chunk-UDEWLHQI.js} +4 -2
  18. package/dist/chunk-UK7R3RC7.js +514 -0
  19. package/dist/chunk-XTNWCNSK.js +464 -0
  20. package/dist/chunk-YHSFRPBS.js +42 -0
  21. package/dist/chunk-YNUQG4GF.js +1173 -0
  22. package/dist/document/index.d.ts +31 -1
  23. package/dist/document/index.js +7 -6
  24. package/dist/filesystem/electron.d.ts +8 -34
  25. package/dist/filesystem/electron.js +7 -4
  26. package/dist/filesystem/host.d.ts +28 -0
  27. package/dist/filesystem/host.js +103 -0
  28. package/dist/filesystem/index.d.ts +52 -6
  29. package/dist/filesystem/index.js +36 -15
  30. package/dist/filesystem/indexeddb.d.ts +8 -1
  31. package/dist/filesystem/indexeddb.js +7 -6
  32. package/dist/filesystem/memory.d.ts +2 -1
  33. package/dist/filesystem/memory.js +3 -2
  34. package/dist/filesystem/native.d.ts +2 -1
  35. package/dist/filesystem/native.js +3 -2
  36. package/dist/filesystem-v2-C8AdSXUN.d.ts +74 -0
  37. package/dist/host/index.d.ts +127 -5
  38. package/dist/host/index.js +100 -4
  39. package/dist/host/mobile.d.ts +389 -0
  40. package/dist/host/mobile.js +315 -0
  41. package/dist/host-provider-v2-CyLTRKJF.d.ts +51 -0
  42. package/dist/index.d.ts +8 -5
  43. package/dist/index.js +153 -34
  44. package/dist/mcp/index.d.ts +2 -2
  45. package/dist/mcp/zod.d.ts +23 -1
  46. package/dist/mcp/zod.js +1 -0
  47. package/dist/settings-HrrCikVX.d.ts +170 -0
  48. package/dist/types-BvDnr3YU.d.ts +88 -0
  49. package/dist/{types-Oy9U5FST.d.ts → types-d0yvHUJz.d.ts} +6 -0
  50. package/dist/{types-Bb3yccTH.d.ts → v2-BVnZZyd4.d.ts} +1 -86
  51. package/dist/vscode/index.d.ts +43 -1
  52. package/dist/vscode/index.js +67 -1
  53. package/dist/workspace/index.d.ts +10 -6
  54. package/dist/workspace/index.js +4 -2
  55. package/dist/workspace-index/index.d.ts +240 -0
  56. package/dist/workspace-index/index.js +1287 -0
  57. package/dist/workspace-settings/index.d.ts +301 -0
  58. package/dist/workspace-settings/index.js +820 -0
  59. package/package.json +22 -2
  60. package/dist/chunk-6XHOOBYF.js +0 -36
  61. package/dist/chunk-QI6YKTQV.js +0 -110
  62. package/dist/types-DBYraXxE.d.ts +0 -557
@@ -0,0 +1,464 @@
1
+ // src/document/recovery-journal.ts
2
+ var DOCUMENT_RECOVERY_JOURNAL_STORAGE_KEY = "docblocks:document-recovery:v1";
3
+ var DOCUMENT_RECOVERY_JOURNAL_SCHEMA_VERSION = 1;
4
+ var DEFAULT_MAX_ENTRIES = 20;
5
+ var DEFAULT_MAX_STORAGE_BYTES = 2e6;
6
+ var DEFAULT_MAX_RECORD_BYTES = 1e6;
7
+ var DEFAULT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
8
+ var DEFAULT_MAX_FUTURE_SKEW_MS = 5 * 60 * 1e3;
9
+ var MAX_TARGET_KEY_LENGTH = 4096;
10
+ var MAX_STORAGE_KEYS = 1e4;
11
+ var knownStorageKeys = /* @__PURE__ */ new WeakMap();
12
+ var DocumentRecoveryJournal = class _DocumentRecoveryJournal {
13
+ constructor(storage, options = {}) {
14
+ this.loadedKeys = [];
15
+ this.storage = storage;
16
+ this.baseStorageKey = options.storageKey?.trim() || DOCUMENT_RECOVERY_JOURNAL_STORAGE_KEY;
17
+ if (options.ownerId !== void 0 && !/^[a-zA-Z0-9-]{1,100}$/.test(options.ownerId)) {
18
+ throw new TypeError("Invalid recovery journal owner.");
19
+ }
20
+ this.options = { ...options, storageKey: this.baseStorageKey };
21
+ this.storageKey = options.ownerId ? `${this.baseStorageKey}:owner:${options.ownerId}` : this.baseStorageKey;
22
+ if (storage) {
23
+ const keys = knownStorageKeys.get(storage) ?? /* @__PURE__ */ new Set();
24
+ if (!options.ownerId) keys.add(this.storageKey);
25
+ knownStorageKeys.set(storage, keys);
26
+ }
27
+ this.maxEntries = positiveInteger(options.maxEntries, DEFAULT_MAX_ENTRIES);
28
+ this.maxStorageBytes = positiveInteger(options.maxStorageBytes, DEFAULT_MAX_STORAGE_BYTES);
29
+ this.maxRecordBytes = Math.min(
30
+ positiveInteger(options.maxRecordBytes, DEFAULT_MAX_RECORD_BYTES),
31
+ this.maxStorageBytes
32
+ );
33
+ this.maxAgeMs = nonNegativeFinite(options.maxAgeMs, DEFAULT_MAX_AGE_MS);
34
+ this.maxFutureSkewMs = nonNegativeFinite(options.maxFutureSkewMs, DEFAULT_MAX_FUTURE_SKEW_MS);
35
+ this.now = options.now ?? Date.now;
36
+ }
37
+ /** Isolate writes and acknowledgements from every other live session. */
38
+ forOwner(ownerId) {
39
+ return new _DocumentRecoveryJournal(this.storage, { ...this.options, ownerId });
40
+ }
41
+ /** Consume only the exact recovered snapshot, never a newer draft from its owner. */
42
+ acknowledgeRecord(record) {
43
+ const owner = new _DocumentRecoveryJournal(this.storage, {
44
+ ...this.options,
45
+ ownerId: record.ownerId
46
+ });
47
+ const records = owner.load(this.now()).records;
48
+ const current = records.find((candidate) => candidate.targetKey === record.targetKey);
49
+ if (!current || current.generation !== record.generation || current.revision !== record.revision || current.content !== record.content || current.persistedContent !== record.persistedContent) {
50
+ return false;
51
+ }
52
+ return owner.persistExact(records.filter((candidate) => candidate !== current));
53
+ }
54
+ /**
55
+ * Synchronously persist the latest dirty snapshot for a target.
56
+ * Storage/quota failures are returned, never thrown into an editor onChange.
57
+ */
58
+ write(input) {
59
+ const timestamp = this.now();
60
+ if (!isValidWrite(input) || !Number.isFinite(timestamp) || timestamp < 0) {
61
+ return { status: "rejected", reason: "invalid-record", evicted: 0 };
62
+ }
63
+ if (!this.storage) {
64
+ return { status: "rejected", reason: "storage-unavailable", evicted: 0 };
65
+ }
66
+ if (estimatedBytes(input.content) > this.maxRecordBytes || input.persistedContent !== null && estimatedBytes(input.persistedContent) > this.maxRecordBytes) {
67
+ return { status: "rejected", reason: "record-too-large", evicted: 0 };
68
+ }
69
+ const loaded = this.load(timestamp);
70
+ if (this.options.ownerId && loaded.records.some(
71
+ (record) => record.targetKey !== input.targetKey && record.generation === input.generation && record.revision === input.revision
72
+ )) {
73
+ return { status: "rejected", reason: "invalid-record", evicted: 0 };
74
+ }
75
+ const existing = loaded.records.find((record) => record.targetKey === input.targetKey);
76
+ if (existing) {
77
+ const ordering = compareGenerationRevision(input, existing);
78
+ if (ordering < 0) return { status: "ignored-stale", evicted: 0 };
79
+ if (ordering === 0) {
80
+ if (existing.content === input.content && existing.persistedContent === input.persistedContent) {
81
+ return { status: "unchanged", evicted: 0 };
82
+ }
83
+ return { status: "rejected", reason: "invalid-record", evicted: 0 };
84
+ }
85
+ }
86
+ const candidate = {
87
+ targetKey: input.targetKey,
88
+ generation: input.generation,
89
+ revision: input.revision,
90
+ content: input.content,
91
+ persistedContent: input.persistedContent,
92
+ createdAt: existing?.createdAt ?? timestamp,
93
+ updatedAt: timestamp
94
+ };
95
+ if (estimatedBytes(JSON.stringify(candidate)) > this.maxRecordBytes) {
96
+ return { status: "rejected", reason: "record-too-large", evicted: 0 };
97
+ }
98
+ if (estimatedBytes(serializeEnvelope([candidate])) > this.maxStorageBytes) {
99
+ return { status: "rejected", reason: "record-too-large", evicted: 0 };
100
+ }
101
+ const next = loaded.records.filter((record) => record.targetKey !== input.targetKey);
102
+ next.push(candidate);
103
+ const persisted = this.persistBounded(next, input.targetKey);
104
+ if (!persisted.stored) {
105
+ return {
106
+ status: "rejected",
107
+ reason: persisted.reason ?? "quota-exceeded",
108
+ evicted: persisted.evicted
109
+ };
110
+ }
111
+ return { status: "stored", evicted: persisted.evicted + this.pruneOwners(input.targetKey) };
112
+ }
113
+ pruneOwners(protectedTarget) {
114
+ if (!this.options.ownerId) return 0;
115
+ const records = this.loadAll().sort(compareNewestFirst);
116
+ let bytes = estimatedBytes(JSON.stringify(records));
117
+ let evicted = 0;
118
+ for (let index = records.length - 1; index >= 0 && (records.length > this.maxEntries || bytes > this.maxStorageBytes); index--) {
119
+ const record = records[index];
120
+ if (record.ownerId === this.options.ownerId && record.targetKey === protectedTarget) continue;
121
+ if (!this.acknowledgeRecord(record)) continue;
122
+ bytes -= estimatedBytes(JSON.stringify(record));
123
+ records.splice(index, 1);
124
+ evicted++;
125
+ }
126
+ return evicted;
127
+ }
128
+ /** Return the recoverable snapshot for one target, if present and valid. */
129
+ lookup(targetKey, generation) {
130
+ if (!isValidTargetKey(targetKey) || !isOptionalGeneration(generation)) return null;
131
+ const record = this.list(targetKey).find(
132
+ (candidate) => candidate.targetKey === targetKey && (generation === void 0 || candidate.generation === generation)
133
+ );
134
+ return record ? cloneRecord(record) : null;
135
+ }
136
+ /** List valid records, newest first. Optionally restrict to one target. */
137
+ list(targetKey) {
138
+ if (targetKey !== void 0 && !isValidTargetKey(targetKey)) return [];
139
+ return this.loadAll().filter((record) => targetKey === void 0 || record.targetKey === targetKey).sort(compareNewestFirst).map(cloneRecord);
140
+ }
141
+ loadAll() {
142
+ if (!this.storage) return [];
143
+ const prefix = `${this.baseStorageKey}:owner:`;
144
+ const keys = this.storageKeys();
145
+ const owners = /* @__PURE__ */ new Set([void 0, this.options.ownerId]);
146
+ for (const key of keys) {
147
+ if (!key.startsWith(prefix)) continue;
148
+ const ownerId = key.slice(prefix.length).split(":")[0];
149
+ if (/^[a-zA-Z0-9-]{1,100}$/.test(ownerId)) owners.add(ownerId);
150
+ }
151
+ const records = [];
152
+ for (const ownerId of owners) {
153
+ const journal = new _DocumentRecoveryJournal(this.storage, { ...this.options, ownerId });
154
+ for (const record of journal.load(this.now()).records) {
155
+ records.push({ ...record, ...ownerId ? { ownerId } : {} });
156
+ }
157
+ }
158
+ return records;
159
+ }
160
+ storageKeys() {
161
+ if (!this.storage) return [];
162
+ const keys = /* @__PURE__ */ new Set([this.baseStorageKey, ...knownStorageKeys.get(this.storage) ?? []]);
163
+ try {
164
+ const count = Math.min(this.storage.length ?? 0, MAX_STORAGE_KEYS);
165
+ for (let index = 0; index < count; index++) {
166
+ const key = this.storage.key?.(index);
167
+ if (key?.startsWith(`${this.baseStorageKey}:owner:`)) keys.add(key);
168
+ }
169
+ } catch {
170
+ }
171
+ return [...keys].slice(0, MAX_STORAGE_KEYS);
172
+ }
173
+ /**
174
+ * Clear a record only when the same generation has durably acknowledged at
175
+ * least the journaled revision. A stale acknowledgement cannot erase a newer
176
+ * crash-recovery snapshot.
177
+ */
178
+ acknowledge(input) {
179
+ if (!isValidAcknowledgement(input) || !this.storage) return false;
180
+ const records = this.load(this.now()).records;
181
+ const record = records.find((candidate) => candidate.targetKey === input.targetKey);
182
+ if (!record || record.generation !== input.generation || record.revision > input.persistedRevision) {
183
+ return false;
184
+ }
185
+ return this.persistExact(records.filter((candidate) => candidate !== record));
186
+ }
187
+ /** Explicitly discard recovery data after a user or lifecycle decision. */
188
+ discard(targetKey, generation) {
189
+ if (!isValidTargetKey(targetKey) || !isOptionalGeneration(generation) || !this.storage) {
190
+ return false;
191
+ }
192
+ const records = this.load(this.now()).records;
193
+ const next = records.filter(
194
+ (record) => record.targetKey !== targetKey || generation !== void 0 && record.generation !== generation
195
+ );
196
+ if (next.length === records.length) return false;
197
+ return this.persistExact(next);
198
+ }
199
+ load(timestamp) {
200
+ if (!this.storage) return { records: [], needsRepair: false };
201
+ let raw;
202
+ let readNeedsRepair = false;
203
+ try {
204
+ if (this.options.ownerId) {
205
+ this.loadedKeys = this.storageKeys().filter((key) => key.startsWith(`${this.storageKey}:`));
206
+ const records2 = [];
207
+ for (const key of this.loadedKeys) {
208
+ const item = this.storage.getItem(key);
209
+ if (item === null || estimatedBytes(item) > this.maxRecordBytes) {
210
+ readNeedsRepair = true;
211
+ continue;
212
+ }
213
+ try {
214
+ const record = JSON.parse(item);
215
+ if (isObject(record) && key === `${this.storageKey}:${record.generation}:${record.revision}`)
216
+ records2.push(record);
217
+ else readNeedsRepair = true;
218
+ } catch {
219
+ readNeedsRepair = true;
220
+ }
221
+ }
222
+ raw = JSON.stringify({ schemaVersion: DOCUMENT_RECOVERY_JOURNAL_SCHEMA_VERSION, records: records2 });
223
+ } else {
224
+ raw = this.storage.getItem(this.storageKey);
225
+ }
226
+ } catch {
227
+ return { records: [], needsRepair: false };
228
+ }
229
+ if (raw === null) return { records: [], needsRepair: false };
230
+ let parsed;
231
+ try {
232
+ parsed = JSON.parse(raw);
233
+ } catch {
234
+ this.tryRemove();
235
+ return { records: [], needsRepair: true };
236
+ }
237
+ if (!isEnvelope(parsed)) {
238
+ this.tryRemove();
239
+ return { records: [], needsRepair: true };
240
+ }
241
+ const byTarget = /* @__PURE__ */ new Map();
242
+ let needsRepair = readNeedsRepair || estimatedBytes(raw) > this.maxStorageBytes;
243
+ for (const candidate of parsed.records) {
244
+ if (!isValidStoredRecord(candidate, timestamp, this.maxAgeMs, this.maxFutureSkewMs)) {
245
+ needsRepair = true;
246
+ continue;
247
+ }
248
+ if (estimatedBytes(JSON.stringify(candidate)) > this.maxRecordBytes) {
249
+ needsRepair = true;
250
+ continue;
251
+ }
252
+ const current = byTarget.get(candidate.targetKey);
253
+ if (!current || compareStoredRecords(candidate, current) > 0) {
254
+ if (current) needsRepair = true;
255
+ byTarget.set(candidate.targetKey, cloneRecord(candidate));
256
+ } else {
257
+ needsRepair = true;
258
+ }
259
+ }
260
+ const records = [...byTarget.values()].sort(compareNewestFirst);
261
+ while (records.length > this.maxEntries) {
262
+ records.pop();
263
+ needsRepair = true;
264
+ }
265
+ while (records.length > 0 && estimatedBytes(serializeEnvelope(records)) > this.maxStorageBytes) {
266
+ records.pop();
267
+ needsRepair = true;
268
+ }
269
+ if (needsRepair) {
270
+ this.persistBounded(records);
271
+ }
272
+ return { records, needsRepair };
273
+ }
274
+ persistBounded(records, protectedTarget) {
275
+ if (!this.storage) {
276
+ return { stored: false, evicted: 0, reason: "storage-unavailable" };
277
+ }
278
+ const next = [...records].sort(compareNewestFirst);
279
+ let evicted = 0;
280
+ while (next.length > this.maxEntries) {
281
+ if (!evictOldest(next, protectedTarget)) break;
282
+ evicted += 1;
283
+ }
284
+ let serialized = serializeEnvelope(next);
285
+ while (estimatedBytes(serialized) > this.maxStorageBytes) {
286
+ if (!evictOldest(next, protectedTarget)) {
287
+ return { stored: false, evicted, reason: "quota-exceeded" };
288
+ }
289
+ evicted += 1;
290
+ serialized = serializeEnvelope(next);
291
+ }
292
+ for (; ; ) {
293
+ try {
294
+ if (this.options.ownerId) this.persistOwned(next, protectedTarget);
295
+ else this.storage.setItem(this.storageKey, serialized);
296
+ return { stored: true, evicted };
297
+ } catch {
298
+ if (!evictOldest(next, protectedTarget)) {
299
+ return { stored: false, evicted, reason: "quota-exceeded" };
300
+ }
301
+ evicted += 1;
302
+ serialized = serializeEnvelope(next);
303
+ }
304
+ }
305
+ }
306
+ persistExact(records) {
307
+ if (!this.storage) return false;
308
+ if (this.options.ownerId) {
309
+ try {
310
+ this.persistOwned(records);
311
+ return true;
312
+ } catch {
313
+ return false;
314
+ }
315
+ }
316
+ if (records.length === 0) {
317
+ try {
318
+ this.storage.removeItem(this.storageKey);
319
+ return true;
320
+ } catch {
321
+ return false;
322
+ }
323
+ }
324
+ try {
325
+ this.storage.setItem(this.storageKey, serializeEnvelope(records));
326
+ return true;
327
+ } catch {
328
+ return false;
329
+ }
330
+ }
331
+ /**
332
+ * Each owner/revision is immutable and has its own key. A recovering window
333
+ * may remove that exact key without racing a live owner's newer write.
334
+ * Only explicit writes create records; cleanup never recreates a saved draft.
335
+ */
336
+ persistOwned(records, writtenTarget) {
337
+ if (!this.storage) return;
338
+ const keyFor = (record) => `${this.storageKey}:${record.generation}:${record.revision}`;
339
+ if (writtenTarget !== void 0) {
340
+ const record = records.find((entry) => entry.targetKey === writtenTarget);
341
+ if (record) {
342
+ const key = keyFor(record);
343
+ this.storage.setItem(key, JSON.stringify(record));
344
+ knownStorageKeys.get(this.storage)?.add(key);
345
+ }
346
+ }
347
+ const retained = new Set(records.map(keyFor));
348
+ for (const key of this.loadedKeys) {
349
+ if (retained.has(key)) continue;
350
+ this.storage.removeItem(key);
351
+ knownStorageKeys.get(this.storage)?.delete(key);
352
+ }
353
+ }
354
+ tryRemove() {
355
+ try {
356
+ this.storage?.removeItem(this.storageKey);
357
+ } catch {
358
+ }
359
+ }
360
+ };
361
+ function getDefaultDocumentRecoveryStorage() {
362
+ try {
363
+ const candidate = Reflect.get(globalThis, "localStorage");
364
+ if (!isStorage(candidate)) return null;
365
+ return candidate;
366
+ } catch {
367
+ return null;
368
+ }
369
+ }
370
+ function serializeEnvelope(records) {
371
+ const envelope = {
372
+ schemaVersion: DOCUMENT_RECOVERY_JOURNAL_SCHEMA_VERSION,
373
+ records
374
+ };
375
+ return JSON.stringify(envelope);
376
+ }
377
+ function estimatedBytes(value) {
378
+ return value.length * 2;
379
+ }
380
+ function positiveInteger(value, fallback) {
381
+ return Number.isSafeInteger(value) && (value ?? 0) > 0 ? value : fallback;
382
+ }
383
+ function nonNegativeFinite(value, fallback) {
384
+ return Number.isFinite(value) && (value ?? -1) >= 0 ? value : fallback;
385
+ }
386
+ function isEnvelope(value) {
387
+ if (!isObject(value)) return false;
388
+ return Object.keys(value).every((key) => key === "schemaVersion" || key === "records") && value.schemaVersion === DOCUMENT_RECOVERY_JOURNAL_SCHEMA_VERSION && Array.isArray(value.records);
389
+ }
390
+ function isValidStoredRecord(value, timestamp, maxAgeMs, maxFutureSkewMs) {
391
+ if (!isObject(value)) return false;
392
+ const fields = [
393
+ "targetKey",
394
+ "generation",
395
+ "revision",
396
+ "content",
397
+ "persistedContent",
398
+ "createdAt",
399
+ "updatedAt"
400
+ ];
401
+ if (Object.keys(value).some((key) => !fields.includes(key)) || !isValidTargetKey(value.targetKey) || !isNonNegativeSafeInteger(value.generation) || !isNonNegativeSafeInteger(value.revision) || typeof value.content !== "string" || value.persistedContent !== null && typeof value.persistedContent !== "string" || !isNonNegativeFiniteNumber(value.createdAt) || !isNonNegativeFiniteNumber(value.updatedAt) || value.createdAt > value.updatedAt) {
402
+ return false;
403
+ }
404
+ if (!Number.isFinite(timestamp) || timestamp < 0) return false;
405
+ if (value.updatedAt > timestamp + maxFutureSkewMs) return false;
406
+ return timestamp - value.updatedAt <= maxAgeMs;
407
+ }
408
+ function isValidWrite(value) {
409
+ return isValidTargetKey(value.targetKey) && isNonNegativeSafeInteger(value.generation) && isNonNegativeSafeInteger(value.revision) && typeof value.content === "string" && (value.persistedContent === null || typeof value.persistedContent === "string");
410
+ }
411
+ function isValidAcknowledgement(value) {
412
+ return isValidTargetKey(value.targetKey) && isNonNegativeSafeInteger(value.generation) && isNonNegativeSafeInteger(value.persistedRevision);
413
+ }
414
+ function isValidTargetKey(value) {
415
+ return typeof value === "string" && value.length > 0 && value.length <= MAX_TARGET_KEY_LENGTH;
416
+ }
417
+ function isOptionalGeneration(value) {
418
+ return value === void 0 || isNonNegativeSafeInteger(value);
419
+ }
420
+ function isNonNegativeSafeInteger(value) {
421
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
422
+ }
423
+ function isNonNegativeFiniteNumber(value) {
424
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
425
+ }
426
+ function isObject(value) {
427
+ return typeof value === "object" && value !== null;
428
+ }
429
+ function isStorage(value) {
430
+ if (!isObject(value)) return false;
431
+ return typeof value.getItem === "function" && typeof value.setItem === "function" && typeof value.removeItem === "function";
432
+ }
433
+ function compareGenerationRevision(left, right) {
434
+ if (left.generation !== right.generation) return left.generation - right.generation;
435
+ return left.revision - right.revision;
436
+ }
437
+ function compareStoredRecords(left, right) {
438
+ return compareGenerationRevision(left, right) || left.updatedAt - right.updatedAt;
439
+ }
440
+ function compareNewestFirst(left, right) {
441
+ return right.updatedAt - left.updatedAt || right.revision - left.revision;
442
+ }
443
+ function cloneRecord(record) {
444
+ return { ...record };
445
+ }
446
+ function evictOldest(records, protectedTarget) {
447
+ let oldestIndex = -1;
448
+ for (let index = 0; index < records.length; index += 1) {
449
+ if (records[index].targetKey === protectedTarget) continue;
450
+ if (oldestIndex < 0 || compareNewestFirst(records[index], records[oldestIndex]) > 0) {
451
+ oldestIndex = index;
452
+ }
453
+ }
454
+ if (oldestIndex < 0) return false;
455
+ records.splice(oldestIndex, 1);
456
+ return true;
457
+ }
458
+
459
+ export {
460
+ DOCUMENT_RECOVERY_JOURNAL_STORAGE_KEY,
461
+ DOCUMENT_RECOVERY_JOURNAL_SCHEMA_VERSION,
462
+ DocumentRecoveryJournal,
463
+ getDefaultDocumentRecoveryStorage
464
+ };
@@ -0,0 +1,42 @@
1
+ // src/filesystem/workspace-entry-rules.ts
2
+ var TOOL_MANAGED_FOLDER_NAMES = /* @__PURE__ */ new Set([
3
+ "node_modules",
4
+ "bower_components",
5
+ "__pycache__"
6
+ ]);
7
+ function isIgnoredWorkspaceEntryName(name) {
8
+ return name.startsWith(".") || TOOL_MANAGED_FOLDER_NAMES.has(name.toLowerCase());
9
+ }
10
+ var MARKDOWN_FILE_EXTENSIONS = Object.freeze([
11
+ ".md",
12
+ ".markdown",
13
+ ".mdown"
14
+ ]);
15
+ function isMarkdownFileName(name) {
16
+ const lower = name.toLowerCase();
17
+ return MARKDOWN_FILE_EXTENSIONS.some(
18
+ (extension) => lower.length > extension.length && lower.endsWith(extension)
19
+ );
20
+ }
21
+ function isCompanionDirectoryName(name) {
22
+ return name.endsWith("_files");
23
+ }
24
+ var SQUISQ_RUNTIME_DIRECTORY_NAME = "_squisq";
25
+ function isBrowsableWorkspaceEntry(name, kind) {
26
+ if (isIgnoredWorkspaceEntryName(name)) return false;
27
+ return kind === "file" || !isCompanionDirectoryName(name);
28
+ }
29
+ function isDiscoverableWorkspaceEntry(name, kind) {
30
+ if (!isBrowsableWorkspaceEntry(name, kind)) return false;
31
+ return kind === "file" || name !== SQUISQ_RUNTIME_DIRECTORY_NAME;
32
+ }
33
+
34
+ export {
35
+ isIgnoredWorkspaceEntryName,
36
+ MARKDOWN_FILE_EXTENSIONS,
37
+ isMarkdownFileName,
38
+ isCompanionDirectoryName,
39
+ SQUISQ_RUNTIME_DIRECTORY_NAME,
40
+ isBrowsableWorkspaceEntry,
41
+ isDiscoverableWorkspaceEntry
42
+ };