@telecrypt-io/storage 0.2.0 → 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/README.md CHANGED
@@ -8,9 +8,9 @@ Files are encrypted on the client before upload. The server stores only opaque c
8
8
  never holds the decryption keys. Shared folders 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
- **Status:** library source only. The current public npm release is
12
- `@telecrypt-io/storage@0.1.3`; no version has been released from this
13
- repository yet.
11
+ **Status:** library source only. `@telecrypt-io/storage@0.2.0` is the current public release,
12
+ published from this repository's protected `v0.2.0` tag with NPM Trusted Publishing/OIDC
13
+ provenance. The older `0.1.3` release is the immutable legacy combined library-and-CLI package.
14
14
 
15
15
  ## Install
16
16
 
@@ -117,6 +117,13 @@ export declare class TeleCryptIOStorage {
117
117
  constructor(client: MatrixClient);
118
118
  /** The underlying matrix-js-sdk client (e.g. to stop it, or for advanced/interop use). */
119
119
  getClient(): MatrixClient;
120
+ /**
121
+ * Refreshes a room's current state from the homeserver. The background sync
122
+ * loop is intentionally asynchronous, so a short-lived CLI process can
123
+ * otherwise list a stale state snapshot immediately after another process
124
+ * changed a file name or branch.
125
+ */
126
+ refreshRoomState(roomId: string): Promise<void>;
120
127
  /**
121
128
  * Recommended entry point: builds the MatrixClient with a persistent crypto
122
129
  * store and the secret-storage callback wiring `keys.*` needs, starts the
@@ -1,4 +1,4 @@
1
- import { ClientEvent, createClient, SyncState } from "matrix-js-sdk";
1
+ import { ClientEvent, createClient, MatrixEvent, SyncState } from "matrix-js-sdk";
2
2
  import { Method } from "matrix-js-sdk/lib/http-api/method.js";
3
3
  import { ClientPrefix } from "matrix-js-sdk/lib/http-api/prefix.js";
4
4
  import { encryptAttachment, decryptAttachment } from "matrix-encrypt-attachment";
@@ -12,6 +12,19 @@ export class TeleCryptIOStorage {
12
12
  getClient() {
13
13
  return this.client;
14
14
  }
15
+ /**
16
+ * Refreshes a room's current state from the homeserver. The background sync
17
+ * loop is intentionally asynchronous, so a short-lived CLI process can
18
+ * otherwise list a stale state snapshot immediately after another process
19
+ * changed a file name or branch.
20
+ */
21
+ async refreshRoomState(roomId) {
22
+ const room = this.client.getRoom(roomId);
23
+ if (!room)
24
+ throw new Error(`Unknown room: ${roomId}`);
25
+ const stateEvents = await this.client.roomState(roomId);
26
+ room.currentState.setStateEvents(stateEvents.map((event) => new MatrixEvent(event)));
27
+ }
15
28
  /**
16
29
  * Recommended entry point: builds the MatrixClient with a persistent crypto
17
30
  * store and the secret-storage callback wiring `keys.*` needs, starts the
@@ -148,6 +148,7 @@ export async function listMembers(storage, folderId) {
148
148
  }
149
149
  export async function listFiles(storage, folderId) {
150
150
  const tree = await resolveTree(storage, folderId);
151
+ await storage.refreshRoomState(folderId);
151
152
  return tree.listFiles().map((f) => ({ id: f.id, name: f.getName() }));
152
153
  }
153
154
  export async function listSubfolders(storage, folderId) {
@@ -173,6 +174,14 @@ export async function renameFile(storage, folderId, fileId, name) {
173
174
  const tree = await resolveTree(storage, folderId);
174
175
  const branch = await resolveFile(tree, fileId);
175
176
  await branch.setName(name);
177
+ // `setName` resolves when the homeserver accepts the state event, but a
178
+ // fresh CLI/UI process can still read the previous local room state for a
179
+ // short time. Do not report success until this client has observed the new
180
+ // name through its normal sync loop.
181
+ await waitForCondition(() => {
182
+ const current = tree.getFile(fileId);
183
+ return current?.getName() === name ? current : null;
184
+ }, { timeoutMs: 15000 });
176
185
  return { id: fileId, name };
177
186
  }
178
187
  export async function deleteFile(storage, folderId, fileId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telecrypt-io/storage",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "license": "BUSL-1.1",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -44,6 +44,7 @@
44
44
  "@typescript-eslint/eslint-plugin": "8.64.0",
45
45
  "@typescript-eslint/parser": "8.64.0",
46
46
  "eslint": "10.8.0",
47
+ "fake-indexeddb": "6.2.5",
47
48
  "tsx": "4.23.1",
48
49
  "typescript": "5.9.3",
49
50
  "vitest": "4.1.10"