@mountra/mountra-sdk 0.3.0 → 0.4.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/dist/index.d.cts CHANGED
@@ -52,6 +52,12 @@ interface DownloadCacheStore {
52
52
  getFile(workspace: string, fileKey: string): Promise<DownloadCacheFile | null>;
53
53
  putFile(workspace: string, fileKey: string, file: DownloadCacheFile): Promise<void>;
54
54
  removeFile(workspace: string, fileKey: string): Promise<void>;
55
+ /**
56
+ * Remove every file whose `path` is `path` or below it, keeping the chunks.
57
+ * Optional: without it, a move or delete through the client clears the
58
+ * whole workspace instead.
59
+ */
60
+ removeFilesUnder?(workspace: string, path: string): Promise<void>;
55
61
  /** Return the chunk bytes and mark the chunk as most recently used. */
56
62
  getChunk(workspace: string, storageKey: string): Promise<Blob | null>;
57
63
  /** Store the chunk bytes, then evict least recently used chunks until at most `maxBytes` remain. */
@@ -68,6 +74,7 @@ declare class InMemoryDownloadCacheStore implements DownloadCacheStore {
68
74
  getFile(workspace: string, fileKey: string): Promise<DownloadCacheFile | null>;
69
75
  putFile(workspace: string, fileKey: string, file: DownloadCacheFile): Promise<void>;
70
76
  removeFile(workspace: string, fileKey: string): Promise<void>;
77
+ removeFilesUnder(workspace: string, path: string): Promise<void>;
71
78
  getChunk(workspace: string, storageKey: string): Promise<Blob | null>;
72
79
  putChunk(workspace: string, storageKey: string, data: Blob, maxBytes: number): Promise<void>;
73
80
  clear(workspace?: string): Promise<void>;
@@ -86,6 +93,7 @@ declare class IndexedDBDownloadCacheStore implements DownloadCacheStore {
86
93
  getFile(workspace: string, fileKey: string): Promise<DownloadCacheFile | null>;
87
94
  putFile(workspace: string, fileKey: string, file: DownloadCacheFile): Promise<void>;
88
95
  removeFile(workspace: string, fileKey: string): Promise<void>;
96
+ removeFilesUnder(workspace: string, path: string): Promise<void>;
89
97
  getChunk(workspace: string, storageKey: string): Promise<Blob | null>;
90
98
  putChunk(workspace: string, storageKey: string, data: Blob, maxBytes: number): Promise<void>;
91
99
  clear(workspace?: string): Promise<void>;
@@ -110,6 +118,8 @@ declare class DownloadCache {
110
118
  storeChunk(workspace: string, chunk: DownloadCacheChunk, data: Blob): Promise<boolean>;
111
119
  storeFile(workspace: string, fileKey: string, file: Omit<DownloadCacheFile, "cachedAt" | "expiresAt">): Promise<void>;
112
120
  invalidateFiles(workspace: string, fileKeys: string[]): Promise<void>;
121
+ /** Drop the files at or below `paths`, which a write changed; their chunks stay cached. */
122
+ invalidatePaths(workspace: string, paths: string[]): Promise<void>;
113
123
  clear(workspace?: string): Promise<void>;
114
124
  usage(workspace?: string): Promise<DownloadCacheUsage>;
115
125
  }
@@ -280,6 +290,8 @@ declare class MountraDownloader {
280
290
  path?: string;
281
291
  ino?: number | string;
282
292
  }): Promise<void>;
293
+ /** Drop the cached files at or below paths that a delete, move, or copy changed. */
294
+ invalidateCachedPaths(selector: WorkspaceSelector, paths: string[]): Promise<void>;
283
295
  /**
284
296
  * Cache a file this client just uploaded, so downloading it needs no
285
297
  * network. Falls back to invalidation when any chunk cannot be cached.
@@ -348,6 +360,197 @@ declare class MountraFile {
348
360
  resume(options?: MountraFileResumeOptions): Promise<DownloadResult>;
349
361
  }
350
362
 
363
+ type MetadataCacheKind = "list" | "tree";
364
+ /** A cached `list` result: the entries of one directory. */
365
+ interface MetadataListRecord {
366
+ kind: "list";
367
+ path: string;
368
+ entries: MountraFileEntry[];
369
+ /**
370
+ * When the request that returned this result was sent. Writes through this
371
+ * client and overlapping fetches may have updated the record since.
372
+ */
373
+ fetchedAt: number;
374
+ }
375
+ /** A cached `tree` result: one directory and its complete subtree. */
376
+ interface MetadataTreeRecord {
377
+ kind: "tree";
378
+ path: string;
379
+ root: MountraFileTreeNode;
380
+ /** See `MetadataListRecord.fetchedAt`. */
381
+ fetchedAt: number;
382
+ }
383
+ type MetadataCacheRecord = MetadataListRecord | MetadataTreeRecord;
384
+ interface MetadataCacheBatch {
385
+ put: MetadataCacheRecord[];
386
+ remove: Array<{
387
+ kind: MetadataCacheKind;
388
+ path: string;
389
+ }>;
390
+ }
391
+ interface MetadataCacheOptions {
392
+ /**
393
+ * Upper bound of cached `list` and `tree` results, shared by all
394
+ * workspaces. A tree counts as one result however large it is. Defaults to
395
+ * 1000; the least recently refreshed results are evicted first.
396
+ */
397
+ maxEntries?: number;
398
+ /** Cache storage. Defaults to IndexedDB, or memory when IndexedDB is unavailable. */
399
+ store?: MetadataCacheStore;
400
+ }
401
+ /**
402
+ * Storage behind the metadata cache. A record is identified by an opaque
403
+ * workspace key together with its `kind` and `path`, so one workspace never
404
+ * observes another workspace's records.
405
+ */
406
+ interface MetadataCacheStore {
407
+ get(workspace: string, kind: MetadataCacheKind, path: string): Promise<MetadataCacheRecord | null>;
408
+ /** The records stored at `path` or at any path below it, of one kind or of both. */
409
+ getSubtree(workspace: string, path: string, kind?: MetadataCacheKind): Promise<MetadataCacheRecord[]>;
410
+ /** Apply the batch atomically, then evict the least recently written records until at most `maxEntries` remain. */
411
+ write(workspace: string, batch: MetadataCacheBatch, maxEntries: number): Promise<void>;
412
+ /** Remove every record, or only the records of one workspace. */
413
+ clear(workspace?: string): Promise<void>;
414
+ }
415
+ declare class InMemoryMetadataCacheStore implements MetadataCacheStore {
416
+ /** Map iteration order is the eviction order: the first entry was written least recently. */
417
+ private readonly records;
418
+ get(workspace: string, kind: MetadataCacheKind, path: string): Promise<MetadataCacheRecord | null>;
419
+ getSubtree(workspace: string, path: string, kind?: MetadataCacheKind): Promise<MetadataCacheRecord[]>;
420
+ write(workspace: string, batch: MetadataCacheBatch, maxEntries: number): Promise<void>;
421
+ clear(workspace?: string): Promise<void>;
422
+ }
423
+ interface IndexedDBMetadataCacheStoreOptions {
424
+ /** Use a separate database, for example one per signed-in user. */
425
+ databaseName?: string;
426
+ }
427
+ /** Records are keyed `[workspace, kind, path]`, so a subtree of one kind is one key range. */
428
+ declare class IndexedDBMetadataCacheStore implements MetadataCacheStore {
429
+ private readonly databaseName;
430
+ private readonly fallback;
431
+ private databasePromise?;
432
+ constructor(options?: IndexedDBMetadataCacheStoreOptions);
433
+ get(workspace: string, kind: MetadataCacheKind, path: string): Promise<MetadataCacheRecord | null>;
434
+ getSubtree(workspace: string, path: string, kind?: MetadataCacheKind): Promise<MetadataCacheRecord[]>;
435
+ write(workspace: string, batch: MetadataCacheBatch, maxEntries: number): Promise<void>;
436
+ clear(workspace?: string): Promise<void>;
437
+ private openDatabase;
438
+ }
439
+
440
+ /** One entry of a directory listing. */
441
+ interface MountraFileEntry {
442
+ name: string;
443
+ /** Absolute path in the workspace. */
444
+ path: string;
445
+ ino: number;
446
+ isDirectory: boolean;
447
+ size: number;
448
+ mtimeMs: number;
449
+ atimeMs: number;
450
+ uid?: number;
451
+ gid?: number;
452
+ uidDisplayName?: string;
453
+ uidUsername?: string;
454
+ uidSubjectId?: string;
455
+ uidSubjectType?: string;
456
+ gidDisplayName?: string;
457
+ gidUsername?: string;
458
+ gidSubjectId?: string;
459
+ gidSubjectType?: string;
460
+ }
461
+ /** A node of a file tree. A directory node holds its complete subtree. */
462
+ interface MountraFileTreeNode {
463
+ name: string;
464
+ /** Absolute path in the workspace. */
465
+ path: string;
466
+ ino: number;
467
+ isDirectory: boolean;
468
+ size: number;
469
+ mtimeMs: number;
470
+ uid?: number;
471
+ gid?: number;
472
+ uidSubjectId?: string;
473
+ uidSubjectType?: string;
474
+ gidSubjectId?: string;
475
+ gidSubjectType?: string;
476
+ children: MountraFileTreeNode[];
477
+ }
478
+ /**
479
+ * How a metadata read uses the client's `metadataCache`:
480
+ * - `sync`: wait for Mountra and return its result.
481
+ * - `async`: return the cached result at once and refresh it in the
482
+ * background. Without a cached result, wait for Mountra as `sync` does.
483
+ *
484
+ * Either way, a result fetched from Mountra is cached before it is returned.
485
+ */
486
+ type MetadataReadMode = "sync" | "async";
487
+ /** `cache` when the result was served from the metadata cache, `remote` when Mountra just returned it. */
488
+ type MetadataSource = "cache" | "remote";
489
+ interface MetadataReadOptions<T> extends WorkspaceSelector {
490
+ /** The directory to read. Defaults to `/`. */
491
+ path?: string;
492
+ /** Defaults to `sync`. */
493
+ mode?: MetadataReadMode;
494
+ /**
495
+ * `async` only: receives the refreshed result of a cached result that was
496
+ * returned, when the two differ.
497
+ */
498
+ onUpdate?: (result: T) => void;
499
+ /** `async` only: receives the error of a failed background refresh. */
500
+ onError?: (error: unknown) => void;
501
+ /** Also cancels the background refresh; no callback runs once it has aborted. */
502
+ signal?: AbortSignal;
503
+ }
504
+ interface ListResult {
505
+ path: string;
506
+ /** Directories first, then by name. */
507
+ entries: MountraFileEntry[];
508
+ source: MetadataSource;
509
+ /**
510
+ * When the request that returned this result was sent. A cached result
511
+ * also reflects writes made through this client since then.
512
+ */
513
+ fetchedAt: number;
514
+ }
515
+ interface TreeResult {
516
+ path: string;
517
+ root: MountraFileTreeNode;
518
+ source: MetadataSource;
519
+ /** See `ListResult.fetchedAt`. */
520
+ fetchedAt: number;
521
+ }
522
+ type ListOptions = MetadataReadOptions<ListResult>;
523
+ type TreeOptions = MetadataReadOptions<TreeResult>;
524
+ interface MkdirOptions extends WorkspaceSelector {
525
+ /** The directory to create. Its parent must exist. */
526
+ path: string;
527
+ signal?: AbortSignal;
528
+ }
529
+ interface RenameOptions extends WorkspaceSelector {
530
+ fromPath: string;
531
+ /** The new name within the same directory. */
532
+ toName: string;
533
+ signal?: AbortSignal;
534
+ }
535
+ interface MoveOptions extends WorkspaceSelector {
536
+ fromPath: string;
537
+ /** The complete destination path, which must not exist yet. */
538
+ toPath: string;
539
+ signal?: AbortSignal;
540
+ }
541
+ /** Copies one file; Mountra does not copy directories. */
542
+ type CopyOptions = MoveOptions;
543
+ interface DeleteOptions extends WorkspaceSelector {
544
+ /** A file, or an empty directory. */
545
+ path: string;
546
+ signal?: AbortSignal;
547
+ }
548
+ interface FileOperationResult {
549
+ /** The path of the created, renamed, moved, or copied entry. */
550
+ path: string;
551
+ ino: number;
552
+ }
553
+
351
554
  type ChunkMethod = "none" | "fix";
352
555
  type WorkspaceId = number | string;
353
556
  declare const JUMBO_CHUNK_THRESHOLD_BYTES: number;
@@ -381,6 +584,12 @@ interface MountraClientOptions extends WorkspaceSelector {
381
584
  * unless set; pass `{}` for the defaults.
382
585
  */
383
586
  downloadCache?: DownloadCacheOptions;
587
+ /**
588
+ * Cache `list` and `tree` results locally, per workspace, in IndexedDB, so
589
+ * reads with `mode: "async"` return at once. Disabled unless set; pass `{}`
590
+ * for the defaults.
591
+ */
592
+ metadataCache?: MetadataCacheOptions;
384
593
  }
385
594
  interface UploadFileOptions extends WorkspaceSelector {
386
595
  path: string;
@@ -593,16 +802,6 @@ interface PreparedUpload {
593
802
  contentHash: string;
594
803
  context: UploadSessionContext;
595
804
  }
596
- declare class MountraApiError extends Error {
597
- readonly status: number;
598
- readonly code?: string;
599
- readonly body?: unknown;
600
- constructor(message: string, input: {
601
- status: number;
602
- code?: string;
603
- body?: unknown;
604
- });
605
- }
606
805
  declare class InMemoryJumboChunkCheckpointStore implements JumboChunkCheckpointStore {
607
806
  private readonly records;
608
807
  load(key: string): Promise<JumboChunkCheckpoint | null>;
@@ -652,6 +851,7 @@ declare class MountraClient {
652
851
  private readonly jumboChunkCheckpointStore;
653
852
  private readonly jumboPartSize;
654
853
  private readonly downloader;
854
+ private readonly metadata;
655
855
  constructor(options: MountraClientOptions);
656
856
  exportFile(options: ExportFileOptions): Promise<ExportFileResponse>;
657
857
  downloadFile(options: DownloadFileOptions): Promise<DownloadResult>;
@@ -662,6 +862,17 @@ declare class MountraClient {
662
862
  /** Clear the download cache of one workspace, or of every workspace when none is given. */
663
863
  clearDownloadCache(selector?: WorkspaceSelector): Promise<void>;
664
864
  getDownloadCacheUsage(selector?: WorkspaceSelector): Promise<DownloadCacheUsage>;
865
+ /** List the entries of a directory. See `MetadataReadMode` for how `mode` uses the metadata cache. */
866
+ list(options?: ListOptions): Promise<ListResult>;
867
+ /** Return a directory with its complete subtree. See `MetadataReadMode` for how `mode` uses the metadata cache. */
868
+ tree(options?: TreeOptions): Promise<TreeResult>;
869
+ mkdir(options: MkdirOptions): Promise<FileOperationResult>;
870
+ rename(options: RenameOptions): Promise<FileOperationResult>;
871
+ move(options: MoveOptions): Promise<FileOperationResult>;
872
+ copy(options: CopyOptions): Promise<FileOperationResult>;
873
+ delete(options: DeleteOptions): Promise<void>;
874
+ /** Clear the metadata cache of one workspace, or of every workspace when none is given. */
875
+ clearMetadataCache(selector?: WorkspaceSelector): Promise<void>;
665
876
  /** Create a stable resource object for one file in this or another workspace. */
666
877
  file(locator: MountraFileLocator): MountraFile;
667
878
  prepareUpload(file: Blob, options: UploadFileOptions): Promise<PreparedUpload>;
@@ -688,4 +899,16 @@ declare class MountraClient {
688
899
  }
689
900
  declare function createMountraClient(options: MountraClientOptions): MountraClient;
690
901
 
691
- export { type AccessToken, type ChunkMethod, DEFAULT_S3_MULTIPART_PART_SIZE_BYTES, type DownloadCacheChunk, type DownloadCacheFile, type DownloadCacheMode, type DownloadCacheOptions, type DownloadCacheStore, type DownloadCacheUsage, type DownloadCheckpoint, type DownloadCheckpointChunk, type DownloadCheckpointRequest, type DownloadCheckpointStore, type DownloadFileOptions, DownloadHttpError, type DownloadProgress, type DownloadResult, type DownloadResumeOptions, type ExportFileChunk, type ExportFileOptions, type ExportFileResponse, type FileChunk, type FileSystemFileHandleLike, type FileSystemWritableFileStreamLike, type FinishUploadResponse, InMemoryDownloadCacheStore, InMemoryDownloadCheckpointStore, InMemoryJumboChunkCheckpointStore, IndexedDBDownloadCacheStore, type IndexedDBDownloadCacheStoreOptions, IndexedDBDownloadCheckpointStore, JUMBO_CHUNK_THRESHOLD_BYTES, type JumboChunkCheckpoint, type JumboChunkCheckpointStore, type JumboChunkCompleteInput, type JumboChunkCreateInput, type JumboChunkUploadPartInput, type JumboChunkUploader, LocalStorageJumboChunkCheckpointStore, MAX_S3_MULTIPART_PARTS, MIN_S3_MULTIPART_PART_SIZE_BYTES, MountraApiError, MountraClient, type MountraClientOptions, MountraDownloader, MountraFile, type MountraFileDownloadOptions, type MountraFileExportOptions, type MountraFileLocator, type MountraFileResumeOptions, type MountraProgress, MountraClient as MountraSDK, type NormalizedMountraFileLocator, type PrepareUploadResponse, type PreparedUpload, type S3MultipartClient, type S3MultipartPart, S3MultipartUploader, type UploadFileOptions, type UploadResult, type UploadResumeOptions, type UploadSessionChunkContext, type UploadSessionContext, type UploadStatusChunk, type UploadStatusResponse, type UploadTarget, type WorkspaceId, type WorkspaceSelector, createMountraClient, isJumboChunk, sha256Hex, splitFileIntoChunks };
902
+ /** An HTTP error returned by Mountra, or by a signed upload URL. */
903
+ declare class MountraApiError extends Error {
904
+ readonly status: number;
905
+ readonly code?: string;
906
+ readonly body?: unknown;
907
+ constructor(message: string, input: {
908
+ status: number;
909
+ code?: string;
910
+ body?: unknown;
911
+ });
912
+ }
913
+
914
+ export { type AccessToken, type ChunkMethod, type CopyOptions, DEFAULT_S3_MULTIPART_PART_SIZE_BYTES, type DeleteOptions, type DownloadCacheChunk, type DownloadCacheFile, type DownloadCacheMode, type DownloadCacheOptions, type DownloadCacheStore, type DownloadCacheUsage, type DownloadCheckpoint, type DownloadCheckpointChunk, type DownloadCheckpointRequest, type DownloadCheckpointStore, type DownloadFileOptions, DownloadHttpError, type DownloadProgress, type DownloadResult, type DownloadResumeOptions, type ExportFileChunk, type ExportFileOptions, type ExportFileResponse, type FileChunk, type FileOperationResult, type FileSystemFileHandleLike, type FileSystemWritableFileStreamLike, type FinishUploadResponse, InMemoryDownloadCacheStore, InMemoryDownloadCheckpointStore, InMemoryJumboChunkCheckpointStore, InMemoryMetadataCacheStore, IndexedDBDownloadCacheStore, type IndexedDBDownloadCacheStoreOptions, IndexedDBDownloadCheckpointStore, IndexedDBMetadataCacheStore, type IndexedDBMetadataCacheStoreOptions, JUMBO_CHUNK_THRESHOLD_BYTES, type JumboChunkCheckpoint, type JumboChunkCheckpointStore, type JumboChunkCompleteInput, type JumboChunkCreateInput, type JumboChunkUploadPartInput, type JumboChunkUploader, type ListOptions, type ListResult, LocalStorageJumboChunkCheckpointStore, MAX_S3_MULTIPART_PARTS, MIN_S3_MULTIPART_PART_SIZE_BYTES, type MetadataCacheBatch, type MetadataCacheKind, type MetadataCacheOptions, type MetadataCacheRecord, type MetadataCacheStore, type MetadataListRecord, type MetadataReadMode, type MetadataReadOptions, type MetadataSource, type MetadataTreeRecord, type MkdirOptions, MountraApiError, MountraClient, type MountraClientOptions, MountraDownloader, MountraFile, type MountraFileDownloadOptions, type MountraFileEntry, type MountraFileExportOptions, type MountraFileLocator, type MountraFileResumeOptions, type MountraFileTreeNode, type MountraProgress, MountraClient as MountraSDK, type MoveOptions, type NormalizedMountraFileLocator, type PrepareUploadResponse, type PreparedUpload, type RenameOptions, type S3MultipartClient, type S3MultipartPart, S3MultipartUploader, type TreeOptions, type TreeResult, type UploadFileOptions, type UploadResult, type UploadResumeOptions, type UploadSessionChunkContext, type UploadSessionContext, type UploadStatusChunk, type UploadStatusResponse, type UploadTarget, type WorkspaceId, type WorkspaceSelector, createMountraClient, isJumboChunk, sha256Hex, splitFileIntoChunks };
package/dist/index.d.ts CHANGED
@@ -52,6 +52,12 @@ interface DownloadCacheStore {
52
52
  getFile(workspace: string, fileKey: string): Promise<DownloadCacheFile | null>;
53
53
  putFile(workspace: string, fileKey: string, file: DownloadCacheFile): Promise<void>;
54
54
  removeFile(workspace: string, fileKey: string): Promise<void>;
55
+ /**
56
+ * Remove every file whose `path` is `path` or below it, keeping the chunks.
57
+ * Optional: without it, a move or delete through the client clears the
58
+ * whole workspace instead.
59
+ */
60
+ removeFilesUnder?(workspace: string, path: string): Promise<void>;
55
61
  /** Return the chunk bytes and mark the chunk as most recently used. */
56
62
  getChunk(workspace: string, storageKey: string): Promise<Blob | null>;
57
63
  /** Store the chunk bytes, then evict least recently used chunks until at most `maxBytes` remain. */
@@ -68,6 +74,7 @@ declare class InMemoryDownloadCacheStore implements DownloadCacheStore {
68
74
  getFile(workspace: string, fileKey: string): Promise<DownloadCacheFile | null>;
69
75
  putFile(workspace: string, fileKey: string, file: DownloadCacheFile): Promise<void>;
70
76
  removeFile(workspace: string, fileKey: string): Promise<void>;
77
+ removeFilesUnder(workspace: string, path: string): Promise<void>;
71
78
  getChunk(workspace: string, storageKey: string): Promise<Blob | null>;
72
79
  putChunk(workspace: string, storageKey: string, data: Blob, maxBytes: number): Promise<void>;
73
80
  clear(workspace?: string): Promise<void>;
@@ -86,6 +93,7 @@ declare class IndexedDBDownloadCacheStore implements DownloadCacheStore {
86
93
  getFile(workspace: string, fileKey: string): Promise<DownloadCacheFile | null>;
87
94
  putFile(workspace: string, fileKey: string, file: DownloadCacheFile): Promise<void>;
88
95
  removeFile(workspace: string, fileKey: string): Promise<void>;
96
+ removeFilesUnder(workspace: string, path: string): Promise<void>;
89
97
  getChunk(workspace: string, storageKey: string): Promise<Blob | null>;
90
98
  putChunk(workspace: string, storageKey: string, data: Blob, maxBytes: number): Promise<void>;
91
99
  clear(workspace?: string): Promise<void>;
@@ -110,6 +118,8 @@ declare class DownloadCache {
110
118
  storeChunk(workspace: string, chunk: DownloadCacheChunk, data: Blob): Promise<boolean>;
111
119
  storeFile(workspace: string, fileKey: string, file: Omit<DownloadCacheFile, "cachedAt" | "expiresAt">): Promise<void>;
112
120
  invalidateFiles(workspace: string, fileKeys: string[]): Promise<void>;
121
+ /** Drop the files at or below `paths`, which a write changed; their chunks stay cached. */
122
+ invalidatePaths(workspace: string, paths: string[]): Promise<void>;
113
123
  clear(workspace?: string): Promise<void>;
114
124
  usage(workspace?: string): Promise<DownloadCacheUsage>;
115
125
  }
@@ -280,6 +290,8 @@ declare class MountraDownloader {
280
290
  path?: string;
281
291
  ino?: number | string;
282
292
  }): Promise<void>;
293
+ /** Drop the cached files at or below paths that a delete, move, or copy changed. */
294
+ invalidateCachedPaths(selector: WorkspaceSelector, paths: string[]): Promise<void>;
283
295
  /**
284
296
  * Cache a file this client just uploaded, so downloading it needs no
285
297
  * network. Falls back to invalidation when any chunk cannot be cached.
@@ -348,6 +360,197 @@ declare class MountraFile {
348
360
  resume(options?: MountraFileResumeOptions): Promise<DownloadResult>;
349
361
  }
350
362
 
363
+ type MetadataCacheKind = "list" | "tree";
364
+ /** A cached `list` result: the entries of one directory. */
365
+ interface MetadataListRecord {
366
+ kind: "list";
367
+ path: string;
368
+ entries: MountraFileEntry[];
369
+ /**
370
+ * When the request that returned this result was sent. Writes through this
371
+ * client and overlapping fetches may have updated the record since.
372
+ */
373
+ fetchedAt: number;
374
+ }
375
+ /** A cached `tree` result: one directory and its complete subtree. */
376
+ interface MetadataTreeRecord {
377
+ kind: "tree";
378
+ path: string;
379
+ root: MountraFileTreeNode;
380
+ /** See `MetadataListRecord.fetchedAt`. */
381
+ fetchedAt: number;
382
+ }
383
+ type MetadataCacheRecord = MetadataListRecord | MetadataTreeRecord;
384
+ interface MetadataCacheBatch {
385
+ put: MetadataCacheRecord[];
386
+ remove: Array<{
387
+ kind: MetadataCacheKind;
388
+ path: string;
389
+ }>;
390
+ }
391
+ interface MetadataCacheOptions {
392
+ /**
393
+ * Upper bound of cached `list` and `tree` results, shared by all
394
+ * workspaces. A tree counts as one result however large it is. Defaults to
395
+ * 1000; the least recently refreshed results are evicted first.
396
+ */
397
+ maxEntries?: number;
398
+ /** Cache storage. Defaults to IndexedDB, or memory when IndexedDB is unavailable. */
399
+ store?: MetadataCacheStore;
400
+ }
401
+ /**
402
+ * Storage behind the metadata cache. A record is identified by an opaque
403
+ * workspace key together with its `kind` and `path`, so one workspace never
404
+ * observes another workspace's records.
405
+ */
406
+ interface MetadataCacheStore {
407
+ get(workspace: string, kind: MetadataCacheKind, path: string): Promise<MetadataCacheRecord | null>;
408
+ /** The records stored at `path` or at any path below it, of one kind or of both. */
409
+ getSubtree(workspace: string, path: string, kind?: MetadataCacheKind): Promise<MetadataCacheRecord[]>;
410
+ /** Apply the batch atomically, then evict the least recently written records until at most `maxEntries` remain. */
411
+ write(workspace: string, batch: MetadataCacheBatch, maxEntries: number): Promise<void>;
412
+ /** Remove every record, or only the records of one workspace. */
413
+ clear(workspace?: string): Promise<void>;
414
+ }
415
+ declare class InMemoryMetadataCacheStore implements MetadataCacheStore {
416
+ /** Map iteration order is the eviction order: the first entry was written least recently. */
417
+ private readonly records;
418
+ get(workspace: string, kind: MetadataCacheKind, path: string): Promise<MetadataCacheRecord | null>;
419
+ getSubtree(workspace: string, path: string, kind?: MetadataCacheKind): Promise<MetadataCacheRecord[]>;
420
+ write(workspace: string, batch: MetadataCacheBatch, maxEntries: number): Promise<void>;
421
+ clear(workspace?: string): Promise<void>;
422
+ }
423
+ interface IndexedDBMetadataCacheStoreOptions {
424
+ /** Use a separate database, for example one per signed-in user. */
425
+ databaseName?: string;
426
+ }
427
+ /** Records are keyed `[workspace, kind, path]`, so a subtree of one kind is one key range. */
428
+ declare class IndexedDBMetadataCacheStore implements MetadataCacheStore {
429
+ private readonly databaseName;
430
+ private readonly fallback;
431
+ private databasePromise?;
432
+ constructor(options?: IndexedDBMetadataCacheStoreOptions);
433
+ get(workspace: string, kind: MetadataCacheKind, path: string): Promise<MetadataCacheRecord | null>;
434
+ getSubtree(workspace: string, path: string, kind?: MetadataCacheKind): Promise<MetadataCacheRecord[]>;
435
+ write(workspace: string, batch: MetadataCacheBatch, maxEntries: number): Promise<void>;
436
+ clear(workspace?: string): Promise<void>;
437
+ private openDatabase;
438
+ }
439
+
440
+ /** One entry of a directory listing. */
441
+ interface MountraFileEntry {
442
+ name: string;
443
+ /** Absolute path in the workspace. */
444
+ path: string;
445
+ ino: number;
446
+ isDirectory: boolean;
447
+ size: number;
448
+ mtimeMs: number;
449
+ atimeMs: number;
450
+ uid?: number;
451
+ gid?: number;
452
+ uidDisplayName?: string;
453
+ uidUsername?: string;
454
+ uidSubjectId?: string;
455
+ uidSubjectType?: string;
456
+ gidDisplayName?: string;
457
+ gidUsername?: string;
458
+ gidSubjectId?: string;
459
+ gidSubjectType?: string;
460
+ }
461
+ /** A node of a file tree. A directory node holds its complete subtree. */
462
+ interface MountraFileTreeNode {
463
+ name: string;
464
+ /** Absolute path in the workspace. */
465
+ path: string;
466
+ ino: number;
467
+ isDirectory: boolean;
468
+ size: number;
469
+ mtimeMs: number;
470
+ uid?: number;
471
+ gid?: number;
472
+ uidSubjectId?: string;
473
+ uidSubjectType?: string;
474
+ gidSubjectId?: string;
475
+ gidSubjectType?: string;
476
+ children: MountraFileTreeNode[];
477
+ }
478
+ /**
479
+ * How a metadata read uses the client's `metadataCache`:
480
+ * - `sync`: wait for Mountra and return its result.
481
+ * - `async`: return the cached result at once and refresh it in the
482
+ * background. Without a cached result, wait for Mountra as `sync` does.
483
+ *
484
+ * Either way, a result fetched from Mountra is cached before it is returned.
485
+ */
486
+ type MetadataReadMode = "sync" | "async";
487
+ /** `cache` when the result was served from the metadata cache, `remote` when Mountra just returned it. */
488
+ type MetadataSource = "cache" | "remote";
489
+ interface MetadataReadOptions<T> extends WorkspaceSelector {
490
+ /** The directory to read. Defaults to `/`. */
491
+ path?: string;
492
+ /** Defaults to `sync`. */
493
+ mode?: MetadataReadMode;
494
+ /**
495
+ * `async` only: receives the refreshed result of a cached result that was
496
+ * returned, when the two differ.
497
+ */
498
+ onUpdate?: (result: T) => void;
499
+ /** `async` only: receives the error of a failed background refresh. */
500
+ onError?: (error: unknown) => void;
501
+ /** Also cancels the background refresh; no callback runs once it has aborted. */
502
+ signal?: AbortSignal;
503
+ }
504
+ interface ListResult {
505
+ path: string;
506
+ /** Directories first, then by name. */
507
+ entries: MountraFileEntry[];
508
+ source: MetadataSource;
509
+ /**
510
+ * When the request that returned this result was sent. A cached result
511
+ * also reflects writes made through this client since then.
512
+ */
513
+ fetchedAt: number;
514
+ }
515
+ interface TreeResult {
516
+ path: string;
517
+ root: MountraFileTreeNode;
518
+ source: MetadataSource;
519
+ /** See `ListResult.fetchedAt`. */
520
+ fetchedAt: number;
521
+ }
522
+ type ListOptions = MetadataReadOptions<ListResult>;
523
+ type TreeOptions = MetadataReadOptions<TreeResult>;
524
+ interface MkdirOptions extends WorkspaceSelector {
525
+ /** The directory to create. Its parent must exist. */
526
+ path: string;
527
+ signal?: AbortSignal;
528
+ }
529
+ interface RenameOptions extends WorkspaceSelector {
530
+ fromPath: string;
531
+ /** The new name within the same directory. */
532
+ toName: string;
533
+ signal?: AbortSignal;
534
+ }
535
+ interface MoveOptions extends WorkspaceSelector {
536
+ fromPath: string;
537
+ /** The complete destination path, which must not exist yet. */
538
+ toPath: string;
539
+ signal?: AbortSignal;
540
+ }
541
+ /** Copies one file; Mountra does not copy directories. */
542
+ type CopyOptions = MoveOptions;
543
+ interface DeleteOptions extends WorkspaceSelector {
544
+ /** A file, or an empty directory. */
545
+ path: string;
546
+ signal?: AbortSignal;
547
+ }
548
+ interface FileOperationResult {
549
+ /** The path of the created, renamed, moved, or copied entry. */
550
+ path: string;
551
+ ino: number;
552
+ }
553
+
351
554
  type ChunkMethod = "none" | "fix";
352
555
  type WorkspaceId = number | string;
353
556
  declare const JUMBO_CHUNK_THRESHOLD_BYTES: number;
@@ -381,6 +584,12 @@ interface MountraClientOptions extends WorkspaceSelector {
381
584
  * unless set; pass `{}` for the defaults.
382
585
  */
383
586
  downloadCache?: DownloadCacheOptions;
587
+ /**
588
+ * Cache `list` and `tree` results locally, per workspace, in IndexedDB, so
589
+ * reads with `mode: "async"` return at once. Disabled unless set; pass `{}`
590
+ * for the defaults.
591
+ */
592
+ metadataCache?: MetadataCacheOptions;
384
593
  }
385
594
  interface UploadFileOptions extends WorkspaceSelector {
386
595
  path: string;
@@ -593,16 +802,6 @@ interface PreparedUpload {
593
802
  contentHash: string;
594
803
  context: UploadSessionContext;
595
804
  }
596
- declare class MountraApiError extends Error {
597
- readonly status: number;
598
- readonly code?: string;
599
- readonly body?: unknown;
600
- constructor(message: string, input: {
601
- status: number;
602
- code?: string;
603
- body?: unknown;
604
- });
605
- }
606
805
  declare class InMemoryJumboChunkCheckpointStore implements JumboChunkCheckpointStore {
607
806
  private readonly records;
608
807
  load(key: string): Promise<JumboChunkCheckpoint | null>;
@@ -652,6 +851,7 @@ declare class MountraClient {
652
851
  private readonly jumboChunkCheckpointStore;
653
852
  private readonly jumboPartSize;
654
853
  private readonly downloader;
854
+ private readonly metadata;
655
855
  constructor(options: MountraClientOptions);
656
856
  exportFile(options: ExportFileOptions): Promise<ExportFileResponse>;
657
857
  downloadFile(options: DownloadFileOptions): Promise<DownloadResult>;
@@ -662,6 +862,17 @@ declare class MountraClient {
662
862
  /** Clear the download cache of one workspace, or of every workspace when none is given. */
663
863
  clearDownloadCache(selector?: WorkspaceSelector): Promise<void>;
664
864
  getDownloadCacheUsage(selector?: WorkspaceSelector): Promise<DownloadCacheUsage>;
865
+ /** List the entries of a directory. See `MetadataReadMode` for how `mode` uses the metadata cache. */
866
+ list(options?: ListOptions): Promise<ListResult>;
867
+ /** Return a directory with its complete subtree. See `MetadataReadMode` for how `mode` uses the metadata cache. */
868
+ tree(options?: TreeOptions): Promise<TreeResult>;
869
+ mkdir(options: MkdirOptions): Promise<FileOperationResult>;
870
+ rename(options: RenameOptions): Promise<FileOperationResult>;
871
+ move(options: MoveOptions): Promise<FileOperationResult>;
872
+ copy(options: CopyOptions): Promise<FileOperationResult>;
873
+ delete(options: DeleteOptions): Promise<void>;
874
+ /** Clear the metadata cache of one workspace, or of every workspace when none is given. */
875
+ clearMetadataCache(selector?: WorkspaceSelector): Promise<void>;
665
876
  /** Create a stable resource object for one file in this or another workspace. */
666
877
  file(locator: MountraFileLocator): MountraFile;
667
878
  prepareUpload(file: Blob, options: UploadFileOptions): Promise<PreparedUpload>;
@@ -688,4 +899,16 @@ declare class MountraClient {
688
899
  }
689
900
  declare function createMountraClient(options: MountraClientOptions): MountraClient;
690
901
 
691
- export { type AccessToken, type ChunkMethod, DEFAULT_S3_MULTIPART_PART_SIZE_BYTES, type DownloadCacheChunk, type DownloadCacheFile, type DownloadCacheMode, type DownloadCacheOptions, type DownloadCacheStore, type DownloadCacheUsage, type DownloadCheckpoint, type DownloadCheckpointChunk, type DownloadCheckpointRequest, type DownloadCheckpointStore, type DownloadFileOptions, DownloadHttpError, type DownloadProgress, type DownloadResult, type DownloadResumeOptions, type ExportFileChunk, type ExportFileOptions, type ExportFileResponse, type FileChunk, type FileSystemFileHandleLike, type FileSystemWritableFileStreamLike, type FinishUploadResponse, InMemoryDownloadCacheStore, InMemoryDownloadCheckpointStore, InMemoryJumboChunkCheckpointStore, IndexedDBDownloadCacheStore, type IndexedDBDownloadCacheStoreOptions, IndexedDBDownloadCheckpointStore, JUMBO_CHUNK_THRESHOLD_BYTES, type JumboChunkCheckpoint, type JumboChunkCheckpointStore, type JumboChunkCompleteInput, type JumboChunkCreateInput, type JumboChunkUploadPartInput, type JumboChunkUploader, LocalStorageJumboChunkCheckpointStore, MAX_S3_MULTIPART_PARTS, MIN_S3_MULTIPART_PART_SIZE_BYTES, MountraApiError, MountraClient, type MountraClientOptions, MountraDownloader, MountraFile, type MountraFileDownloadOptions, type MountraFileExportOptions, type MountraFileLocator, type MountraFileResumeOptions, type MountraProgress, MountraClient as MountraSDK, type NormalizedMountraFileLocator, type PrepareUploadResponse, type PreparedUpload, type S3MultipartClient, type S3MultipartPart, S3MultipartUploader, type UploadFileOptions, type UploadResult, type UploadResumeOptions, type UploadSessionChunkContext, type UploadSessionContext, type UploadStatusChunk, type UploadStatusResponse, type UploadTarget, type WorkspaceId, type WorkspaceSelector, createMountraClient, isJumboChunk, sha256Hex, splitFileIntoChunks };
902
+ /** An HTTP error returned by Mountra, or by a signed upload URL. */
903
+ declare class MountraApiError extends Error {
904
+ readonly status: number;
905
+ readonly code?: string;
906
+ readonly body?: unknown;
907
+ constructor(message: string, input: {
908
+ status: number;
909
+ code?: string;
910
+ body?: unknown;
911
+ });
912
+ }
913
+
914
+ export { type AccessToken, type ChunkMethod, type CopyOptions, DEFAULT_S3_MULTIPART_PART_SIZE_BYTES, type DeleteOptions, type DownloadCacheChunk, type DownloadCacheFile, type DownloadCacheMode, type DownloadCacheOptions, type DownloadCacheStore, type DownloadCacheUsage, type DownloadCheckpoint, type DownloadCheckpointChunk, type DownloadCheckpointRequest, type DownloadCheckpointStore, type DownloadFileOptions, DownloadHttpError, type DownloadProgress, type DownloadResult, type DownloadResumeOptions, type ExportFileChunk, type ExportFileOptions, type ExportFileResponse, type FileChunk, type FileOperationResult, type FileSystemFileHandleLike, type FileSystemWritableFileStreamLike, type FinishUploadResponse, InMemoryDownloadCacheStore, InMemoryDownloadCheckpointStore, InMemoryJumboChunkCheckpointStore, InMemoryMetadataCacheStore, IndexedDBDownloadCacheStore, type IndexedDBDownloadCacheStoreOptions, IndexedDBDownloadCheckpointStore, IndexedDBMetadataCacheStore, type IndexedDBMetadataCacheStoreOptions, JUMBO_CHUNK_THRESHOLD_BYTES, type JumboChunkCheckpoint, type JumboChunkCheckpointStore, type JumboChunkCompleteInput, type JumboChunkCreateInput, type JumboChunkUploadPartInput, type JumboChunkUploader, type ListOptions, type ListResult, LocalStorageJumboChunkCheckpointStore, MAX_S3_MULTIPART_PARTS, MIN_S3_MULTIPART_PART_SIZE_BYTES, type MetadataCacheBatch, type MetadataCacheKind, type MetadataCacheOptions, type MetadataCacheRecord, type MetadataCacheStore, type MetadataListRecord, type MetadataReadMode, type MetadataReadOptions, type MetadataSource, type MetadataTreeRecord, type MkdirOptions, MountraApiError, MountraClient, type MountraClientOptions, MountraDownloader, MountraFile, type MountraFileDownloadOptions, type MountraFileEntry, type MountraFileExportOptions, type MountraFileLocator, type MountraFileResumeOptions, type MountraFileTreeNode, type MountraProgress, MountraClient as MountraSDK, type MoveOptions, type NormalizedMountraFileLocator, type PrepareUploadResponse, type PreparedUpload, type RenameOptions, type S3MultipartClient, type S3MultipartPart, S3MultipartUploader, type TreeOptions, type TreeResult, type UploadFileOptions, type UploadResult, type UploadResumeOptions, type UploadSessionChunkContext, type UploadSessionContext, type UploadStatusChunk, type UploadStatusResponse, type UploadTarget, type WorkspaceId, type WorkspaceSelector, createMountraClient, isJumboChunk, sha256Hex, splitFileIntoChunks };