jazz-tools 0.15.11 → 0.15.12

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.js CHANGED
@@ -34,7 +34,7 @@ import {
34
34
  subscribeToCoValue,
35
35
  zodReExport_exports,
36
36
  zodSchemaToCoSchema
37
- } from "./chunk-MLLG3GBR.js";
37
+ } from "./chunk-DZFT4EZM.js";
38
38
 
39
39
  // src/tools/auth/clerk/index.ts
40
40
  import {
@@ -1,5 +1,3 @@
1
- "use client";
2
-
3
1
  // src/react/provider.tsx
4
2
  import {
5
3
  JazzBrowserContextManager
@@ -698,4 +696,4 @@ export {
698
696
  usePassphraseAuth2 as usePassphraseAuth,
699
697
  useProgressiveImg
700
698
  };
701
- //# sourceMappingURL=index.js.map
699
+ //# sourceMappingURL=index.js.mapRL=index.js.map
@@ -1,5 +1,3 @@
1
- "use client";
2
-
3
1
  // src/react/testing.tsx
4
2
  export * from "jazz-tools/react-core/testing";
5
- //# sourceMappingURL=testing.js.map
3
+ //# sourceMappingURL=testing.js.map=testing.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/testing.tsx"],"sourcesContent":["export * from \"jazz-tools/react-core/testing\";\n"],"mappings":";;;AAAA,cAAc;","names":[]}
1
+ {"version":3,"sources":["../../src/react/testing.tsx"],"sourcesContent":["export * from \"jazz-tools/react-core/testing\";\n"],"mappings":";AAAA,cAAc;","names":[]}]}
package/dist/testing.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  createAnonymousJazzContext,
7
7
  createJazzContext,
8
8
  randomSessionProvider
9
- } from "./chunk-MLLG3GBR.js";
9
+ } from "./chunk-DZFT4EZM.js";
10
10
 
11
11
  // src/tools/testing.ts
12
12
  import { LocalNode } from "cojson";
@@ -1 +1 @@
1
- {"version":3,"file":"ContextManager.d.ts","sourceRoot":"","sources":["../../../src/tools/implementation/ContextManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ContextManager.d.ts","sourceRoot":"","sources":["../../../src/tools/implementation/ContextManager.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"CoValueCoreSubscription.d.ts","sourceRoot":"","sources":["../../../src/tools/subscribe/CoValueCoreSubscription.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEtE,qBAAa,uBAAuB;IAOzB,IAAI,EAAE,SAAS;IACf,EAAE,EAAE,MAAM;IACV,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,aAAa,KAAK,IAAI;IACrD,SAAS,CAAC,EAAE,OAAO;IAT5B,YAAY,EAAE,MAAM,IAAI,CAAY;IACpC,YAAY,UAAS;IAErB,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;gBAGnB,IAAI,EAAE,SAAS,EACf,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,aAAa,KAAK,IAAI,EACrD,SAAS,CAAC,EAAE,OAAO,YAAA;IAsB5B,gBAAgB;IAwBhB,SAAS,CAAC,KAAK,EAAE,UAAU;IAU3B,WAAW;CAKZ"}
1
+ {"version":3,"file":"CoValueCoreSubscription.d.ts","sourceRoot":"","sources":["../../../src/tools/subscribe/CoValueCoreSubscription.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEtE,qBAAa,uBAAuB;IAOzB,IAAI,EAAE,SAAS;IACf,EAAE,EAAE,MAAM;IACV,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,aAAa,KAAK,IAAI;IACrD,SAAS,CAAC,EAAE,OAAO;IAT5B,YAAY,EAAE,MAAM,IAAI,CAAY;IACpC,YAAY,UAAS;IAErB,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;gBAGnB,IAAI,EAAE,SAAS,EACf,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,aAAa,KAAK,IAAI,EACrD,SAAS,CAAC,EAAE,OAAO,YAAA;IA0B5B,gBAAgB;IAwBhB,SAAS,CAAC,KAAK,EAAE,UAAU;IAU3B,WAAW;CAKZ"}
@@ -0,0 +1,5 @@
1
+ export declare function createAsyncStorage({ filename }: {
2
+ filename?: string;
3
+ }): Promise<import("cojson").StorageApiAsync>;
4
+ export declare function getDbPath(defaultDbPath?: string): string;
5
+ //# sourceMappingURL=testStorage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testStorage.d.ts","sourceRoot":"","sources":["../../../src/tools/tests/testStorage.ts"],"names":[],"mappings":"AA+CA,wBAAsB,kBAAkB,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,6CAU3E;AAED,wBAAgB,SAAS,CAAC,aAAa,CAAC,EAAE,MAAM,UAU/C"}
package/package.json CHANGED
@@ -139,7 +139,7 @@
139
139
  },
140
140
  "type": "module",
141
141
  "license": "MIT",
142
- "version": "0.15.11",
142
+ "version": "0.15.12",
143
143
  "dependencies": {
144
144
  "@manuscripts/prosemirror-recreate-steps": "^0.1.4",
145
145
  "@scure/base": "1.2.1",
@@ -158,9 +158,9 @@
158
158
  "prosemirror-state": "^1.4.3",
159
159
  "prosemirror-transform": "^1.9.0",
160
160
  "zod": "3.25.28",
161
- "cojson": "0.15.11",
162
- "cojson-storage-indexeddb": "0.15.11",
163
- "cojson-transport-ws": "0.15.11"
161
+ "cojson": "0.15.12",
162
+ "cojson-storage-indexeddb": "0.15.12",
163
+ "cojson-transport-ws": "0.15.12"
164
164
  },
165
165
  "devDependencies": {
166
166
  "@scure/bip39": "^1.3.0",
@@ -47,6 +47,26 @@ describe("useCoState", () => {
47
47
  expect(result.current?.value).toBe("123");
48
48
  });
49
49
 
50
+ it("should return null on invalid id", async () => {
51
+ const TestMap = co.map({
52
+ value: z.string(),
53
+ });
54
+
55
+ const account = await createJazzTestAccount({
56
+ isCurrentActiveAccount: true,
57
+ });
58
+
59
+ const { result } = renderHook(() => useCoState(TestMap, "test", {}), {
60
+ account,
61
+ });
62
+
63
+ expect(result.current).toBeUndefined();
64
+
65
+ await waitFor(() => {
66
+ expect(result.current).toBeNull();
67
+ });
68
+ });
69
+
50
70
  it("should update the value when the coValue changes", async () => {
51
71
  const TestMap = co.map({
52
72
  value: z.string(),
@@ -279,8 +279,12 @@ export class JazzContextManager<
279
279
  },
280
280
  );
281
281
 
282
- prevContext.node.syncManager.addPeer(currentAccountAsPeer);
282
+ // Closing storage on the prevContext to avoid conflicting transactions and getting stuck on waitForAllCoValuesSync
283
+ // The storage is reachable through currentContext using the connectedPeers
284
+ prevContext.node.removeStorage();
285
+
283
286
  currentContext.node.syncManager.addPeer(prevAccountAsPeer);
287
+ prevContext.node.syncManager.addPeer(currentAccountAsPeer);
284
288
 
285
289
  try {
286
290
  await this.props.onAnonymousAccountDiscarded?.(prevContext.me);
@@ -28,6 +28,10 @@ export class CoValueCoreSubscription {
28
28
  this.subscribeToState();
29
29
  this.listener("unavailable");
30
30
  }
31
+ })
32
+ .catch((error) => {
33
+ console.error("Unexpected error loading CoValue: ", error);
34
+ this.listener("unavailable");
31
35
  });
32
36
  }
33
37
  }
@@ -1,3 +1,4 @@
1
+ import { StorageAPI } from "cojson";
1
2
  import { WasmCrypto } from "cojson/crypto/WasmCrypto";
2
3
  import { beforeEach, describe, expect, test, vi } from "vitest";
3
4
  import {
@@ -32,6 +33,7 @@ import {
32
33
  getPeerConnectedToTestSyncServer,
33
34
  setupJazzTestSync,
34
35
  } from "../testing";
36
+ import { createAsyncStorage, getDbPath } from "./testStorage";
35
37
 
36
38
  const Crypto = await WasmCrypto.create();
37
39
 
@@ -40,12 +42,14 @@ class TestJazzContextManager<Acc extends Account> extends JazzContextManager<
40
42
  JazzContextManagerBaseProps<Acc> & {
41
43
  defaultProfileName?: string;
42
44
  AccountSchema?: AccountClass<Acc>;
45
+ storage?: string;
43
46
  }
44
47
  > {
45
48
  async getNewContext(
46
49
  props: JazzContextManagerBaseProps<Acc> & {
47
50
  defaultProfileName?: string;
48
51
  AccountSchema?: AccountClass<Acc> & CoValueFromRaw<Acc>;
52
+ storage?: string;
49
53
  },
50
54
  authProps?: JazzContextManagerAuthProps,
51
55
  ) {
@@ -58,6 +62,7 @@ class TestJazzContextManager<Acc extends Account> extends JazzContextManager<
58
62
  sessionProvider: randomSessionProvider,
59
63
  authSecretStorage: this.getAuthSecretStorage(),
60
64
  AccountSchema: props.AccountSchema,
65
+ storage: await createAsyncStorage({ filename: props.storage }),
61
66
  });
62
67
 
63
68
  return {
@@ -76,12 +81,14 @@ class TestJazzContextManager<Acc extends Account> extends JazzContextManager<
76
81
  describe("ContextManager", () => {
77
82
  let manager: TestJazzContextManager<Account>;
78
83
  let authSecretStorage: AuthSecretStorage;
84
+ let storage: StorageAPI;
79
85
 
80
86
  function getCurrentValue() {
81
87
  return manager.getCurrentValue() as JazzAuthContext<Account>;
82
88
  }
83
89
 
84
90
  beforeEach(async () => {
91
+ storage = await createAsyncStorage({});
85
92
  KvStoreContext.getInstance().initialize(new InMemoryKVStore());
86
93
  authSecretStorage = new AuthSecretStorage();
87
94
  await authSecretStorage.clear();
@@ -232,6 +239,78 @@ describe("ContextManager", () => {
232
239
  expect(onAnonymousAccountDiscarded).not.toHaveBeenCalled();
233
240
  });
234
241
 
242
+ test("onAnonymousAccountDiscarded should not block the authentication when storage is active", async () => {
243
+ const dbFilename = getDbPath();
244
+
245
+ const AccountRoot = co.map({
246
+ value: z.string(),
247
+ get transferredRoot(): z.ZodOptional<typeof AccountRoot> {
248
+ return co.optional(AccountRoot);
249
+ },
250
+ });
251
+
252
+ let lastRootId: string | undefined;
253
+
254
+ const CustomAccount = co
255
+ .account({
256
+ root: AccountRoot,
257
+ profile: co.profile(),
258
+ })
259
+ .withMigration(async (account) => {
260
+ account.root = AccountRoot.create(
261
+ {
262
+ value: "Hello",
263
+ },
264
+ Group.create(this).makePublic(),
265
+ );
266
+ });
267
+
268
+ const customManager = new TestJazzContextManager<
269
+ InstanceOfSchema<typeof CustomAccount>
270
+ >();
271
+
272
+ await customManager.createContext({
273
+ AccountSchema: anySchemaToCoSchema(CustomAccount),
274
+ storage: dbFilename,
275
+ onAnonymousAccountDiscarded: async (anonymousAccount) => {
276
+ const anonymousAccountWithRoot = await anonymousAccount.ensureLoaded({
277
+ resolve: { root: true },
278
+ });
279
+
280
+ const me = await CustomAccount.getMe().ensureLoaded({
281
+ resolve: { root: true },
282
+ });
283
+
284
+ me.root.transferredRoot = anonymousAccountWithRoot.root;
285
+ },
286
+ });
287
+
288
+ const prevContextNode = customManager.getCurrentValue()!.node;
289
+
290
+ expect(prevContextNode.storage).toBeDefined();
291
+
292
+ const account = (
293
+ customManager.getCurrentValue() as JazzAuthContext<
294
+ InstanceOfSchema<typeof CustomAccount>
295
+ >
296
+ ).me;
297
+
298
+ await customManager.authenticate({
299
+ accountID: account.id,
300
+ accountSecret: account._raw.core.node.getCurrentAgent().agentSecret,
301
+ provider: "test",
302
+ });
303
+
304
+ // The storage should be closed and set to undefined
305
+ expect(prevContextNode.storage).toBeUndefined();
306
+
307
+ const me = await CustomAccount.getMe().ensureLoaded({
308
+ resolve: { root: { transferredRoot: true } },
309
+ });
310
+
311
+ expect(me.root.transferredRoot?.value).toBe("Hello");
312
+ });
313
+
235
314
  test("the migration should be applied correctly on existing accounts", async () => {
236
315
  const AccountRoot = co.map({
237
316
  value: z.string(),
@@ -266,8 +345,6 @@ describe("ContextManager", () => {
266
345
  >
267
346
  ).me;
268
347
 
269
- console.log("before", account._refs.root?.id);
270
-
271
348
  await customManager.authenticate({
272
349
  accountID: account.id,
273
350
  accountSecret: account._raw.core.node.getCurrentAgent().agentSecret,
@@ -278,8 +355,6 @@ describe("ContextManager", () => {
278
355
  resolve: { root: true },
279
356
  });
280
357
 
281
- console.log("after", me._refs.root?.id);
282
-
283
358
  expect(me.root.id).toBe(lastRootId);
284
359
  });
285
360
 
@@ -33,6 +33,15 @@ test("load a value", async () => {
33
33
  expect(john?.name).toBe("John");
34
34
  });
35
35
 
36
+ test("return null if id is invalid", async () => {
37
+ const Person = co.map({
38
+ name: z.string(),
39
+ });
40
+
41
+ const john = await Person.load("test");
42
+ expect(john).toBeNull();
43
+ });
44
+
36
45
  test("retry an unavailable value", async () => {
37
46
  const Person = co.map({
38
47
  name: z.string(),
@@ -0,0 +1,70 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { unlinkSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { SQLiteDatabaseDriverAsync, getSqliteStorageAsync } from "cojson";
6
+ import Database, { type Database as DatabaseT } from "libsql";
7
+ import { onTestFinished } from "vitest";
8
+
9
+ class LibSQLSqliteAsyncDriver implements SQLiteDatabaseDriverAsync {
10
+ private readonly db: DatabaseT;
11
+
12
+ constructor(filename: string) {
13
+ this.db = new Database(filename, {});
14
+ }
15
+
16
+ async initialize() {
17
+ await this.db.pragma("journal_mode = WAL");
18
+ }
19
+
20
+ async run(sql: string, params: unknown[]) {
21
+ this.db.prepare(sql).run(params);
22
+ }
23
+
24
+ async query<T>(sql: string, params: unknown[]): Promise<T[]> {
25
+ return this.db.prepare(sql).all(params) as T[];
26
+ }
27
+
28
+ async get<T>(sql: string, params: unknown[]): Promise<T | undefined> {
29
+ return this.db.prepare(sql).get(params) as T | undefined;
30
+ }
31
+
32
+ async transaction(callback: () => unknown) {
33
+ await this.run("BEGIN TRANSACTION", []);
34
+
35
+ try {
36
+ await callback();
37
+ await this.run("COMMIT", []);
38
+ } catch (error) {
39
+ await this.run("ROLLBACK", []);
40
+ }
41
+ }
42
+
43
+ async closeDb() {
44
+ this.db.close();
45
+ }
46
+ }
47
+
48
+ export async function createAsyncStorage({ filename }: { filename?: string }) {
49
+ const storage = await getSqliteStorageAsync(
50
+ new LibSQLSqliteAsyncDriver(getDbPath(filename)),
51
+ );
52
+
53
+ onTestFinished(() => {
54
+ storage.close();
55
+ });
56
+
57
+ return storage;
58
+ }
59
+
60
+ export function getDbPath(defaultDbPath?: string) {
61
+ const dbPath = defaultDbPath ?? join(tmpdir(), `test-${randomUUID()}.db`);
62
+
63
+ if (!defaultDbPath) {
64
+ onTestFinished(() => {
65
+ unlinkSync(dbPath);
66
+ });
67
+ }
68
+
69
+ return dbPath;
70
+ }