jazz-tools 0.18.18 → 0.18.20
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/.turbo/turbo-build.log +45 -45
- package/CHANGELOG.md +27 -0
- package/dist/better-auth/auth/client.d.ts.map +1 -1
- package/dist/better-auth/auth/client.js +3 -2
- package/dist/better-auth/auth/client.js.map +1 -1
- package/dist/browser/index.js +2 -2
- package/dist/browser/index.js.map +1 -1
- package/dist/{chunk-FHRKDKDY.js → chunk-TVHI2UMO.js} +49 -2
- package/dist/chunk-TVHI2UMO.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/react-core/hooks.d.ts.map +1 -1
- package/dist/react-core/index.js +2 -2
- package/dist/react-core/index.js.map +1 -1
- package/dist/testing.js +1 -1
- package/dist/tools/coValues/coList.d.ts.map +1 -1
- package/dist/tools/coValues/coMap.d.ts +2 -2
- package/dist/tools/coValues/coMap.d.ts.map +1 -1
- package/dist/tools/coValues/coPlainText.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.d.ts +1 -1
- package/dist/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/TypeOfZodSchema.d.ts +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/TypeOfZodSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/zodReExport.d.ts +1 -1
- package/dist/tools/implementation/zodSchema/zodReExport.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/better-auth/auth/client.ts +3 -2
- package/src/better-auth/auth/tests/client.test.ts +22 -0
- package/src/browser/auth/PasskeyAuth.ts +2 -2
- package/src/react-core/hooks.ts +3 -2
- package/src/react-core/tests/useInboxSender.test.ts +37 -3
- package/src/tools/coValues/coList.ts +11 -0
- package/src/tools/coValues/coMap.ts +5 -5
- package/src/tools/coValues/coPlainText.ts +9 -0
- package/src/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.ts +47 -2
- package/src/tools/implementation/zodSchema/typeConverters/TypeOfZodSchema.ts +9 -4
- package/src/tools/implementation/zodSchema/zodReExport.ts +1 -0
- package/src/tools/subscribe/index.ts +1 -1
- package/src/tools/tests/coList.test.ts +34 -0
- package/src/tools/tests/coMap.test.ts +26 -2
- package/src/tools/tests/coPlainText.test.ts +25 -1
- package/src/tools/tests/subscribe.test.ts +41 -0
- package/src/tools/tests/zod.test.ts +131 -0
- package/dist/chunk-FHRKDKDY.js.map +0 -1
- package/jazz-tools-0.18.6.tgz +0 -0
package/.turbo/turbo-build.log
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
> jazz-tools@0.18.
|
2
|
+
> jazz-tools@0.18.20 build /home/runner/_work/jazz/jazz/packages/jazz-tools
|
3
3
|
> tsup && pnpm types && pnpm build:svelte
|
4
4
|
|
5
5
|
[34mCLI[39m Building entry: {"index":"src/index.ts","testing":"src/testing.ts"}
|
@@ -114,98 +114,98 @@
|
|
114
114
|
[34mESM[39m Build start
|
115
115
|
[34mCLI[39m Cleaning output folder
|
116
116
|
[34mESM[39m Build start
|
117
|
-
[32mESM[39m [1mdist/react/ssr.js [22m[32m688.00 B[39m
|
118
|
-
[32mESM[39m [1mdist/react/ssr.js.map [22m[32m1.12 KB[39m
|
119
|
-
[32mESM[39m ⚡️ Build success in 28ms
|
120
117
|
[32mESM[39m [1mdist/tiptap/index.js [22m[32m564.00 B[39m
|
121
118
|
[32mESM[39m [1mdist/tiptap/index.js.map [22m[32m1.21 KB[39m
|
122
|
-
[32mESM[39m ⚡️ Build success in
|
119
|
+
[32mESM[39m ⚡️ Build success in 20ms
|
120
|
+
[32mESM[39m [1mdist/react/ssr.js [22m[32m688.00 B[39m
|
121
|
+
[32mESM[39m [1mdist/react/ssr.js.map [22m[32m1.12 KB[39m
|
122
|
+
[32mESM[39m ⚡️ Build success in 23ms
|
123
123
|
[32mESM[39m [1mdist/worker/index.js [22m[32m3.19 KB[39m
|
124
124
|
[32mESM[39m [1mdist/worker/edge-wasm.js [22m[32m215.00 B[39m
|
125
125
|
[32mESM[39m [1mdist/worker/index.js.map [22m[32m6.17 KB[39m
|
126
126
|
[32mESM[39m [1mdist/worker/edge-wasm.js.map [22m[32m434.00 B[39m
|
127
|
-
[32mESM[39m ⚡️ Build success in
|
128
|
-
[32mESM[39m [1mdist/better-auth/auth/client.js [22m[32m4.
|
127
|
+
[32mESM[39m ⚡️ Build success in 39ms
|
128
|
+
[32mESM[39m [1mdist/better-auth/auth/client.js [22m[32m4.50 KB[39m
|
129
129
|
[32mESM[39m [1mdist/better-auth/auth/server.js [22m[32m8.36 KB[39m
|
130
130
|
[32mESM[39m [1mdist/better-auth/auth/react.js [22m[32m799.00 B[39m
|
131
|
-
[32mESM[39m [1mdist/better-auth/auth/client.js.map [22m[32m8.
|
131
|
+
[32mESM[39m [1mdist/better-auth/auth/client.js.map [22m[32m8.32 KB[39m
|
132
132
|
[32mESM[39m [1mdist/better-auth/auth/server.js.map [22m[32m15.29 KB[39m
|
133
133
|
[32mESM[39m [1mdist/better-auth/auth/react.js.map [22m[32m2.04 KB[39m
|
134
|
-
[32mESM[39m ⚡️ Build success in
|
135
|
-
[32mESM[39m [1mdist/react-
|
136
|
-
[32mESM[39m [1mdist/react-
|
137
|
-
[32mESM[39m [1mdist/react-
|
138
|
-
[32mESM[39m [1mdist/react-
|
139
|
-
[32mESM[39m [1mdist/react-
|
140
|
-
[32mESM[39m [1mdist/react-
|
141
|
-
[32mESM[39m ⚡️ Build success in
|
134
|
+
[32mESM[39m ⚡️ Build success in 44ms
|
135
|
+
[32mESM[39m [1mdist/react-native/index.js [22m[32m2.53 KB[39m
|
136
|
+
[32mESM[39m [1mdist/react-native/testing.js [22m[32m120.00 B[39m
|
137
|
+
[32mESM[39m [1mdist/react-native/crypto.js [22m[32m161.00 B[39m
|
138
|
+
[32mESM[39m [1mdist/react-native/index.js.map [22m[32m5.68 KB[39m
|
139
|
+
[32mESM[39m [1mdist/react-native/testing.js.map [22m[32m176.00 B[39m
|
140
|
+
[32mESM[39m [1mdist/react-native/crypto.js.map [22m[32m197.00 B[39m
|
141
|
+
[32mESM[39m ⚡️ Build success in 48ms
|
142
142
|
[32mESM[39m [1mdist/media/index.js [22m[32m236.00 B[39m
|
143
143
|
[32mESM[39m [1mdist/media/index.native.js [22m[32m2.90 KB[39m
|
144
|
-
[32mESM[39m [1mdist/media/chunk-W3S526L3.js [22m[32m6.47 KB[39m
|
145
144
|
[32mESM[39m [1mdist/media/index.server.js [22m[32m2.95 KB[39m
|
146
145
|
[32mESM[39m [1mdist/media/index.browser.js [22m[32m2.79 KB[39m
|
146
|
+
[32mESM[39m [1mdist/media/chunk-W3S526L3.js [22m[32m6.47 KB[39m
|
147
147
|
[32mESM[39m [1mdist/media/index.js.map [22m[32m71.00 B[39m
|
148
148
|
[32mESM[39m [1mdist/media/index.native.js.map [22m[32m6.09 KB[39m
|
149
149
|
[32mESM[39m [1mdist/media/index.server.js.map [22m[32m6.37 KB[39m
|
150
|
-
[32mESM[39m [1mdist/media/chunk-W3S526L3.js.map [22m[32m16.57 KB[39m
|
151
150
|
[32mESM[39m [1mdist/media/index.browser.js.map [22m[32m6.15 KB[39m
|
152
|
-
[32mESM[39m
|
153
|
-
[32mESM[39m
|
154
|
-
[32mESM[39m [1mdist/
|
155
|
-
[32mESM[39m
|
156
|
-
[32mESM[39m [1mdist/react-
|
157
|
-
[32mESM[39m [1mdist/react-
|
158
|
-
[32mESM[39m [1mdist/react-
|
159
|
-
[32mESM[39m [1mdist/react-
|
160
|
-
[32mESM[39m
|
161
|
-
[32mESM[39m [1mdist/
|
162
|
-
[32mESM[39m
|
151
|
+
[32mESM[39m [1mdist/media/chunk-W3S526L3.js.map [22m[32m16.57 KB[39m
|
152
|
+
[32mESM[39m ⚡️ Build success in 55ms
|
153
|
+
[32mESM[39m [1mdist/react-core/index.js [22m[32m11.11 KB[39m
|
154
|
+
[32mESM[39m [1mdist/react-core/testing.js [22m[32m1.22 KB[39m
|
155
|
+
[32mESM[39m [1mdist/react-core/chunk-7DYMJ74I.js [22m[32m279.00 B[39m
|
156
|
+
[32mESM[39m [1mdist/react-core/index.js.map [22m[32m35.83 KB[39m
|
157
|
+
[32mESM[39m [1mdist/react-core/testing.js.map [22m[32m1.86 KB[39m
|
158
|
+
[32mESM[39m [1mdist/react-core/chunk-7DYMJ74I.js.map [22m[32m533.00 B[39m
|
159
|
+
[32mESM[39m ⚡️ Build success in 53ms
|
160
|
+
[32mESM[39m [1mdist/browser/index.js [22m[32m14.16 KB[39m
|
161
|
+
[32mESM[39m [1mdist/browser/index.js.map [22m[32m30.05 KB[39m
|
162
|
+
[32mESM[39m ⚡️ Build success in 62ms
|
163
163
|
[32mESM[39m [1mdist/expo/index.js [22m[32m4.68 KB[39m
|
164
164
|
[32mESM[39m [1mdist/expo/testing.js [22m[32m112.00 B[39m
|
165
165
|
[32mESM[39m [1mdist/expo/crypto.js [22m[32m153.00 B[39m
|
166
166
|
[32mESM[39m [1mdist/expo/index.js.map [22m[32m10.23 KB[39m
|
167
|
-
[32mESM[39m [1mdist/expo/testing.js.map [22m[32m168.00 B[39m
|
168
167
|
[32mESM[39m [1mdist/expo/crypto.js.map [22m[32m189.00 B[39m
|
169
|
-
[32mESM[39m
|
168
|
+
[32mESM[39m [1mdist/expo/testing.js.map [22m[32m168.00 B[39m
|
169
|
+
[32mESM[39m ⚡️ Build success in 65ms
|
170
170
|
[32mESM[39m [1mdist/react-native-core/index.js [22m[32m18.65 KB[39m
|
171
171
|
[32mESM[39m [1mdist/react-native-core/testing.js [22m[32m119.00 B[39m
|
172
172
|
[32mESM[39m [1mdist/react-native-core/crypto.js [22m[32m2.10 KB[39m
|
173
173
|
[32mESM[39m [1mdist/react-native-core/index.js.map [22m[32m37.83 KB[39m
|
174
174
|
[32mESM[39m [1mdist/react-native-core/testing.js.map [22m[32m175.00 B[39m
|
175
175
|
[32mESM[39m [1mdist/react-native-core/crypto.js.map [22m[32m4.25 KB[39m
|
176
|
-
[32mESM[39m ⚡️ Build success in
|
177
|
-
[32mESM[39m [1mdist/better-auth/database-adapter/index.js [22m[32m26.34 KB[39m
|
178
|
-
[32mESM[39m [1mdist/better-auth/database-adapter/index.js.map [22m[32m57.62 KB[39m
|
179
|
-
[32mESM[39m ⚡️ Build success in 51ms
|
176
|
+
[32mESM[39m ⚡️ Build success in 59ms
|
180
177
|
[32mESM[39m [1mdist/react/testing.js [22m[32m122.00 B[39m
|
181
178
|
[32mESM[39m [1mdist/react/index.js [22m[32m24.93 KB[39m
|
182
179
|
[32mESM[39m [1mdist/react/testing.js.map [22m[32m165.00 B[39m
|
183
180
|
[32mESM[39m [1mdist/react/index.js.map [22m[32m53.78 KB[39m
|
184
|
-
[32mESM[39m ⚡️ Build success in
|
181
|
+
[32mESM[39m ⚡️ Build success in 62ms
|
182
|
+
[32mESM[39m [1mdist/better-auth/database-adapter/index.js [22m[32m26.34 KB[39m
|
183
|
+
[32mESM[39m [1mdist/better-auth/database-adapter/index.js.map [22m[32m57.62 KB[39m
|
184
|
+
[32mESM[39m ⚡️ Build success in 57ms
|
185
185
|
[32mESM[39m [1mdist/prosemirror/index.js [22m[32m77.76 KB[39m
|
186
186
|
[32mESM[39m [1mdist/prosemirror/index.js.map [22m[32m307.20 KB[39m
|
187
|
-
[32mESM[39m ⚡️ Build success in
|
187
|
+
[32mESM[39m ⚡️ Build success in 64ms
|
188
188
|
[32mESM[39m [1mdist/inspector/index.js [22m[32m69.71 KB[39m
|
189
189
|
[32mESM[39m [1mdist/inspector/index.js.map [22m[32m121.38 KB[39m
|
190
|
-
[32mESM[39m ⚡️ Build success in
|
191
|
-
[32mESM[39m [1mdist/index.js [22m[32m26.13 KB[39m
|
190
|
+
[32mESM[39m ⚡️ Build success in 78ms
|
192
191
|
[32mESM[39m [1mdist/testing.js [22m[32m8.33 KB[39m
|
193
|
-
[32mESM[39m [1mdist/
|
192
|
+
[32mESM[39m [1mdist/index.js [22m[32m26.13 KB[39m
|
193
|
+
[32mESM[39m [1mdist/chunk-TVHI2UMO.js [22m[32m177.69 KB[39m
|
194
194
|
[32mESM[39m [1mdist/testing.js.map [22m[32m15.87 KB[39m
|
195
195
|
[32mESM[39m [1mdist/index.js.map [22m[32m52.92 KB[39m
|
196
|
-
[32mESM[39m [1mdist/chunk-
|
197
|
-
[32mESM[39m ⚡️ Build success in
|
196
|
+
[32mESM[39m [1mdist/chunk-TVHI2UMO.js.map [22m[32m422.99 KB[39m
|
197
|
+
[32mESM[39m ⚡️ Build success in 102ms
|
198
198
|
[32mESM[39m [1mdist/inspector/register-custom-element.js [22m[32m218.00 B[39m
|
199
199
|
[32mESM[39m [1mdist/inspector/register-custom-element.js.map [22m[32m314.00 B[39m
|
200
200
|
[32mESM[39m [1mdist/inspector/custom-element-G6SPZEBR.js [22m[32m1.54 MB[39m
|
201
201
|
[32mESM[39m [1mdist/inspector/custom-element-G6SPZEBR.js.map [22m[32m2.36 MB[39m
|
202
|
-
[32mESM[39m ⚡️ Build success in
|
202
|
+
[32mESM[39m ⚡️ Build success in 143ms
|
203
203
|
|
204
|
-
> jazz-tools@0.18.
|
204
|
+
> jazz-tools@0.18.20 types /home/runner/_work/jazz/jazz/packages/jazz-tools
|
205
205
|
> tsc --outDir dist
|
206
206
|
|
207
207
|
|
208
|
-
> jazz-tools@0.18.
|
208
|
+
> jazz-tools@0.18.20 build:svelte /home/runner/_work/jazz/jazz/packages/jazz-tools
|
209
209
|
> rm -rf dist/svelte && svelte-package -i src/svelte -o dist/svelte --tsconfig tsconfig.svelte.json
|
210
210
|
|
211
211
|
src/svelte -> dist/svelte
|
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,32 @@
|
|
1
1
|
# jazz-tools
|
2
2
|
|
3
|
+
## 0.18.20
|
4
|
+
|
5
|
+
### Patch Changes
|
6
|
+
|
7
|
+
- c34a793: Allow usage of z.codec with custom encoders in CoValues
|
8
|
+
- 2c01529: Increased passkey challenge length to improve compatibility with KeePassXC
|
9
|
+
- 7b0facc: Upgrade Zod to 4.1
|
10
|
+
- 47c7dd3: fix: regenerate InboxSender when active account changes
|
11
|
+
- d0e2210: Batch subscribe updates during the applyDiff execution
|
12
|
+
- Updated dependencies [e75b3d6]
|
13
|
+
- Updated dependencies [ecf4967]
|
14
|
+
- Updated dependencies [d0e2210]
|
15
|
+
- cojson@0.18.20
|
16
|
+
- cojson-storage-indexeddb@0.18.20
|
17
|
+
- cojson-transport-ws@0.18.20
|
18
|
+
|
19
|
+
## 0.18.19
|
20
|
+
|
21
|
+
### Patch Changes
|
22
|
+
|
23
|
+
- f88db5f: Ensure subscription scope is cached for each CoValue
|
24
|
+
- 8eac2fc: Fix refs in partially loaded CoMaps being incorrectly marked as optional
|
25
|
+
- 08b6c03: fix: keep sync between Better Auth's session and Jazz's
|
26
|
+
- cojson@0.18.19
|
27
|
+
- cojson-storage-indexeddb@0.18.19
|
28
|
+
- cojson-transport-ws@0.18.19
|
29
|
+
|
3
30
|
## 0.18.18
|
4
31
|
|
5
32
|
### Patch Changes
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/better-auth/auth/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EACP,iBAAiB,EAEjB,eAAe,EAChB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAS9C;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB;;wBAmBC,UAAU,CAAC,OAAO,UAAU,CAAC;;;sCAIvB,eAAe,CAAC,OAAO,CAAC;4CAGlB,iBAAiB;;;;;;;;;;;
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/better-auth/auth/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EACP,iBAAiB,EAEjB,eAAe,EAChB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAS9C;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB;;wBAmBC,UAAU,CAAC,OAAO,UAAU,CAAC;;;sCAIvB,eAAe,CAAC,OAAO,CAAC;4CAGlB,iBAAiB;;;;;;;;;;;CA6H1D,CAAC"}
|
@@ -84,9 +84,10 @@ var jazzPluginClient = () => {
|
|
84
84
|
if (context.request.url.toString().includes("/get-session")) {
|
85
85
|
if (context.data === null) {
|
86
86
|
if (authSecretStorage.isAuthenticated === true) {
|
87
|
-
console.
|
88
|
-
"Jazz is authenticated, but the session is null"
|
87
|
+
console.info(
|
88
|
+
"Jazz is authenticated, but the session is null. Logging out"
|
89
89
|
);
|
90
|
+
await jazzContext.logOut();
|
90
91
|
}
|
91
92
|
return;
|
92
93
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../src/better-auth/auth/client.ts"],"sourcesContent":["import type { BetterAuthClientPlugin } from \"better-auth\";\nimport type {\n Account,\n AuthSecretStorage,\n AuthSetPayload,\n JazzContextType,\n} from \"jazz-tools\";\nimport type { jazzPlugin } from \"./server.js\";\n\nconst SIGNUP_URLS = [\n \"/sign-up\",\n \"/sign-in/social\",\n \"/sign-in/oauth2\",\n \"/email-otp/send-verification-otp\",\n];\n\n/**\n * @example\n * ```ts\n * const auth = betterAuth({\n * plugins: [jazzPluginClient()],\n * });\n * ```\n */\nexport const jazzPluginClient = () => {\n let jazzContext: JazzContextType<Account>;\n let authSecretStorage: AuthSecretStorage;\n let signOutUnsubscription: () => void;\n\n const authenticateOnJazz = async (jazzAuth: AuthSetPayload) => {\n const parsedJazzAuth = {\n ...jazzAuth,\n secretSeed: jazzAuth.secretSeed\n ? Uint8Array.from(jazzAuth.secretSeed)\n : undefined,\n };\n\n await jazzContext.authenticate(parsedJazzAuth);\n await authSecretStorage.set(parsedJazzAuth);\n };\n\n return {\n id: \"jazz-plugin\",\n $InferServerPlugin: {} as ReturnType<typeof jazzPlugin>,\n getActions: ($fetch, $store) => {\n return {\n jazz: {\n setJazzContext: (context: JazzContextType<Account>) => {\n jazzContext = context;\n },\n setAuthSecretStorage: (storage: AuthSecretStorage) => {\n authSecretStorage = storage;\n if (signOutUnsubscription) signOutUnsubscription();\n\n // This is a workaround to logout from Better Auth when user logs out directly from Jazz\n signOutUnsubscription = authSecretStorage.onUpdate(\n (isAuthenticated) => {\n if (isAuthenticated === false) {\n const session = $store.atoms.session?.get();\n if (!session) return;\n\n // if the user logs out from Better Auth, the get session is immediately called\n // so we must wait the next fetched session to understand if we need to call sign-out\n if (session.isPending || session.isRefetching) {\n // listen once for next session's data\n const unsub = $store.atoms.session?.listen((session) => {\n unsub?.();\n // if the session is null, user has been already logged out from Better Auth\n if (session.data !== null) {\n $fetch(\"/sign-out\", { method: \"POST\" });\n }\n });\n }\n // if the session is not pending, it means user logged out from Jazz only\n // so we call the sign-out api\n else {\n $fetch(\"/sign-out\", { method: \"POST\" });\n }\n }\n },\n );\n },\n },\n };\n },\n fetchPlugins: [\n {\n id: \"jazz-plugin\",\n name: \"jazz-plugin\",\n hooks: {\n async onRequest(context) {\n if (\n SIGNUP_URLS.some((url) => context.url.toString().includes(url))\n ) {\n const credentials = await authSecretStorage.get();\n\n if (!credentials) {\n throw new Error(\"Jazz credentials not found\");\n }\n\n context.headers.set(\n \"x-jazz-auth\",\n JSON.stringify({\n accountID: credentials.accountID,\n secretSeed: credentials.secretSeed,\n accountSecret: credentials.accountSecret,\n }),\n );\n }\n },\n async onSuccess(context) {\n if (context.request.url.toString().includes(\"/sign-up\")) {\n await authenticateOnJazz(context.data.jazzAuth);\n return;\n }\n\n if (context.request.url.toString().includes(\"/sign-in/email\")) {\n await authenticateOnJazz(context.data.jazzAuth);\n return;\n }\n\n if (context.request.url.toString().includes(\"/get-session\")) {\n if (context.data === null) {\n if (authSecretStorage.isAuthenticated === true) {\n console.
|
1
|
+
{"version":3,"sources":["../../../src/better-auth/auth/client.ts"],"sourcesContent":["import type { BetterAuthClientPlugin } from \"better-auth\";\nimport type {\n Account,\n AuthSecretStorage,\n AuthSetPayload,\n JazzContextType,\n} from \"jazz-tools\";\nimport type { jazzPlugin } from \"./server.js\";\n\nconst SIGNUP_URLS = [\n \"/sign-up\",\n \"/sign-in/social\",\n \"/sign-in/oauth2\",\n \"/email-otp/send-verification-otp\",\n];\n\n/**\n * @example\n * ```ts\n * const auth = betterAuth({\n * plugins: [jazzPluginClient()],\n * });\n * ```\n */\nexport const jazzPluginClient = () => {\n let jazzContext: JazzContextType<Account>;\n let authSecretStorage: AuthSecretStorage;\n let signOutUnsubscription: () => void;\n\n const authenticateOnJazz = async (jazzAuth: AuthSetPayload) => {\n const parsedJazzAuth = {\n ...jazzAuth,\n secretSeed: jazzAuth.secretSeed\n ? Uint8Array.from(jazzAuth.secretSeed)\n : undefined,\n };\n\n await jazzContext.authenticate(parsedJazzAuth);\n await authSecretStorage.set(parsedJazzAuth);\n };\n\n return {\n id: \"jazz-plugin\",\n $InferServerPlugin: {} as ReturnType<typeof jazzPlugin>,\n getActions: ($fetch, $store) => {\n return {\n jazz: {\n setJazzContext: (context: JazzContextType<Account>) => {\n jazzContext = context;\n },\n setAuthSecretStorage: (storage: AuthSecretStorage) => {\n authSecretStorage = storage;\n if (signOutUnsubscription) signOutUnsubscription();\n\n // This is a workaround to logout from Better Auth when user logs out directly from Jazz\n signOutUnsubscription = authSecretStorage.onUpdate(\n (isAuthenticated) => {\n if (isAuthenticated === false) {\n const session = $store.atoms.session?.get();\n if (!session) return;\n\n // if the user logs out from Better Auth, the get session is immediately called\n // so we must wait the next fetched session to understand if we need to call sign-out\n if (session.isPending || session.isRefetching) {\n // listen once for next session's data\n const unsub = $store.atoms.session?.listen((session) => {\n unsub?.();\n // if the session is null, user has been already logged out from Better Auth\n if (session.data !== null) {\n $fetch(\"/sign-out\", { method: \"POST\" });\n }\n });\n }\n // if the session is not pending, it means user logged out from Jazz only\n // so we call the sign-out api\n else {\n $fetch(\"/sign-out\", { method: \"POST\" });\n }\n }\n },\n );\n },\n },\n };\n },\n fetchPlugins: [\n {\n id: \"jazz-plugin\",\n name: \"jazz-plugin\",\n hooks: {\n async onRequest(context) {\n if (\n SIGNUP_URLS.some((url) => context.url.toString().includes(url))\n ) {\n const credentials = await authSecretStorage.get();\n\n if (!credentials) {\n throw new Error(\"Jazz credentials not found\");\n }\n\n context.headers.set(\n \"x-jazz-auth\",\n JSON.stringify({\n accountID: credentials.accountID,\n secretSeed: credentials.secretSeed,\n accountSecret: credentials.accountSecret,\n }),\n );\n }\n },\n async onSuccess(context) {\n if (context.request.url.toString().includes(\"/sign-up\")) {\n await authenticateOnJazz(context.data.jazzAuth);\n return;\n }\n\n if (context.request.url.toString().includes(\"/sign-in/email\")) {\n await authenticateOnJazz(context.data.jazzAuth);\n return;\n }\n\n if (context.request.url.toString().includes(\"/get-session\")) {\n if (context.data === null) {\n if (authSecretStorage.isAuthenticated === true) {\n console.info(\n \"Jazz is authenticated, but the session is null. Logging out\",\n );\n await jazzContext.logOut();\n }\n return;\n }\n\n if (!context.data?.user) {\n return;\n }\n\n if (authSecretStorage.isAuthenticated === false) {\n console.info(\n \"Jazz is not authenticated, using Better Auth stored credentials\",\n );\n await authenticateOnJazz(context.data.jazzAuth);\n return;\n }\n\n const sessionAccountID = context.data.user.accountID;\n\n const credentials = await authSecretStorage.get();\n\n if (!credentials) {\n throw new Error(\"Jazz credentials not found\");\n }\n\n if (credentials.accountID !== sessionAccountID) {\n console.info(\n \"Jazz credentials mismatch, using Better Auth stored credentials\",\n );\n await authenticateOnJazz(context.data.jazzAuth);\n }\n return;\n }\n\n if (context.request.url.toString().includes(\"/sign-out\")) {\n await jazzContext.logOut();\n return;\n }\n\n if (context.request.url.toString().includes(\"/delete-user\")) {\n await jazzContext.logOut();\n return;\n }\n },\n },\n },\n ],\n } satisfies BetterAuthClientPlugin;\n};\n"],"mappings":"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","names":["session"]}
|
package/dist/browser/index.js
CHANGED
@@ -133,7 +133,7 @@ var BrowserPasskeyAuth = class {
|
|
133
133
|
try {
|
134
134
|
await navigator.credentials.create({
|
135
135
|
publicKey: {
|
136
|
-
challenge: this.crypto.randomBytes(20),
|
136
|
+
challenge: new Uint8Array(this.crypto.randomBytes(20)),
|
137
137
|
rp: {
|
138
138
|
name: this.appName,
|
139
139
|
id: this.appHostname
|
@@ -166,7 +166,7 @@ var BrowserPasskeyAuth = class {
|
|
166
166
|
try {
|
167
167
|
const value = await navigator.credentials.get({
|
168
168
|
publicKey: {
|
169
|
-
challenge: Uint8Array.
|
169
|
+
challenge: new Uint8Array(this.crypto.randomBytes(20)),
|
170
170
|
rpId: this.appHostname,
|
171
171
|
allowCredentials: [],
|
172
172
|
timeout: 6e4,
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/browser/index.ts","../../src/browser/utils/export-account-inspector.ts","../../src/browser/auth/PasskeyAuth.ts","../../src/browser/createBrowserContext.ts","../../src/browser/storageOptions.ts","../../src/browser/BrowserContextManager.ts","../../src/browser/auth/LocalStorageKVStore.ts"],"sourcesContent":["import {\n Account,\n CoValue,\n CoValueClassOrSchema,\n InviteSecret,\n createInviteLink as baseCreateInviteLink,\n consumeInviteLink,\n} from \"jazz-tools\";\nimport { setupInspector } from \"./utils/export-account-inspector.js\";\nexport { BrowserPasskeyAuth } from \"./auth/PasskeyAuth.js\";\n\nsetupInspector();\n\nexport * from \"./createBrowserContext.js\";\nexport * from \"./BrowserContextManager.js\";\n\nexport { LocalStorageKVStore } from \"./auth/LocalStorageKVStore.js\";\n\n/** @category Invite Links */\nexport function createInviteLink<C extends CoValue>(\n value: C,\n role: \"reader\" | \"writer\" | \"admin\" | \"writeOnly\",\n // default to same address as window.location, but without hash\n {\n baseURL = window.location.href.replace(/#.*$/, \"\"),\n valueHint,\n }: { baseURL?: string; valueHint?: string } = {},\n): string {\n return baseCreateInviteLink(value, role, baseURL, valueHint);\n}\n\n/** @category Invite Links */\nexport { parseInviteLink } from \"jazz-tools\";\n\n/** @category Invite Links */\nexport async function consumeInviteLinkFromWindowLocation<\n S extends CoValueClassOrSchema,\n>({\n as,\n forValueHint,\n invitedObjectSchema,\n}: {\n as?: Account;\n forValueHint?: string;\n invitedObjectSchema: S;\n}): Promise<\n | {\n valueID: string;\n valueHint?: string;\n inviteSecret: InviteSecret;\n }\n | undefined\n> {\n const result = await consumeInviteLink({\n inviteURL: window.location.href,\n as,\n forValueHint,\n invitedObjectSchema,\n });\n\n if (result) {\n window.history.replaceState(\n {},\n \"\",\n window.location.href.replace(/#.*$/, \"\"),\n );\n }\n\n return result;\n}\n","import { AuthSecretStorage } from \"jazz-tools\";\n\nasync function exportAccountToInspector() {\n const authSecretStorage = new AuthSecretStorage();\n const localStorageData = await authSecretStorage.get();\n\n if (!localStorageData) {\n console.error(\"No account data found in localStorage\");\n return;\n }\n\n const encodedAccountSecret = btoa(localStorageData.accountSecret);\n window.open(\n new URL(\n `#/import/${localStorageData?.accountID}/${encodedAccountSecret}`,\n \"https://inspector.jazz.tools\",\n ).toString(),\n \"_blank\",\n );\n}\n\nfunction listenForCmdJ() {\n if (typeof window === \"undefined\") return;\n\n const cb = (e: any) => {\n if (e.metaKey && e.key === \"j\") {\n if (\n confirm(\n \"Are you sure you want to inspect your account using inspector.jazz.tools? This lets anyone with the secret inspector URL read your data and impersonate you.\",\n )\n ) {\n exportAccountToInspector();\n }\n }\n };\n\n window.addEventListener(\"keydown\", cb);\n\n return () => {\n window.removeEventListener(\"keydown\", cb);\n };\n}\n\n/**\n * Automatically sets up the Cmd+J listener if 'allowJazzInspector' is present in the URL\n * @returns A cleanup function if the listener was set up, undefined otherwise\n */\nexport function setupInspector() {\n if (typeof window === \"undefined\") return;\n\n const url = new URL(window.location.href);\n if (\n url.hash.includes(\"allowJazzInspector\") ||\n process.env.NODE_ENV === \"development\"\n ) {\n return listenForCmdJ();\n }\n}\n","import { CryptoProvider, RawAccountID, cojsonInternals } from \"cojson\";\nimport {\n Account,\n AuthSecretStorage,\n AuthenticateAccountFunction,\n ID,\n} from \"jazz-tools\";\n\n/**\n * `BrowserPasskeyAuth` provides a `JazzAuth` object for passkey authentication.\n *\n * ```ts\n * import { BrowserPasskeyAuth } from \"jazz-tools/browser\";\n *\n * const auth = new BrowserPasskeyAuth(driver, appName);\n * ```\n *\n * @category Auth Providers\n */\nexport class BrowserPasskeyAuth {\n constructor(\n protected crypto: CryptoProvider,\n protected authenticate: AuthenticateAccountFunction,\n protected authSecretStorage: AuthSecretStorage,\n public appName: string,\n public appHostname: string = window.location.hostname,\n ) {}\n\n static readonly id = \"passkey\";\n\n logIn = async () => {\n const { crypto, authenticate } = this;\n\n const webAuthNCredential = await this.getPasskeyCredentials();\n\n if (!webAuthNCredential) {\n return;\n }\n\n const webAuthNCredentialPayload = new Uint8Array(\n webAuthNCredential.response.userHandle,\n );\n const accountSecretSeed = webAuthNCredentialPayload.slice(\n 0,\n cojsonInternals.secretSeedLength,\n );\n\n const secret = crypto.agentSecretFromSecretSeed(accountSecretSeed);\n\n const accountID = cojsonInternals.rawCoIDfromBytes(\n webAuthNCredentialPayload.slice(\n cojsonInternals.secretSeedLength,\n cojsonInternals.secretSeedLength + cojsonInternals.shortHashLength,\n ),\n ) as ID<Account>;\n\n await authenticate({\n accountID,\n accountSecret: secret,\n });\n\n await this.authSecretStorage.set({\n accountID,\n secretSeed: accountSecretSeed,\n accountSecret: secret,\n provider: \"passkey\",\n });\n };\n\n signUp = async (username: string) => {\n const credentials = await this.authSecretStorage.get();\n\n if (!credentials?.secretSeed) {\n throw new Error(\n \"Not enough credentials to register the account with passkey\",\n );\n }\n\n await this.createPasskeyCredentials({\n accountID: credentials.accountID,\n secretSeed: credentials.secretSeed,\n username,\n });\n\n const currentAccount = await Account.getMe().$jazz.ensureLoaded({\n resolve: {\n profile: true,\n },\n });\n\n if (username.trim().length !== 0) {\n currentAccount.profile.$jazz.set(\"name\", username);\n }\n\n await this.authSecretStorage.set({\n accountID: credentials.accountID,\n secretSeed: credentials.secretSeed,\n accountSecret: credentials.accountSecret,\n provider: \"passkey\",\n });\n };\n\n private async createPasskeyCredentials({\n accountID,\n secretSeed,\n username,\n }: {\n accountID: ID<Account>;\n secretSeed: Uint8Array;\n username: string;\n }) {\n const webAuthNCredentialPayload = new Uint8Array(\n cojsonInternals.secretSeedLength + cojsonInternals.shortHashLength,\n );\n\n webAuthNCredentialPayload.set(secretSeed);\n webAuthNCredentialPayload.set(\n cojsonInternals.rawCoIDtoBytes(accountID as unknown as RawAccountID),\n cojsonInternals.secretSeedLength,\n );\n\n try {\n await navigator.credentials.create({\n publicKey: {\n challenge: this.crypto.randomBytes(20),\n rp: {\n name: this.appName,\n id: this.appHostname,\n },\n user: {\n id: webAuthNCredentialPayload,\n name: username + ` (${new Date().toLocaleString()})`,\n displayName: username,\n },\n pubKeyCredParams: [\n { alg: -7, type: \"public-key\" },\n { alg: -8, type: \"public-key\" },\n { alg: -37, type: \"public-key\" },\n { alg: -257, type: \"public-key\" },\n ],\n authenticatorSelection: {\n requireResidentKey: true,\n residentKey: \"required\",\n userVerification: \"preferred\",\n },\n timeout: 60000,\n attestation: \"direct\",\n },\n });\n } catch (error) {\n throw new Error(\"Passkey creation aborted\", { cause: error });\n }\n }\n\n private async getPasskeyCredentials() {\n try {\n const value = await navigator.credentials.get({\n publicKey: {\n challenge: Uint8Array.from([0, 1, 2]),\n rpId: this.appHostname,\n allowCredentials: [],\n timeout: 60000,\n userVerification: \"preferred\",\n },\n mediation: \"optional\",\n });\n\n return value as\n | (Credential & { response: { userHandle: ArrayBuffer } })\n | null;\n } catch (error) {\n throw new Error(\"Passkey creation aborted\", { cause: error });\n }\n }\n}\n","import { LocalNode, Peer, RawAccountID } from \"cojson\";\nimport { getIndexedDBStorage } from \"cojson-storage-indexeddb\";\nimport { WebSocketPeerWithReconnection } from \"cojson-transport-ws\";\nimport { WasmCrypto } from \"cojson/crypto/WasmCrypto\";\nimport {\n Account,\n AccountClass,\n AgentID,\n AnyAccountSchema,\n AuthCredentials,\n AuthSecretStorage,\n CoValue,\n CoValueFromRaw,\n CryptoProvider,\n ID,\n InviteSecret,\n NewAccountProps,\n SessionID,\n SyncConfig,\n cojsonInternals,\n createAnonymousJazzContext,\n} from \"jazz-tools\";\nimport { createJazzContext } from \"jazz-tools\";\nimport { StorageConfig, getStorageOptions } from \"./storageOptions.js\";\nimport { setupInspector } from \"./utils/export-account-inspector.js\";\n\nsetupInspector();\n\nexport type BaseBrowserContextOptions = {\n sync: SyncConfig;\n reconnectionTimeout?: number;\n storage?: StorageConfig;\n crypto?: CryptoProvider;\n authSecretStorage: AuthSecretStorage;\n};\n\nclass BrowserWebSocketPeerWithReconnection extends WebSocketPeerWithReconnection {\n onNetworkChange(callback: (connected: boolean) => void): () => void {\n const handler = () => callback(navigator.onLine);\n window.addEventListener(\"online\", handler);\n window.addEventListener(\"offline\", handler);\n\n return () => {\n window.removeEventListener(\"online\", handler);\n window.removeEventListener(\"offline\", handler);\n };\n }\n}\n\nasync function setupPeers(options: BaseBrowserContextOptions) {\n const crypto = options.crypto || (await WasmCrypto.create());\n let node: LocalNode | undefined = undefined;\n\n const { useIndexedDB } = getStorageOptions(options.storage);\n\n const peersToLoadFrom: Peer[] = [];\n\n const storage = useIndexedDB ? await getIndexedDBStorage() : undefined;\n\n if (options.sync.when === \"never\") {\n return {\n addConnectionListener: () => () => {},\n connected: () => false,\n toggleNetwork: () => {},\n peersToLoadFrom,\n storage,\n setNode: () => {},\n crypto,\n };\n }\n\n const wsPeer = new BrowserWebSocketPeerWithReconnection({\n peer: options.sync.peer,\n reconnectionTimeout: options.reconnectionTimeout,\n addPeer: (peer) => {\n if (node) {\n node.syncManager.addPeer(peer);\n } else {\n peersToLoadFrom.push(peer);\n }\n },\n removePeer: (peer) => {\n peersToLoadFrom.splice(peersToLoadFrom.indexOf(peer), 1);\n },\n });\n\n function toggleNetwork(enabled: boolean) {\n if (enabled) {\n wsPeer.enable();\n } else {\n wsPeer.disable();\n }\n }\n\n function setNode(value: LocalNode) {\n node = value;\n }\n\n if (options.sync.when === \"always\" || !options.sync.when) {\n toggleNetwork(true);\n }\n\n return {\n toggleNetwork,\n addConnectionListener(listener: (connected: boolean) => void) {\n wsPeer.subscribe(listener);\n\n return () => {\n wsPeer.unsubscribe(listener);\n };\n },\n connected() {\n return wsPeer.connected;\n },\n peersToLoadFrom,\n storage,\n setNode,\n crypto,\n };\n}\n\nexport async function createJazzBrowserGuestContext(\n options: BaseBrowserContextOptions,\n) {\n const {\n toggleNetwork,\n peersToLoadFrom,\n setNode,\n crypto,\n storage,\n addConnectionListener,\n connected,\n } = await setupPeers(options);\n\n const context = await createAnonymousJazzContext({\n crypto,\n peersToLoadFrom,\n storage,\n });\n\n setNode(context.agent.node);\n\n options.authSecretStorage.emitUpdate(null);\n\n return {\n guest: context.agent,\n node: context.agent.node,\n done: () => {\n // TODO: Sync all the covalues before closing the connection & context\n toggleNetwork(false);\n context.done();\n },\n logOut: () => {\n return context.logOut();\n },\n addConnectionListener,\n connected,\n };\n}\n\nexport type BrowserContextOptions<\n S extends\n | (AccountClass<Account> & CoValueFromRaw<Account>)\n | AnyAccountSchema,\n> = {\n credentials?: AuthCredentials;\n AccountSchema?: S;\n newAccountProps?: NewAccountProps;\n defaultProfileName?: string;\n} & BaseBrowserContextOptions;\n\nexport async function createJazzBrowserContext<\n S extends\n | (AccountClass<Account> & CoValueFromRaw<Account>)\n | AnyAccountSchema,\n>(options: BrowserContextOptions<S>) {\n const {\n toggleNetwork,\n peersToLoadFrom,\n setNode,\n crypto,\n storage,\n addConnectionListener,\n connected,\n } = await setupPeers(options);\n\n let unsubscribeAuthUpdate = () => {};\n\n if (options.sync.when === \"signedUp\") {\n const authSecretStorage = options.authSecretStorage;\n const credentials = options.credentials ?? (await authSecretStorage.get());\n\n function handleAuthUpdate(isAuthenticated: boolean) {\n if (isAuthenticated) {\n toggleNetwork(true);\n } else {\n toggleNetwork(false);\n }\n }\n\n unsubscribeAuthUpdate = authSecretStorage.onUpdate(handleAuthUpdate);\n handleAuthUpdate(authSecretStorage.getIsAuthenticated(credentials));\n }\n\n const context = await createJazzContext({\n credentials: options.credentials,\n newAccountProps: options.newAccountProps,\n peersToLoadFrom,\n storage,\n crypto,\n defaultProfileName: options.defaultProfileName,\n AccountSchema: options.AccountSchema,\n sessionProvider: provideBrowserLockSession,\n authSecretStorage: options.authSecretStorage,\n });\n\n setNode(context.node);\n\n return {\n me: context.account,\n node: context.node,\n authSecretStorage: context.authSecretStorage,\n done: () => {\n // TODO: Sync all the covalues before closing the connection & context\n toggleNetwork(false);\n unsubscribeAuthUpdate();\n context.done();\n },\n logOut: () => {\n unsubscribeAuthUpdate();\n return context.logOut();\n },\n addConnectionListener,\n connected,\n };\n}\n\n/** @category Auth Providers */\nexport type SessionProvider = (\n accountID: ID<Account> | AgentID,\n) => Promise<SessionID>;\n\nexport function provideBrowserLockSession(\n accountID: ID<Account> | AgentID,\n crypto: CryptoProvider,\n) {\n if (typeof navigator === \"undefined\" || !navigator.locks?.request) {\n // Fallback to random session ID for each tab session\n return Promise.resolve({\n sessionID: crypto.newRandomSessionID(accountID as RawAccountID | AgentID),\n sessionDone: () => {},\n });\n }\n\n let sessionDone!: () => void;\n const donePromise = new Promise<void>((resolve) => {\n sessionDone = resolve;\n });\n\n let resolveSession: (sessionID: SessionID) => void;\n const sessionPromise = new Promise<SessionID>((resolve) => {\n resolveSession = resolve;\n });\n\n void (async function () {\n for (let idx = 0; idx < 100; idx++) {\n // To work better around StrictMode\n for (let retry = 0; retry < 2; retry++) {\n // console.debug(\"Trying to get lock\", accountID + \"_\" + idx);\n const sessionFinishedOrNoLock = await navigator.locks.request(\n accountID + \"_\" + idx,\n { ifAvailable: true },\n async (lock) => {\n if (!lock) return \"noLock\";\n\n const sessionID =\n localStorage.getItem(accountID + \"_\" + idx) ||\n crypto.newRandomSessionID(accountID as RawAccountID | AgentID);\n localStorage.setItem(accountID + \"_\" + idx, sessionID);\n\n resolveSession(sessionID as SessionID);\n\n await donePromise;\n console.log(\"Done with lock\", accountID + \"_\" + idx, sessionID);\n return \"sessionFinished\";\n },\n );\n\n if (sessionFinishedOrNoLock === \"sessionFinished\") {\n return;\n }\n }\n }\n throw new Error(\"Couldn't get lock on session after 100x2 tries\");\n })();\n\n return sessionPromise.then((sessionID) => ({\n sessionID,\n sessionDone,\n }));\n}\n\n/** @category Invite Links */\nexport function createInviteLink<C extends CoValue>(\n value: C,\n role: \"reader\" | \"writer\" | \"admin\" | \"writeOnly\",\n // default to same address as window.location, but without hash\n {\n baseURL = window.location.href.replace(/#.*$/, \"\"),\n valueHint,\n }: { baseURL?: string; valueHint?: string } = {},\n): string {\n const coValueCore = value.$jazz.raw.core;\n let currentCoValue = coValueCore;\n\n while (currentCoValue.verified.header.ruleset.type === \"ownedByGroup\") {\n currentCoValue = currentCoValue.getGroup().core;\n }\n\n const { ruleset, meta } = currentCoValue.verified.header;\n\n if (ruleset.type !== \"group\" || meta?.type === \"account\") {\n throw new Error(\"Can't create invite link for object without group\");\n }\n\n const group = cojsonInternals.expectGroup(currentCoValue.getCurrentContent());\n const inviteSecret = group.createInvite(role);\n\n return `${baseURL}#/invite/${valueHint ? valueHint + \"/\" : \"\"}${\n value.$jazz.id\n }/${inviteSecret}`;\n}\n\n/** @category Invite Links */\nexport function parseInviteLink<C extends CoValue>(\n inviteURL: string,\n):\n | {\n valueID: ID<C>;\n valueHint?: string;\n inviteSecret: InviteSecret;\n }\n | undefined {\n const url = new URL(inviteURL);\n const parts = url.hash.split(\"/\");\n\n let valueHint: string | undefined;\n let valueID: ID<C> | undefined;\n let inviteSecret: InviteSecret | undefined;\n\n if (parts[0] === \"#\" && parts[1] === \"invite\") {\n if (parts.length === 5) {\n valueHint = parts[2];\n valueID = parts[3] as ID<C>;\n inviteSecret = parts[4] as InviteSecret;\n } else if (parts.length === 4) {\n valueID = parts[2] as ID<C>;\n inviteSecret = parts[3] as InviteSecret;\n }\n\n if (!valueID || !inviteSecret) {\n return undefined;\n }\n return { valueID, inviteSecret, valueHint };\n }\n}\n","type StorageOption = \"indexedDB\";\ntype CombinedStorageOption = [\"indexedDB\"];\nexport type StorageConfig =\n | StorageOption\n | CombinedStorageOption\n | [StorageOption];\n\nexport function getStorageOptions(storage?: StorageConfig): {\n useIndexedDB: boolean;\n} {\n const useIndexedDB =\n !storage ||\n (Array.isArray(storage) && storage.includes(\"indexedDB\")) ||\n storage === \"indexedDB\";\n\n return { useIndexedDB };\n}\n","import {\n Account,\n AccountClass,\n AnyAccountSchema,\n CoValueFromRaw,\n InMemoryKVStore,\n InstanceOfSchema,\n JazzContextManager,\n SyncConfig,\n} from \"jazz-tools\";\nimport { JazzContextManagerAuthProps } from \"jazz-tools\";\nimport { LocalStorageKVStore } from \"./auth/LocalStorageKVStore.js\";\nimport {\n BaseBrowserContextOptions,\n createJazzBrowserContext,\n createJazzBrowserGuestContext,\n} from \"./createBrowserContext.js\";\n\nexport type JazzContextManagerProps<\n S extends\n | (AccountClass<Account> & CoValueFromRaw<Account>)\n | AnyAccountSchema,\n> = {\n guestMode?: boolean;\n sync: SyncConfig;\n onLogOut?: () => void;\n logOutReplacement?: () => void;\n onAnonymousAccountDiscarded?: (\n anonymousAccount: InstanceOfSchema<S>,\n ) => Promise<void>;\n storage?: BaseBrowserContextOptions[\"storage\"];\n AccountSchema?: S;\n defaultProfileName?: string;\n};\n\nexport class JazzBrowserContextManager<\n S extends\n | (AccountClass<Account> & CoValueFromRaw<Account>)\n | AnyAccountSchema,\n> extends JazzContextManager<InstanceOfSchema<S>, JazzContextManagerProps<S>> {\n // TODO: When the storage changes, if the user is changed, update the context\n getKvStore() {\n if (typeof window === \"undefined\") {\n // To handle running in SSR\n return new InMemoryKVStore();\n } else {\n return new LocalStorageKVStore();\n }\n }\n\n async getNewContext(\n props: JazzContextManagerProps<S>,\n authProps?: JazzContextManagerAuthProps,\n ) {\n if (props.guestMode) {\n return createJazzBrowserGuestContext({\n sync: props.sync,\n storage: props.storage,\n authSecretStorage: this.authSecretStorage,\n });\n } else {\n return createJazzBrowserContext<S>({\n sync: props.sync,\n storage: props.storage,\n AccountSchema: props.AccountSchema,\n credentials: authProps?.credentials,\n newAccountProps: authProps?.newAccountProps,\n defaultProfileName: props.defaultProfileName,\n authSecretStorage: this.authSecretStorage,\n });\n }\n }\n\n propsChanged(props: JazzContextManagerProps<S>) {\n if (!this.props) {\n return true;\n }\n\n return (\n this.props.sync.when !== props.sync.when ||\n this.props.sync.peer !== props.sync.peer ||\n this.props.guestMode !== props.guestMode\n );\n }\n}\n","import { KvStore } from \"jazz-tools\";\n\nexport class LocalStorageKVStore implements KvStore {\n constructor() {}\n\n async get(key: string) {\n return localStorage.getItem(key);\n }\n\n async set(key: string, value: string) {\n localStorage.setItem(key, value);\n }\n\n async delete(key: string) {\n localStorage.removeItem(key);\n }\n\n async clearAll() {\n localStorage.clear();\n }\n}\n"],"mappings":";AAAA;AAAA,EAKE,oBAAoB;AAAA,EACpB;AAAA,OACK;;;ACPP,SAAS,yBAAyB;AAElC,eAAe,2BAA2B;AACxC,QAAM,oBAAoB,IAAI,kBAAkB;AAChD,QAAM,mBAAmB,MAAM,kBAAkB,IAAI;AAErD,MAAI,CAAC,kBAAkB;AACrB,YAAQ,MAAM,uCAAuC;AACrD;AAAA,EACF;AAEA,QAAM,uBAAuB,KAAK,iBAAiB,aAAa;AAChE,SAAO;AAAA,IACL,IAAI;AAAA,MACF,YAAY,kBAAkB,SAAS,IAAI,oBAAoB;AAAA,MAC/D;AAAA,IACF,EAAE,SAAS;AAAA,IACX;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB;AACvB,MAAI,OAAO,WAAW,YAAa;AAEnC,QAAM,KAAK,CAAC,MAAW;AACrB,QAAI,EAAE,WAAW,EAAE,QAAQ,KAAK;AAC9B,UACE;AAAA,QACE;AAAA,MACF,GACA;AACA,iCAAyB;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAEA,SAAO,iBAAiB,WAAW,EAAE;AAErC,SAAO,MAAM;AACX,WAAO,oBAAoB,WAAW,EAAE;AAAA,EAC1C;AACF;AAMO,SAAS,iBAAiB;AAC/B,MAAI,OAAO,WAAW,YAAa;AAEnC,QAAM,MAAM,IAAI,IAAI,OAAO,SAAS,IAAI;AACxC,MACE,IAAI,KAAK,SAAS,oBAAoB,KACtC,QAAQ,IAAI,aAAa,eACzB;AACA,WAAO,cAAc;AAAA,EACvB;AACF;;;ACzDA,SAAuC,uBAAuB;AAC9D;AAAA,EACE;AAAA,OAIK;AAaA,IAAM,qBAAN,MAAyB;AAAA,EAC9B,YACY,QACA,cACA,mBACH,SACA,cAAsB,OAAO,SAAS,UAC7C;AALU;AACA;AACA;AACH;AACA;AAKT,iBAAQ,YAAY;AAClB,YAAM,EAAE,QAAQ,aAAa,IAAI;AAEjC,YAAM,qBAAqB,MAAM,KAAK,sBAAsB;AAE5D,UAAI,CAAC,oBAAoB;AACvB;AAAA,MACF;AAEA,YAAM,4BAA4B,IAAI;AAAA,QACpC,mBAAmB,SAAS;AAAA,MAC9B;AACA,YAAM,oBAAoB,0BAA0B;AAAA,QAClD;AAAA,QACA,gBAAgB;AAAA,MAClB;AAEA,YAAM,SAAS,OAAO,0BAA0B,iBAAiB;AAEjE,YAAM,YAAY,gBAAgB;AAAA,QAChC,0BAA0B;AAAA,UACxB,gBAAgB;AAAA,UAChB,gBAAgB,mBAAmB,gBAAgB;AAAA,QACrD;AAAA,MACF;AAEA,YAAM,aAAa;AAAA,QACjB;AAAA,QACA,eAAe;AAAA,MACjB,CAAC;AAED,YAAM,KAAK,kBAAkB,IAAI;AAAA,QAC/B;AAAA,QACA,YAAY;AAAA,QACZ,eAAe;AAAA,QACf,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAEA,kBAAS,OAAO,aAAqB;AACnC,YAAM,cAAc,MAAM,KAAK,kBAAkB,IAAI;AAErD,UAAI,CAAC,aAAa,YAAY;AAC5B,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAEA,YAAM,KAAK,yBAAyB;AAAA,QAClC,WAAW,YAAY;AAAA,QACvB,YAAY,YAAY;AAAA,QACxB;AAAA,MACF,CAAC;AAED,YAAM,iBAAiB,MAAM,QAAQ,MAAM,EAAE,MAAM,aAAa;AAAA,QAC9D,SAAS;AAAA,UACP,SAAS;AAAA,QACX;AAAA,MACF,CAAC;AAED,UAAI,SAAS,KAAK,EAAE,WAAW,GAAG;AAChC,uBAAe,QAAQ,MAAM,IAAI,QAAQ,QAAQ;AAAA,MACnD;AAEA,YAAM,KAAK,kBAAkB,IAAI;AAAA,QAC/B,WAAW,YAAY;AAAA,QACvB,YAAY,YAAY;AAAA,QACxB,eAAe,YAAY;AAAA,QAC3B,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EA1EG;AAAA,EA4EH,MAAc,yBAAyB;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAIG;AACD,UAAM,4BAA4B,IAAI;AAAA,MACpC,gBAAgB,mBAAmB,gBAAgB;AAAA,IACrD;AAEA,8BAA0B,IAAI,UAAU;AACxC,8BAA0B;AAAA,MACxB,gBAAgB,eAAe,SAAoC;AAAA,MACnE,gBAAgB;AAAA,IAClB;AAEA,QAAI;AACF,YAAM,UAAU,YAAY,OAAO;AAAA,QACjC,WAAW;AAAA,UACT,WAAW,KAAK,OAAO,YAAY,EAAE;AAAA,UACrC,IAAI;AAAA,YACF,MAAM,KAAK;AAAA,YACX,IAAI,KAAK;AAAA,UACX;AAAA,UACA,MAAM;AAAA,YACJ,IAAI;AAAA,YACJ,MAAM,WAAW,MAAK,oBAAI,KAAK,GAAE,eAAe,CAAC;AAAA,YACjD,aAAa;AAAA,UACf;AAAA,UACA,kBAAkB;AAAA,YAChB,EAAE,KAAK,IAAI,MAAM,aAAa;AAAA,YAC9B,EAAE,KAAK,IAAI,MAAM,aAAa;AAAA,YAC9B,EAAE,KAAK,KAAK,MAAM,aAAa;AAAA,YAC/B,EAAE,KAAK,MAAM,MAAM,aAAa;AAAA,UAClC;AAAA,UACA,wBAAwB;AAAA,YACtB,oBAAoB;AAAA,YACpB,aAAa;AAAA,YACb,kBAAkB;AAAA,UACpB;AAAA,UACA,SAAS;AAAA,UACT,aAAa;AAAA,QACf;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,4BAA4B,EAAE,OAAO,MAAM,CAAC;AAAA,IAC9D;AAAA,EACF;AAAA,EAEA,MAAc,wBAAwB;AACpC,QAAI;AACF,YAAM,QAAQ,MAAM,UAAU,YAAY,IAAI;AAAA,QAC5C,WAAW;AAAA,UACT,WAAW,WAAW,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;AAAA,UACpC,MAAM,KAAK;AAAA,UACX,kBAAkB,CAAC;AAAA,UACnB,SAAS;AAAA,UACT,kBAAkB;AAAA,QACpB;AAAA,QACA,WAAW;AAAA,MACb,CAAC;AAED,aAAO;AAAA,IAGT,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,4BAA4B,EAAE,OAAO,MAAM,CAAC;AAAA,IAC9D;AAAA,EACF;AACF;AA3Ja,mBASK,KAAK;;;AC3BvB,SAAS,2BAA2B;AACpC,SAAS,qCAAqC;AAC9C,SAAS,kBAAkB;AAC3B;AAAA,EAeE,mBAAAA;AAAA,EACA;AAAA,OACK;AACP,SAAS,yBAAyB;;;ACf3B,SAAS,kBAAkB,SAEhC;AACA,QAAM,eACJ,CAAC,WACA,MAAM,QAAQ,OAAO,KAAK,QAAQ,SAAS,WAAW,KACvD,YAAY;AAEd,SAAO,EAAE,aAAa;AACxB;;;ADUA,eAAe;AAUf,IAAM,uCAAN,cAAmD,8BAA8B;AAAA,EAC/E,gBAAgB,UAAoD;AAClE,UAAM,UAAU,MAAM,SAAS,UAAU,MAAM;AAC/C,WAAO,iBAAiB,UAAU,OAAO;AACzC,WAAO,iBAAiB,WAAW,OAAO;AAE1C,WAAO,MAAM;AACX,aAAO,oBAAoB,UAAU,OAAO;AAC5C,aAAO,oBAAoB,WAAW,OAAO;AAAA,IAC/C;AAAA,EACF;AACF;AAEA,eAAe,WAAW,SAAoC;AAC5D,QAAM,SAAS,QAAQ,UAAW,MAAM,WAAW,OAAO;AAC1D,MAAI,OAA8B;AAElC,QAAM,EAAE,aAAa,IAAI,kBAAkB,QAAQ,OAAO;AAE1D,QAAM,kBAA0B,CAAC;AAEjC,QAAM,UAAU,eAAe,MAAM,oBAAoB,IAAI;AAE7D,MAAI,QAAQ,KAAK,SAAS,SAAS;AACjC,WAAO;AAAA,MACL,uBAAuB,MAAM,MAAM;AAAA,MAAC;AAAA,MACpC,WAAW,MAAM;AAAA,MACjB,eAAe,MAAM;AAAA,MAAC;AAAA,MACtB;AAAA,MACA;AAAA,MACA,SAAS,MAAM;AAAA,MAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,IAAI,qCAAqC;AAAA,IACtD,MAAM,QAAQ,KAAK;AAAA,IACnB,qBAAqB,QAAQ;AAAA,IAC7B,SAAS,CAAC,SAAS;AACjB,UAAI,MAAM;AACR,aAAK,YAAY,QAAQ,IAAI;AAAA,MAC/B,OAAO;AACL,wBAAgB,KAAK,IAAI;AAAA,MAC3B;AAAA,IACF;AAAA,IACA,YAAY,CAAC,SAAS;AACpB,sBAAgB,OAAO,gBAAgB,QAAQ,IAAI,GAAG,CAAC;AAAA,IACzD;AAAA,EACF,CAAC;AAED,WAAS,cAAc,SAAkB;AACvC,QAAI,SAAS;AACX,aAAO,OAAO;AAAA,IAChB,OAAO;AACL,aAAO,QAAQ;AAAA,IACjB;AAAA,EACF;AAEA,WAAS,QAAQ,OAAkB;AACjC,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,KAAK,SAAS,YAAY,CAAC,QAAQ,KAAK,MAAM;AACxD,kBAAc,IAAI;AAAA,EACpB;AAEA,SAAO;AAAA,IACL;AAAA,IACA,sBAAsB,UAAwC;AAC5D,aAAO,UAAU,QAAQ;AAEzB,aAAO,MAAM;AACX,eAAO,YAAY,QAAQ;AAAA,MAC7B;AAAA,IACF;AAAA,IACA,YAAY;AACV,aAAO,OAAO;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAsB,8BACpB,SACA;AACA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,MAAM,WAAW,OAAO;AAE5B,QAAM,UAAU,MAAM,2BAA2B;AAAA,IAC/C;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,UAAQ,QAAQ,MAAM,IAAI;AAE1B,UAAQ,kBAAkB,WAAW,IAAI;AAEzC,SAAO;AAAA,IACL,OAAO,QAAQ;AAAA,IACf,MAAM,QAAQ,MAAM;AAAA,IACpB,MAAM,MAAM;AAEV,oBAAc,KAAK;AACnB,cAAQ,KAAK;AAAA,IACf;AAAA,IACA,QAAQ,MAAM;AACZ,aAAO,QAAQ,OAAO;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAaA,eAAsB,yBAIpB,SAAmC;AACnC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,MAAM,WAAW,OAAO;AAE5B,MAAI,wBAAwB,MAAM;AAAA,EAAC;AAEnC,MAAI,QAAQ,KAAK,SAAS,YAAY;AAIpC,QAASC,oBAAT,SAA0B,iBAA0B;AAClD,UAAI,iBAAiB;AACnB,sBAAc,IAAI;AAAA,MACpB,OAAO;AACL,sBAAc,KAAK;AAAA,MACrB;AAAA,IACF;AANS,2BAAAA;AAHT,UAAM,oBAAoB,QAAQ;AAClC,UAAM,cAAc,QAAQ,eAAgB,MAAM,kBAAkB,IAAI;AAUxE,4BAAwB,kBAAkB,SAASA,iBAAgB;AACnE,IAAAA,kBAAiB,kBAAkB,mBAAmB,WAAW,CAAC;AAAA,EACpE;AAEA,QAAM,UAAU,MAAM,kBAAkB;AAAA,IACtC,aAAa,QAAQ;AAAA,IACrB,iBAAiB,QAAQ;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA,oBAAoB,QAAQ;AAAA,IAC5B,eAAe,QAAQ;AAAA,IACvB,iBAAiB;AAAA,IACjB,mBAAmB,QAAQ;AAAA,EAC7B,CAAC;AAED,UAAQ,QAAQ,IAAI;AAEpB,SAAO;AAAA,IACL,IAAI,QAAQ;AAAA,IACZ,MAAM,QAAQ;AAAA,IACd,mBAAmB,QAAQ;AAAA,IAC3B,MAAM,MAAM;AAEV,oBAAc,KAAK;AACnB,4BAAsB;AACtB,cAAQ,KAAK;AAAA,IACf;AAAA,IACA,QAAQ,MAAM;AACZ,4BAAsB;AACtB,aAAO,QAAQ,OAAO;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAOO,SAAS,0BACd,WACA,QACA;AACA,MAAI,OAAO,cAAc,eAAe,CAAC,UAAU,OAAO,SAAS;AAEjE,WAAO,QAAQ,QAAQ;AAAA,MACrB,WAAW,OAAO,mBAAmB,SAAmC;AAAA,MACxE,aAAa,MAAM;AAAA,MAAC;AAAA,IACtB,CAAC;AAAA,EACH;AAEA,MAAI;AACJ,QAAM,cAAc,IAAI,QAAc,CAAC,YAAY;AACjD,kBAAc;AAAA,EAChB,CAAC;AAED,MAAI;AACJ,QAAM,iBAAiB,IAAI,QAAmB,CAAC,YAAY;AACzD,qBAAiB;AAAA,EACnB,CAAC;AAED,OAAM,iBAAkB;AACtB,aAAS,MAAM,GAAG,MAAM,KAAK,OAAO;AAElC,eAAS,QAAQ,GAAG,QAAQ,GAAG,SAAS;AAEtC,cAAM,0BAA0B,MAAM,UAAU,MAAM;AAAA,UACpD,YAAY,MAAM;AAAA,UAClB,EAAE,aAAa,KAAK;AAAA,UACpB,OAAO,SAAS;AACd,gBAAI,CAAC,KAAM,QAAO;AAElB,kBAAM,YACJ,aAAa,QAAQ,YAAY,MAAM,GAAG,KAC1C,OAAO,mBAAmB,SAAmC;AAC/D,yBAAa,QAAQ,YAAY,MAAM,KAAK,SAAS;AAErD,2BAAe,SAAsB;AAErC,kBAAM;AACN,oBAAQ,IAAI,kBAAkB,YAAY,MAAM,KAAK,SAAS;AAC9D,mBAAO;AAAA,UACT;AAAA,QACF;AAEA,YAAI,4BAA4B,mBAAmB;AACjD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE,EAAG;AAEH,SAAO,eAAe,KAAK,CAAC,eAAe;AAAA,IACzC;AAAA,IACA;AAAA,EACF,EAAE;AACJ;;;AE5SA;AAAA,EAKE;AAAA,EAEA;AAAA,OAEK;;;ACPA,IAAM,sBAAN,MAA6C;AAAA,EAClD,cAAc;AAAA,EAAC;AAAA,EAEf,MAAM,IAAI,KAAa;AACrB,WAAO,aAAa,QAAQ,GAAG;AAAA,EACjC;AAAA,EAEA,MAAM,IAAI,KAAa,OAAe;AACpC,iBAAa,QAAQ,KAAK,KAAK;AAAA,EACjC;AAAA,EAEA,MAAM,OAAO,KAAa;AACxB,iBAAa,WAAW,GAAG;AAAA,EAC7B;AAAA,EAEA,MAAM,WAAW;AACf,iBAAa,MAAM;AAAA,EACrB;AACF;;;ADeO,IAAM,4BAAN,cAIG,mBAAoE;AAAA;AAAA,EAE5E,aAAa;AACX,QAAI,OAAO,WAAW,aAAa;AAEjC,aAAO,IAAI,gBAAgB;AAAA,IAC7B,OAAO;AACL,aAAO,IAAI,oBAAoB;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,MAAM,cACJ,OACA,WACA;AACA,QAAI,MAAM,WAAW;AACnB,aAAO,8BAA8B;AAAA,QACnC,MAAM,MAAM;AAAA,QACZ,SAAS,MAAM;AAAA,QACf,mBAAmB,KAAK;AAAA,MAC1B,CAAC;AAAA,IACH,OAAO;AACL,aAAO,yBAA4B;AAAA,QACjC,MAAM,MAAM;AAAA,QACZ,SAAS,MAAM;AAAA,QACf,eAAe,MAAM;AAAA,QACrB,aAAa,WAAW;AAAA,QACxB,iBAAiB,WAAW;AAAA,QAC5B,oBAAoB,MAAM;AAAA,QAC1B,mBAAmB,KAAK;AAAA,MAC1B,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,aAAa,OAAmC;AAC9C,QAAI,CAAC,KAAK,OAAO;AACf,aAAO;AAAA,IACT;AAEA,WACE,KAAK,MAAM,KAAK,SAAS,MAAM,KAAK,QACpC,KAAK,MAAM,KAAK,SAAS,MAAM,KAAK,QACpC,KAAK,MAAM,cAAc,MAAM;AAAA,EAEnC;AACF;;;ALpDA,SAAS,uBAAuB;AArBhC,eAAe;AAQR,SAAS,iBACd,OACA,MAEA;AAAA,EACE,UAAU,OAAO,SAAS,KAAK,QAAQ,QAAQ,EAAE;AAAA,EACjD;AACF,IAA8C,CAAC,GACvC;AACR,SAAO,qBAAqB,OAAO,MAAM,SAAS,SAAS;AAC7D;AAMA,eAAsB,oCAEpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAWE;AACA,QAAM,SAAS,MAAM,kBAAkB;AAAA,IACrC,WAAW,OAAO,SAAS;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,MAAI,QAAQ;AACV,WAAO,QAAQ;AAAA,MACb,CAAC;AAAA,MACD;AAAA,MACA,OAAO,SAAS,KAAK,QAAQ,QAAQ,EAAE;AAAA,IACzC;AAAA,EACF;AAEA,SAAO;AACT;","names":["cojsonInternals","handleAuthUpdate"]}
|
1
|
+
{"version":3,"sources":["../../src/browser/index.ts","../../src/browser/utils/export-account-inspector.ts","../../src/browser/auth/PasskeyAuth.ts","../../src/browser/createBrowserContext.ts","../../src/browser/storageOptions.ts","../../src/browser/BrowserContextManager.ts","../../src/browser/auth/LocalStorageKVStore.ts"],"sourcesContent":["import {\n Account,\n CoValue,\n CoValueClassOrSchema,\n InviteSecret,\n createInviteLink as baseCreateInviteLink,\n consumeInviteLink,\n} from \"jazz-tools\";\nimport { setupInspector } from \"./utils/export-account-inspector.js\";\nexport { BrowserPasskeyAuth } from \"./auth/PasskeyAuth.js\";\n\nsetupInspector();\n\nexport * from \"./createBrowserContext.js\";\nexport * from \"./BrowserContextManager.js\";\n\nexport { LocalStorageKVStore } from \"./auth/LocalStorageKVStore.js\";\n\n/** @category Invite Links */\nexport function createInviteLink<C extends CoValue>(\n value: C,\n role: \"reader\" | \"writer\" | \"admin\" | \"writeOnly\",\n // default to same address as window.location, but without hash\n {\n baseURL = window.location.href.replace(/#.*$/, \"\"),\n valueHint,\n }: { baseURL?: string; valueHint?: string } = {},\n): string {\n return baseCreateInviteLink(value, role, baseURL, valueHint);\n}\n\n/** @category Invite Links */\nexport { parseInviteLink } from \"jazz-tools\";\n\n/** @category Invite Links */\nexport async function consumeInviteLinkFromWindowLocation<\n S extends CoValueClassOrSchema,\n>({\n as,\n forValueHint,\n invitedObjectSchema,\n}: {\n as?: Account;\n forValueHint?: string;\n invitedObjectSchema: S;\n}): Promise<\n | {\n valueID: string;\n valueHint?: string;\n inviteSecret: InviteSecret;\n }\n | undefined\n> {\n const result = await consumeInviteLink({\n inviteURL: window.location.href,\n as,\n forValueHint,\n invitedObjectSchema,\n });\n\n if (result) {\n window.history.replaceState(\n {},\n \"\",\n window.location.href.replace(/#.*$/, \"\"),\n );\n }\n\n return result;\n}\n","import { AuthSecretStorage } from \"jazz-tools\";\n\nasync function exportAccountToInspector() {\n const authSecretStorage = new AuthSecretStorage();\n const localStorageData = await authSecretStorage.get();\n\n if (!localStorageData) {\n console.error(\"No account data found in localStorage\");\n return;\n }\n\n const encodedAccountSecret = btoa(localStorageData.accountSecret);\n window.open(\n new URL(\n `#/import/${localStorageData?.accountID}/${encodedAccountSecret}`,\n \"https://inspector.jazz.tools\",\n ).toString(),\n \"_blank\",\n );\n}\n\nfunction listenForCmdJ() {\n if (typeof window === \"undefined\") return;\n\n const cb = (e: any) => {\n if (e.metaKey && e.key === \"j\") {\n if (\n confirm(\n \"Are you sure you want to inspect your account using inspector.jazz.tools? This lets anyone with the secret inspector URL read your data and impersonate you.\",\n )\n ) {\n exportAccountToInspector();\n }\n }\n };\n\n window.addEventListener(\"keydown\", cb);\n\n return () => {\n window.removeEventListener(\"keydown\", cb);\n };\n}\n\n/**\n * Automatically sets up the Cmd+J listener if 'allowJazzInspector' is present in the URL\n * @returns A cleanup function if the listener was set up, undefined otherwise\n */\nexport function setupInspector() {\n if (typeof window === \"undefined\") return;\n\n const url = new URL(window.location.href);\n if (\n url.hash.includes(\"allowJazzInspector\") ||\n process.env.NODE_ENV === \"development\"\n ) {\n return listenForCmdJ();\n }\n}\n","import { CryptoProvider, RawAccountID, cojsonInternals } from \"cojson\";\nimport {\n Account,\n AuthSecretStorage,\n AuthenticateAccountFunction,\n ID,\n} from \"jazz-tools\";\n\n/**\n * `BrowserPasskeyAuth` provides a `JazzAuth` object for passkey authentication.\n *\n * ```ts\n * import { BrowserPasskeyAuth } from \"jazz-tools/browser\";\n *\n * const auth = new BrowserPasskeyAuth(driver, appName);\n * ```\n *\n * @category Auth Providers\n */\nexport class BrowserPasskeyAuth {\n constructor(\n protected crypto: CryptoProvider,\n protected authenticate: AuthenticateAccountFunction,\n protected authSecretStorage: AuthSecretStorage,\n public appName: string,\n public appHostname: string = window.location.hostname,\n ) {}\n\n static readonly id = \"passkey\";\n\n logIn = async () => {\n const { crypto, authenticate } = this;\n\n const webAuthNCredential = await this.getPasskeyCredentials();\n\n if (!webAuthNCredential) {\n return;\n }\n\n const webAuthNCredentialPayload = new Uint8Array(\n webAuthNCredential.response.userHandle,\n );\n const accountSecretSeed = webAuthNCredentialPayload.slice(\n 0,\n cojsonInternals.secretSeedLength,\n );\n\n const secret = crypto.agentSecretFromSecretSeed(accountSecretSeed);\n\n const accountID = cojsonInternals.rawCoIDfromBytes(\n webAuthNCredentialPayload.slice(\n cojsonInternals.secretSeedLength,\n cojsonInternals.secretSeedLength + cojsonInternals.shortHashLength,\n ),\n ) as ID<Account>;\n\n await authenticate({\n accountID,\n accountSecret: secret,\n });\n\n await this.authSecretStorage.set({\n accountID,\n secretSeed: accountSecretSeed,\n accountSecret: secret,\n provider: \"passkey\",\n });\n };\n\n signUp = async (username: string) => {\n const credentials = await this.authSecretStorage.get();\n\n if (!credentials?.secretSeed) {\n throw new Error(\n \"Not enough credentials to register the account with passkey\",\n );\n }\n\n await this.createPasskeyCredentials({\n accountID: credentials.accountID,\n secretSeed: credentials.secretSeed,\n username,\n });\n\n const currentAccount = await Account.getMe().$jazz.ensureLoaded({\n resolve: {\n profile: true,\n },\n });\n\n if (username.trim().length !== 0) {\n currentAccount.profile.$jazz.set(\"name\", username);\n }\n\n await this.authSecretStorage.set({\n accountID: credentials.accountID,\n secretSeed: credentials.secretSeed,\n accountSecret: credentials.accountSecret,\n provider: \"passkey\",\n });\n };\n\n private async createPasskeyCredentials({\n accountID,\n secretSeed,\n username,\n }: {\n accountID: ID<Account>;\n secretSeed: Uint8Array;\n username: string;\n }) {\n const webAuthNCredentialPayload = new Uint8Array(\n cojsonInternals.secretSeedLength + cojsonInternals.shortHashLength,\n );\n\n webAuthNCredentialPayload.set(secretSeed);\n webAuthNCredentialPayload.set(\n cojsonInternals.rawCoIDtoBytes(accountID as unknown as RawAccountID),\n cojsonInternals.secretSeedLength,\n );\n\n try {\n await navigator.credentials.create({\n publicKey: {\n challenge: new Uint8Array(this.crypto.randomBytes(20)),\n rp: {\n name: this.appName,\n id: this.appHostname,\n },\n user: {\n id: webAuthNCredentialPayload,\n name: username + ` (${new Date().toLocaleString()})`,\n displayName: username,\n },\n pubKeyCredParams: [\n { alg: -7, type: \"public-key\" },\n { alg: -8, type: \"public-key\" },\n { alg: -37, type: \"public-key\" },\n { alg: -257, type: \"public-key\" },\n ],\n authenticatorSelection: {\n requireResidentKey: true,\n residentKey: \"required\",\n userVerification: \"preferred\",\n },\n timeout: 60000,\n attestation: \"direct\",\n },\n });\n } catch (error) {\n throw new Error(\"Passkey creation aborted\", { cause: error });\n }\n }\n\n private async getPasskeyCredentials() {\n try {\n const value = await navigator.credentials.get({\n publicKey: {\n challenge: new Uint8Array(this.crypto.randomBytes(20)),\n rpId: this.appHostname,\n allowCredentials: [],\n timeout: 60000,\n userVerification: \"preferred\",\n },\n mediation: \"optional\",\n });\n\n return value as\n | (Credential & { response: { userHandle: ArrayBuffer } })\n | null;\n } catch (error) {\n throw new Error(\"Passkey creation aborted\", { cause: error });\n }\n }\n}\n","import { LocalNode, Peer, RawAccountID } from \"cojson\";\nimport { getIndexedDBStorage } from \"cojson-storage-indexeddb\";\nimport { WebSocketPeerWithReconnection } from \"cojson-transport-ws\";\nimport { WasmCrypto } from \"cojson/crypto/WasmCrypto\";\nimport {\n Account,\n AccountClass,\n AgentID,\n AnyAccountSchema,\n AuthCredentials,\n AuthSecretStorage,\n CoValue,\n CoValueFromRaw,\n CryptoProvider,\n ID,\n InviteSecret,\n NewAccountProps,\n SessionID,\n SyncConfig,\n cojsonInternals,\n createAnonymousJazzContext,\n} from \"jazz-tools\";\nimport { createJazzContext } from \"jazz-tools\";\nimport { StorageConfig, getStorageOptions } from \"./storageOptions.js\";\nimport { setupInspector } from \"./utils/export-account-inspector.js\";\n\nsetupInspector();\n\nexport type BaseBrowserContextOptions = {\n sync: SyncConfig;\n reconnectionTimeout?: number;\n storage?: StorageConfig;\n crypto?: CryptoProvider;\n authSecretStorage: AuthSecretStorage;\n};\n\nclass BrowserWebSocketPeerWithReconnection extends WebSocketPeerWithReconnection {\n onNetworkChange(callback: (connected: boolean) => void): () => void {\n const handler = () => callback(navigator.onLine);\n window.addEventListener(\"online\", handler);\n window.addEventListener(\"offline\", handler);\n\n return () => {\n window.removeEventListener(\"online\", handler);\n window.removeEventListener(\"offline\", handler);\n };\n }\n}\n\nasync function setupPeers(options: BaseBrowserContextOptions) {\n const crypto = options.crypto || (await WasmCrypto.create());\n let node: LocalNode | undefined = undefined;\n\n const { useIndexedDB } = getStorageOptions(options.storage);\n\n const peersToLoadFrom: Peer[] = [];\n\n const storage = useIndexedDB ? await getIndexedDBStorage() : undefined;\n\n if (options.sync.when === \"never\") {\n return {\n addConnectionListener: () => () => {},\n connected: () => false,\n toggleNetwork: () => {},\n peersToLoadFrom,\n storage,\n setNode: () => {},\n crypto,\n };\n }\n\n const wsPeer = new BrowserWebSocketPeerWithReconnection({\n peer: options.sync.peer,\n reconnectionTimeout: options.reconnectionTimeout,\n addPeer: (peer) => {\n if (node) {\n node.syncManager.addPeer(peer);\n } else {\n peersToLoadFrom.push(peer);\n }\n },\n removePeer: (peer) => {\n peersToLoadFrom.splice(peersToLoadFrom.indexOf(peer), 1);\n },\n });\n\n function toggleNetwork(enabled: boolean) {\n if (enabled) {\n wsPeer.enable();\n } else {\n wsPeer.disable();\n }\n }\n\n function setNode(value: LocalNode) {\n node = value;\n }\n\n if (options.sync.when === \"always\" || !options.sync.when) {\n toggleNetwork(true);\n }\n\n return {\n toggleNetwork,\n addConnectionListener(listener: (connected: boolean) => void) {\n wsPeer.subscribe(listener);\n\n return () => {\n wsPeer.unsubscribe(listener);\n };\n },\n connected() {\n return wsPeer.connected;\n },\n peersToLoadFrom,\n storage,\n setNode,\n crypto,\n };\n}\n\nexport async function createJazzBrowserGuestContext(\n options: BaseBrowserContextOptions,\n) {\n const {\n toggleNetwork,\n peersToLoadFrom,\n setNode,\n crypto,\n storage,\n addConnectionListener,\n connected,\n } = await setupPeers(options);\n\n const context = await createAnonymousJazzContext({\n crypto,\n peersToLoadFrom,\n storage,\n });\n\n setNode(context.agent.node);\n\n options.authSecretStorage.emitUpdate(null);\n\n return {\n guest: context.agent,\n node: context.agent.node,\n done: () => {\n // TODO: Sync all the covalues before closing the connection & context\n toggleNetwork(false);\n context.done();\n },\n logOut: () => {\n return context.logOut();\n },\n addConnectionListener,\n connected,\n };\n}\n\nexport type BrowserContextOptions<\n S extends\n | (AccountClass<Account> & CoValueFromRaw<Account>)\n | AnyAccountSchema,\n> = {\n credentials?: AuthCredentials;\n AccountSchema?: S;\n newAccountProps?: NewAccountProps;\n defaultProfileName?: string;\n} & BaseBrowserContextOptions;\n\nexport async function createJazzBrowserContext<\n S extends\n | (AccountClass<Account> & CoValueFromRaw<Account>)\n | AnyAccountSchema,\n>(options: BrowserContextOptions<S>) {\n const {\n toggleNetwork,\n peersToLoadFrom,\n setNode,\n crypto,\n storage,\n addConnectionListener,\n connected,\n } = await setupPeers(options);\n\n let unsubscribeAuthUpdate = () => {};\n\n if (options.sync.when === \"signedUp\") {\n const authSecretStorage = options.authSecretStorage;\n const credentials = options.credentials ?? (await authSecretStorage.get());\n\n function handleAuthUpdate(isAuthenticated: boolean) {\n if (isAuthenticated) {\n toggleNetwork(true);\n } else {\n toggleNetwork(false);\n }\n }\n\n unsubscribeAuthUpdate = authSecretStorage.onUpdate(handleAuthUpdate);\n handleAuthUpdate(authSecretStorage.getIsAuthenticated(credentials));\n }\n\n const context = await createJazzContext({\n credentials: options.credentials,\n newAccountProps: options.newAccountProps,\n peersToLoadFrom,\n storage,\n crypto,\n defaultProfileName: options.defaultProfileName,\n AccountSchema: options.AccountSchema,\n sessionProvider: provideBrowserLockSession,\n authSecretStorage: options.authSecretStorage,\n });\n\n setNode(context.node);\n\n return {\n me: context.account,\n node: context.node,\n authSecretStorage: context.authSecretStorage,\n done: () => {\n // TODO: Sync all the covalues before closing the connection & context\n toggleNetwork(false);\n unsubscribeAuthUpdate();\n context.done();\n },\n logOut: () => {\n unsubscribeAuthUpdate();\n return context.logOut();\n },\n addConnectionListener,\n connected,\n };\n}\n\n/** @category Auth Providers */\nexport type SessionProvider = (\n accountID: ID<Account> | AgentID,\n) => Promise<SessionID>;\n\nexport function provideBrowserLockSession(\n accountID: ID<Account> | AgentID,\n crypto: CryptoProvider,\n) {\n if (typeof navigator === \"undefined\" || !navigator.locks?.request) {\n // Fallback to random session ID for each tab session\n return Promise.resolve({\n sessionID: crypto.newRandomSessionID(accountID as RawAccountID | AgentID),\n sessionDone: () => {},\n });\n }\n\n let sessionDone!: () => void;\n const donePromise = new Promise<void>((resolve) => {\n sessionDone = resolve;\n });\n\n let resolveSession: (sessionID: SessionID) => void;\n const sessionPromise = new Promise<SessionID>((resolve) => {\n resolveSession = resolve;\n });\n\n void (async function () {\n for (let idx = 0; idx < 100; idx++) {\n // To work better around StrictMode\n for (let retry = 0; retry < 2; retry++) {\n // console.debug(\"Trying to get lock\", accountID + \"_\" + idx);\n const sessionFinishedOrNoLock = await navigator.locks.request(\n accountID + \"_\" + idx,\n { ifAvailable: true },\n async (lock) => {\n if (!lock) return \"noLock\";\n\n const sessionID =\n localStorage.getItem(accountID + \"_\" + idx) ||\n crypto.newRandomSessionID(accountID as RawAccountID | AgentID);\n localStorage.setItem(accountID + \"_\" + idx, sessionID);\n\n resolveSession(sessionID as SessionID);\n\n await donePromise;\n console.log(\"Done with lock\", accountID + \"_\" + idx, sessionID);\n return \"sessionFinished\";\n },\n );\n\n if (sessionFinishedOrNoLock === \"sessionFinished\") {\n return;\n }\n }\n }\n throw new Error(\"Couldn't get lock on session after 100x2 tries\");\n })();\n\n return sessionPromise.then((sessionID) => ({\n sessionID,\n sessionDone,\n }));\n}\n\n/** @category Invite Links */\nexport function createInviteLink<C extends CoValue>(\n value: C,\n role: \"reader\" | \"writer\" | \"admin\" | \"writeOnly\",\n // default to same address as window.location, but without hash\n {\n baseURL = window.location.href.replace(/#.*$/, \"\"),\n valueHint,\n }: { baseURL?: string; valueHint?: string } = {},\n): string {\n const coValueCore = value.$jazz.raw.core;\n let currentCoValue = coValueCore;\n\n while (currentCoValue.verified.header.ruleset.type === \"ownedByGroup\") {\n currentCoValue = currentCoValue.getGroup().core;\n }\n\n const { ruleset, meta } = currentCoValue.verified.header;\n\n if (ruleset.type !== \"group\" || meta?.type === \"account\") {\n throw new Error(\"Can't create invite link for object without group\");\n }\n\n const group = cojsonInternals.expectGroup(currentCoValue.getCurrentContent());\n const inviteSecret = group.createInvite(role);\n\n return `${baseURL}#/invite/${valueHint ? valueHint + \"/\" : \"\"}${\n value.$jazz.id\n }/${inviteSecret}`;\n}\n\n/** @category Invite Links */\nexport function parseInviteLink<C extends CoValue>(\n inviteURL: string,\n):\n | {\n valueID: ID<C>;\n valueHint?: string;\n inviteSecret: InviteSecret;\n }\n | undefined {\n const url = new URL(inviteURL);\n const parts = url.hash.split(\"/\");\n\n let valueHint: string | undefined;\n let valueID: ID<C> | undefined;\n let inviteSecret: InviteSecret | undefined;\n\n if (parts[0] === \"#\" && parts[1] === \"invite\") {\n if (parts.length === 5) {\n valueHint = parts[2];\n valueID = parts[3] as ID<C>;\n inviteSecret = parts[4] as InviteSecret;\n } else if (parts.length === 4) {\n valueID = parts[2] as ID<C>;\n inviteSecret = parts[3] as InviteSecret;\n }\n\n if (!valueID || !inviteSecret) {\n return undefined;\n }\n return { valueID, inviteSecret, valueHint };\n }\n}\n","type StorageOption = \"indexedDB\";\ntype CombinedStorageOption = [\"indexedDB\"];\nexport type StorageConfig =\n | StorageOption\n | CombinedStorageOption\n | [StorageOption];\n\nexport function getStorageOptions(storage?: StorageConfig): {\n useIndexedDB: boolean;\n} {\n const useIndexedDB =\n !storage ||\n (Array.isArray(storage) && storage.includes(\"indexedDB\")) ||\n storage === \"indexedDB\";\n\n return { useIndexedDB };\n}\n","import {\n Account,\n AccountClass,\n AnyAccountSchema,\n CoValueFromRaw,\n InMemoryKVStore,\n InstanceOfSchema,\n JazzContextManager,\n SyncConfig,\n} from \"jazz-tools\";\nimport { JazzContextManagerAuthProps } from \"jazz-tools\";\nimport { LocalStorageKVStore } from \"./auth/LocalStorageKVStore.js\";\nimport {\n BaseBrowserContextOptions,\n createJazzBrowserContext,\n createJazzBrowserGuestContext,\n} from \"./createBrowserContext.js\";\n\nexport type JazzContextManagerProps<\n S extends\n | (AccountClass<Account> & CoValueFromRaw<Account>)\n | AnyAccountSchema,\n> = {\n guestMode?: boolean;\n sync: SyncConfig;\n onLogOut?: () => void;\n logOutReplacement?: () => void;\n onAnonymousAccountDiscarded?: (\n anonymousAccount: InstanceOfSchema<S>,\n ) => Promise<void>;\n storage?: BaseBrowserContextOptions[\"storage\"];\n AccountSchema?: S;\n defaultProfileName?: string;\n};\n\nexport class JazzBrowserContextManager<\n S extends\n | (AccountClass<Account> & CoValueFromRaw<Account>)\n | AnyAccountSchema,\n> extends JazzContextManager<InstanceOfSchema<S>, JazzContextManagerProps<S>> {\n // TODO: When the storage changes, if the user is changed, update the context\n getKvStore() {\n if (typeof window === \"undefined\") {\n // To handle running in SSR\n return new InMemoryKVStore();\n } else {\n return new LocalStorageKVStore();\n }\n }\n\n async getNewContext(\n props: JazzContextManagerProps<S>,\n authProps?: JazzContextManagerAuthProps,\n ) {\n if (props.guestMode) {\n return createJazzBrowserGuestContext({\n sync: props.sync,\n storage: props.storage,\n authSecretStorage: this.authSecretStorage,\n });\n } else {\n return createJazzBrowserContext<S>({\n sync: props.sync,\n storage: props.storage,\n AccountSchema: props.AccountSchema,\n credentials: authProps?.credentials,\n newAccountProps: authProps?.newAccountProps,\n defaultProfileName: props.defaultProfileName,\n authSecretStorage: this.authSecretStorage,\n });\n }\n }\n\n propsChanged(props: JazzContextManagerProps<S>) {\n if (!this.props) {\n return true;\n }\n\n return (\n this.props.sync.when !== props.sync.when ||\n this.props.sync.peer !== props.sync.peer ||\n this.props.guestMode !== props.guestMode\n );\n }\n}\n","import { KvStore } from \"jazz-tools\";\n\nexport class LocalStorageKVStore implements KvStore {\n constructor() {}\n\n async get(key: string) {\n return localStorage.getItem(key);\n }\n\n async set(key: string, value: string) {\n localStorage.setItem(key, value);\n }\n\n async delete(key: string) {\n localStorage.removeItem(key);\n }\n\n async clearAll() {\n localStorage.clear();\n }\n}\n"],"mappings":"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","names":["cojsonInternals","handleAuthUpdate"]}
|
@@ -13,6 +13,7 @@ __export(zodReExport_exports, {
|
|
13
13
|
boolean: () => boolean,
|
14
14
|
cidrv4: () => cidrv4,
|
15
15
|
cidrv6: () => cidrv6,
|
16
|
+
codec: () => codec,
|
16
17
|
cuid: () => cuid,
|
17
18
|
cuid2: () => cuid2,
|
18
19
|
date: () => date,
|
@@ -87,6 +88,7 @@ import {
|
|
87
88
|
union,
|
88
89
|
discriminatedUnion,
|
89
90
|
int,
|
91
|
+
codec,
|
90
92
|
optional,
|
91
93
|
array,
|
92
94
|
tuple,
|
@@ -1314,9 +1316,14 @@ var CoListJazzApi = class extends CoValueJazzApi {
|
|
1314
1316
|
return isSame;
|
1315
1317
|
} : void 0;
|
1316
1318
|
const patches = [...calcPatch(current, result, comparator)];
|
1319
|
+
if (patches.length === 0) {
|
1320
|
+
return this.coList;
|
1321
|
+
}
|
1322
|
+
this.raw.core.pauseNotifyUpdate();
|
1317
1323
|
for (const [from, to, insert] of patches.reverse()) {
|
1318
1324
|
this.splice(from, to - from, ...insert);
|
1319
1325
|
}
|
1326
|
+
this.raw.core.resumeNotifyUpdate();
|
1320
1327
|
return this.coList;
|
1321
1328
|
}
|
1322
1329
|
/**
|
@@ -3160,6 +3167,10 @@ var CoTextJazzApi = class extends CoValueJazzApi {
|
|
3160
3167
|
const currentGraphemes = this.raw.toGraphemes(current);
|
3161
3168
|
const otherGraphemes = this.raw.toGraphemes(other);
|
3162
3169
|
const patches = [...calcPatch2(currentGraphemes, otherGraphemes)];
|
3170
|
+
if (patches.length === 0) {
|
3171
|
+
return;
|
3172
|
+
}
|
3173
|
+
this.raw.core.pauseNotifyUpdate();
|
3163
3174
|
for (const [from, to, insert] of patches.reverse()) {
|
3164
3175
|
if (to > from) {
|
3165
3176
|
this.coText.deleteRange({ from, to });
|
@@ -3168,6 +3179,7 @@ var CoTextJazzApi = class extends CoValueJazzApi {
|
|
3168
3179
|
this.coText.insertBefore(from, this.raw.fromGraphemes(insert));
|
3169
3180
|
}
|
3170
3181
|
}
|
3182
|
+
this.raw.core.resumeNotifyUpdate();
|
3171
3183
|
}
|
3172
3184
|
/**
|
3173
3185
|
* Given an already loaded `CoPlainText`, subscribe to updates to the `CoPlainText` and ensure that the specified fields are loaded to the specified depth.
|
@@ -4285,7 +4297,7 @@ function getSubscriptionScope(value) {
|
|
4285
4297
|
optional: false
|
4286
4298
|
});
|
4287
4299
|
Object.defineProperty(value.$jazz, "_subscriptionScope", {
|
4288
|
-
value:
|
4300
|
+
value: newSubscriptionScope,
|
4289
4301
|
writable: false,
|
4290
4302
|
enumerable: false,
|
4291
4303
|
configurable: false
|
@@ -5153,6 +5165,23 @@ function isUnionOfPrimitivesDeeply(schema) {
|
|
5153
5165
|
}
|
5154
5166
|
|
5155
5167
|
// src/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.ts
|
5168
|
+
function makeCodecCoField(codec2) {
|
5169
|
+
return coField.optional.encoded({
|
5170
|
+
encode: (value) => {
|
5171
|
+
if (value === void 0) return void 0;
|
5172
|
+
if (value === null) return null;
|
5173
|
+
return codec2._zod.def.reverseTransform(value, {
|
5174
|
+
value,
|
5175
|
+
issues: []
|
5176
|
+
});
|
5177
|
+
},
|
5178
|
+
decode: (value) => {
|
5179
|
+
if (value === null) return null;
|
5180
|
+
if (value === void 0) return void 0;
|
5181
|
+
return codec2._zod.def.transform(value, { value, issues: [] });
|
5182
|
+
}
|
5183
|
+
});
|
5184
|
+
}
|
5156
5185
|
function schemaFieldToCoFieldDef(schema) {
|
5157
5186
|
if (isCoValueClass(schema)) {
|
5158
5187
|
return coField.ref(schema);
|
@@ -5225,6 +5254,24 @@ function schemaFieldToCoFieldDef(schema) {
|
|
5225
5254
|
"z.union()/z.discriminatedUnion() of collaborative types is not supported. Use co.discriminatedUnion() instead."
|
5226
5255
|
);
|
5227
5256
|
}
|
5257
|
+
} else if (zodSchemaDef.type === "pipe") {
|
5258
|
+
const isCodec = zodSchemaDef.transform !== void 0 && zodSchemaDef.reverseTransform !== void 0;
|
5259
|
+
if (!isCodec) {
|
5260
|
+
throw new Error(
|
5261
|
+
"z.pipe() is not supported. Only z.codec() is supported."
|
5262
|
+
);
|
5263
|
+
}
|
5264
|
+
try {
|
5265
|
+
schemaFieldToCoFieldDef(zodSchemaDef.in);
|
5266
|
+
} catch (error) {
|
5267
|
+
if (error instanceof Error) {
|
5268
|
+
error.message = `z.codec() is only supported if the input schema is already supported. ${error.message}`;
|
5269
|
+
}
|
5270
|
+
throw error;
|
5271
|
+
}
|
5272
|
+
return makeCodecCoField(
|
5273
|
+
schema
|
5274
|
+
);
|
5228
5275
|
} else {
|
5229
5276
|
throw new Error(
|
5230
5277
|
`Unsupported zod type: ${schema._zod?.def?.type || JSON.stringify(schema)}`
|
@@ -6152,4 +6199,4 @@ export {
|
|
6152
6199
|
JazzContextManager
|
6153
6200
|
};
|
6154
6201
|
/* istanbul ignore file -- @preserve */
|
6155
|
-
//# sourceMappingURL=chunk-
|
6202
|
+
//# sourceMappingURL=chunk-TVHI2UMO.js.map
|