@lapis-notes/api 0.1.4 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +206 -0
- package/README.md +21 -2
- package/dist/__tests__/fixtures/indexed-mutations.json +6862 -0
- package/dist/__tests__/fixtures/memory-storage.json +309 -0
- package/dist/__tests__/fixtures/native-facade-contract.json +3224 -0
- package/dist/__tests__/fixtures/projection-query.json +195 -0
- package/dist/__tests__/fixtures/projection-values.json +60 -0
- package/dist/__tests__/fixtures/search-preparation.json +1513 -0
- package/dist/__tests__/fixtures/search-retrieval.json +15409 -0
- package/dist/__tests__/fixtures/search-semantic-model.json +3691 -0
- package/dist/__tests__/fixtures/search-semantic-retrieval.json +6603 -0
- package/dist/__tests__/fixtures/search-storage.json +409 -0
- package/dist/__tests__/fixtures/task-projection.json +428 -0
- package/dist/__tests__/indexed-mutation-support.js +262 -0
- package/dist/__tests__/projection-query-support.js +40 -0
- package/dist/__tests__/search-retrieval-support.js +47 -0
- package/dist/app-database-host.d.ts +1 -0
- package/dist/app-shell-plugin-persistence.d.ts +3 -2
- package/dist/app-shell-plugin-persistence.js +37 -3
- package/dist/cache.svelte.d.ts +8 -1
- package/dist/cache.svelte.js +103 -5
- package/dist/command.svelte.js +29 -2
- package/dist/components/editor/editor.css +4 -0
- package/dist/components/editor/editor.svelte +21 -9
- package/dist/components/editor/embedded-editor-surface.js +3 -1
- package/dist/components/editor/inline-title-alignment.d.ts +3 -0
- package/dist/components/editor/inline-title-alignment.js +57 -0
- package/dist/configuration.svelte.d.ts +270 -206
- package/dist/configuration.svelte.js +161 -86
- package/dist/context.svelte.d.ts +21 -3
- package/dist/context.svelte.js +63 -20
- package/dist/diagnostics.d.ts +8 -0
- package/dist/diagnostics.js +6 -0
- package/dist/editor-save-context.d.ts +12 -1
- package/dist/editor-save-context.js +32 -1
- package/dist/editor-view-registry.d.ts +10 -0
- package/dist/editor-view-registry.js +44 -4
- package/dist/editor.svelte.js +128 -37
- package/dist/embed-registry.d.ts +10 -0
- package/dist/embed-registry.js +15 -0
- package/dist/file-editing-failures.d.ts +2 -0
- package/dist/file-editing-failures.js +29 -0
- package/dist/file-editing-native-issues.d.ts +19 -0
- package/dist/file-editing-native-issues.js +65 -0
- package/dist/file-editing-sessions.d.ts +56 -8
- package/dist/file-editing-sessions.js +185 -15
- package/dist/file-manager.d.ts +8 -1
- package/dist/file-manager.js +37 -3
- package/dist/file-state-store.d.ts +5 -0
- package/dist/file-state-store.js +34 -0
- package/dist/file-text-conflicts.d.ts +25 -0
- package/dist/file-text-conflicts.js +35 -0
- package/dist/file-text-mutation.d.ts +13 -0
- package/dist/file-text-mutation.js +100 -0
- package/dist/file-text-persistence.d.ts +36 -0
- package/dist/file-text-persistence.js +234 -0
- package/dist/file-text-state-writer.d.ts +34 -0
- package/dist/file-text-state-writer.js +183 -0
- package/dist/files-configuration.d.ts +20 -0
- package/dist/files-configuration.js +47 -0
- package/dist/generated/plugin-host-modules.schema.generated.d.ts +87 -37
- package/dist/generated/plugin-host-modules.schema.generated.js +102 -37
- package/dist/glob.d.ts +3 -0
- package/dist/glob.js +2 -1
- package/dist/icons/changes.d.ts +3 -0
- package/dist/icons/changes.js +16 -0
- package/dist/icons/index.d.ts +5 -1
- package/dist/icons/index.js +44 -3
- package/dist/icons/registry.d.ts +35 -0
- package/dist/icons/registry.js +154 -0
- package/dist/icons/safe-svg.d.ts +2 -0
- package/dist/icons/safe-svg.js +44 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +3 -1
- package/dist/lapis-extension.d.ts +6 -2
- package/dist/lapis-extension.js +2 -0
- package/dist/metadata.svelte.js +45 -2
- package/dist/native-background-indexing.d.ts +48 -0
- package/dist/native-background-indexing.js +208 -0
- package/dist/native-database-protocol.d.ts +29 -0
- package/dist/native-database-protocol.js +1 -0
- package/dist/native-editing-intent-lease.d.ts +17 -0
- package/dist/native-editing-intent-lease.js +188 -0
- package/dist/native-editing-intents-protocol.d.ts +70 -0
- package/dist/native-editing-intents-protocol.js +1 -0
- package/dist/native-editing-intents.d.ts +8 -0
- package/dist/native-editing-intents.js +1 -0
- package/dist/native-editing-problems.d.ts +3 -0
- package/dist/native-editing-problems.js +180 -0
- package/dist/native-editing-recovery.d.ts +24 -0
- package/dist/native-editing-recovery.js +198 -0
- package/dist/native-editing-session.d.ts +51 -0
- package/dist/native-editing-session.js +251 -0
- package/dist/native-history-index-protocol.d.ts +80 -0
- package/dist/native-history-index-protocol.js +1 -0
- package/dist/native-history-index.d.ts +6 -0
- package/dist/native-history-index.js +1 -0
- package/dist/native-indexing-protocol.d.ts +63 -0
- package/dist/native-indexing-protocol.js +1 -0
- package/dist/native-participant-protocol.d.ts +67 -0
- package/dist/native-participant-protocol.js +3 -0
- package/dist/native-queue-protocol.d.ts +73 -0
- package/dist/native-queue-protocol.js +3 -0
- package/dist/native-tasks-protocol.d.ts +264 -0
- package/dist/native-tasks-protocol.js +1 -0
- package/dist/native-tasks.d.ts +35 -0
- package/dist/native-tasks.js +79 -0
- package/dist/native-turn-protocol.d.ts +81 -0
- package/dist/native-turn-protocol.js +1 -0
- package/dist/native-turns.d.ts +29 -0
- package/dist/native-turns.js +2 -0
- package/dist/plugin-asset-server.js +3 -2
- package/dist/plugin-dependency-resolver.d.ts +1 -1
- package/dist/plugin-distribution/compatibility.d.ts +1 -1
- package/dist/plugin-distribution/compatibility.js +10 -5
- package/dist/plugin-distribution/installed-plugin-state.js +2 -1
- package/dist/plugin-distribution/installer.d.ts +6 -0
- package/dist/plugin-distribution/installer.js +90 -37
- package/dist/plugin-distribution/manager.d.ts +4 -1
- package/dist/plugin-distribution/manager.js +12 -5
- package/dist/plugin-distribution/registry-cache.js +2 -1
- package/dist/plugin-distribution/registry-source-state.js +2 -1
- package/dist/plugin-distribution/schemas.d.ts +26 -8
- package/dist/plugin-distribution/schemas.js +2 -1
- package/dist/plugin-distribution/types.d.ts +4 -0
- package/dist/plugin-manager.d.ts +20 -4
- package/dist/plugin-manager.js +228 -64
- package/dist/plugin-runtime-entry.d.ts +1 -1
- package/dist/plugin-runtime-entry.js +16 -0
- package/dist/plugin.d.ts +18 -2
- package/dist/plugin.js +93 -39
- package/dist/registry-schema/catalog-v1.d.ts +60 -9
- package/dist/registry-schema/catalog-v1.js +2 -1
- package/dist/registry-schema/catalog-v2.d.ts +60 -9
- package/dist/registry-schema/catalog-v2.js +1 -1
- package/dist/search-result-provider.d.ts +95 -0
- package/dist/search-result-provider.js +42 -0
- package/dist/status-bar.svelte.d.ts +26 -20
- package/dist/status-bar.svelte.js +1 -0
- package/dist/storage/app-database.d.ts +6 -2
- package/dist/storage/app-database.js +41 -34
- package/dist/storage/desktop-native.d.ts +5 -3
- package/dist/storage/desktop-native.js +59 -6
- package/dist/storage/directory-watcher.d.ts +27 -0
- package/dist/storage/directory-watcher.js +201 -0
- package/dist/storage/fs.d.ts +14 -27
- package/dist/storage/fs.js +2 -168
- package/dist/storage/index-projection.js +33 -15
- package/dist/storage/memory-vault-adapter.d.ts +2 -0
- package/dist/storage/memory-vault-adapter.js +14 -1
- package/dist/storage/path.d.ts +6 -2
- package/dist/storage/path.js +8 -2
- package/dist/storage/projection-query-candidates.d.ts +3 -0
- package/dist/storage/projection-query-candidates.js +69 -0
- package/dist/storage/remote-app-database.d.ts +2 -2
- package/dist/storage/remote-app-database.js +1 -1
- package/dist/storage/runtime.d.ts +3 -0
- package/dist/storage/runtime.js +3 -0
- package/dist/storage/search-embedding-record.d.ts +3 -0
- package/dist/storage/search-embedding-record.js +18 -0
- package/dist/storage/turso-app-database.d.ts +2 -0
- package/dist/storage/turso-app-database.js +67 -30
- package/dist/storage/vault-listing.d.ts +3 -0
- package/dist/storage/vault-listing.js +36 -0
- package/dist/storage/vault-reconciliation.d.ts +19 -0
- package/dist/storage/vault-reconciliation.js +137 -0
- package/dist/storage/vault-session.d.ts +8 -0
- package/dist/storage/vault-session.js +10 -2
- package/dist/storage/vault.svelte.d.ts +53 -4
- package/dist/storage/vault.svelte.js +223 -87
- package/dist/sync-host.d.ts +12 -3
- package/dist/sync-host.js +5 -1
- package/dist/vault-change-views.d.ts +4 -0
- package/dist/vault-change-views.js +43 -0
- package/dist/vault-changes.d.ts +37 -0
- package/dist/vault-changes.js +228 -0
- package/dist/view.svelte.d.ts +182 -149
- package/dist/view.svelte.js +11 -2
- package/dist/workspace-close-guard.d.ts +3 -0
- package/dist/workspace-close-guard.js +35 -0
- package/dist/workspace-host-internal.js +10 -2
- package/dist/workspace-layout-normalizer.d.ts +4 -2
- package/dist/workspace-layout-normalizer.js +5 -5
- package/dist/workspace-view-document.d.ts +3 -0
- package/dist/workspace-view-document.js +12 -0
- package/dist/workspace.svelte.d.ts +13 -2
- package/dist/workspace.svelte.js +371 -82
- package/package.json +45 -8
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { rebindSearchDocument } from "./search-embedding-record";
|
|
1
2
|
import { canCollectSearchQueryPropertyNames, canCollectSearchQueryTerms, collectSearchQueryPropertyNames, collectSearchQueryTerms, parseSearchQueryAst, } from "../search-query";
|
|
2
3
|
import { cosineSimilarity, createSearchEmbeddingProvider, } from "./search-embedding-provider";
|
|
3
4
|
import { evaluateSearchQueryForDocument, findSearchQueryRangesInText, isStructuredSearchQuery, } from "./search-query-evaluator";
|
|
4
5
|
import { assertProjectionReadAccess, assertProjectionWriteAccess, evaluateProjectionQuery, indexedValuesForRow, MAX_PROJECTION_ROWS_PER_SOURCE, projectionIndexStatus, PUBLIC_TASKS_PROJECTION_ID, sourceIsCurrent, } from "./index-projection";
|
|
5
6
|
import { taskQueryToIndexQuery, TASK_PROJECTION_FIELDS, TASK_PROJECTION_VERSION, } from "./task-projection";
|
|
7
|
+
export { isNativeDesktopRuntime } from "./runtime";
|
|
6
8
|
export function supportsSearchQueryEnhancementRuntime(runtimeTarget) {
|
|
7
9
|
return runtimeTarget === "deno-desktop";
|
|
8
10
|
}
|
|
@@ -245,7 +247,16 @@ function buildSearchChunks(path, content, metadata) {
|
|
|
245
247
|
const chunkEnd = remaining > metadata.chunking.targetChars
|
|
246
248
|
? findBestCutoff(breakPoints, chunkStart, targetEnd, metadata.chunking.breakpointWindowChars, metadata.chunking.breakpointDecay, codeFences)
|
|
247
249
|
: content.length;
|
|
248
|
-
|
|
250
|
+
let safeEnd = chunkEnd > chunkStart ? chunkEnd : targetEnd;
|
|
251
|
+
// Search offsets use UTF-16, but chunks must remain complete Unicode text.
|
|
252
|
+
if (safeEnd > 0 &&
|
|
253
|
+
safeEnd < content.length &&
|
|
254
|
+
content.charCodeAt(safeEnd - 1) >= 0xd800 &&
|
|
255
|
+
content.charCodeAt(safeEnd - 1) <= 0xdbff &&
|
|
256
|
+
content.charCodeAt(safeEnd) >= 0xdc00 &&
|
|
257
|
+
content.charCodeAt(safeEnd) <= 0xdfff) {
|
|
258
|
+
safeEnd += 1;
|
|
259
|
+
}
|
|
249
260
|
const chunk = createChunk(path, content, metadata, chunkStart, safeEnd);
|
|
250
261
|
if (!chunk) {
|
|
251
262
|
if (safeEnd <= chunkStart) {
|
|
@@ -554,6 +565,18 @@ function renameChunkId(chunkId, oldPath, newPath) {
|
|
|
554
565
|
}
|
|
555
566
|
return `${newPath}${chunkId.slice(oldPath.length)}`;
|
|
556
567
|
}
|
|
568
|
+
function searchSnippetBounds(text, start, end) {
|
|
569
|
+
const splitsPair = (offset) => offset > 0 &&
|
|
570
|
+
offset < text.length &&
|
|
571
|
+
text.charCodeAt(offset - 1) >= 0xd800 &&
|
|
572
|
+
text.charCodeAt(offset - 1) <= 0xdbff &&
|
|
573
|
+
text.charCodeAt(offset) >= 0xdc00 &&
|
|
574
|
+
text.charCodeAt(offset) <= 0xdfff;
|
|
575
|
+
return [
|
|
576
|
+
splitsPair(start) ? start - 1 : start,
|
|
577
|
+
splitsPair(end) ? end + 1 : end,
|
|
578
|
+
];
|
|
579
|
+
}
|
|
557
580
|
function buildFieldSnippet(field, text, ranges, snippetLength) {
|
|
558
581
|
if (!ranges.length || !text.length)
|
|
559
582
|
return [];
|
|
@@ -569,8 +592,9 @@ function buildFieldSnippet(field, text, ranges, snippetLength) {
|
|
|
569
592
|
}
|
|
570
593
|
const focus = ranges[0];
|
|
571
594
|
const padding = Math.max(16, Math.floor(snippetLength / 3));
|
|
572
|
-
const
|
|
573
|
-
const
|
|
595
|
+
const initialStart = Math.max(0, focus.start - padding);
|
|
596
|
+
const initialEnd = Math.min(text.length, Math.max(initialStart + snippetLength, focus.end + padding));
|
|
597
|
+
const [start, end] = searchSnippetBounds(text, initialStart, initialEnd);
|
|
574
598
|
return [
|
|
575
599
|
{
|
|
576
600
|
field,
|
|
@@ -612,8 +636,9 @@ function buildContentSnippets(text, ranges, snippetLength) {
|
|
|
612
636
|
return { ...snippet, ranges };
|
|
613
637
|
}
|
|
614
638
|
const focus = ranges[0];
|
|
615
|
-
const
|
|
616
|
-
const
|
|
639
|
+
const initialStart = Math.max(0, focus.start - Math.floor(snippetLength / 3));
|
|
640
|
+
const initialEnd = Math.min(snippet.text.length, Math.max(initialStart + snippetLength, focus.end + Math.floor(snippetLength / 3)));
|
|
641
|
+
const [start, end] = searchSnippetBounds(snippet.text, initialStart, initialEnd);
|
|
617
642
|
return {
|
|
618
643
|
field: "content",
|
|
619
644
|
text: snippet.text.slice(start, end),
|
|
@@ -1335,7 +1360,7 @@ export class MemoryAppDatabase {
|
|
|
1335
1360
|
...clone(input.patch),
|
|
1336
1361
|
ownerId: input.patch.status === "running" ? existing.ownerId : undefined,
|
|
1337
1362
|
leaseUntil: input.patch.status === "running"
|
|
1338
|
-
? input.patch.leaseUntil ?? existing.leaseUntil
|
|
1363
|
+
? (input.patch.leaseUntil ?? existing.leaseUntil)
|
|
1339
1364
|
: undefined,
|
|
1340
1365
|
};
|
|
1341
1366
|
this.memoryJobs.set(updated.id, updated);
|
|
@@ -1898,13 +1923,15 @@ export class MemoryAppDatabase {
|
|
|
1898
1923
|
const targetProjection = query.direction === "in"
|
|
1899
1924
|
? edge.projectionId
|
|
1900
1925
|
: (edge.targetProjectionId ?? query.projectionId);
|
|
1926
|
+
const targetDefinition = this.projections.get(targetProjection);
|
|
1927
|
+
assertProjectionReadAccess(targetDefinition, readerPluginId);
|
|
1901
1928
|
const row = query.direction === "in"
|
|
1902
1929
|
? this.projectionRows.get(this.projectionRowKey(targetProjection, edge.sourceRowId))
|
|
1903
1930
|
: edge.targetRowId
|
|
1904
1931
|
? this.projectionRows.get(this.projectionRowKey(targetProjection, edge.targetRowId))
|
|
1905
1932
|
: [...this.projectionRows.values()].find((candidate) => candidate.projectionId === targetProjection &&
|
|
1906
1933
|
candidate.sourcePath === edge.targetPath);
|
|
1907
|
-
if (!row)
|
|
1934
|
+
if (!row || !this.currentProjectionData(row, targetDefinition))
|
|
1908
1935
|
continue;
|
|
1909
1936
|
if (query.targetWhere &&
|
|
1910
1937
|
!evaluateProjectionQuery([row], { where: query.targetWhere }, 0, "ready").rows.length) {
|
|
@@ -2103,28 +2130,7 @@ export class MemoryAppDatabase {
|
|
|
2103
2130
|
}
|
|
2104
2131
|
}
|
|
2105
2132
|
rebindSearchDocumentForProvider(document) {
|
|
2106
|
-
|
|
2107
|
-
if (!provider || !document.chunks?.length) {
|
|
2108
|
-
return clone(document);
|
|
2109
|
-
}
|
|
2110
|
-
return {
|
|
2111
|
-
...clone(document),
|
|
2112
|
-
chunks: document.chunks.map((chunk) => {
|
|
2113
|
-
if (!chunk.text.trim().length) {
|
|
2114
|
-
return clone(chunk);
|
|
2115
|
-
}
|
|
2116
|
-
return {
|
|
2117
|
-
...clone(chunk),
|
|
2118
|
-
embedding: {
|
|
2119
|
-
status: "pending",
|
|
2120
|
-
modelId: provider.config.modelId ?? "lapis/token-hash-v0",
|
|
2121
|
-
modelVersion: provider.config.modelVersion,
|
|
2122
|
-
dimensions: provider.config.dimensions,
|
|
2123
|
-
dirty: true,
|
|
2124
|
-
},
|
|
2125
|
-
};
|
|
2126
|
-
}),
|
|
2127
|
-
};
|
|
2133
|
+
return rebindSearchDocument(document, this.searchEmbeddingProvider?.config ?? null);
|
|
2128
2134
|
}
|
|
2129
2135
|
toState() {
|
|
2130
2136
|
return {
|
|
@@ -2154,9 +2160,7 @@ export class MemoryAppDatabase {
|
|
|
2154
2160
|
projectionRevision: this.projectionRevision,
|
|
2155
2161
|
memorySources: [...this.memorySources.values()].map((value) => clone(value)),
|
|
2156
2162
|
memoryCandidates: [...this.memoryCandidates.values()].map((value) => clone(value)),
|
|
2157
|
-
memoryCandidateOrigins: [
|
|
2158
|
-
...this.memoryCandidateOrigins.values(),
|
|
2159
|
-
].flatMap((origins) => origins.map((origin) => clone(origin))),
|
|
2163
|
+
memoryCandidateOrigins: [...this.memoryCandidateOrigins.values()].flatMap((origins) => origins.map((origin) => clone(origin))),
|
|
2160
2164
|
memoryRecallSignals: [...this.memoryRecallSignals.values()].map((value) => clone(value)),
|
|
2161
2165
|
memoryJobs: [...this.memoryJobs.values()].map((value) => clone(value)),
|
|
2162
2166
|
};
|
|
@@ -2252,6 +2256,9 @@ export class MemoryAppDatabase {
|
|
|
2252
2256
|
errorChunkCount += 1;
|
|
2253
2257
|
lastError ??= embedding.error ?? null;
|
|
2254
2258
|
break;
|
|
2259
|
+
default:
|
|
2260
|
+
pendingChunkCount += 1;
|
|
2261
|
+
break;
|
|
2255
2262
|
}
|
|
2256
2263
|
}
|
|
2257
2264
|
return {
|
|
@@ -2286,7 +2293,7 @@ export class MemoryAppDatabase {
|
|
|
2286
2293
|
this.searchIndexStats.readyChunkCount += stats.readyChunkCount;
|
|
2287
2294
|
this.searchIndexStats.pendingChunkCount += stats.pendingChunkCount;
|
|
2288
2295
|
this.searchIndexStats.errorChunkCount += stats.errorChunkCount;
|
|
2289
|
-
if (stats.lastError) {
|
|
2296
|
+
if (stats.lastError !== null) {
|
|
2290
2297
|
this.searchIndexStats.lastError = stats.lastError;
|
|
2291
2298
|
this.searchIndexLastErrorPath = path;
|
|
2292
2299
|
}
|
|
@@ -2301,7 +2308,7 @@ export class MemoryAppDatabase {
|
|
|
2301
2308
|
this.searchIndexStats.lastError = null;
|
|
2302
2309
|
this.searchIndexLastErrorPath = null;
|
|
2303
2310
|
for (const [nextPath, nextStats] of this.searchIndexStatsByPath) {
|
|
2304
|
-
if (nextPath === path ||
|
|
2311
|
+
if (nextPath === path || nextStats.lastError === null) {
|
|
2305
2312
|
continue;
|
|
2306
2313
|
}
|
|
2307
2314
|
this.searchIndexStats.lastError = nextStats.lastError;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import type { AppDatabaseChangeSet, AppDatabaseNotificationSeverity } from "./app-database";
|
|
9
9
|
import type { ChangeEvent, AsyncResourceAdapter, DataWriteOptions, ListedFiles, NativeWatchAdapter, NativeWatchSubscription, Stat, VaultAdapter, VaultAdapterCapabilities, VaultReadHandle, AtomicDataWriteOptions, VaultIdentityAdapter, WatchErrorEvent, WatchOptions } from "./fs";
|
|
10
10
|
import { type KeyValueStore, type VaultProfile } from "./vault-state";
|
|
11
|
-
export type NativeDesktopRuntime = "deno-desktop";
|
|
11
|
+
export type NativeDesktopRuntime = "deno-desktop" | "tauri-desktop";
|
|
12
12
|
export type NativeDesktopPlatformOs = "macos" | "windows" | "linux" | "unknown";
|
|
13
13
|
export interface NativeDesktopPlatformInfo {
|
|
14
14
|
readonly runtime: NativeDesktopRuntime;
|
|
@@ -18,7 +18,7 @@ export interface NativeDesktopPlatformInfo {
|
|
|
18
18
|
readonly appVersion?: string;
|
|
19
19
|
readonly packaged?: boolean;
|
|
20
20
|
}
|
|
21
|
-
export type NativeDesktopCapabilityId = "resource" | "database" | "search" | "notebook" | "language-service" | "model" | "plugin-sidecar" | "plugin-assets" | "file-watch" | "notifications" | "file-system-actions" | "nostr-signer" | "agent-runtime" | "terminal-runtime" | "secure-storage";
|
|
21
|
+
export type NativeDesktopCapabilityId = "system-trash" | "exclusive-create" | "conditional-text-write" | "resource" | "database" | "search" | "notebook" | "language-service" | "model" | "plugin-sidecar" | "plugin-assets" | "file-watch" | "notifications" | "file-system-actions" | "nostr-signer" | "agent-runtime" | "terminal-runtime" | "secure-storage";
|
|
22
22
|
export type NativeAgentProcessMessage = {
|
|
23
23
|
processId: string;
|
|
24
24
|
type: "stdout" | "stderr" | "exit";
|
|
@@ -151,8 +151,10 @@ export declare class NativeDesktopVaultAdapter implements VaultAdapter, VaultIde
|
|
|
151
151
|
stat(normalizedPath: string): Promise<Stat | null>;
|
|
152
152
|
read(normalizedPath: string): Promise<string>;
|
|
153
153
|
readBinary(normalizedPath: string): Promise<ArrayBuffer>;
|
|
154
|
+
writeExclusive(normalizedPath: string, data: string | ArrayBuffer, options?: DataWriteOptions): Promise<void>;
|
|
154
155
|
openRead(normalizedPath: string): Promise<VaultReadHandle>;
|
|
155
156
|
atomicWrite(normalizedPath: string, source: ReadableStream<Uint8Array>, options?: AtomicDataWriteOptions): Promise<void>;
|
|
157
|
+
writeTextIfUnchanged(normalizedPath: string, data: string, expected: string | null, options?: DataWriteOptions): Promise<void>;
|
|
156
158
|
write(normalizedPath: string, data: string, options?: DataWriteOptions): Promise<void>;
|
|
157
159
|
writeBinary(normalizedPath: string, data: ArrayBuffer, options?: DataWriteOptions): Promise<void>;
|
|
158
160
|
append(normalizedPath: string, data: string, options?: DataWriteOptions): Promise<void>;
|
|
@@ -169,7 +171,7 @@ export declare class NativeDesktopVaultAdapter implements VaultAdapter, VaultIde
|
|
|
169
171
|
copy(normalizedPath: string, normalizedNewPath: string): Promise<void>;
|
|
170
172
|
getResourcePath(normalizedPath: string): string;
|
|
171
173
|
getResourceUrl(normalizedPath: string): Promise<string>;
|
|
172
|
-
trashSystem(): Promise<boolean>;
|
|
174
|
+
trashSystem(normalizedPath: string): Promise<boolean>;
|
|
173
175
|
trashLocal(normalizedPath: string): Promise<void>;
|
|
174
176
|
}
|
|
175
177
|
export declare function pickNativeDesktopVault(options?: NativeVaultOptions): Promise<{
|
|
@@ -237,13 +237,15 @@ export class NativeDesktopVaultAdapter {
|
|
|
237
237
|
}
|
|
238
238
|
getCapabilities() {
|
|
239
239
|
return {
|
|
240
|
+
exclusiveCreate: hasNativeDesktopCapability("exclusive-create"),
|
|
241
|
+
conditionalTextWrite: hasNativeDesktopCapability("conditional-text-write"),
|
|
240
242
|
persistent: true,
|
|
241
243
|
userVisibleFiles: true,
|
|
242
244
|
requiresPermission: false,
|
|
243
245
|
nativeWatch: hasNativeDesktopCapability("file-watch") ||
|
|
244
246
|
typeof getNativeDesktopBridge()?.watch === "function",
|
|
245
247
|
resourceUrls: true,
|
|
246
|
-
systemTrash:
|
|
248
|
+
systemTrash: hasNativeDesktopCapability("system-trash"),
|
|
247
249
|
};
|
|
248
250
|
}
|
|
249
251
|
watch(normalizedPath, options, listener) {
|
|
@@ -251,9 +253,15 @@ export class NativeDesktopVaultAdapter {
|
|
|
251
253
|
const subscriptions = normalizedPath
|
|
252
254
|
.map((path) => this.watch(path, options, listener))
|
|
253
255
|
.filter((subscription) => Boolean(subscription));
|
|
256
|
+
const ready = Promise.all(subscriptions.map((subscription) => subscription.ready)).then(() => { });
|
|
257
|
+
void ready.catch(() => { });
|
|
254
258
|
return {
|
|
255
|
-
|
|
256
|
-
|
|
259
|
+
ready,
|
|
260
|
+
close: async () => {
|
|
261
|
+
const results = await Promise.allSettled(subscriptions.map(async (subscription) => subscription.close()));
|
|
262
|
+
const failed = results.find((result) => result.status === "rejected");
|
|
263
|
+
if (failed?.status === "rejected")
|
|
264
|
+
throw failed.reason;
|
|
257
265
|
},
|
|
258
266
|
};
|
|
259
267
|
}
|
|
@@ -284,6 +292,20 @@ export class NativeDesktopVaultAdapter {
|
|
|
284
292
|
});
|
|
285
293
|
return new Uint8Array(data).buffer;
|
|
286
294
|
}
|
|
295
|
+
async writeExclusive(normalizedPath, data, options = {}) {
|
|
296
|
+
const path = normalizeVaultPath(normalizedPath);
|
|
297
|
+
if (!hasNativeDesktopCapability("exclusive-create"))
|
|
298
|
+
throw createFsError("ENOTSUP", "Exclusive file creation is unavailable");
|
|
299
|
+
const bytes = typeof data === "string"
|
|
300
|
+
? new TextEncoder().encode(data)
|
|
301
|
+
: new Uint8Array(data);
|
|
302
|
+
await invokeNative("desktop_fs_create_exclusive", {
|
|
303
|
+
rootPath: this.rootPath,
|
|
304
|
+
normalizedPath: path,
|
|
305
|
+
data: [...bytes],
|
|
306
|
+
options,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
287
309
|
async openRead(normalizedPath) {
|
|
288
310
|
const path = normalizeVaultPath(normalizedPath);
|
|
289
311
|
const rootPath = this.rootPath;
|
|
@@ -335,7 +357,7 @@ export class NativeDesktopVaultAdapter {
|
|
|
335
357
|
try {
|
|
336
358
|
while (true) {
|
|
337
359
|
if (options.signal?.aborted) {
|
|
338
|
-
throw options.signal.reason ?? new DOMException("Aborted", "AbortError");
|
|
360
|
+
throw (options.signal.reason ?? new DOMException("Aborted", "AbortError"));
|
|
339
361
|
}
|
|
340
362
|
const next = await reader.read();
|
|
341
363
|
if (next.done)
|
|
@@ -365,6 +387,19 @@ export class NativeDesktopVaultAdapter {
|
|
|
365
387
|
reader.releaseLock();
|
|
366
388
|
}
|
|
367
389
|
}
|
|
390
|
+
async writeTextIfUnchanged(normalizedPath, data, expected, options) {
|
|
391
|
+
if (expected !== null && typeof expected !== "string")
|
|
392
|
+
throw new Error("Invalid expected text snapshot");
|
|
393
|
+
if (!hasNativeDesktopCapability("conditional-text-write"))
|
|
394
|
+
throw new Error("Conditional text writes are unavailable in this native host");
|
|
395
|
+
await invokeNative("desktop_fs_write_text_if_unchanged", {
|
|
396
|
+
rootPath: this.rootPath,
|
|
397
|
+
normalizedPath: normalizeVaultPath(normalizedPath),
|
|
398
|
+
data,
|
|
399
|
+
expected,
|
|
400
|
+
options,
|
|
401
|
+
});
|
|
402
|
+
}
|
|
368
403
|
async write(normalizedPath, data, options) {
|
|
369
404
|
await invokeNative("desktop_fs_write_text", {
|
|
370
405
|
rootPath: this.rootPath,
|
|
@@ -458,8 +493,26 @@ export class NativeDesktopVaultAdapter {
|
|
|
458
493
|
}
|
|
459
494
|
return this.getResourcePath(normalizedPath);
|
|
460
495
|
}
|
|
461
|
-
async trashSystem() {
|
|
462
|
-
|
|
496
|
+
async trashSystem(normalizedPath) {
|
|
497
|
+
const path = normalizeVaultPath(normalizedPath);
|
|
498
|
+
if (path === "/")
|
|
499
|
+
throw createFsError("EINVAL", "Cannot trash the vault root");
|
|
500
|
+
if (!hasNativeDesktopCapability("system-trash"))
|
|
501
|
+
return false;
|
|
502
|
+
try {
|
|
503
|
+
const handled = await invokeNative("desktop_fs_trash_system", {
|
|
504
|
+
rootPath: this.rootPath,
|
|
505
|
+
normalizedPath: path,
|
|
506
|
+
});
|
|
507
|
+
if (typeof handled !== "boolean")
|
|
508
|
+
throw createFsError("EINVAL", "Invalid native trash acknowledgement");
|
|
509
|
+
return handled;
|
|
510
|
+
}
|
|
511
|
+
catch (error) {
|
|
512
|
+
if (error?.code === "ENOTSUP")
|
|
513
|
+
return false;
|
|
514
|
+
throw error;
|
|
515
|
+
}
|
|
463
516
|
}
|
|
464
517
|
async trashLocal(normalizedPath) {
|
|
465
518
|
const path = normalizeVaultPath(normalizedPath);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { EventDispatcher } from "../events";
|
|
2
|
+
import type { ChangeEvent, DataAdapter, NativeWatchSubscription, WatchErrorEvent, WatchOptions } from "./fs";
|
|
3
|
+
export declare class DirectoryWatcher extends EventDispatcher<{
|
|
4
|
+
error: [{
|
|
5
|
+
error: unknown;
|
|
6
|
+
path: string;
|
|
7
|
+
}];
|
|
8
|
+
all: [event: ChangeEvent | WatchErrorEvent];
|
|
9
|
+
create: [path: string];
|
|
10
|
+
modify: [path: string];
|
|
11
|
+
delete: [path: string];
|
|
12
|
+
}> {
|
|
13
|
+
readonly adapter: DataAdapter;
|
|
14
|
+
readonly pollingInterval: number;
|
|
15
|
+
private watchers;
|
|
16
|
+
private retired;
|
|
17
|
+
constructor(adapter: DataAdapter, pollingInterval?: number);
|
|
18
|
+
watch(path: string | string[], options?: WatchOptions): NativeWatchSubscription;
|
|
19
|
+
unwatch(path: string): Promise<void>;
|
|
20
|
+
close(): Promise<void>;
|
|
21
|
+
private live;
|
|
22
|
+
private retire;
|
|
23
|
+
private deliver;
|
|
24
|
+
private eventPath;
|
|
25
|
+
private snapshot;
|
|
26
|
+
private poll;
|
|
27
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { EventDispatcher } from "../events";
|
|
2
|
+
import { joinPath, normalizePath } from "./path";
|
|
3
|
+
async function drain(operations) {
|
|
4
|
+
const results = await Promise.allSettled(operations);
|
|
5
|
+
const failed = results.find((result) => result.status === "rejected");
|
|
6
|
+
if (failed?.status === "rejected")
|
|
7
|
+
throw failed.reason;
|
|
8
|
+
}
|
|
9
|
+
export class DirectoryWatcher extends EventDispatcher {
|
|
10
|
+
adapter;
|
|
11
|
+
pollingInterval;
|
|
12
|
+
watchers = new Map();
|
|
13
|
+
retired = new Set();
|
|
14
|
+
constructor(adapter, pollingInterval = 5000) {
|
|
15
|
+
super();
|
|
16
|
+
this.adapter = adapter;
|
|
17
|
+
this.pollingInterval = pollingInterval;
|
|
18
|
+
}
|
|
19
|
+
watch(path, options = {}) {
|
|
20
|
+
if (Array.isArray(path)) {
|
|
21
|
+
const subscriptions = path.map((entry) => this.watch(entry, options));
|
|
22
|
+
const ready = Promise.all(subscriptions.map((entry) => entry.ready)).then(() => { });
|
|
23
|
+
void ready.catch(() => { });
|
|
24
|
+
return {
|
|
25
|
+
ready,
|
|
26
|
+
close: () => drain(subscriptions.map(async (entry) => entry.close())),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
path = normalizePath(path);
|
|
30
|
+
const previous = this.watchers.get(path);
|
|
31
|
+
if (previous)
|
|
32
|
+
void this.retire(previous).catch(() => { });
|
|
33
|
+
const state = {
|
|
34
|
+
path,
|
|
35
|
+
recursive: options.recursive ?? false,
|
|
36
|
+
interval: options.interval ?? this.pollingInterval,
|
|
37
|
+
active: true,
|
|
38
|
+
registering: false,
|
|
39
|
+
snapshot: null,
|
|
40
|
+
timeout: null,
|
|
41
|
+
native: null,
|
|
42
|
+
pending: Promise.resolve(),
|
|
43
|
+
};
|
|
44
|
+
this.watchers.set(path, state);
|
|
45
|
+
let ready = Promise.resolve();
|
|
46
|
+
const adapter = this.adapter;
|
|
47
|
+
if (typeof adapter.watch === "function" &&
|
|
48
|
+
adapter.getCapabilities?.().nativeWatch === true) {
|
|
49
|
+
state.registering = true;
|
|
50
|
+
try {
|
|
51
|
+
state.native =
|
|
52
|
+
adapter.watch(path, options, (event) => {
|
|
53
|
+
if (!this.live(state))
|
|
54
|
+
return;
|
|
55
|
+
this.deliver(event.type === "error"
|
|
56
|
+
? { ...event, path: this.eventPath(event.path) }
|
|
57
|
+
: {
|
|
58
|
+
...event,
|
|
59
|
+
path: this.eventPath(event.path),
|
|
60
|
+
...(event.previousPath === undefined
|
|
61
|
+
? {}
|
|
62
|
+
: { previousPath: this.eventPath(event.previousPath) }),
|
|
63
|
+
});
|
|
64
|
+
}) ?? null;
|
|
65
|
+
ready = state.native?.ready ?? ready;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
state.active = false;
|
|
69
|
+
if (this.watchers.get(path) === state)
|
|
70
|
+
this.watchers.delete(path);
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
state.registering = false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
state.pending = this.poll(state);
|
|
79
|
+
ready = state.pending;
|
|
80
|
+
}
|
|
81
|
+
void ready.catch(() => { });
|
|
82
|
+
return { ready, close: () => this.retire(state) };
|
|
83
|
+
}
|
|
84
|
+
unwatch(path) {
|
|
85
|
+
path = normalizePath(path);
|
|
86
|
+
return drain([...new Set([...this.watchers.values(), ...this.retired])]
|
|
87
|
+
.filter((state) => state.path === path)
|
|
88
|
+
.map((state) => this.retire(state)));
|
|
89
|
+
}
|
|
90
|
+
close() {
|
|
91
|
+
return drain([...new Set([...this.watchers.values(), ...this.retired])].map((state) => this.retire(state)));
|
|
92
|
+
}
|
|
93
|
+
live(state) {
|
|
94
|
+
return state.active && this.watchers.get(state.path) === state;
|
|
95
|
+
}
|
|
96
|
+
retire(state) {
|
|
97
|
+
state.active = false;
|
|
98
|
+
if (this.watchers.get(state.path) === state)
|
|
99
|
+
this.watchers.delete(state.path);
|
|
100
|
+
if (state.timeout)
|
|
101
|
+
clearTimeout(state.timeout);
|
|
102
|
+
state.timeout = null;
|
|
103
|
+
if (state.closing)
|
|
104
|
+
return state.closing;
|
|
105
|
+
this.retired.add(state);
|
|
106
|
+
let cleanup;
|
|
107
|
+
try {
|
|
108
|
+
cleanup = state.registering
|
|
109
|
+
? Promise.resolve().then(() => state.native?.close())
|
|
110
|
+
: state.native?.close();
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
cleanup = Promise.reject(error);
|
|
114
|
+
}
|
|
115
|
+
state.closing = drain([state.pending, cleanup]).then(() => {
|
|
116
|
+
this.retired.delete(state);
|
|
117
|
+
});
|
|
118
|
+
void state.closing.catch(() => {
|
|
119
|
+
state.closing = undefined;
|
|
120
|
+
});
|
|
121
|
+
return state.closing;
|
|
122
|
+
}
|
|
123
|
+
deliver(event) {
|
|
124
|
+
this.dispatch("all", event);
|
|
125
|
+
if (event.type === "error")
|
|
126
|
+
this.dispatch("error", { error: event.error, path: event.path });
|
|
127
|
+
else
|
|
128
|
+
this.dispatch(event.type, event.path);
|
|
129
|
+
}
|
|
130
|
+
eventPath(path) {
|
|
131
|
+
const normalized = normalizePath(path);
|
|
132
|
+
return normalized === "/" ? "/" : normalized.replace(/^\/+/, "");
|
|
133
|
+
}
|
|
134
|
+
async snapshot(path, recursive) {
|
|
135
|
+
const snapshot = new Map();
|
|
136
|
+
const stats = await this.adapter.stat(path);
|
|
137
|
+
if (!stats)
|
|
138
|
+
return snapshot;
|
|
139
|
+
snapshot.set(this.eventPath(path), stats);
|
|
140
|
+
if (stats.type !== "folder")
|
|
141
|
+
return snapshot;
|
|
142
|
+
const { files, folders } = await this.adapter.list(path);
|
|
143
|
+
for (const file of files) {
|
|
144
|
+
const entry = joinPath(path, file);
|
|
145
|
+
const stat = await this.adapter.stat(entry);
|
|
146
|
+
if (stat)
|
|
147
|
+
snapshot.set(this.eventPath(entry), stat);
|
|
148
|
+
}
|
|
149
|
+
for (const folder of folders) {
|
|
150
|
+
const entry = joinPath(path, folder);
|
|
151
|
+
if (recursive) {
|
|
152
|
+
for (const [key, stat] of await this.snapshot(entry, true))
|
|
153
|
+
snapshot.set(key, stat);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
const stat = await this.adapter.stat(entry);
|
|
157
|
+
if (stat)
|
|
158
|
+
snapshot.set(this.eventPath(entry), stat);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return snapshot;
|
|
162
|
+
}
|
|
163
|
+
async poll(state) {
|
|
164
|
+
try {
|
|
165
|
+
const next = await this.snapshot(state.path, state.recursive);
|
|
166
|
+
if (!this.live(state))
|
|
167
|
+
return;
|
|
168
|
+
if (state.snapshot) {
|
|
169
|
+
const changes = [];
|
|
170
|
+
for (const [path, stat] of next) {
|
|
171
|
+
const previous = state.snapshot.get(path);
|
|
172
|
+
if (!previous)
|
|
173
|
+
changes.push({ type: "create", path });
|
|
174
|
+
else if (previous.mtime !== stat.mtime ||
|
|
175
|
+
previous.size !== stat.size ||
|
|
176
|
+
previous.type !== stat.type)
|
|
177
|
+
changes.push({ type: "modify", path });
|
|
178
|
+
}
|
|
179
|
+
for (const path of state.snapshot.keys())
|
|
180
|
+
if (!next.has(path))
|
|
181
|
+
changes.push({ type: "delete", path });
|
|
182
|
+
for (const event of changes) {
|
|
183
|
+
if (!this.live(state))
|
|
184
|
+
break;
|
|
185
|
+
this.deliver(event);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
state.snapshot = next;
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
if (this.live(state))
|
|
192
|
+
this.deliver({ type: "error", path: state.path, error });
|
|
193
|
+
}
|
|
194
|
+
finally {
|
|
195
|
+
if (this.live(state))
|
|
196
|
+
state.timeout = setTimeout(() => {
|
|
197
|
+
state.pending = this.poll(state);
|
|
198
|
+
}, state.interval);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
package/dist/storage/fs.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { EventDispatcher } from "../events";
|
|
2
1
|
import type { Vault } from "./vault.svelte";
|
|
3
2
|
interface FileProperties {
|
|
4
3
|
/**
|
|
@@ -90,6 +89,7 @@ export type WatchOptions = {
|
|
|
90
89
|
interval?: number;
|
|
91
90
|
};
|
|
92
91
|
export interface ChangeEvent {
|
|
92
|
+
previousPath?: string;
|
|
93
93
|
type: "create" | "modify" | "delete";
|
|
94
94
|
path: string;
|
|
95
95
|
}
|
|
@@ -99,7 +99,9 @@ export interface WatchErrorEvent {
|
|
|
99
99
|
error: unknown;
|
|
100
100
|
}
|
|
101
101
|
export interface NativeWatchSubscription {
|
|
102
|
-
|
|
102
|
+
/** Resolves after native registration and its initial snapshot complete. */
|
|
103
|
+
readonly ready?: Promise<void>;
|
|
104
|
+
close(): void | Promise<void>;
|
|
103
105
|
}
|
|
104
106
|
export interface NativeWatchAdapter {
|
|
105
107
|
watch(path: string | string[], options: WatchOptions, listener: (event: ChangeEvent | WatchErrorEvent) => void): NativeWatchSubscription | void;
|
|
@@ -140,6 +142,8 @@ export interface DataAdapter {
|
|
|
140
142
|
trashLocal(normalizedPath: string): Promise<void>;
|
|
141
143
|
}
|
|
142
144
|
export interface VaultAdapterCapabilities {
|
|
145
|
+
exclusiveCreate?: boolean;
|
|
146
|
+
conditionalTextWrite?: boolean;
|
|
143
147
|
persistent: boolean;
|
|
144
148
|
userVisibleFiles: boolean;
|
|
145
149
|
requiresPermission: boolean;
|
|
@@ -155,6 +159,13 @@ export interface VaultAdapterCapabilities {
|
|
|
155
159
|
*/
|
|
156
160
|
export interface VaultAdapter extends DataAdapter {
|
|
157
161
|
getCapabilities?(): Partial<VaultAdapterCapabilities>;
|
|
162
|
+
/** Publish new complete bytes without replacing an existing destination. */
|
|
163
|
+
writeExclusive?(normalizedPath: string, data: string | ArrayBuffer, options?: DataWriteOptions): Promise<void>;
|
|
164
|
+
/**
|
|
165
|
+
* Reject when the file no longer has these exact contents (null means
|
|
166
|
+
* absent).
|
|
167
|
+
*/
|
|
168
|
+
writeTextIfUnchanged?(normalizedPath: string, data: string, expected: string | null, options?: DataWriteOptions): Promise<void>;
|
|
158
169
|
openRead?(normalizedPath: string): Promise<VaultReadHandle>;
|
|
159
170
|
atomicWrite?(normalizedPath: string, source: ReadableStream<Uint8Array>, options?: AtomicDataWriteOptions): Promise<void>;
|
|
160
171
|
}
|
|
@@ -165,30 +176,7 @@ export interface AsyncResourceAdapter {
|
|
|
165
176
|
getResourceUrl(normalizedPath: string): Promise<string>;
|
|
166
177
|
revokeResourceUrl?(url: string): void;
|
|
167
178
|
}
|
|
168
|
-
export
|
|
169
|
-
error: [{
|
|
170
|
-
error: unknown;
|
|
171
|
-
path: string;
|
|
172
|
-
}];
|
|
173
|
-
all: [event: ChangeEvent | WatchErrorEvent];
|
|
174
|
-
create: [path: string];
|
|
175
|
-
modify: [path: string];
|
|
176
|
-
delete: [path: string];
|
|
177
|
-
}> {
|
|
178
|
-
readonly adapter: DataAdapter;
|
|
179
|
-
readonly pollingInterval: number;
|
|
180
|
-
private watchers;
|
|
181
|
-
constructor(adapter: DataAdapter, pollingInterval?: number);
|
|
182
|
-
watch(path: string | string[], options?: WatchOptions): {
|
|
183
|
-
close: () => void;
|
|
184
|
-
} | undefined;
|
|
185
|
-
unwatch(path: string): void;
|
|
186
|
-
close(): void;
|
|
187
|
-
private takeSnapshot;
|
|
188
|
-
private toEventPath;
|
|
189
|
-
private checkForChanges;
|
|
190
|
-
private diffSnapshot;
|
|
191
|
-
}
|
|
179
|
+
export { DirectoryWatcher } from "./directory-watcher";
|
|
192
180
|
export declare class FileCache {
|
|
193
181
|
private capacity;
|
|
194
182
|
private cache;
|
|
@@ -202,4 +190,3 @@ export declare class FileCache {
|
|
|
202
190
|
has(key: string): boolean;
|
|
203
191
|
keys(): string[];
|
|
204
192
|
}
|
|
205
|
-
export {};
|