@telecrypt-io/storage 0.2.0 → 0.2.2

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,14 +8,14 @@ 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.2` is the current public release,
12
+ published from this repository's protected `v0.2.2` 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
 
17
17
  ```bash
18
- npm install @telecrypt-io/storage
18
+ npm install @telecrypt-io/storage@0.2.2
19
19
  ```
20
20
 
21
21
  This gives you the `TeleCryptIOStorage` library and its browser-safe `core` API.
@@ -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
@@ -28,11 +28,10 @@ export interface OidcTokenSet {
28
28
  *
29
29
  * NODE CALLERS: this internally constructs oidc-client-ts state that
30
30
  * requires `window.sessionStorage`/`window.localStorage` to exist (a real
31
- * browser has both natively). Under plain Node, wrap this ONE call in
32
- * `src/cli/oidcWindowPolyfill.ts`'s `withOidcWindowShim()` — see that file's
33
- * doc comment for why it must be scoped narrowly (a permanent global
34
- * `window` breaks the rust-crypto WASM's own environment detection) and why
35
- * it's safe here specifically (called once, before any crypto/WASM exists).
31
+ * browser has both natively). A Node adapter may install those only around
32
+ * this call: a permanent global `window` breaks rust-crypto WASM's own
33
+ * environment detection. The functional-test-only adapter is kept in
34
+ * `test/harness/oidcWindowShim.ts`, rather than in the production SDK.
36
35
  */
37
36
  export declare function discoverOidcIssuer(homeserverBaseUrl: string): Promise<OidcClientConfig>;
38
37
  /**
package/dist/core/oidc.js CHANGED
@@ -19,11 +19,10 @@ import { CliError } from "./errors.js";
19
19
  *
20
20
  * NODE CALLERS: this internally constructs oidc-client-ts state that
21
21
  * requires `window.sessionStorage`/`window.localStorage` to exist (a real
22
- * browser has both natively). Under plain Node, wrap this ONE call in
23
- * `src/cli/oidcWindowPolyfill.ts`'s `withOidcWindowShim()` — see that file's
24
- * doc comment for why it must be scoped narrowly (a permanent global
25
- * `window` breaks the rust-crypto WASM's own environment detection) and why
26
- * it's safe here specifically (called once, before any crypto/WASM exists).
22
+ * browser has both natively). A Node adapter may install those only around
23
+ * this call: a permanent global `window` breaks rust-crypto WASM's own
24
+ * environment detection. The functional-test-only adapter is kept in
25
+ * `test/harness/oidcWindowShim.ts`, rather than in the production SDK.
27
26
  */
28
27
  export async function discoverOidcIssuer(homeserverBaseUrl) {
29
28
  const client = createClient({ baseUrl: homeserverBaseUrl });
@@ -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.2",
4
4
  "license": "BUSL-1.1",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -28,6 +28,7 @@
28
28
  "build": "tsc",
29
29
  "lint": "eslint src test --ext .ts",
30
30
  "test": "vitest run",
31
+ "test:unit": "vitest run --config vitest.unit.config.ts",
31
32
  "test:watch": "vitest",
32
33
  "synapse:up": "./throwaway_synapse/up.sh",
33
34
  "synapse:fresh": "./throwaway_synapse/up.sh --fresh",
@@ -44,6 +45,7 @@
44
45
  "@typescript-eslint/eslint-plugin": "8.64.0",
45
46
  "@typescript-eslint/parser": "8.64.0",
46
47
  "eslint": "10.8.0",
48
+ "fake-indexeddb": "6.2.5",
47
49
  "tsx": "4.23.1",
48
50
  "typescript": "5.9.3",
49
51
  "vitest": "4.1.10"