jazz-tools 0.18.15 → 0.18.17

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.
Files changed (91) hide show
  1. package/.svelte-kit/__package__/media/image.svelte +104 -98
  2. package/.svelte-kit/__package__/media/image.svelte.d.ts.map +1 -1
  3. package/.svelte-kit/__package__/tests/media/image.svelte.test.js +16 -2
  4. package/.turbo/turbo-build.log +48 -38
  5. package/CHANGELOG.md +20 -0
  6. package/dist/better-auth/database-adapter/index.d.ts +50 -0
  7. package/dist/better-auth/database-adapter/index.d.ts.map +1 -0
  8. package/dist/better-auth/database-adapter/index.js +920 -0
  9. package/dist/better-auth/database-adapter/index.js.map +1 -0
  10. package/dist/better-auth/database-adapter/repository/account.d.ts +24 -0
  11. package/dist/better-auth/database-adapter/repository/account.d.ts.map +1 -0
  12. package/dist/better-auth/database-adapter/repository/generic.d.ts +45 -0
  13. package/dist/better-auth/database-adapter/repository/generic.d.ts.map +1 -0
  14. package/dist/better-auth/database-adapter/repository/index.d.ts +6 -0
  15. package/dist/better-auth/database-adapter/repository/index.d.ts.map +1 -0
  16. package/dist/better-auth/database-adapter/repository/session.d.ts +29 -0
  17. package/dist/better-auth/database-adapter/repository/session.d.ts.map +1 -0
  18. package/dist/better-auth/database-adapter/repository/user.d.ts +30 -0
  19. package/dist/better-auth/database-adapter/repository/user.d.ts.map +1 -0
  20. package/dist/better-auth/database-adapter/repository/verification.d.ts +18 -0
  21. package/dist/better-auth/database-adapter/repository/verification.d.ts.map +1 -0
  22. package/dist/better-auth/database-adapter/schema.d.ts +27 -0
  23. package/dist/better-auth/database-adapter/schema.d.ts.map +1 -0
  24. package/dist/better-auth/database-adapter/tests/index.test.d.ts +2 -0
  25. package/dist/better-auth/database-adapter/tests/index.test.d.ts.map +1 -0
  26. package/dist/better-auth/database-adapter/tests/repository/account.test.d.ts +2 -0
  27. package/dist/better-auth/database-adapter/tests/repository/account.test.d.ts.map +1 -0
  28. package/dist/better-auth/database-adapter/tests/repository/generic.test.d.ts +2 -0
  29. package/dist/better-auth/database-adapter/tests/repository/generic.test.d.ts.map +1 -0
  30. package/dist/better-auth/database-adapter/tests/repository/session.test.d.ts +2 -0
  31. package/dist/better-auth/database-adapter/tests/repository/session.test.d.ts.map +1 -0
  32. package/dist/better-auth/database-adapter/tests/repository/user.test.d.ts +2 -0
  33. package/dist/better-auth/database-adapter/tests/repository/user.test.d.ts.map +1 -0
  34. package/dist/better-auth/database-adapter/tests/repository/verification.test.d.ts +2 -0
  35. package/dist/better-auth/database-adapter/tests/repository/verification.test.d.ts.map +1 -0
  36. package/dist/better-auth/database-adapter/tests/sync-utils.d.ts +16 -0
  37. package/dist/better-auth/database-adapter/tests/sync-utils.d.ts.map +1 -0
  38. package/dist/better-auth/database-adapter/tests/utils.test.d.ts +2 -0
  39. package/dist/better-auth/database-adapter/tests/utils.test.d.ts.map +1 -0
  40. package/dist/better-auth/database-adapter/utils.d.ts +16 -0
  41. package/dist/better-auth/database-adapter/utils.d.ts.map +1 -0
  42. package/dist/{chunk-GRN6OAUX.js → chunk-OTWWOZMB.js} +73 -4
  43. package/dist/chunk-OTWWOZMB.js.map +1 -0
  44. package/dist/index.js +1 -1
  45. package/dist/react/index.js +2 -0
  46. package/dist/react/index.js.map +1 -1
  47. package/dist/react/media/image.d.ts.map +1 -1
  48. package/dist/react-native-core/index.js +3 -1
  49. package/dist/react-native-core/index.js.map +1 -1
  50. package/dist/react-native-core/media/image.d.ts.map +1 -1
  51. package/dist/svelte/media/image.svelte +104 -98
  52. package/dist/svelte/media/image.svelte.d.ts.map +1 -1
  53. package/dist/svelte/tests/media/image.svelte.test.js +16 -2
  54. package/dist/testing.js +1 -1
  55. package/dist/tools/implementation/refs.d.ts +1 -1
  56. package/dist/tools/implementation/refs.d.ts.map +1 -1
  57. package/dist/tools/subscribe/CoValueCoreSubscription.d.ts +4 -0
  58. package/dist/tools/subscribe/CoValueCoreSubscription.d.ts.map +1 -1
  59. package/dist/tools/subscribe/SubscriptionScope.d.ts +7 -0
  60. package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
  61. package/dist/tools/subscribe/index.d.ts.map +1 -1
  62. package/jazz-tools-0.18.6.tgz +0 -0
  63. package/package.json +10 -5
  64. package/src/better-auth/database-adapter/index.ts +228 -0
  65. package/src/better-auth/database-adapter/repository/account.ts +131 -0
  66. package/src/better-auth/database-adapter/repository/generic.ts +297 -0
  67. package/src/better-auth/database-adapter/repository/index.ts +5 -0
  68. package/src/better-auth/database-adapter/repository/session.ts +190 -0
  69. package/src/better-auth/database-adapter/repository/user.ts +158 -0
  70. package/src/better-auth/database-adapter/repository/verification.ts +37 -0
  71. package/src/better-auth/database-adapter/schema.ts +222 -0
  72. package/src/better-auth/database-adapter/tests/index.test.ts +690 -0
  73. package/src/better-auth/database-adapter/tests/repository/account.test.ts +149 -0
  74. package/src/better-auth/database-adapter/tests/repository/generic.test.ts +183 -0
  75. package/src/better-auth/database-adapter/tests/repository/session.test.ts +419 -0
  76. package/src/better-auth/database-adapter/tests/repository/user.test.ts +673 -0
  77. package/src/better-auth/database-adapter/tests/repository/verification.test.ts +101 -0
  78. package/src/better-auth/database-adapter/tests/sync-utils.ts +127 -0
  79. package/src/better-auth/database-adapter/tests/utils.test.ts +787 -0
  80. package/src/better-auth/database-adapter/utils.ts +178 -0
  81. package/src/react/media/image.tsx +2 -0
  82. package/src/react/tests/media/image.test.tsx +20 -2
  83. package/src/react-native-core/media/image.tsx +4 -1
  84. package/src/svelte/media/image.svelte +104 -98
  85. package/src/svelte/tests/media/image.svelte.test.ts +18 -2
  86. package/src/tools/implementation/refs.ts +27 -3
  87. package/src/tools/subscribe/CoValueCoreSubscription.ts +14 -0
  88. package/src/tools/subscribe/SubscriptionScope.ts +62 -1
  89. package/src/tools/subscribe/index.ts +8 -0
  90. package/tsup.config.ts +7 -0
  91. package/dist/chunk-GRN6OAUX.js.map +0 -1
@@ -1,118 +1,122 @@
1
1
  <script lang="ts">
2
- import { ImageDefinition } from "jazz-tools";
3
- import { highestResAvailable } from "jazz-tools/media";
4
- import { onDestroy } from "svelte";
5
- import { CoState } from "../jazz.class.svelte";
6
- import type { ImageProps } from "./image.types.js";
7
-
8
- const { imageId, width, height, ...rest }: ImageProps = $props();
9
-
10
- const imageState = new CoState(ImageDefinition, () => imageId);
11
- let lastBestImage: [string, string] | null = null;
12
-
13
- /**
14
- * For lazy loading, we use the browser's strategy for images with loading="lazy".
15
- * We use an empty image, and when the browser triggers the load event, we load the best available image.
16
- * On page loading, if the image url is already in browser's cache, the load event is triggered immediately.
17
- * This is why we need to use a different blob url for every image.
18
- */
19
- let waitingLazyLoading = $state(rest.loading === "lazy");
20
- const lazyPlaceholder = $derived.by(() =>
21
- waitingLazyLoading ? URL.createObjectURL(emptyPixelBlob) : undefined,
22
- );
23
-
24
- const dimensions = $derived.by<{
25
- width: number | undefined;
26
- height: number | undefined;
27
- }>(() => {
28
- const originalWidth = imageState.current?.originalSize?.[0];
29
- const originalHeight = imageState.current?.originalSize?.[1];
30
-
31
- // Both width and height are "original"
32
- if (width === "original" && height === "original") {
33
- return { width: originalWidth, height: originalHeight };
34
- }
2
+ import { ImageDefinition } from "jazz-tools";
3
+ import { highestResAvailable } from "jazz-tools/media";
4
+ import { onDestroy } from "svelte";
5
+ import { CoState } from "../jazz.class.svelte";
6
+ import type { ImageProps } from "./image.types.js";
7
+
8
+ const { imageId, width, height, ...rest }: ImageProps = $props();
9
+
10
+ const imageState = new CoState(ImageDefinition, () => imageId);
11
+ let lastBestImage: [string, string] | null = null;
12
+
13
+ /**
14
+ * For lazy loading, we use the browser's strategy for images with loading="lazy".
15
+ * We use an empty image, and when the browser triggers the load event, we load the best available image.
16
+ * On page loading, if the image url is already in browser's cache, the load event is triggered immediately.
17
+ * This is why we need to use a different blob url for every image.
18
+ */
19
+ let waitingLazyLoading = $state(rest.loading === "lazy");
20
+ const lazyPlaceholder = $derived.by(() =>
21
+ waitingLazyLoading ? URL.createObjectURL(emptyPixelBlob) : undefined,
22
+ );
23
+
24
+ const dimensions = $derived.by<{
25
+ width: number | undefined;
26
+ height: number | undefined;
27
+ }>(() => {
28
+ const originalWidth = imageState.current?.originalSize?.[0];
29
+ const originalHeight = imageState.current?.originalSize?.[1];
35
30
 
36
- // Width is "original", height is a number
37
- if (width === "original" && typeof height === "number") {
38
- if (originalWidth && originalHeight) {
39
- return {
40
- width: Math.round((height * originalWidth) / originalHeight),
41
- height,
42
- };
31
+ // Both width and height are "original"
32
+ if (width === "original" && height === "original") {
33
+ return { width: originalWidth, height: originalHeight };
43
34
  }
44
- return { width: undefined, height };
45
- }
46
35
 
47
- // Height is "original", width is a number
48
- if (height === "original" && typeof width === "number") {
49
- if (originalWidth && originalHeight) {
50
- return {
51
- width,
52
- height: Math.round((width * originalHeight) / originalWidth),
53
- };
36
+ // Width is "original", height is a number
37
+ if (width === "original" && typeof height === "number") {
38
+ if (originalWidth && originalHeight) {
39
+ return {
40
+ width: Math.round((height * originalWidth) / originalHeight),
41
+ height,
42
+ };
43
+ }
44
+ return { width: undefined, height };
54
45
  }
55
- return { width, height: undefined };
56
- }
57
46
 
58
- // In all other cases, use the property value:
59
- return {
60
- width: width === "original" ? originalWidth : width,
61
- height: height === "original" ? originalHeight : height,
62
- };
63
- });
47
+ // Height is "original", width is a number
48
+ if (height === "original" && typeof width === "number") {
49
+ if (originalWidth && originalHeight) {
50
+ return {
51
+ width,
52
+ height: Math.round((width * originalHeight) / originalWidth),
53
+ };
54
+ }
55
+ return { width, height: undefined };
56
+ }
64
57
 
65
- const src = $derived.by(() => {
66
- if (waitingLazyLoading) {
67
- return lazyPlaceholder;
68
- }
58
+ // In all other cases, use the property value:
59
+ return {
60
+ width: width === "original" ? originalWidth : width,
61
+ height: height === "original" ? originalHeight : height,
62
+ };
63
+ });
69
64
 
70
- const image = imageState.current;
71
- if (!image) return undefined;
65
+ const src = $derived.by(() => {
66
+ if (waitingLazyLoading) {
67
+ return lazyPlaceholder;
68
+ }
72
69
 
73
- const bestImage = highestResAvailable(
74
- image,
75
- dimensions.width || dimensions.height || 9999,
76
- dimensions.height || dimensions.width || 9999,
77
- );
70
+ const image = imageState.current;
71
+ if (image === undefined)
72
+ return "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==";
78
73
 
79
- if (!bestImage) return image.placeholderDataURL;
80
- if (lastBestImage?.[0] === bestImage.image.$jazz.id) return lastBestImage?.[1];
74
+ if (!image) return undefined;
81
75
 
82
- const blob = bestImage.image.toBlob();
76
+ const bestImage = highestResAvailable(
77
+ image,
78
+ dimensions.width || dimensions.height || 9999,
79
+ dimensions.height || dimensions.width || 9999,
80
+ );
83
81
 
84
- if (blob) {
85
- const url = URL.createObjectURL(blob);
86
- revokeObjectURL(lastBestImage?.[1]);
87
- lastBestImage = [bestImage.image.$jazz.id, url];
88
- return url;
89
- }
82
+ if (!bestImage) return image.placeholderDataURL;
83
+ if (lastBestImage?.[0] === bestImage.image.$jazz.id)
84
+ return lastBestImage?.[1];
85
+
86
+ const blob = bestImage.image.toBlob();
87
+
88
+ if (blob) {
89
+ const url = URL.createObjectURL(blob);
90
+ revokeObjectURL(lastBestImage?.[1]);
91
+ lastBestImage = [bestImage.image.$jazz.id, url];
92
+ return url;
93
+ }
90
94
 
91
- return image.placeholderDataURL;
92
- });
95
+ return image.placeholderDataURL;
96
+ });
93
97
 
94
- // Cleanup object URL on component destroy
95
- onDestroy(() => {
96
- revokeObjectURL(lastBestImage?.[1]);
97
- });
98
+ // Cleanup object URL on component destroy
99
+ onDestroy(() => {
100
+ revokeObjectURL(lastBestImage?.[1]);
101
+ });
98
102
 
99
- function revokeObjectURL(url: string | undefined) {
100
- if (url && url.startsWith("blob:")) {
101
- URL.revokeObjectURL(url);
103
+ function revokeObjectURL(url: string | undefined) {
104
+ if (url && url.startsWith("blob:")) {
105
+ URL.revokeObjectURL(url);
106
+ }
102
107
  }
103
- }
104
108
 
105
- const emptyPixelBlob = new Blob(
106
- [
107
- Uint8Array.from(
108
- atob(
109
- "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==",
109
+ const emptyPixelBlob = new Blob(
110
+ [
111
+ Uint8Array.from(
112
+ atob(
113
+ "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==",
114
+ ),
115
+ (c) => c.charCodeAt(0),
110
116
  ),
111
- (c) => c.charCodeAt(0),
112
- ),
113
- ],
114
- { type: "image/png" },
115
- );
117
+ ],
118
+ { type: "image/png" },
119
+ );
116
120
  </script>
117
121
 
118
122
  <img
@@ -120,6 +124,8 @@ const emptyPixelBlob = new Blob(
120
124
  width={dimensions.width}
121
125
  height={dimensions.height}
122
126
  alt={rest.alt}
123
- onload={() => {waitingLazyLoading = false}}
127
+ onload={() => {
128
+ waitingLazyLoading = false;
129
+ }}
124
130
  {...rest}
125
131
  />
@@ -1 +1 @@
1
- {"version":3,"file":"image.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/media/image.svelte.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AA2HnD,QAAA,MAAM,KAAK,gDAAsC,CAAC;AAClD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"image.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/media/image.svelte.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAiInD,QAAA,MAAM,KAAK,gDAAsC,CAAC;AAClD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}
@@ -10,7 +10,7 @@ describe("Image", async () => {
10
10
  });
11
11
  const renderWithAccount = (props) => render(Image, props, { account });
12
12
  describe("initial rendering", () => {
13
- it("should render nothing if coValue is not found", async () => {
13
+ it("should render a blank placeholder while waiting for the coValue to load", async () => {
14
14
  const { container } = renderWithAccount({
15
15
  imageId: "co_zMTubMby3QiKDYnW9e2BEXW7Xaq",
16
16
  alt: "test",
@@ -20,7 +20,21 @@ describe("Image", async () => {
20
20
  expect(img.getAttribute("width")).toBe(null);
21
21
  expect(img.getAttribute("height")).toBe(null);
22
22
  expect(img.alt).toBe("test");
23
- expect(img.src).toBe("");
23
+ expect(img.src).toBe("data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==");
24
+ });
25
+ it("should render nothing if coValue is not found", async () => {
26
+ const { container } = renderWithAccount({
27
+ imageId: "co_zMTubMby3QiKDYnW9e2BEXW7Xaq",
28
+ alt: "test",
29
+ });
30
+ await waitFor(() => {
31
+ const img = container.querySelector("img");
32
+ expect(img).toBeDefined();
33
+ expect(img.getAttribute("width")).toBe(null);
34
+ expect(img.getAttribute("height")).toBe(null);
35
+ expect(img.alt).toBe("test");
36
+ expect(img.src).toBe("");
37
+ });
24
38
  });
25
39
  it("should render an empty image if the image is not loaded yet", async () => {
26
40
  const original = FileStream.create({ owner: account.$jazz.owner });
package/dist/testing.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  createAnonymousJazzContext,
7
7
  createJazzContext,
8
8
  randomSessionProvider
9
- } from "./chunk-GRN6OAUX.js";
9
+ } from "./chunk-OTWWOZMB.js";
10
10
 
11
11
  // src/tools/testing.ts
12
12
  import { LocalNode } from "cojson";
@@ -1,5 +1,5 @@
1
1
  import { type Account } from "../coValues/account.js";
2
- import type { AnonymousJazzAgent, CoValue, ID, RefEncoded } from "../internal.js";
2
+ import { AnonymousJazzAgent, CoValue, ID, RefEncoded } from "../internal.js";
3
3
  export declare class Ref<out V extends CoValue> {
4
4
  readonly id: ID<V>;
5
5
  readonly controlledAccount: Account | AnonymousJazzAgent;
@@ -1 +1 @@
1
- {"version":3,"file":"refs.d.ts","sourceRoot":"","sources":["../../../src/tools/implementation/refs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EACV,kBAAkB,EAClB,OAAO,EACP,EAAE,EACF,UAAU,EACX,MAAM,gBAAgB,CAAC;AAOxB,qBAAa,GAAG,CAAC,GAAG,CAAC,CAAC,SAAS,OAAO;IAElC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAClB,QAAQ,CAAC,iBAAiB,EAAE,OAAO,GAAG,kBAAkB;IACxD,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,OAAO;gBAHf,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EACT,iBAAiB,EAAE,OAAO,GAAG,kBAAkB,EAC/C,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,EACrB,MAAM,EAAE,OAAO;IAOpB,IAAI,IAAI,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAiC/B,IAAI,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,CAEhC;CACF;AAED,wBAAgB,QAAQ,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM,EACnD,MAAM,EAAE,OAAO,EACf,WAAW,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,EAAE,CAAC,OAAO,CAAC,GAAG,SAAS,EACnD,cAAc,EAAE,MAAM,IAAI,EAAE,EAC5B,iBAAiB,EAAE,OAAO,GAAG,kBAAkB,EAC/C,eAAe,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,UAAU,CAAC,OAAO,CAAC,GAClD;KAAG,CAAC,IAAI,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC;CAAE,GAAG;IACjC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IACxD,MAAM,EAAE,MAAM,CAAC;CAChB,CAgDA;AAED,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,SAAS,OAAO,GACxD,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GACnB,KAAK,CAAC"}
1
+ {"version":3,"file":"refs.d.ts","sourceRoot":"","sources":["../../../src/tools/implementation/refs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EACL,kBAAkB,EAClB,OAAO,EACP,EAAE,EACF,UAAU,EAEX,MAAM,gBAAgB,CAAC;AAOxB,qBAAa,GAAG,CAAC,GAAG,CAAC,CAAC,SAAS,OAAO;IAElC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAClB,QAAQ,CAAC,iBAAiB,EAAE,OAAO,GAAG,kBAAkB;IACxD,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,OAAO;gBAHf,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EACT,iBAAiB,EAAE,OAAO,GAAG,kBAAkB,EAC/C,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,EACrB,MAAM,EAAE,OAAO;IAOpB,IAAI,IAAI,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAwD/B,IAAI,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,CAEhC;CACF;AAED,wBAAgB,QAAQ,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM,EACnD,MAAM,EAAE,OAAO,EACf,WAAW,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,EAAE,CAAC,OAAO,CAAC,GAAG,SAAS,EACnD,cAAc,EAAE,MAAM,IAAI,EAAE,EAC5B,iBAAiB,EAAE,OAAO,GAAG,kBAAkB,EAC/C,eAAe,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,UAAU,CAAC,OAAO,CAAC,GAClD;KAAG,CAAC,IAAI,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC;CAAE,GAAG;IACjC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IACxD,MAAM,EAAE,MAAM,CAAC;CAChB,CAgDA;AAED,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,SAAS,OAAO,GACxD,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GACnB,KAAK,CAAC"}
@@ -16,6 +16,10 @@ export declare class CoValueCoreSubscription {
16
16
  private listener;
17
17
  private skipRetry?;
18
18
  constructor(localNode: LocalNode, id: string, listener: (value: RawCoValue | "unavailable") => void, skipRetry?: boolean, branch?: BranchDefinition);
19
+ /**
20
+ * Rehydrates the subscription by resetting the unsubscribed flag and initializing the subscription again
21
+ */
22
+ pullValue(): void;
19
23
  /**
20
24
  * Main entry point for subscription initialization.
21
25
  * Determines the subscription strategy based on current availability and branch requirements.
@@ -1 +1 @@
1
- {"version":3,"file":"CoValueCoreSubscription.d.ts","sourceRoot":"","sources":["../../../src/tools/subscribe/CoValueCoreSubscription.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,SAAS,EAET,UAAU,EACX,MAAM,QAAQ,CAAC;AAChB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;;;;GAKG;AACH,qBAAa,uBAAuB;IAClC,OAAO,CAAC,YAAY,CAAwB;IAC5C,OAAO,CAAC,YAAY,CAAS;IAE7B,OAAO,CAAC,aAAa,CAAC,CAAU;IAChC,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,QAAQ,CAA8C;IAC9D,OAAO,CAAC,SAAS,CAAC,CAAU;gBAG1B,SAAS,EAAE,SAAS,EACpB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,aAAa,KAAK,IAAI,EACrD,SAAS,CAAC,EAAE,OAAO,EACnB,MAAM,CAAC,EAAE,gBAAgB;IAY3B;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAmB9B;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAuB7B;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAqB5B;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAY/B;;;OAGG;IACH,OAAO,CAAC,WAAW;IAsBnB;;;OAGG;IACH,OAAO,CAAC,4BAA4B;IA6BpC;;;OAGG;IACH,OAAO,CAAC,SAAS;IASjB,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,aAAa,GAAG,IAAI;IAM7C;;;OAGG;IACH,WAAW,IAAI,IAAI;CAKpB"}
1
+ {"version":3,"file":"CoValueCoreSubscription.d.ts","sourceRoot":"","sources":["../../../src/tools/subscribe/CoValueCoreSubscription.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,SAAS,EAET,UAAU,EACX,MAAM,QAAQ,CAAC;AAChB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;;;;GAKG;AACH,qBAAa,uBAAuB;IAClC,OAAO,CAAC,YAAY,CAAwB;IAC5C,OAAO,CAAC,YAAY,CAAS;IAE7B,OAAO,CAAC,aAAa,CAAC,CAAU;IAChC,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,QAAQ,CAA8C;IAC9D,OAAO,CAAC,SAAS,CAAC,CAAU;gBAG1B,SAAS,EAAE,SAAS,EACpB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,aAAa,KAAK,IAAI,EACrD,SAAS,CAAC,EAAE,OAAO,EACnB,MAAM,CAAC,EAAE,gBAAgB;IAY3B;;OAEG;IACH,SAAS;IAWT;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAmB9B;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAuB7B;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAqB5B;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAY/B;;;OAGG;IACH,OAAO,CAAC,WAAW;IAsBnB;;;OAGG;IACH,OAAO,CAAC,4BAA4B;IA6BpC;;;OAGG;IACH,OAAO,CAAC,SAAS;IASjB,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,aAAa,GAAG,IAAI;IAM7C;;;OAGG;IACH,WAAW,IAAI,IAAI;CAKpB"}
@@ -34,6 +34,7 @@ export declare class SubscriptionScope<D extends CoValue> {
34
34
  totalValidTransactions: number;
35
35
  migrated: boolean;
36
36
  migrating: boolean;
37
+ closed: boolean;
37
38
  silenceUpdates: boolean;
38
39
  constructor(node: LocalNode, resolve: RefsToResolve<D>, id: ID<D>, schema: RefEncoded<D>, skipRetry?: boolean, bestEffortResolution?: boolean, unstable_branch?: BranchDefinition | undefined);
39
40
  updateValue(value: SubscriptionValue<D, any>): void;
@@ -50,6 +51,12 @@ export declare class SubscriptionScope<D extends CoValue> {
50
51
  setListener(listener: (value: SubscriptionValue<D, any>) => void): void;
51
52
  subscribeToKey(key: string): void;
52
53
  isSubscribedToId(id: string): boolean;
54
+ /**
55
+ * Checks if the currently unloaded value has got some updates
56
+ *
57
+ * Used to make the autoload work on closed subscription scopes
58
+ */
59
+ pullValue(listener: (value: SubscriptionValue<D, any>) => void): void;
53
60
  subscribeToId(id: string, descriptor: RefEncoded<any>): void;
54
61
  loadChildren(): boolean;
55
62
  loadCoMapKey(map: CoMap, key: string, depth: Record<string, any> | true): string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"SubscriptionScope.d.ts","sourceRoot":"","sources":["../../../src/tools/subscribe/SubscriptionScope.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SubscriptionScope.d.ts","sourceRoot":"","sources":["../../../src/tools/subscribe/SubscriptionScope.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/subscribe/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAgB,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,OAAO,EAAE,KAAK,EAAE,CAAC,qDAwB/D;AAED,yBAAyB;AAEzB;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,OAAO,EAChD,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,OAeZ;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,OAAO,EAC/C,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,OAa5B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/subscribe/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAgB,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,OAAO,EAAE,KAAK,EAAE,CAAC,qDA0B/D;AAED,yBAAyB;AAEzB;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,OAAO,EAChD,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,OAqBZ;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,OAAO,EAC/C,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,OAa5B"}
Binary file
package/package.json CHANGED
@@ -164,6 +164,11 @@
164
164
  "types": "./dist/better-auth/auth/server.d.ts",
165
165
  "default": "./dist/better-auth/auth/server.js"
166
166
  },
167
+ "./better-auth/database-adapter": {
168
+ "@jazz-tools/source": "./src/better-auth/database-adapter/index.ts",
169
+ "types": "./dist/better-auth/database-adapter/index.d.ts",
170
+ "default": "./dist/better-auth/database-adapter/index.js"
171
+ },
167
172
  "./load-edge-wasm": {
168
173
  "@jazz-tools/source": "./src/worker/edge-wasm.ts",
169
174
  "types": "./dist/worker/edge-wasm.d.ts",
@@ -172,7 +177,7 @@
172
177
  },
173
178
  "type": "module",
174
179
  "license": "MIT",
175
- "version": "0.18.15",
180
+ "version": "0.18.17",
176
181
  "dependencies": {
177
182
  "@manuscripts/prosemirror-recreate-steps": "^0.1.4",
178
183
  "@scure/base": "1.2.1",
@@ -189,9 +194,9 @@
189
194
  "prosemirror-transform": "^1.9.0",
190
195
  "use-sync-external-store": "^1.5.0",
191
196
  "zod": "3.25.76",
192
- "cojson": "0.18.15",
193
- "cojson-storage-indexeddb": "0.18.15",
194
- "cojson-transport-ws": "0.18.15"
197
+ "cojson": "0.18.17",
198
+ "cojson-storage-indexeddb": "0.18.17",
199
+ "cojson-transport-ws": "0.18.17"
195
200
  },
196
201
  "devDependencies": {
197
202
  "@scure/bip39": "^1.3.0",
@@ -218,7 +223,7 @@
218
223
  "@bam.tech/react-native-image-resizer": "*",
219
224
  "@op-engineering/op-sqlite": "*",
220
225
  "@react-native-community/netinfo": "*",
221
- "better-auth": "^1.3.0",
226
+ "better-auth": "^1.3.2",
222
227
  "expo-file-system": "*",
223
228
  "expo-secure-store": "*",
224
229
  "expo-sqlite": "*",
@@ -0,0 +1,228 @@
1
+ import { type AdapterDebugLogs, createAdapter } from "better-auth/adapters";
2
+ import type { Account } from "jazz-tools";
3
+ import { startWorker } from "jazz-tools/worker";
4
+ import {
5
+ JazzRepository,
6
+ UserRepository,
7
+ SessionRepository,
8
+ VerificationRepository,
9
+ AccountRepository,
10
+ } from "./repository";
11
+ import { createJazzSchema, tableItem2Record } from "./schema.js";
12
+
13
+ export interface JazzAdapterConfig {
14
+ /**
15
+ * Helps you debug issues with the adapter.
16
+ */
17
+ debugLogs?: AdapterDebugLogs;
18
+ /**
19
+ * The sync server to use.
20
+ */
21
+ syncServer: string;
22
+ /**
23
+ * The worker account ID to use.
24
+ */
25
+ accountID: string;
26
+ /**
27
+ * The worker account secret to use.
28
+ */
29
+ accountSecret: string;
30
+ }
31
+
32
+ /**
33
+ * Creates a Better Auth database adapter that integrates with Jazz framework.
34
+ *
35
+ * This adapter provides a seamless integration between Better Auth and Jazz,
36
+ * allowing you to use Jazz as database for for Better Auth's authentication system.
37
+ *
38
+ * @param config - Configuration object for the Jazz Better Auth adapter
39
+ * @param config.syncServer - The Jazz sync server URL to connect to (e.g., "wss://your-sync-server.com")
40
+ * @param config.accountID - The worker account ID for the Jazz worker that will handle auth operations
41
+ * @param config.accountSecret - The worker account secret for authenticating with the Jazz sync server
42
+ * @param config.debugLogs - Optional debug logging configuration to help troubleshoot adapter issues
43
+ *
44
+ * @returns A Better Auth adapter instance configured to work with Jazz
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * import { JazzBetterAuthDatabaseAdapter } from "jazz-tools/better-auth/database-adapter";
49
+ * import { createAuth } from "better-auth";
50
+ *
51
+ * const auth = createAuth({
52
+ * adapter: JazzBetterAuthDatabaseAdapter({
53
+ * syncServer: "wss://your-jazz-sync-server.com",
54
+ * accountID: "auth-worker-account-id",
55
+ * accountSecret: "your-worker-account-secret",
56
+ * }),
57
+ * // ... other auth configuration
58
+ * });
59
+ * ```
60
+ */
61
+ export const JazzBetterAuthDatabaseAdapter = (
62
+ config: JazzAdapterConfig,
63
+ ): ReturnType<typeof createAdapter> =>
64
+ createAdapter({
65
+ config: {
66
+ adapterId: "jazz-tools-adapter", // A unique identifier for the adapter.
67
+ adapterName: "Jazz Tools Adapter", // The name of the adapter.
68
+ debugLogs: config.debugLogs ?? false, // Whether to enable debug logs.
69
+ supportsJSON: true, // Whether the database supports JSON. (Default: false)
70
+ supportsDates: true, // Whether the database supports dates. (Default: true)
71
+ supportsBooleans: true, // Whether the database supports booleans. (Default: true)
72
+ supportsNumericIds: false, // Whether the database supports auto-incrementing numeric IDs. (Default: true)
73
+ disableIdGeneration: true,
74
+ },
75
+ adapter: ({ schema }) => {
76
+ const JazzSchema = createJazzSchema(schema);
77
+
78
+ let worker: Account | undefined = undefined;
79
+
80
+ async function getWorker() {
81
+ if (worker) {
82
+ return worker;
83
+ }
84
+
85
+ const result = await startWorker({
86
+ AccountSchema: JazzSchema.WorkerAccount,
87
+ syncServer: config.syncServer,
88
+ accountID: config.accountID,
89
+ accountSecret: config.accountSecret,
90
+ skipInboxLoad: true,
91
+ asActiveAccount: false,
92
+ });
93
+
94
+ worker = result.worker;
95
+
96
+ return worker;
97
+ }
98
+
99
+ async function initRepository(
100
+ model: string,
101
+ ensureSync: boolean = false,
102
+ ): Promise<JazzRepository> {
103
+ let Repository: typeof JazzRepository | undefined = undefined;
104
+ switch (model) {
105
+ case "user":
106
+ Repository = UserRepository;
107
+ break;
108
+ case "session":
109
+ Repository = SessionRepository;
110
+ break;
111
+ case "verification":
112
+ Repository = VerificationRepository;
113
+ break;
114
+ case "account":
115
+ Repository = AccountRepository;
116
+ break;
117
+ }
118
+
119
+ if (!Repository) {
120
+ Repository = JazzRepository;
121
+ }
122
+
123
+ const worker = await getWorker();
124
+ const database = await JazzSchema.loadDatabase(worker);
125
+
126
+ const repository = new Repository(
127
+ JazzSchema.DatabaseRoot,
128
+ database,
129
+ worker,
130
+ schema,
131
+ ensureSync,
132
+ );
133
+
134
+ return repository;
135
+ }
136
+
137
+ return {
138
+ create: async ({ data, model, select }): Promise<any> => {
139
+ // console.log("create", { data, model, select });
140
+ const repository = await initRepository(model, true);
141
+
142
+ const created = await repository.create(model, data);
143
+
144
+ await repository.ensureSync();
145
+
146
+ return tableItem2Record(created);
147
+ },
148
+ update: async ({ model, where, update }): Promise<any> => {
149
+ // console.log("update", { model, where, update });
150
+ const repository = await initRepository(model, true);
151
+
152
+ const updated = await repository.update(
153
+ model,
154
+ where,
155
+ update as Record<string, any>,
156
+ );
157
+
158
+ if (updated.length === 0) {
159
+ return null;
160
+ }
161
+
162
+ await repository.ensureSync();
163
+
164
+ return tableItem2Record(updated[0]!);
165
+ },
166
+ updateMany: async ({ model, where, update }) => {
167
+ // console.log("updateMany", { model, where, update });
168
+ const repository = await initRepository(model, true);
169
+
170
+ const updated = await repository.update(model, where, update);
171
+
172
+ await repository.ensureSync();
173
+
174
+ return updated.length;
175
+ },
176
+ delete: async ({ model, where }) => {
177
+ // console.log("delete", { model, where });
178
+ const repository = await initRepository(model, true);
179
+
180
+ await repository.deleteValue(model, where);
181
+
182
+ await repository.ensureSync();
183
+ },
184
+ findOne: async ({ model, where }): Promise<any> => {
185
+ // console.log("findOne", { model, where });
186
+ const repository = await initRepository(model);
187
+
188
+ const item = await repository.findOne(model, where);
189
+
190
+ return tableItem2Record(item);
191
+ },
192
+ findMany: async ({
193
+ model,
194
+ where,
195
+ limit,
196
+ sortBy,
197
+ offset,
198
+ }): Promise<any[]> => {
199
+ const repository = await initRepository(model);
200
+
201
+ const items = await repository.findMany(
202
+ model,
203
+ where,
204
+ limit,
205
+ sortBy,
206
+ offset,
207
+ );
208
+
209
+ return items.map(tableItem2Record);
210
+ },
211
+ deleteMany: async ({ model, where }) => {
212
+ const repository = await initRepository(model, true);
213
+
214
+ const deleted = await repository.deleteValue(model, where);
215
+
216
+ await repository.ensureSync();
217
+
218
+ return deleted;
219
+ },
220
+ count: async ({ model, where }) => {
221
+ // console.log("count", { model, where });
222
+ const repository = await initRepository(model);
223
+
224
+ return repository.count(model, where);
225
+ },
226
+ };
227
+ },
228
+ });