@telecrypt-io/storage 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/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  End-to-end encrypted file storage and sharing, built on Matrix.
6
6
 
7
7
  Files are encrypted on the client before upload. The server stores only opaque ciphertext and
8
- never holds the decryption keys. Shared folders let multiple people add and read files, and a
8
+ never holds the decryption keys. Shared vaults let multiple people add and read files, and a
9
9
  Recovery Key restores your files on a new device — even if you lose the original.
10
10
 
11
11
  This repository publishes the library package from protected exact-version tags with NPM Trusted
@@ -14,7 +14,7 @@ Publishing/OIDC provenance. The command-line client is maintained in its own rep
14
14
  ## Install
15
15
 
16
16
  ```bash
17
- npm install @telecrypt-io/storage@0.3.0
17
+ npm install @telecrypt-io/storage@0.4.0
18
18
  ```
19
19
 
20
20
  This gives you the `TeleCryptIOStorage` library and its browser-safe `core` API.
@@ -30,8 +30,8 @@ import * as core from "@telecrypt-io/storage/core";
30
30
  const storage = await TeleCryptIOStorage.create({
31
31
  baseUrl, userId, accessToken, deviceId,
32
32
  });
33
- const folder = await core.createFolder(storage, "Photos");
34
- await core.uploadFile(storage, folder.id, "cat.jpg", bytes, "image/jpeg");
33
+ const vault = await core.createVault(storage, "Photos");
34
+ await core.uploadFile(storage, vault.id, "cat.jpg", bytes, "image/jpeg");
35
35
  ```
36
36
 
37
37
  The command-line client is sourced by
@@ -44,10 +44,10 @@ application is sourced by
44
44
  Built on [MSC3089](https://github.com/matrix-org/matrix-spec-proposals/pull/3089), which models
45
45
  a file tree using Matrix primitives:
46
46
 
47
- | File-system concept | Matrix concept |
47
+ | Storage concept | Matrix concept |
48
48
  |---|---|
49
- | Folder | A Space (room marked as a file tree) |
50
- | Subfolder | A child Space |
49
+ | Vault | A Space (room marked as a file tree) |
50
+ | Folder | A child Space |
51
51
  | File | An event pointing at encrypted uploaded content |
52
52
  | Version | A newer event superseding the old |
53
53
  | Sharing | Room invitation |
@@ -194,7 +194,7 @@ export declare class TeleCryptIOStorage {
194
194
  }>;
195
195
  };
196
196
  /**
197
- * Creates a new top-level shared folder (tree space).
197
+ * Creates a new top-level shared vault (tree space).
198
198
  *
199
199
  * Works around a genuine race in matrix-js-sdk's own
200
200
  * `unstableCreateFileTree()`: it creates the room via a plain
@@ -209,7 +209,7 @@ export declare class TeleCryptIOStorage {
209
209
  * how we get "Unknown room" at all); this method waits for the client's
210
210
  * own ongoing sync loop to surface it, then wraps it directly via
211
211
  * `unstableGetFileTreeSpace`, instead of surfacing a spurious failure for
212
- * a folder that in fact exists.
212
+ * a vault that in fact exists.
213
213
  */
214
214
  createTree(name: string): Promise<TreeSpace>;
215
215
  listTrees(): Promise<TreeSpace[]>;
@@ -230,7 +230,7 @@ export declare class TeleCryptIOStorage {
230
230
  createSubtree(parent: TreeSpace, name: string): Promise<TreeSpace>;
231
231
  getTree(roomId: string): TreeSpace | null;
232
232
  /**
233
- * Lists the participants of a shared folder (tree space) and their role,
233
+ * Lists the participants of a shared vault (tree space) and their role,
234
234
  * derived from room membership (join/invite state) + power levels.
235
235
  * Includes invited-but-not-yet-joined members as well as joined ones;
236
236
  * excludes anyone who has left/been kicked/banned.
@@ -250,7 +250,7 @@ export class TeleCryptIOStorage {
250
250
  };
251
251
  }
252
252
  /**
253
- * Creates a new top-level shared folder (tree space).
253
+ * Creates a new top-level shared vault (tree space).
254
254
  *
255
255
  * Works around a genuine race in matrix-js-sdk's own
256
256
  * `unstableCreateFileTree()`: it creates the room via a plain
@@ -265,7 +265,7 @@ export class TeleCryptIOStorage {
265
265
  * how we get "Unknown room" at all); this method waits for the client's
266
266
  * own ongoing sync loop to surface it, then wraps it directly via
267
267
  * `unstableGetFileTreeSpace`, instead of surfacing a spurious failure for
268
- * a folder that in fact exists.
268
+ * a vault that in fact exists.
269
269
  */
270
270
  async createTree(name) {
271
271
  const knownRoomIdsBefore = new Set(this.client.getRooms().map((r) => r.roomId));
@@ -369,7 +369,7 @@ export class TeleCryptIOStorage {
369
369
  return this.client.unstableGetFileTreeSpace(roomId);
370
370
  }
371
371
  /**
372
- * Lists the participants of a shared folder (tree space) and their role,
372
+ * Lists the participants of a shared vault (tree space) and their role,
373
373
  * derived from room membership (join/invite state) + power levels.
374
374
  * Includes invited-but-not-yet-joined members as well as joined ones;
375
375
  * excludes anyone who has left/been kicked/banned.
@@ -1,6 +1,6 @@
1
1
  /** A user-facing operation error: a clean, prefix-free message meant to be
2
2
  * shown directly to a user — never a raw stack trace. Thrown for expected failure
3
- * conditions (bad login, wrong recovery key, missing file/folder, not
3
+ * conditions (bad login, wrong recovery key, missing file, vault, or folder, not
4
4
  * logged in, ...). Platform-agnostic: no Node/CLI dependencies. */
5
5
  export declare class StorageError extends Error {
6
6
  constructor(message: string);
@@ -1,6 +1,6 @@
1
1
  /** A user-facing operation error: a clean, prefix-free message meant to be
2
2
  * shown directly to a user — never a raw stack trace. Thrown for expected failure
3
- * conditions (bad login, wrong recovery key, missing file/folder, not
3
+ * conditions (bad login, wrong recovery key, missing file, vault, or folder, not
4
4
  * logged in, ...). Platform-agnostic: no Node/CLI dependencies. */
5
5
  export class StorageError extends Error {
6
6
  constructor(message) {
@@ -11,41 +11,51 @@
11
11
  * platform-specific and stays with the caller.
12
12
  */
13
13
  import { TeleCryptIOStorage } from "../TeleCryptIOStorage.js";
14
- import type { DownloadedFile, FileDetails, FileInfo, FolderDetails, FolderInfo, DeleteResult, JoinResult, Member, RecoveryRestore, RecoverySetup, RenameResult, ShareResult, UnshareResult } from "./types.js";
15
- export declare function createFolder(storage: TeleCryptIOStorage, name: string): Promise<FolderInfo>;
16
- /** Top-level folders only — excludes subdirectories of an existing tree. */
17
- export declare function listFolders(storage: TeleCryptIOStorage): Promise<FolderInfo[]>;
18
- /** Current account's effective role for a folder, or null while it is unavailable. */
19
- export declare function getMyFolderRole(storage: TeleCryptIOStorage, folderId: string): string | null;
20
- export declare function joinFolder(storage: TeleCryptIOStorage, folderId: string): Promise<JoinResult>;
14
+ import type { DownloadedFile, FolderDetails, FolderInfo, FileDetails, FileInfo, VaultDetails, VaultInfo, DeleteResult, JoinResult, Member, RecoveryRestore, RecoverySetup, RenameResult, ShareResult, UnshareResult } from "./types.js";
15
+ export declare function createVault(storage: TeleCryptIOStorage, name: string): Promise<VaultInfo>;
16
+ /** Top-level vaults only — excludes subdirectories of an existing tree. */
17
+ export declare function listVaults(storage: TeleCryptIOStorage): Promise<VaultInfo[]>;
18
+ /** Current account's effective role for a vault, or null while it is unavailable. */
19
+ export declare function getMyVaultRole(storage: TeleCryptIOStorage, vaultId: string): string | null;
20
+ export declare function joinVault(storage: TeleCryptIOStorage, vaultId: string): Promise<JoinResult>;
21
21
  /** Rooms where this account is invited and the room looks like a file tree. */
22
- export declare function listPendingInvites(storage: TeleCryptIOStorage): Promise<FolderInfo[]>;
23
- /** Decline a folder invite (same as leaving before join). */
24
- export declare function declineInvite(storage: TeleCryptIOStorage, folderId: string): Promise<{
25
- folderId: string;
22
+ export declare function listPendingInvites(storage: TeleCryptIOStorage): Promise<VaultInfo[]>;
23
+ /** Decline a vault invite (same as leaving before join). */
24
+ export declare function declineInvite(storage: TeleCryptIOStorage, vaultId: string): Promise<{
25
+ vaultId: string;
26
26
  declined: boolean;
27
27
  }>;
28
28
  /**
29
- * Invites `userId` to the folder at `role` and applies the role's
29
+ * Invites `userId` to the vault at `role` and applies the role's
30
30
  * permissions. Doubles as "change an existing participant's role" (call
31
31
  * again with a different role): inviting someone who's already a member is
32
32
  * a 403 from the server, not a real failure — that specific error is
33
33
  * swallowed and the role change still applies. Any other invite failure
34
34
  * (e.g. unknown user) propagates.
35
35
  */
36
- export declare function shareFolder(storage: TeleCryptIOStorage, folderId: string, userId: string, role: string): Promise<ShareResult>;
37
- export declare function unshareFolder(storage: TeleCryptIOStorage, folderId: string, userId: string): Promise<UnshareResult>;
38
- export declare function listMembers(storage: TeleCryptIOStorage, folderId: string): Promise<Member[]>;
39
- export declare function listFiles(storage: TeleCryptIOStorage, folderId: string): Promise<FileInfo[]>;
40
- export declare function listSubfolders(storage: TeleCryptIOStorage, folderId: string): Promise<FolderInfo[]>;
41
- export declare function createSubfolder(storage: TeleCryptIOStorage, folderId: string, name: string): Promise<FolderInfo>;
36
+ export declare function shareVault(storage: TeleCryptIOStorage, vaultId: string, userId: string, role: string): Promise<ShareResult>;
37
+ export declare function unshareVault(storage: TeleCryptIOStorage, vaultId: string, userId: string): Promise<UnshareResult>;
38
+ export declare function listMembers(storage: TeleCryptIOStorage, vaultId: string): Promise<Member[]>;
39
+ export declare function listFiles(storage: TeleCryptIOStorage, treeId: string): Promise<FileInfo[]>;
40
+ /** Lists the direct child folders of a vault or folder. */
41
+ export declare function listSubfolders(storage: TeleCryptIOStorage, parentId: string): Promise<FolderInfo[]>;
42
+ export declare function createSubfolder(storage: TeleCryptIOStorage, parentId: string, name: string): Promise<FolderInfo>;
43
+ /** Renames a top-level Vault. */
44
+ export declare function renameVault(storage: TeleCryptIOStorage, vaultId: string, name: string): Promise<RenameResult>;
45
+ /** Renames a nested folder. */
42
46
  export declare function renameFolder(storage: TeleCryptIOStorage, folderId: string, name: string): Promise<RenameResult>;
47
+ /** Deletes a top-level Vault. */
48
+ export declare function deleteVault(storage: TeleCryptIOStorage, vaultId: string): Promise<DeleteResult>;
49
+ /** Deletes a nested folder. */
43
50
  export declare function deleteFolder(storage: TeleCryptIOStorage, folderId: string): Promise<DeleteResult>;
44
- export declare function renameFile(storage: TeleCryptIOStorage, folderId: string, fileId: string, name: string): Promise<RenameResult>;
45
- export declare function deleteFile(storage: TeleCryptIOStorage, folderId: string, fileId: string): Promise<DeleteResult>;
46
- export declare function uploadFile(storage: TeleCryptIOStorage, folderId: string, name: string, bytes: Uint8Array, mimetype: string): Promise<FileInfo>;
47
- export declare function downloadFile(storage: TeleCryptIOStorage, folderId: string, fileId: string): Promise<DownloadedFile>;
51
+ export declare function renameFile(storage: TeleCryptIOStorage, treeId: string, fileId: string, name: string): Promise<RenameResult>;
52
+ export declare function deleteFile(storage: TeleCryptIOStorage, treeId: string, fileId: string): Promise<DeleteResult>;
53
+ export declare function uploadFile(storage: TeleCryptIOStorage, treeId: string, name: string, bytes: Uint8Array, mimetype: string): Promise<FileInfo>;
54
+ export declare function downloadFile(storage: TeleCryptIOStorage, treeId: string, fileId: string): Promise<DownloadedFile>;
48
55
  export declare function setupRecovery(storage: TeleCryptIOStorage): Promise<RecoverySetup>;
49
56
  export declare function restoreRecovery(storage: TeleCryptIOStorage, recoveryKey: string): Promise<RecoveryRestore>;
50
- export declare function getFileDetails(storage: TeleCryptIOStorage, folderId: string, fileId: string): Promise<FileDetails>;
57
+ export declare function getFileDetails(storage: TeleCryptIOStorage, treeId: string, fileId: string): Promise<FileDetails>;
58
+ /** Returns details for a top-level Vault. */
59
+ export declare function getVaultDetails(storage: TeleCryptIOStorage, vaultId: string): Promise<VaultDetails>;
60
+ /** Returns details for a nested folder. */
51
61
  export declare function getFolderDetails(storage: TeleCryptIOStorage, folderId: string): Promise<FolderDetails>;
@@ -43,24 +43,24 @@ async function withRateLimitRetry(operation) {
43
43
  }
44
44
  }
45
45
  /**
46
- * Resolves a folder by ID, polling briefly: a room this same account just
46
+ * Resolves a vault or folder by ID, polling briefly: a room this same account just
47
47
  * created (or was just invited to, by another process/session) can be
48
48
  * momentarily absent from a from-scratch `/sync` before showing up moments
49
49
  * later — real async settling, not an instant "not found". Throws a clean
50
- * error if the folder still isn't visible once the poll times out.
50
+ * error if the storage tree still isn't visible once the poll times out.
51
51
  */
52
- async function resolveTree(storage, folderId) {
52
+ async function resolveTree(storage, treeId) {
53
53
  try {
54
- return await waitForCondition(() => storage.getTree(folderId), {
54
+ return await waitForCondition(() => storage.getTree(treeId), {
55
55
  timeoutMs: 15000,
56
56
  });
57
57
  }
58
58
  catch {
59
- throw new StorageError(`folder not found: ${folderId}`);
59
+ throw new StorageError(`storage space not found: ${treeId}`);
60
60
  }
61
61
  }
62
62
  /** As `resolveTree`, but for a specific file within an already-resolved
63
- * folder — covers the same settling window for a file another
63
+ * vault or folder — covers the same settling window for a file another
64
64
  * process/session just uploaded. */
65
65
  async function resolveFile(tree, fileId) {
66
66
  try {
@@ -73,31 +73,31 @@ async function resolveFile(tree, fileId) {
73
73
  function toArrayBuffer(bytes) {
74
74
  return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
75
75
  }
76
- export async function createFolder(storage, name) {
76
+ export async function createVault(storage, name) {
77
77
  const tree = await withRateLimitRetry(() => storage.createTree(name));
78
78
  return { id: tree.id, name };
79
79
  }
80
- /** Top-level folders only — excludes subdirectories of an existing tree. */
81
- export async function listFolders(storage) {
80
+ /** Top-level vaults only — excludes subdirectories of an existing tree. */
81
+ export async function listVaults(storage) {
82
82
  const trees = await storage.listTrees();
83
83
  return trees.filter((t) => t.isTopLevel).map((t) => ({ id: t.id, name: t.room.name }));
84
84
  }
85
- /** Current account's effective role for a folder, or null while it is unavailable. */
86
- export function getMyFolderRole(storage, folderId) {
85
+ /** Current account's effective role for a vault, or null while it is unavailable. */
86
+ export function getMyVaultRole(storage, vaultId) {
87
87
  const userId = storage.getClient().getUserId();
88
- const tree = storage.getTree(folderId);
88
+ const tree = storage.getTree(vaultId);
89
89
  if (!userId || !tree)
90
90
  return null;
91
91
  return tree.getPermissions(userId);
92
92
  }
93
- export async function joinFolder(storage, folderId) {
93
+ export async function joinVault(storage, vaultId) {
94
94
  try {
95
- await withRateLimitRetry(() => storage.getClient().joinRoom(folderId));
95
+ await withRateLimitRetry(() => storage.getClient().joinRoom(vaultId));
96
96
  }
97
97
  catch (err) {
98
98
  throw new StorageError(`join failed: ${err.message}`);
99
99
  }
100
- return { folderId, joined: true };
100
+ return { vaultId, joined: true };
101
101
  }
102
102
  function roomDisplayName(storage, roomId, fallbackName) {
103
103
  const client = storage.getClient();
@@ -140,38 +140,38 @@ export async function listPendingInvites(storage) {
140
140
  }
141
141
  return invites;
142
142
  }
143
- /** Decline a folder invite (same as leaving before join). */
144
- export async function declineInvite(storage, folderId) {
143
+ /** Decline a vault invite (same as leaving before join). */
144
+ export async function declineInvite(storage, vaultId) {
145
145
  const client = storage.getClient();
146
146
  try {
147
147
  await withRateLimitRetry(async () => {
148
- await client.leave(folderId);
148
+ await client.leave(vaultId);
149
149
  // The server only allows forgetting a room once this account's
150
150
  // membership is `leave`; forgetting removes the room from the local
151
151
  // store immediately, so a declined invite stops showing up in
152
- // listFolders/listPendingInvites without waiting for the leave event
152
+ // listVaults/listPendingInvites without waiting for the leave event
153
153
  // to round-trip through the background sync loop.
154
- await client.forget(folderId);
154
+ await client.forget(vaultId);
155
155
  });
156
156
  }
157
157
  catch (err) {
158
158
  throw new StorageError(`decline failed: ${err.message}`);
159
159
  }
160
- return { folderId, declined: true };
160
+ return { vaultId, declined: true };
161
161
  }
162
162
  /**
163
- * Invites `userId` to the folder at `role` and applies the role's
163
+ * Invites `userId` to the vault at `role` and applies the role's
164
164
  * permissions. Doubles as "change an existing participant's role" (call
165
165
  * again with a different role): inviting someone who's already a member is
166
166
  * a 403 from the server, not a real failure — that specific error is
167
167
  * swallowed and the role change still applies. Any other invite failure
168
168
  * (e.g. unknown user) propagates.
169
169
  */
170
- export async function shareFolder(storage, folderId, userId, role) {
170
+ export async function shareVault(storage, vaultId, userId, role) {
171
171
  if (role !== "viewer" && role !== "editor") {
172
172
  throw new StorageError(`invalid --role "${role}" (must be viewer or editor)`);
173
173
  }
174
- const tree = await resolveTree(storage, folderId);
174
+ const tree = await resolveTree(storage, vaultId);
175
175
  try {
176
176
  await withRateLimitRetry(() => tree.invite(userId));
177
177
  }
@@ -181,46 +181,55 @@ export async function shareFolder(storage, folderId, userId, role) {
181
181
  }
182
182
  }
183
183
  await withRateLimitRetry(() => tree.setPermissions(userId, role));
184
- return { folderId, userId, role };
184
+ return { vaultId, userId, role };
185
185
  }
186
- export async function unshareFolder(storage, folderId, userId) {
187
- await resolveTree(storage, folderId);
186
+ export async function unshareVault(storage, vaultId, userId) {
187
+ await resolveTree(storage, vaultId);
188
188
  try {
189
- await withRateLimitRetry(() => storage.getClient().kick(folderId, userId, "unshared"));
189
+ await withRateLimitRetry(() => storage.getClient().kick(vaultId, userId, "unshared"));
190
190
  }
191
191
  catch (err) {
192
192
  throw new StorageError(`unshare failed: ${err.message}`);
193
193
  }
194
- return { folderId, userId, removed: true };
194
+ return { vaultId, userId, removed: true };
195
195
  }
196
- export async function listMembers(storage, folderId) {
197
- const tree = await resolveTree(storage, folderId);
196
+ export async function listMembers(storage, vaultId) {
197
+ const tree = await resolveTree(storage, vaultId);
198
198
  return withRateLimitRetry(() => storage.listMembers(tree));
199
199
  }
200
- export async function listFiles(storage, folderId) {
201
- const tree = await resolveTree(storage, folderId);
202
- await storage.refreshRoomState(folderId);
200
+ export async function listFiles(storage, treeId) {
201
+ const tree = await resolveTree(storage, treeId);
202
+ await storage.refreshRoomState(treeId);
203
203
  return tree.listFiles().map((f) => ({ id: f.id, name: f.getName() }));
204
204
  }
205
- export async function listSubfolders(storage, folderId) {
206
- const tree = await resolveTree(storage, folderId);
205
+ /** Lists the direct child folders of a vault or folder. */
206
+ export async function listSubfolders(storage, parentId) {
207
+ const tree = await resolveTree(storage, parentId);
207
208
  return tree.getDirectories().map((d) => ({ id: d.id, name: d.room.name }));
208
209
  }
209
- export async function createSubfolder(storage, folderId, name) {
210
- const tree = await resolveTree(storage, folderId);
210
+ export async function createSubfolder(storage, parentId, name) {
211
+ const tree = await resolveTree(storage, parentId);
211
212
  const sub = await withRateLimitRetry(() => storage.createSubtree(tree, name));
212
213
  return { id: sub.id, name };
213
214
  }
214
- export async function renameFolder(storage, folderId, name) {
215
- const tree = await resolveTree(storage, folderId);
215
+ async function renameTree(storage, treeId, name) {
216
+ const tree = await resolveTree(storage, treeId);
216
217
  await withRateLimitRetry(() => tree.setName(name));
217
- return { id: folderId, name };
218
+ return { id: treeId, name };
218
219
  }
219
- export async function deleteFolder(storage, folderId) {
220
- const tree = await resolveTree(storage, folderId);
220
+ /** Renames a top-level Vault. */
221
+ export async function renameVault(storage, vaultId, name) {
222
+ return renameTree(storage, vaultId, name);
223
+ }
224
+ /** Renames a nested folder. */
225
+ export async function renameFolder(storage, folderId, name) {
226
+ return renameTree(storage, folderId, name);
227
+ }
228
+ async function deleteTree(storage, treeId) {
229
+ const tree = await resolveTree(storage, treeId);
221
230
  // `tree.delete()` kicks members and leaves this room AND every
222
231
  // subdirectory room, but never forgets any of them, so they all linger in
223
- // the local store and listFolders keeps returning the deleted folder until
232
+ // the local store and tree listings keep returning the deleted tree until
224
233
  // the leave events round-trip through the background sync loop (30-60s
225
234
  // under full-suite load). Forgetting removes each room from the local
226
235
  // store immediately; the server only accepts a forget once membership is
@@ -229,15 +238,23 @@ export async function deleteFolder(storage, folderId) {
229
238
  const client = storage.getClient();
230
239
  await withRateLimitRetry(async () => {
231
240
  await tree.delete();
232
- await client.forget(folderId);
241
+ await client.forget(treeId);
233
242
  for (const subId of subdirectoryIds) {
234
243
  await client.forget(subId);
235
244
  }
236
245
  });
237
- return { id: folderId, deleted: true };
246
+ return { id: treeId, deleted: true };
247
+ }
248
+ /** Deletes a top-level Vault. */
249
+ export async function deleteVault(storage, vaultId) {
250
+ return deleteTree(storage, vaultId);
238
251
  }
239
- export async function renameFile(storage, folderId, fileId, name) {
240
- const tree = await resolveTree(storage, folderId);
252
+ /** Deletes a nested folder. */
253
+ export async function deleteFolder(storage, folderId) {
254
+ return deleteTree(storage, folderId);
255
+ }
256
+ export async function renameFile(storage, treeId, fileId, name) {
257
+ const tree = await resolveTree(storage, treeId);
241
258
  const branch = await resolveFile(tree, fileId);
242
259
  await withRateLimitRetry(() => branch.setName(name));
243
260
  // `setName` resolves when the homeserver accepts the state event, but a
@@ -250,19 +267,19 @@ export async function renameFile(storage, folderId, fileId, name) {
250
267
  }, { timeoutMs: 15000 });
251
268
  return { id: fileId, name };
252
269
  }
253
- export async function deleteFile(storage, folderId, fileId) {
254
- const tree = await resolveTree(storage, folderId);
270
+ export async function deleteFile(storage, treeId, fileId) {
271
+ const tree = await resolveTree(storage, treeId);
255
272
  const branch = await resolveFile(tree, fileId);
256
273
  await withRateLimitRetry(() => branch.delete());
257
274
  return { id: fileId, deleted: true };
258
275
  }
259
- export async function uploadFile(storage, folderId, name, bytes, mimetype) {
260
- const tree = await resolveTree(storage, folderId);
276
+ export async function uploadFile(storage, treeId, name, bytes, mimetype) {
277
+ const tree = await resolveTree(storage, treeId);
261
278
  const fileId = await withRateLimitRetry(() => storage.uploadFile(tree, name, toArrayBuffer(bytes), mimetype));
262
279
  return { id: fileId, name, mimetype };
263
280
  }
264
- export async function downloadFile(storage, folderId, fileId) {
265
- const tree = await resolveTree(storage, folderId);
281
+ export async function downloadFile(storage, treeId, fileId) {
282
+ const tree = await resolveTree(storage, treeId);
266
283
  const branch = await resolveFile(tree, fileId);
267
284
  let result;
268
285
  try {
@@ -288,8 +305,8 @@ function tsToIso(ts) {
288
305
  return null;
289
306
  return new Date(ts).toISOString();
290
307
  }
291
- export async function getFileDetails(storage, folderId, fileId) {
292
- const tree = await resolveTree(storage, folderId);
308
+ export async function getFileDetails(storage, treeId, fileId) {
309
+ const tree = await resolveTree(storage, treeId);
293
310
  const branch = await resolveFile(tree, fileId);
294
311
  const name = branch.getName();
295
312
  let mimetype = null;
@@ -328,10 +345,10 @@ export async function getFileDetails(storage, folderId, fileId) {
328
345
  }
329
346
  return { name, mimetype, size, createdAt, updatedAt };
330
347
  }
331
- export async function getFolderDetails(storage, folderId) {
332
- const tree = await resolveTree(storage, folderId);
348
+ async function getTreeDetails(storage, treeId) {
349
+ const tree = await resolveTree(storage, treeId);
333
350
  const client = storage.getClient();
334
- const room = client.getRoom(folderId);
351
+ const room = client.getRoom(treeId);
335
352
  let createdAt = null;
336
353
  let memberCount = null;
337
354
  if (room) {
@@ -345,9 +362,17 @@ export async function getFolderDetails(storage, folderId) {
345
362
  }
346
363
  }
347
364
  return {
348
- name: tree.room.name || roomDisplayName(storage, folderId),
349
- id: folderId,
365
+ name: tree.room.name || roomDisplayName(storage, treeId),
366
+ id: treeId,
350
367
  createdAt,
351
368
  memberCount,
352
369
  };
353
370
  }
371
+ /** Returns details for a top-level Vault. */
372
+ export async function getVaultDetails(storage, vaultId) {
373
+ return getTreeDetails(storage, vaultId);
374
+ }
375
+ /** Returns details for a nested folder. */
376
+ export async function getFolderDetails(storage, folderId) {
377
+ return getTreeDetails(storage, folderId);
378
+ }
@@ -1,4 +1,9 @@
1
1
  /** The typed result contract for every `core/operations.ts` function. */
2
+ export interface VaultInfo {
3
+ id: string;
4
+ name: string;
5
+ }
6
+ /** A nested directory node inside a vault. */
2
7
  export interface FolderInfo {
3
8
  id: string;
4
9
  name: string;
@@ -14,17 +19,17 @@ export interface Member {
14
19
  membership: string;
15
20
  }
16
21
  export interface ShareResult {
17
- folderId: string;
22
+ vaultId: string;
18
23
  userId: string;
19
24
  role: string;
20
25
  }
21
26
  export interface UnshareResult {
22
- folderId: string;
27
+ vaultId: string;
23
28
  userId: string;
24
29
  removed: boolean;
25
30
  }
26
31
  export interface JoinResult {
27
- folderId: string;
32
+ vaultId: string;
28
33
  joined: boolean;
29
34
  }
30
35
  export interface DeleteResult {
@@ -55,6 +60,13 @@ export interface FileDetails {
55
60
  createdAt: string | null;
56
61
  updatedAt: string | null;
57
62
  }
63
+ export interface VaultDetails {
64
+ name: string;
65
+ id: string;
66
+ createdAt: string | null;
67
+ memberCount: number | null;
68
+ }
69
+ /** Details for a nested directory node inside a vault. */
58
70
  export interface FolderDetails {
59
71
  name: string;
60
72
  id: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telecrypt-io/storage",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "license": "BUSL-1.1",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",