jazz-tools 0.17.0 → 0.17.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.svelte-kit/__package__/media/image.svelte +1 -1
- package/.turbo/turbo-build.log +39 -39
- package/CHANGELOG.md +23 -0
- package/dist/index.js.map +1 -1
- package/dist/media/{chunk-BBSS3NEY.js → chunk-JBLT443O.js} +15 -15
- package/dist/media/{chunk-BBSS3NEY.js.map → chunk-JBLT443O.js.map} +1 -1
- package/dist/media/index.browser.js +1 -1
- package/dist/media/index.js +1 -1
- package/dist/media/index.native.d.ts.map +1 -1
- package/dist/media/index.native.js +13 -4
- package/dist/media/index.native.js.map +1 -1
- package/dist/media/utils.d.ts.map +1 -1
- package/dist/react/index.js +19 -13
- package/dist/react/index.js.map +1 -1
- package/dist/svelte/media/image.svelte +1 -1
- package/dist/tools/coValues/request.d.ts +1 -1
- package/dist/tools/coValues/request.d.ts.map +1 -1
- package/dist/tools/exports.d.ts +1 -1
- package/dist/tools/exports.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/media/index.native.ts +17 -4
- package/src/media/utils.test.ts +57 -11
- package/src/media/utils.ts +18 -15
- package/src/react/media/image.tsx +18 -12
- package/src/svelte/media/image.svelte +1 -1
- package/src/tools/coValues/request.ts +1 -1
- package/src/tools/exports.ts +1 -0
@@ -13,7 +13,7 @@ interface ImageProps extends Omit<HTMLImgAttributes, "width" | "height"> {
|
|
13
13
|
|
14
14
|
const { imageId, width, height, ...rest }: ImageProps = $props();
|
15
15
|
|
16
|
-
const imageState = new CoState(ImageDefinition, imageId);
|
16
|
+
const imageState = new CoState(ImageDefinition, () => imageId);
|
17
17
|
let lastBestImage: [string, string] | null = null;
|
18
18
|
|
19
19
|
/**
|
package/.turbo/turbo-build.log
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
> jazz-tools@0.17.
|
2
|
+
> jazz-tools@0.17.2 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"}
|
@@ -100,84 +100,84 @@
|
|
100
100
|
[34mESM[39m Build start
|
101
101
|
[34mCLI[39m Cleaning output folder
|
102
102
|
[34mESM[39m Build start
|
103
|
-
[32mESM[39m [1mdist/tiptap/index.js [22m[32m564.00 B[39m
|
104
|
-
[32mESM[39m [1mdist/tiptap/index.js.map [22m[32m1.21 KB[39m
|
105
|
-
[32mESM[39m ⚡️ Build success in 16ms
|
106
|
-
[32mESM[39m [1mdist/react/ssr.js [22m[32m688.00 B[39m
|
107
|
-
[32mESM[39m [1mdist/react/ssr.js.map [22m[32m1.12 KB[39m
|
108
|
-
[32mESM[39m ⚡️ Build success in 18ms
|
109
103
|
[32mESM[39m [1mdist/worker/index.js [22m[32m2.31 KB[39m
|
110
104
|
[32mESM[39m [1mdist/worker/index.js.map [22m[32m4.77 KB[39m
|
111
|
-
[32mESM[39m ⚡️ Build success in
|
105
|
+
[32mESM[39m ⚡️ Build success in 19ms
|
106
|
+
[32mESM[39m [1mdist/react/ssr.js [22m[32m688.00 B[39m
|
107
|
+
[32mESM[39m [1mdist/react/ssr.js.map [22m[32m1.12 KB[39m
|
108
|
+
[32mESM[39m ⚡️ Build success in 23ms
|
109
|
+
[32mESM[39m [1mdist/tiptap/index.js [22m[32m564.00 B[39m
|
110
|
+
[32mESM[39m [1mdist/tiptap/index.js.map [22m[32m1.21 KB[39m
|
111
|
+
[32mESM[39m ⚡️ Build success in 25ms
|
112
112
|
[32mESM[39m [1mdist/media/index.js [22m[32m236.00 B[39m
|
113
113
|
[32mESM[39m [1mdist/media/index.browser.js [22m[32m3.21 KB[39m
|
114
|
-
[32mESM[39m [1mdist/media/index.native.js [22m[32m3.
|
115
|
-
[32mESM[39m [1mdist/media/chunk-
|
114
|
+
[32mESM[39m [1mdist/media/index.native.js [22m[32m3.53 KB[39m
|
115
|
+
[32mESM[39m [1mdist/media/chunk-JBLT443O.js [22m[32m6.33 KB[39m
|
116
116
|
[32mESM[39m [1mdist/media/index.js.map [22m[32m71.00 B[39m
|
117
|
-
[32mESM[39m [1mdist/media/index.native.js.map [22m[32m6.18 KB[39m
|
118
117
|
[32mESM[39m [1mdist/media/index.browser.js.map [22m[32m6.02 KB[39m
|
119
|
-
[32mESM[39m [1mdist/media/chunk-
|
120
|
-
[32mESM[39m
|
118
|
+
[32mESM[39m [1mdist/media/chunk-JBLT443O.js.map [22m[32m15.68 KB[39m
|
119
|
+
[32mESM[39m [1mdist/media/index.native.js.map [22m[32m6.52 KB[39m
|
120
|
+
[32mESM[39m ⚡️ Build success in 45ms
|
121
|
+
[32mESM[39m [1mdist/expo/index.js [22m[32m4.65 KB[39m
|
122
|
+
[32mESM[39m [1mdist/expo/testing.js [22m[32m112.00 B[39m
|
123
|
+
[32mESM[39m [1mdist/expo/crypto.js [22m[32m109.00 B[39m
|
124
|
+
[32mESM[39m [1mdist/expo/index.js.map [22m[32m10.17 KB[39m
|
125
|
+
[32mESM[39m [1mdist/expo/testing.js.map [22m[32m168.00 B[39m
|
126
|
+
[32mESM[39m [1mdist/expo/crypto.js.map [22m[32m166.00 B[39m
|
127
|
+
[32mESM[39m ⚡️ Build success in 45ms
|
121
128
|
[32mESM[39m [1mdist/react-core/index.js [22m[32m8.41 KB[39m
|
122
129
|
[32mESM[39m [1mdist/react-core/testing.js [22m[32m1.17 KB[39m
|
123
130
|
[32mESM[39m [1mdist/react-core/chunk-7DYMJ74I.js [22m[32m279.00 B[39m
|
124
131
|
[32mESM[39m [1mdist/react-core/index.js.map [22m[32m20.68 KB[39m
|
125
132
|
[32mESM[39m [1mdist/react-core/testing.js.map [22m[32m1.82 KB[39m
|
126
133
|
[32mESM[39m [1mdist/react-core/chunk-7DYMJ74I.js.map [22m[32m533.00 B[39m
|
127
|
-
[32mESM[39m ⚡️ Build success in
|
128
|
-
[32mESM[39m [1mdist/browser/index.js [22m[32m13.43 KB[39m
|
129
|
-
[32mESM[39m [1mdist/browser/index.js.map [22m[32m28.65 KB[39m
|
130
|
-
[32mESM[39m ⚡️ Build success in 30ms
|
134
|
+
[32mESM[39m ⚡️ Build success in 42ms
|
131
135
|
[32mESM[39m [1mdist/react-native/index.js [22m[32m2.53 KB[39m
|
132
136
|
[32mESM[39m [1mdist/react-native/testing.js [22m[32m120.00 B[39m
|
133
137
|
[32mESM[39m [1mdist/react-native/crypto.js [22m[32m117.00 B[39m
|
134
138
|
[32mESM[39m [1mdist/react-native/index.js.map [22m[32m5.68 KB[39m
|
135
139
|
[32mESM[39m [1mdist/react-native/testing.js.map [22m[32m176.00 B[39m
|
136
140
|
[32mESM[39m [1mdist/react-native/crypto.js.map [22m[32m174.00 B[39m
|
137
|
-
[32mESM[39m ⚡️ Build success in
|
138
|
-
[32mESM[39m [1mdist/
|
139
|
-
[32mESM[39m [1mdist/
|
140
|
-
[32mESM[39m
|
141
|
-
[32mESM[39m [1mdist/expo/index.js.map [22m[32m10.17 KB[39m
|
142
|
-
[32mESM[39m [1mdist/expo/crypto.js.map [22m[32m166.00 B[39m
|
143
|
-
[32mESM[39m [1mdist/expo/testing.js.map [22m[32m168.00 B[39m
|
144
|
-
[32mESM[39m ⚡️ Build success in 29ms
|
145
|
-
[32mESM[39m [1mdist/react/index.js [22m[32m24.37 KB[39m
|
146
|
-
[32mESM[39m [1mdist/react/testing.js [22m[32m122.00 B[39m
|
147
|
-
[32mESM[39m [1mdist/react/index.js.map [22m[32m52.10 KB[39m
|
148
|
-
[32mESM[39m [1mdist/react/testing.js.map [22m[32m165.00 B[39m
|
149
|
-
[32mESM[39m ⚡️ Build success in 34ms
|
141
|
+
[32mESM[39m ⚡️ Build success in 41ms
|
142
|
+
[32mESM[39m [1mdist/browser/index.js [22m[32m13.43 KB[39m
|
143
|
+
[32mESM[39m [1mdist/browser/index.js.map [22m[32m28.65 KB[39m
|
144
|
+
[32mESM[39m ⚡️ Build success in 48ms
|
150
145
|
[32mESM[39m [1mdist/react-native-core/index.js [22m[32m17.90 KB[39m
|
151
146
|
[32mESM[39m [1mdist/react-native-core/testing.js [22m[32m119.00 B[39m
|
152
147
|
[32mESM[39m [1mdist/react-native-core/crypto.js [22m[32m2.10 KB[39m
|
153
148
|
[32mESM[39m [1mdist/react-native-core/index.js.map [22m[32m36.65 KB[39m
|
154
149
|
[32mESM[39m [1mdist/react-native-core/testing.js.map [22m[32m175.00 B[39m
|
155
150
|
[32mESM[39m [1mdist/react-native-core/crypto.js.map [22m[32m4.25 KB[39m
|
156
|
-
[32mESM[39m ⚡️ Build success in
|
151
|
+
[32mESM[39m ⚡️ Build success in 46ms
|
152
|
+
[32mESM[39m [1mdist/react/testing.js [22m[32m122.00 B[39m
|
153
|
+
[32mESM[39m [1mdist/react/index.js [22m[32m24.55 KB[39m
|
154
|
+
[32mESM[39m [1mdist/react/testing.js.map [22m[32m165.00 B[39m
|
155
|
+
[32mESM[39m [1mdist/react/index.js.map [22m[32m52.42 KB[39m
|
156
|
+
[32mESM[39m ⚡️ Build success in 50ms
|
157
157
|
[32mESM[39m [1mdist/prosemirror/index.js [22m[32m76.90 KB[39m
|
158
158
|
[32mESM[39m [1mdist/prosemirror/index.js.map [22m[32m305.53 KB[39m
|
159
|
-
[32mESM[39m ⚡️ Build success in
|
159
|
+
[32mESM[39m ⚡️ Build success in 55ms
|
160
160
|
[32mESM[39m [1mdist/inspector/index.js [22m[32m60.40 KB[39m
|
161
161
|
[32mESM[39m [1mdist/inspector/index.js.map [22m[32m107.91 KB[39m
|
162
|
-
[32mESM[39m ⚡️ Build success in
|
163
|
-
[32mESM[39m [1mdist/testing.js [22m[32m6.76 KB[39m
|
162
|
+
[32mESM[39m ⚡️ Build success in 71ms
|
164
163
|
[32mESM[39m [1mdist/index.js [22m[32m25.95 KB[39m
|
164
|
+
[32mESM[39m [1mdist/testing.js [22m[32m6.76 KB[39m
|
165
165
|
[32mESM[39m [1mdist/chunk-2SH44VLX.js [22m[32m150.65 KB[39m
|
166
|
-
[32mESM[39m [1mdist/testing.js.map [22m[32m13.07 KB[39m
|
167
166
|
[32mESM[39m [1mdist/index.js.map [22m[32m52.62 KB[39m
|
167
|
+
[32mESM[39m [1mdist/testing.js.map [22m[32m13.07 KB[39m
|
168
168
|
[32mESM[39m [1mdist/chunk-2SH44VLX.js.map [22m[32m361.51 KB[39m
|
169
|
-
[32mESM[39m ⚡️ Build success in
|
169
|
+
[32mESM[39m ⚡️ Build success in 85ms
|
170
170
|
[32mESM[39m [1mdist/inspector/register-custom-element.js [22m[32m218.00 B[39m
|
171
171
|
[32mESM[39m [1mdist/inspector/register-custom-element.js.map [22m[32m314.00 B[39m
|
172
172
|
[32mESM[39m [1mdist/inspector/custom-element-I7L56H6B.js [22m[32m1.53 MB[39m
|
173
173
|
[32mESM[39m [1mdist/inspector/custom-element-I7L56H6B.js.map [22m[32m2.35 MB[39m
|
174
|
-
[32mESM[39m ⚡️ Build success in
|
174
|
+
[32mESM[39m ⚡️ Build success in 129ms
|
175
175
|
|
176
|
-
> jazz-tools@0.17.
|
176
|
+
> jazz-tools@0.17.2 types /home/runner/_work/jazz/jazz/packages/jazz-tools
|
177
177
|
> tsc --outDir dist
|
178
178
|
|
179
179
|
|
180
|
-
> jazz-tools@0.17.
|
180
|
+
> jazz-tools@0.17.2 build:svelte /home/runner/_work/jazz/jazz/packages/jazz-tools
|
181
181
|
> rm -rf dist/svelte && svelte-package -i src/svelte -o dist/svelte --tsconfig tsconfig.svelte.json
|
182
182
|
|
183
183
|
src/svelte -> dist/svelte
|
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,28 @@
|
|
1
1
|
# jazz-tools
|
2
2
|
|
3
|
+
## 0.17.2
|
4
|
+
|
5
|
+
### Patch Changes
|
6
|
+
|
7
|
+
- 794681a: fix unused blob creation on react Image component
|
8
|
+
- 83fc22f: React Native resizer is now imported dynamically, as it is an optional dependency
|
9
|
+
- Updated dependencies [5b2b16a]
|
10
|
+
- cojson@0.17.2
|
11
|
+
- cojson-storage-indexeddb@0.17.2
|
12
|
+
- cojson-transport-ws@0.17.2
|
13
|
+
|
14
|
+
## 0.17.1
|
15
|
+
|
16
|
+
### Patch Changes
|
17
|
+
|
18
|
+
- 0bcbf55: Export the HttpRoute type
|
19
|
+
- d1bdbf5: fix: ensure file downloaded in loadImageBySize
|
20
|
+
- 4b73834: fix(jazz-tools/svelte): Make Image reactive to imageId change
|
21
|
+
- Updated dependencies [2fd88b9]
|
22
|
+
- cojson@0.17.1
|
23
|
+
- cojson-storage-indexeddb@0.17.1
|
24
|
+
- cojson-transport-ws@0.17.1
|
25
|
+
|
3
26
|
## 0.17.0
|
4
27
|
|
5
28
|
### Minor Changes
|
package/dist/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../src/tools/auth/clerk/index.ts","../src/tools/auth/clerk/getClerkUsername.ts","../src/tools/auth/clerk/types.ts","../src/tools/auth/DemoAuth.ts","../src/tools/auth/PassphraseAuth.ts","../src/tools/implementation/invites.ts","../src/tools/coValues/request.ts","../src/tools/index.ts"],"sourcesContent":["import {\n Account,\n AuthCredentials,\n AuthSecretStorage,\n AuthenticateAccountFunction,\n} from \"jazz-tools\";\nimport { getClerkUsername } from \"./getClerkUsername.js\";\nimport {\n ClerkCredentials,\n MinimalClerkClient,\n isClerkAuthStateEqual,\n isClerkCredentials,\n} from \"./types.js\";\n\nexport type { MinimalClerkClient };\nexport { isClerkCredentials };\n\nexport class JazzClerkAuth {\n constructor(\n private authenticate: AuthenticateAccountFunction,\n private authSecretStorage: AuthSecretStorage,\n ) {}\n\n /**\n * Loads the Jazz auth data from the Clerk user and sets it in the auth secret storage.\n */\n static loadClerkAuthData(\n credentials: ClerkCredentials,\n storage: AuthSecretStorage,\n ) {\n return storage.set({\n accountID: credentials.jazzAccountID,\n accountSecret: credentials.jazzAccountSecret,\n secretSeed: credentials.jazzAccountSeed\n ? Uint8Array.from(credentials.jazzAccountSeed)\n : undefined,\n provider: \"clerk\",\n });\n }\n\n static async initializeAuth(clerk: MinimalClerkClient) {\n const secretStorage = new AuthSecretStorage();\n\n if (!isClerkCredentials(clerk.user?.unsafeMetadata)) {\n return;\n }\n\n await JazzClerkAuth.loadClerkAuthData(\n clerk.user.unsafeMetadata,\n secretStorage,\n );\n }\n\n private isFirstCall = true;\n\n registerListener(clerkClient: MinimalClerkClient) {\n let previousUser: MinimalClerkClient[\"user\"] | null =\n clerkClient.user ?? null;\n\n // Need to use addListener because the clerk user object is not updated when the user logs in\n return clerkClient.addListener((event) => {\n const user = (event as Pick<MinimalClerkClient, \"user\">).user ?? null;\n\n if (!isClerkAuthStateEqual(previousUser, user) || this.isFirstCall) {\n this.onClerkUserChange({ user });\n previousUser = user;\n this.isFirstCall = false;\n }\n });\n }\n\n onClerkUserChange = async (clerkClient: Pick<MinimalClerkClient, \"user\">) => {\n const isAuthenticated = this.authSecretStorage.isAuthenticated;\n\n // LogOut is driven by Clerk. The framework adapters will need to pass `logOutReplacement` to the `JazzProvider`\n // to make the logOut work correctly.\n if (!clerkClient.user) {\n if (isAuthenticated) {\n this.authSecretStorage.clear();\n }\n return;\n }\n\n if (isAuthenticated) return;\n\n const clerkCredentials = clerkClient.user\n .unsafeMetadata as ClerkCredentials;\n\n if (!clerkCredentials.jazzAccountID) {\n await this.signIn(clerkClient);\n } else {\n await this.logIn(clerkClient);\n }\n };\n\n logIn = async (clerkClient: Pick<MinimalClerkClient, \"user\">) => {\n if (!clerkClient.user) {\n throw new Error(\"Not signed in on Clerk\");\n }\n\n const clerkCredentials = clerkClient.user.unsafeMetadata;\n if (!isClerkCredentials(clerkCredentials)) {\n throw new Error(\"No credentials found on Clerk\");\n }\n\n const credentials = {\n accountID: clerkCredentials.jazzAccountID,\n accountSecret: clerkCredentials.jazzAccountSecret,\n secretSeed: clerkCredentials.jazzAccountSeed\n ? Uint8Array.from(clerkCredentials.jazzAccountSeed)\n : undefined,\n provider: \"clerk\",\n } satisfies AuthCredentials;\n\n await this.authenticate(credentials);\n\n await JazzClerkAuth.loadClerkAuthData(\n {\n jazzAccountID: credentials.accountID,\n jazzAccountSecret: credentials.accountSecret,\n jazzAccountSeed: clerkCredentials.jazzAccountSeed,\n },\n this.authSecretStorage,\n );\n };\n\n signIn = async (clerkClient: Pick<MinimalClerkClient, \"user\">) => {\n const credentials = await this.authSecretStorage.get();\n\n if (!credentials) {\n throw new Error(\"No credentials found\");\n }\n\n const jazzAccountSeed = credentials.secretSeed\n ? Array.from(credentials.secretSeed)\n : undefined;\n\n await clerkClient.user?.update({\n unsafeMetadata: {\n jazzAccountID: credentials.accountID,\n jazzAccountSecret: credentials.accountSecret,\n jazzAccountSeed,\n } satisfies ClerkCredentials,\n });\n\n const currentAccount = await Account.getMe().ensureLoaded({\n resolve: {\n profile: true,\n },\n });\n\n const username = getClerkUsername(clerkClient);\n\n if (username) {\n currentAccount.profile.name = username;\n }\n\n await JazzClerkAuth.loadClerkAuthData(\n {\n jazzAccountID: credentials.accountID,\n jazzAccountSecret: credentials.accountSecret,\n jazzAccountSeed,\n },\n this.authSecretStorage,\n );\n };\n}\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace BrowserClerkAuth {\n export interface Driver {\n onError: (error: string | Error) => void;\n }\n}\n","import type { MinimalClerkClient } from \"./types.js\";\n\nexport function getClerkUsername(\n clerkClient: Pick<MinimalClerkClient, \"user\">,\n) {\n if (!clerkClient.user) {\n return null;\n }\n\n if (clerkClient.user.fullName) {\n return clerkClient.user.fullName;\n }\n\n if (clerkClient.user.firstName) {\n if (clerkClient.user.lastName) {\n return `${clerkClient.user.firstName} ${clerkClient.user.lastName}`;\n }\n\n return clerkClient.user.firstName;\n }\n\n if (clerkClient.user.username) {\n return clerkClient.user.username;\n }\n\n if (clerkClient.user.primaryEmailAddress?.emailAddress) {\n const emailUsername =\n clerkClient.user.primaryEmailAddress.emailAddress.split(\"@\")[0];\n\n if (emailUsername) {\n return emailUsername;\n }\n }\n\n return clerkClient.user.id;\n}\n","import { AgentSecret } from \"cojson\";\nimport { Account, ID } from \"jazz-tools\";\n\nexport type MinimalClerkClient = {\n user:\n | {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n unsafeMetadata: Record<string, any>;\n fullName: string | null;\n username: string | null;\n firstName: string | null;\n lastName: string | null;\n id: string;\n primaryEmailAddress: {\n emailAddress: string | null;\n } | null;\n update: (args: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n unsafeMetadata: Record<string, any>;\n }) => Promise<unknown>;\n }\n | null\n | undefined;\n signOut: () => Promise<void>;\n addListener: (listener: (data: unknown) => void) => void;\n};\n\nexport type ClerkCredentials = {\n jazzAccountID: ID<Account>;\n jazzAccountSecret: AgentSecret;\n jazzAccountSeed?: number[];\n};\n\n/**\n * Checks if the Clerk user metadata contains the necessary credentials for Jazz auth.\n * **Note**: It does not validate the credentials, only checks if the necessary fields are present in the metadata object.\n */\nexport function isClerkCredentials(\n data: NonNullable<MinimalClerkClient[\"user\"]>[\"unsafeMetadata\"] | undefined,\n): data is ClerkCredentials {\n return !!data && \"jazzAccountID\" in data && \"jazzAccountSecret\" in data;\n}\n\nexport function isClerkAuthStateEqual(\n previousUser: MinimalClerkClient[\"user\"] | null | undefined,\n newUser: MinimalClerkClient[\"user\"] | null | undefined,\n) {\n if (Boolean(previousUser) !== Boolean(newUser)) {\n return false;\n }\n\n const previousCredentials = isClerkCredentials(previousUser?.unsafeMetadata);\n const newCredentials = isClerkCredentials(newUser?.unsafeMetadata);\n\n return previousCredentials === newCredentials;\n}\n","import { AgentSecret } from \"cojson\";\nimport { Account, ID } from \"../internal.js\";\nimport { AuthenticateAccountFunction } from \"../types.js\";\nimport { AuthSecretStorage } from \"./AuthSecretStorage.js\";\nimport { KvStore, KvStoreContext } from \"./KvStoreContext.js\";\n\ntype StorageData = {\n accountID: ID<Account>;\n accountSecret: AgentSecret;\n secretSeed?: number[];\n};\n\n/**\n * `DemoAuth` provides a `JazzAuth` object for demo authentication.\n *\n * Demo authentication is useful for quickly testing your app, as it allows you to create new accounts and log in as existing ones.\n *\n * ```\n * import { DemoAuth } from \"jazz-tools\";\n *\n * const auth = new DemoAuth(jazzContext.authenticate, new AuthSecretStorage());\n * ```\n *\n * @category Auth Providers\n */\nexport class DemoAuth {\n constructor(\n private authenticate: AuthenticateAccountFunction,\n private authSecretStorage: AuthSecretStorage,\n ) {}\n\n logIn = async (username: string) => {\n const existingUsers = await this.getExisitingUsersWithData();\n const storageData = existingUsers[username];\n\n if (!storageData?.accountID) {\n throw new Error(\"User not found\");\n }\n\n await this.authenticate({\n accountID: storageData.accountID,\n accountSecret: storageData.accountSecret,\n });\n\n await this.authSecretStorage.set({\n accountID: storageData.accountID,\n accountSecret: storageData.accountSecret,\n secretSeed: storageData.secretSeed\n ? new Uint8Array(storageData.secretSeed)\n : undefined,\n provider: \"demo\",\n });\n };\n\n signUp = async (username: string) => {\n const existingUsers = await this.getExistingUsers();\n if (existingUsers.includes(username)) {\n throw new Error(\"User already registered\");\n }\n\n const credentials = await this.authSecretStorage.get();\n\n if (!credentials) {\n throw new Error(\"No credentials found\");\n }\n\n const currentAccount = await Account.getMe().ensureLoaded({\n resolve: {\n profile: true,\n },\n });\n\n currentAccount.profile.name = username;\n\n await this.authSecretStorage.set({\n accountID: credentials.accountID,\n accountSecret: credentials.accountSecret,\n secretSeed: credentials.secretSeed\n ? new Uint8Array(credentials.secretSeed)\n : undefined,\n provider: \"demo\",\n });\n\n await this.addToExistingUsers(username, {\n accountID: credentials.accountID,\n accountSecret: credentials.accountSecret,\n secretSeed: credentials.secretSeed\n ? Array.from(credentials.secretSeed)\n : undefined,\n });\n };\n\n private async addToExistingUsers(username: string, data: StorageData) {\n const existingUsers = await this.getExisitingUsersWithData();\n\n if (existingUsers[username]) {\n return;\n }\n\n existingUsers[username] = data;\n\n const kvStore = KvStoreContext.getInstance().getStorage();\n await kvStore.set(\"demo-auth-users\", JSON.stringify(existingUsers));\n }\n\n private async getExisitingUsersWithData() {\n const kvStore = KvStoreContext.getInstance().getStorage();\n await migrateExistingUsers(kvStore);\n\n const existingUsers = await kvStore.get(\"demo-auth-users\");\n return existingUsers ? JSON.parse(existingUsers) : {};\n }\n\n getExistingUsers = async () => {\n return Object.keys(await this.getExisitingUsersWithData());\n };\n}\n\nexport function encodeUsername(username: string) {\n return btoa(username)\n .replace(/=/g, \"-\")\n .replace(/\\+/g, \"_\")\n .replace(/\\//g, \".\");\n}\n\nasync function getStorageVersion(kvStore: KvStore) {\n try {\n const version = await kvStore.get(\"demo-auth-storage-version\");\n return version ? parseInt(version) : 1;\n } catch (error) {\n return 1;\n }\n}\n\nasync function setStorageVersion(kvStore: KvStore, version: number) {\n await kvStore.set(\"demo-auth-storage-version\", version.toString());\n}\n\nasync function getExistingUsersList(kvStore: KvStore) {\n const existingUsers = await kvStore.get(\"demo-auth-existing-users\");\n return existingUsers ? existingUsers.split(\",\") : [];\n}\n\n/**\n * Migrates existing users keys to work with any storage.\n */\nasync function migrateExistingUsers(kvStore: KvStore) {\n if ((await getStorageVersion(kvStore)) < 2) {\n const existingUsers = await getExistingUsersList(kvStore);\n\n for (const username of existingUsers) {\n const legacyKey = `demo-auth-existing-users-${username}`;\n const storageData = await kvStore.get(legacyKey);\n if (storageData) {\n await kvStore.set(\n `demo-auth-existing-users-${encodeUsername(username)}`,\n storageData,\n );\n await kvStore.delete(legacyKey);\n }\n }\n\n await setStorageVersion(kvStore, 2);\n }\n\n if ((await getStorageVersion(kvStore)) < 3) {\n const existingUsersList = await getExistingUsersList(kvStore);\n\n const existingUsers: Record<string, StorageData> = {};\n const keysToDelete: string[] = [\"demo-auth-existing-users\"];\n\n for (const username of existingUsersList) {\n const key = `demo-auth-existing-users-${encodeUsername(username)}`;\n const storageData = await kvStore.get(key);\n if (storageData) {\n existingUsers[username] = JSON.parse(storageData);\n keysToDelete.push(key);\n }\n }\n\n await kvStore.set(\"demo-auth-users\", JSON.stringify(existingUsers));\n\n for (const key of keysToDelete) {\n await kvStore.delete(key);\n }\n\n await setStorageVersion(kvStore, 3);\n }\n}\n","import * as bip39 from \"@scure/bip39\";\nimport { entropyToMnemonic } from \"@scure/bip39\";\nimport { CryptoProvider, cojsonInternals } from \"cojson\";\nimport type { ID } from \"../internal.js\";\nimport { Account } from \"../internal.js\";\nimport type {\n AuthenticateAccountFunction,\n RegisterAccountFunction,\n} from \"../types.js\";\nimport { AuthSecretStorage } from \"./AuthSecretStorage.js\";\n\n/**\n * `PassphraseAuth` provides a `JazzAuth` object for passphrase authentication.\n *\n * ```ts\n * import { PassphraseAuth } from \"jazz-tools\";\n *\n * const auth = new PassphraseAuth(crypto, jazzContext.authenticate, new AuthSecretStorage(), wordlist);\n * ```\n *\n * @category Auth Providers\n */\nexport class PassphraseAuth {\n passphrase: string = \"\";\n\n constructor(\n private crypto: CryptoProvider,\n private authenticate: AuthenticateAccountFunction,\n private register: RegisterAccountFunction,\n private authSecretStorage: AuthSecretStorage,\n public wordlist: string[],\n ) {}\n\n logIn = async (passphrase: string) => {\n const { crypto, authenticate } = this;\n\n let secretSeed;\n\n try {\n secretSeed = bip39.mnemonicToEntropy(passphrase, this.wordlist);\n } catch (e) {\n throw new Error(\"Invalid passphrase\");\n }\n\n const accountSecret = crypto.agentSecretFromSecretSeed(secretSeed);\n\n const accountID = cojsonInternals.idforHeader(\n cojsonInternals.accountHeaderForInitialAgentSecret(accountSecret, crypto),\n crypto,\n ) as ID<Account>;\n\n await authenticate({\n accountID,\n accountSecret,\n });\n\n await this.authSecretStorage.set({\n accountID,\n secretSeed,\n accountSecret,\n provider: \"passphrase\",\n });\n\n this.passphrase = passphrase;\n this.notify();\n };\n\n signUp = async (name?: string) => {\n const credentials = await this.authSecretStorage.get();\n\n if (!credentials || !credentials.secretSeed) {\n throw new Error(\"No credentials found\");\n }\n\n const passphrase = entropyToMnemonic(credentials.secretSeed, this.wordlist);\n\n await this.authSecretStorage.set({\n accountID: credentials.accountID,\n secretSeed: credentials.secretSeed,\n accountSecret: credentials.accountSecret,\n provider: \"passphrase\",\n });\n\n if (name?.trim()) {\n const currentAccount = await Account.getMe().ensureLoaded({\n resolve: {\n profile: true,\n },\n });\n\n currentAccount.profile.name = name;\n }\n\n return passphrase;\n };\n\n registerNewAccount = async (passphrase: string, name: string) => {\n const secretSeed = bip39.mnemonicToEntropy(passphrase, this.wordlist);\n const accountSecret = this.crypto.agentSecretFromSecretSeed(secretSeed);\n const accountID = await this.register(accountSecret, { name });\n\n await this.authSecretStorage.set({\n accountID,\n secretSeed,\n accountSecret,\n provider: \"passphrase\",\n });\n\n return accountID;\n };\n\n getCurrentAccountPassphrase = async () => {\n const credentials = await this.authSecretStorage.get();\n\n if (!credentials || !credentials.secretSeed) {\n throw new Error(\"No credentials found\");\n }\n\n return entropyToMnemonic(credentials.secretSeed, this.wordlist);\n };\n\n generateRandomPassphrase = () => {\n return entropyToMnemonic(this.crypto.newRandomSecretSeed(), this.wordlist);\n };\n\n loadCurrentAccountPassphrase = async () => {\n const passphrase = await this.getCurrentAccountPassphrase();\n this.passphrase = passphrase;\n this.notify();\n };\n\n listeners = new Set<() => void>();\n subscribe = (callback: () => void) => {\n this.listeners.add(callback);\n\n return () => {\n this.listeners.delete(callback);\n };\n };\n\n notify() {\n for (const listener of this.listeners) {\n listener();\n }\n }\n}\n","import { type InviteSecret, cojsonInternals } from \"cojson\";\nimport { Account } from \"../coValues/account.js\";\nimport type {\n CoValue,\n CoValueClass,\n CoValueClassOrSchema,\n ID,\n} from \"../internal.js\";\n\n/** @category Invite Links */\nexport function createInviteLink<C extends CoValue>(\n value: C,\n role: \"reader\" | \"writer\" | \"admin\" | \"writeOnly\",\n baseURL: string,\n valueHint?: string,\n): string {\n const coValueCore = value._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.id\n }/${inviteSecret}`;\n}\n\n/** @category Invite Links */\nexport function parseInviteLink(inviteURL: string):\n | {\n valueID: string;\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: string | 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];\n inviteSecret = parts[4] as InviteSecret;\n } else if (parts.length === 4) {\n valueID = parts[2];\n inviteSecret = parts[3] as InviteSecret;\n }\n\n if (!valueID || !inviteSecret) {\n return undefined;\n }\n return { valueID, inviteSecret, valueHint };\n }\n}\n\n/** @category Invite Links */\nexport function consumeInviteLink<S extends CoValueClassOrSchema>({\n inviteURL,\n as = Account.getMe(),\n forValueHint,\n invitedObjectSchema,\n}: {\n inviteURL: string;\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 return new Promise((resolve, reject) => {\n const result = parseInviteLink(inviteURL);\n\n if (result && result.valueHint === forValueHint) {\n as.acceptInvite(result.valueID, result.inviteSecret, invitedObjectSchema)\n .then(() => {\n resolve(result);\n })\n .catch(reject);\n } else {\n resolve(undefined);\n }\n });\n}\n","import {\n CoValueCore,\n CojsonInternalTypes,\n CryptoProvider,\n RawAccount,\n RawCoMap,\n cojsonInternals,\n} from \"cojson\";\nimport z from \"zod/v4\";\nimport {\n AnyZodOrCoValueSchema,\n CoMap,\n CoMapSchema,\n CoMapSchemaInit,\n CoValueClass,\n CoreCoMapSchema,\n Group,\n Loaded,\n ResolveQuery,\n ResolveQueryStrict,\n Simplify,\n coMapDefiner,\n coValueClassFromCoValueClassOrSchema,\n exportCoValue,\n importContentPieces,\n loadCoValue,\n} from \"../internal.js\";\nimport { isCoValueId } from \"../lib/id.js\";\nimport { Account } from \"./account.js\";\n\ntype MessageShape = Record<string, AnyZodOrCoValueSchema>;\n\ntype RequestSchemaDefinition<\n S extends MessageShape,\n R extends ResolveQuery<CoMapSchema<S>> = true,\n> =\n | S\n | {\n schema: S;\n resolve?: R;\n };\n\n/**\n * Configuration options for defining HTTP request/response schemas in Jazz.\n *\n * This interface defines the structure for creating typed HTTP routes with\n * request and response validation using CoMap schemas.\n *\n * @template RequestShape - The shape of the request message schema (must extend MessageShape)\n * @template RequestResolve - The resolve query type for the request CoMap schema\n * @template ResponseShape - The shape of the response message schema (must extend MessageShape)\n * @template ResponseResolve - The resolve query type for the response CoMap schema\n */\ninterface RequestOptions<\n RequestShape extends MessageShape,\n RequestResolve extends ResolveQuery<CoMapSchema<RequestShape>>,\n ResponseShape extends MessageShape,\n ResponseResolve extends ResolveQuery<CoMapSchema<ResponseShape>>,\n> {\n /**\n * The URL endpoint for the HTTP route.\n * This is used by the client to send requests to the server.\n */\n url: string;\n\n /**\n * The id of the worker Account or Group.\n */\n workerId: string;\n\n /**\n * Schema definition for the request payload.\n * Can be either a direct schema object or an object with schema and optional resolve properties.\n * The schema defines the structure and validation rules for incoming requests.\n */\n request: RequestSchemaDefinition<\n RequestShape,\n ResolveQueryStrict<CoMapSchema<RequestShape>, RequestResolve>\n >;\n\n /**\n * Schema definition for the response payload.\n * Can be either a direct schema object or an object with schema and optional resolve properties.\n * The schema defines the structure and validation rules for outgoing responses.\n */\n response: RequestSchemaDefinition<\n ResponseShape,\n ResolveQueryStrict<CoMapSchema<ResponseShape>, ResponseResolve>\n >;\n}\n\ntype AsNullablePayload<T extends MessageShape> = T extends Record<string, never>\n ? undefined\n : never;\ntype MessageValuePayload<T extends MessageShape> =\n | Simplify<CoMapSchemaInit<T>>\n | AsNullablePayload<T>;\n\nfunction createMessageEnvelope<S extends MessageShape>(\n schema: CoreCoMapSchema,\n value: MessageValuePayload<S>,\n owner: Account,\n sharedWith: Account | Group,\n type: \"request\" | \"response\",\n): Loaded<CoMapSchema<S>> {\n const group = Group.create({ owner });\n\n if (type === \"request\") {\n group.addMember(sharedWith, \"writer\");\n } else {\n group.addMember(sharedWith, \"reader\");\n }\n\n // @ts-expect-error - CoreCoMapSchema doesn't have static methods\n return schema.create(value ?? {}, group);\n}\n\n/**\n * Function that exports the input CoValue in a serializable format and prepares the information\n * required for the other side to safely verify the identity of the sender.\n */\nasync function serializeMessagePayload({\n type,\n schema,\n resolve,\n value,\n owner,\n target,\n}: {\n // Skipping type validation here to avoid excessive type complexity that affects the typecheck performance\n type: \"request\" | \"response\";\n schema: CoreCoMapSchema;\n resolve: any;\n value: any;\n owner: Account;\n target: Account | Group;\n}) {\n const me = owner ?? Account.getMe();\n const node = me._raw.core.node;\n const crypto = node.crypto;\n\n const agent = node.getCurrentAgent();\n const signerID = agent.currentSignerID();\n const signerSecret = agent.currentSignerSecret();\n\n const envelope = createMessageEnvelope(schema, value, me, target, type);\n\n const contentPieces =\n (await exportCoValue(schema, envelope.id, {\n resolve,\n loadAs: me,\n bestEffortResolution: true,\n })) ?? [];\n\n const createdAt = Date.now();\n\n const signPayload = crypto.secureHash({\n contentPieces,\n id: envelope.id,\n createdAt,\n signerID,\n });\n\n const authToken = crypto.sign(signerSecret, signPayload);\n\n return {\n contentPieces,\n id: envelope.id,\n createdAt,\n authToken,\n signerID,\n };\n}\n\nconst requestSchema = z.object({\n contentPieces: z.array(z.json()),\n id: z.custom<`co_z${string}`>(isCoValueId),\n createdAt: z.number(),\n authToken: z.custom<`signature_z${string}`>(\n (value) => typeof value === \"string\" && value.startsWith(\"signature_z\"),\n ),\n signerID: z.custom<`signer_z${string}`>(\n (value) => typeof value === \"string\" && value.startsWith(\"signer_z\"),\n ),\n});\n\n/**\n * Function that parses the message payload, verifies the identity of the sender and loads the data.\n *\n * @returns The data from the message.\n */\nasync function handleMessagePayload({\n type,\n schema,\n resolve,\n request,\n loadAs,\n}: {\n type: \"request\" | \"response\";\n // Skipping type validation here to avoid excessive type complexity that affects the typecheck performance\n schema: CoreCoMapSchema;\n resolve: any;\n request: unknown;\n loadAs: Account;\n}) {\n const node = loadAs._raw.core.node;\n const crypto = node.crypto;\n\n const requestParsed = requestSchema.safeParse(request);\n\n if (!requestParsed.success) {\n throw new JazzRequestError(\n \"Request payload is not valid\",\n 400,\n requestParsed.error,\n );\n }\n\n const requestData = requestParsed.data;\n\n if (type === \"request\") {\n const core = await node.loadCoValueCore(requestData.id, undefined, true);\n\n // Check if the message has already been handled to prevent replay attacks\n if (core.isAvailable()) {\n const content = core.getCurrentContent() as RawCoMap;\n\n if (content.get(\"$handled\") === loadAs.id) {\n throw new JazzRequestError(\"Request payload is already handled\", 400);\n }\n }\n\n // Check if the message is expired as extra protection\n if (requestData.createdAt + 1000 * 60 < Date.now()) {\n throw new JazzRequestError(\"Authentication token is expired\", 401);\n }\n }\n\n // Verify the signature of the message to prevent tampering\n const signPayload = crypto.secureHash({\n contentPieces: requestData.contentPieces,\n id: requestData.id,\n createdAt: requestData.createdAt,\n signerID: requestData.signerID,\n });\n\n if (\n !safeVerifySignature(\n crypto,\n signPayload,\n requestData.signerID,\n requestData.authToken,\n )\n ) {\n throw new JazzRequestError(\"Invalid signature\", 401);\n }\n\n let contentPieces =\n requestData.contentPieces as CojsonInternalTypes.NewContentMessage[];\n\n if (type === \"request\") {\n const coValueContent = contentPieces.find(\n (piece) => piece.id === requestData.id,\n );\n\n if (coValueContent && coValueContent.header) {\n const validValues = cojsonInternals.getDependedOnCoValues(\n coValueContent.header,\n coValueContent,\n );\n validValues.add(requestData.id);\n contentPieces = contentPieces.filter((piece) =>\n validValues.has(piece.id),\n );\n } else {\n contentPieces = [];\n }\n }\n\n importContentPieces(contentPieces, loadAs);\n\n const coValue = await node.loadCoValueCore(requestData.id);\n const accountId = getCoValueCreatorAccountId(coValue);\n\n const madeBy = await Account.load(accountId, {\n loadAs,\n });\n\n if (!madeBy) {\n throw new JazzRequestError(\"Creator account not found\", 400);\n }\n\n const coSchema = coValueClassFromCoValueClassOrSchema(\n schema,\n ) as CoValueClass<CoMap>;\n const value = await loadCoValue<CoMap, true>(coSchema, requestData.id, {\n resolve,\n loadAs,\n });\n\n if (!value) {\n throw new JazzRequestError(\"Value not found\", 400);\n }\n\n if (type === \"request\") {\n value._raw.set(\"$handled\", loadAs.id);\n }\n\n return {\n value: value as unknown,\n madeBy,\n };\n}\n\nfunction parseSchemaAndResolve<\n S extends MessageShape,\n R extends ResolveQuery<CoMapSchema<S>>,\n>(options: RequestSchemaDefinition<S, R>) {\n if (\"schema\" in options) {\n return {\n // Using a type cast to reduce the type complexity\n schema: coMapDefiner(options.schema) as CoreCoMapSchema,\n resolve: options.resolve as any,\n };\n }\n\n return {\n schema: coMapDefiner(options) as CoreCoMapSchema,\n resolve: true as any,\n };\n}\n\nclass HttpRoute<\n RequestShape extends MessageShape = z.core.$ZodLooseShape,\n RequestResolve extends ResolveQuery<CoMapSchema<RequestShape>> = any,\n ResponseShape extends MessageShape = z.core.$ZodLooseShape,\n ResponseResolve extends ResolveQuery<CoMapSchema<ResponseShape>> = any,\n> {\n private requestDefinition: {\n schema: CoreCoMapSchema;\n resolve: any;\n };\n private responseDefinition: {\n schema: CoreCoMapSchema;\n resolve: any;\n };\n private url: string;\n private workerId: string;\n\n constructor(\n params: RequestOptions<\n RequestShape,\n RequestResolve,\n ResponseShape,\n ResponseResolve\n >,\n ) {\n this.requestDefinition = parseSchemaAndResolve(params.request);\n this.responseDefinition = parseSchemaAndResolve(params.response);\n this.url = params.url;\n this.workerId = params.workerId;\n\n if (params.workerId === undefined) {\n throw new TypeError(\"Worker ID is required\");\n }\n }\n\n async send(\n values: MessageValuePayload<RequestShape>,\n options?: { owner?: Account },\n ): Promise<Loaded<CoMapSchema<ResponseShape>, ResponseResolve>> {\n const as = options?.owner ?? Account.getMe();\n\n const target = await loadWorkerAccountOrGroup(this.workerId, as);\n if (!target) {\n throw new JazzRequestError(\"Worker account not found\", 400);\n }\n\n const response = await fetch(this.url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(\n await serializeMessagePayload({\n type: \"request\",\n schema: this.requestDefinition.schema,\n resolve: true, // export only the envelope\n value: values,\n owner: as,\n target,\n }),\n ),\n });\n\n if (!response.ok) {\n if (response.headers.has(\"X-Jazz-Request-Error\")) {\n const error = await response.json();\n throw new JazzRequestError(error.message, error.code, error.details);\n }\n\n throw new JazzRequestError(\"Request failed\", response.status);\n }\n\n const responseBody = await response.json();\n\n const responseParsed = z\n .object({\n type: z.literal(\"success\"),\n payload: z.any(),\n })\n .safeParse(responseBody);\n\n if (!responseParsed.success) {\n throw new JazzRequestError(\n \"Response payload is not valid\",\n 400,\n responseParsed.error,\n );\n }\n\n const data = await handleMessagePayload({\n type: \"response\",\n schema: this.responseDefinition.schema,\n resolve: this.responseDefinition.resolve,\n request: responseParsed.data.payload,\n loadAs: as,\n });\n\n return data.value as Loaded<CoMapSchema<ResponseShape>, ResponseResolve>;\n }\n\n handle = async (\n request: Request,\n as: Account,\n callback: (\n value: Loaded<CoMapSchema<RequestShape>, RequestResolve>,\n madeBy: Account,\n ) =>\n | Promise<MessageValuePayload<ResponseShape>>\n | MessageValuePayload<ResponseShape>,\n ): Promise<Response> => {\n try {\n const response = await this.executeHandleRequest(request, as, callback);\n return response;\n } catch (error) {\n // Serialize the error to make it possible to handle it on the client side\n if (isJazzRequestError(error)) {\n return new Response(JSON.stringify(error.toJSON()), {\n status: error.code,\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Jazz-Request-Error\": \"true\",\n },\n });\n }\n\n throw error;\n }\n };\n\n executeHandleRequest = async (\n request: Request,\n as: Account,\n callback: (\n value: Loaded<CoMapSchema<RequestShape>, RequestResolve>,\n madeBy: Account,\n ) =>\n | Promise<MessageValuePayload<ResponseShape>>\n | MessageValuePayload<ResponseShape>,\n ): Promise<Response> => {\n const node = as._raw.core.node;\n const body = await request.json();\n const data = await handleMessagePayload({\n type: \"request\",\n schema: this.requestDefinition.schema,\n resolve: this.requestDefinition.resolve,\n request: body,\n loadAs: as,\n });\n\n const tracking = node.syncManager.trackDirtyCoValues();\n\n const responseValue = await callback(\n data.value as Loaded<CoMapSchema<RequestShape>, RequestResolve>,\n data.madeBy,\n );\n\n const responsePayload = await serializeMessagePayload({\n type: \"response\",\n schema: this.responseDefinition.schema,\n resolve: this.responseDefinition.resolve,\n value: responseValue,\n owner: as,\n target: data.madeBy,\n });\n\n const responseBody = JSON.stringify({\n type: \"success\",\n payload: responsePayload,\n });\n\n // TODO: Detect the defer support from the environment\n await Promise.all(\n Array.from(tracking.done(), (id) => node.syncManager.waitForSync(id)),\n );\n\n return new Response(responseBody, {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n };\n\n get requestSchema(): CoMapSchema<RequestShape> {\n return this.requestDefinition.schema as CoMapSchema<RequestShape>;\n }\n\n get responseSchema() {\n return this.responseDefinition.schema as CoMapSchema<ResponseShape>;\n }\n}\n\n/**\n * Define a request route.\n *\n * @param params - The parameters for the request route.\n * @returns The request route.\n *\n * @see {@link https://jazz.tools/docs/react/server-side/http-requests}\n */\nexport function experimental_defineRequest<\n RequestShape extends MessageShape,\n RequestResolve extends ResolveQuery<CoMapSchema<RequestShape>>,\n ResponseShape extends MessageShape,\n ResponseResolve extends ResolveQuery<CoMapSchema<ResponseShape>>,\n>(\n params: RequestOptions<\n RequestShape,\n RequestResolve,\n ResponseShape,\n ResponseResolve\n >,\n) {\n return new HttpRoute(params);\n}\n\nfunction getCoValueCreatorAccountId(coValue: CoValueCore) {\n if (!coValue.isAvailable()) {\n throw new Error(\"Unable to load the request payload\");\n }\n\n const creatorSessionId = coValue.getValidSortedTransactions().at(0)\n ?.txID.sessionID;\n\n if (!creatorSessionId) {\n throw new JazzRequestError(\n \"Request payload is not valid, creator session ID not found\",\n 400,\n );\n }\n\n const accountId =\n cojsonInternals.accountOrAgentIDfromSessionID(creatorSessionId);\n\n if (!isCoValueId(accountId)) {\n throw new JazzRequestError(\n \"Request payload is not valid, the creator is not a valid account\",\n 400,\n );\n }\n\n return accountId;\n}\n\nexport class JazzRequestError {\n public readonly isJazzRequestError = true;\n\n constructor(\n public readonly message: string,\n public readonly code: number,\n public readonly details?: unknown,\n ) {}\n\n toJSON() {\n return { message: this.message, code: this.code, details: this.details };\n }\n}\n\nexport function isJazzRequestError(error: unknown): error is JazzRequestError {\n return (\n error instanceof JazzRequestError ||\n (typeof error === \"object\" &&\n error !== null &&\n \"isJazzRequestError\" in error &&\n Boolean(error.isJazzRequestError))\n );\n}\n\nfunction safeVerifySignature(\n crypto: CryptoProvider,\n signPayload: `hash_z${string}`,\n signerID: `signer_z${string}`,\n authToken: `signature_z${string}`,\n) {\n try {\n return crypto.verify(authToken, signPayload, signerID);\n } catch (error) {\n return false;\n }\n}\n\nasync function loadWorkerAccountOrGroup(id: string, loadAs: Account) {\n const node = loadAs._raw.core.node;\n const coValue = await node.loadCoValueCore(id as `co_z${string}`);\n\n if (!coValue.isAvailable()) {\n return null;\n }\n\n const content = coValue.getCurrentContent();\n\n if (content instanceof RawAccount) {\n return Account.load(content.id, {\n loadAs,\n });\n }\n\n return Group.load(content.id, {\n loadAs,\n });\n}\n","export * from \"./exports.js\";\n\nexport {\n cojsonInternals,\n logger,\n LogLevel,\n} from \"cojson\";\n"],"mappings":"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","names":["Account","AuthSecretStorage","Account","AuthSecretStorage","cojsonInternals","cojsonInternals","cojsonInternals","cojsonInternals","cojsonInternals"]}
|
1
|
+
{"version":3,"sources":["../src/tools/auth/clerk/index.ts","../src/tools/auth/clerk/getClerkUsername.ts","../src/tools/auth/clerk/types.ts","../src/tools/auth/DemoAuth.ts","../src/tools/auth/PassphraseAuth.ts","../src/tools/implementation/invites.ts","../src/tools/coValues/request.ts","../src/tools/index.ts"],"sourcesContent":["import {\n Account,\n AuthCredentials,\n AuthSecretStorage,\n AuthenticateAccountFunction,\n} from \"jazz-tools\";\nimport { getClerkUsername } from \"./getClerkUsername.js\";\nimport {\n ClerkCredentials,\n MinimalClerkClient,\n isClerkAuthStateEqual,\n isClerkCredentials,\n} from \"./types.js\";\n\nexport type { MinimalClerkClient };\nexport { isClerkCredentials };\n\nexport class JazzClerkAuth {\n constructor(\n private authenticate: AuthenticateAccountFunction,\n private authSecretStorage: AuthSecretStorage,\n ) {}\n\n /**\n * Loads the Jazz auth data from the Clerk user and sets it in the auth secret storage.\n */\n static loadClerkAuthData(\n credentials: ClerkCredentials,\n storage: AuthSecretStorage,\n ) {\n return storage.set({\n accountID: credentials.jazzAccountID,\n accountSecret: credentials.jazzAccountSecret,\n secretSeed: credentials.jazzAccountSeed\n ? Uint8Array.from(credentials.jazzAccountSeed)\n : undefined,\n provider: \"clerk\",\n });\n }\n\n static async initializeAuth(clerk: MinimalClerkClient) {\n const secretStorage = new AuthSecretStorage();\n\n if (!isClerkCredentials(clerk.user?.unsafeMetadata)) {\n return;\n }\n\n await JazzClerkAuth.loadClerkAuthData(\n clerk.user.unsafeMetadata,\n secretStorage,\n );\n }\n\n private isFirstCall = true;\n\n registerListener(clerkClient: MinimalClerkClient) {\n let previousUser: MinimalClerkClient[\"user\"] | null =\n clerkClient.user ?? null;\n\n // Need to use addListener because the clerk user object is not updated when the user logs in\n return clerkClient.addListener((event) => {\n const user = (event as Pick<MinimalClerkClient, \"user\">).user ?? null;\n\n if (!isClerkAuthStateEqual(previousUser, user) || this.isFirstCall) {\n this.onClerkUserChange({ user });\n previousUser = user;\n this.isFirstCall = false;\n }\n });\n }\n\n onClerkUserChange = async (clerkClient: Pick<MinimalClerkClient, \"user\">) => {\n const isAuthenticated = this.authSecretStorage.isAuthenticated;\n\n // LogOut is driven by Clerk. The framework adapters will need to pass `logOutReplacement` to the `JazzProvider`\n // to make the logOut work correctly.\n if (!clerkClient.user) {\n if (isAuthenticated) {\n this.authSecretStorage.clear();\n }\n return;\n }\n\n if (isAuthenticated) return;\n\n const clerkCredentials = clerkClient.user\n .unsafeMetadata as ClerkCredentials;\n\n if (!clerkCredentials.jazzAccountID) {\n await this.signIn(clerkClient);\n } else {\n await this.logIn(clerkClient);\n }\n };\n\n logIn = async (clerkClient: Pick<MinimalClerkClient, \"user\">) => {\n if (!clerkClient.user) {\n throw new Error(\"Not signed in on Clerk\");\n }\n\n const clerkCredentials = clerkClient.user.unsafeMetadata;\n if (!isClerkCredentials(clerkCredentials)) {\n throw new Error(\"No credentials found on Clerk\");\n }\n\n const credentials = {\n accountID: clerkCredentials.jazzAccountID,\n accountSecret: clerkCredentials.jazzAccountSecret,\n secretSeed: clerkCredentials.jazzAccountSeed\n ? Uint8Array.from(clerkCredentials.jazzAccountSeed)\n : undefined,\n provider: \"clerk\",\n } satisfies AuthCredentials;\n\n await this.authenticate(credentials);\n\n await JazzClerkAuth.loadClerkAuthData(\n {\n jazzAccountID: credentials.accountID,\n jazzAccountSecret: credentials.accountSecret,\n jazzAccountSeed: clerkCredentials.jazzAccountSeed,\n },\n this.authSecretStorage,\n );\n };\n\n signIn = async (clerkClient: Pick<MinimalClerkClient, \"user\">) => {\n const credentials = await this.authSecretStorage.get();\n\n if (!credentials) {\n throw new Error(\"No credentials found\");\n }\n\n const jazzAccountSeed = credentials.secretSeed\n ? Array.from(credentials.secretSeed)\n : undefined;\n\n await clerkClient.user?.update({\n unsafeMetadata: {\n jazzAccountID: credentials.accountID,\n jazzAccountSecret: credentials.accountSecret,\n jazzAccountSeed,\n } satisfies ClerkCredentials,\n });\n\n const currentAccount = await Account.getMe().ensureLoaded({\n resolve: {\n profile: true,\n },\n });\n\n const username = getClerkUsername(clerkClient);\n\n if (username) {\n currentAccount.profile.name = username;\n }\n\n await JazzClerkAuth.loadClerkAuthData(\n {\n jazzAccountID: credentials.accountID,\n jazzAccountSecret: credentials.accountSecret,\n jazzAccountSeed,\n },\n this.authSecretStorage,\n );\n };\n}\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace BrowserClerkAuth {\n export interface Driver {\n onError: (error: string | Error) => void;\n }\n}\n","import type { MinimalClerkClient } from \"./types.js\";\n\nexport function getClerkUsername(\n clerkClient: Pick<MinimalClerkClient, \"user\">,\n) {\n if (!clerkClient.user) {\n return null;\n }\n\n if (clerkClient.user.fullName) {\n return clerkClient.user.fullName;\n }\n\n if (clerkClient.user.firstName) {\n if (clerkClient.user.lastName) {\n return `${clerkClient.user.firstName} ${clerkClient.user.lastName}`;\n }\n\n return clerkClient.user.firstName;\n }\n\n if (clerkClient.user.username) {\n return clerkClient.user.username;\n }\n\n if (clerkClient.user.primaryEmailAddress?.emailAddress) {\n const emailUsername =\n clerkClient.user.primaryEmailAddress.emailAddress.split(\"@\")[0];\n\n if (emailUsername) {\n return emailUsername;\n }\n }\n\n return clerkClient.user.id;\n}\n","import { AgentSecret } from \"cojson\";\nimport { Account, ID } from \"jazz-tools\";\n\nexport type MinimalClerkClient = {\n user:\n | {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n unsafeMetadata: Record<string, any>;\n fullName: string | null;\n username: string | null;\n firstName: string | null;\n lastName: string | null;\n id: string;\n primaryEmailAddress: {\n emailAddress: string | null;\n } | null;\n update: (args: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n unsafeMetadata: Record<string, any>;\n }) => Promise<unknown>;\n }\n | null\n | undefined;\n signOut: () => Promise<void>;\n addListener: (listener: (data: unknown) => void) => void;\n};\n\nexport type ClerkCredentials = {\n jazzAccountID: ID<Account>;\n jazzAccountSecret: AgentSecret;\n jazzAccountSeed?: number[];\n};\n\n/**\n * Checks if the Clerk user metadata contains the necessary credentials for Jazz auth.\n * **Note**: It does not validate the credentials, only checks if the necessary fields are present in the metadata object.\n */\nexport function isClerkCredentials(\n data: NonNullable<MinimalClerkClient[\"user\"]>[\"unsafeMetadata\"] | undefined,\n): data is ClerkCredentials {\n return !!data && \"jazzAccountID\" in data && \"jazzAccountSecret\" in data;\n}\n\nexport function isClerkAuthStateEqual(\n previousUser: MinimalClerkClient[\"user\"] | null | undefined,\n newUser: MinimalClerkClient[\"user\"] | null | undefined,\n) {\n if (Boolean(previousUser) !== Boolean(newUser)) {\n return false;\n }\n\n const previousCredentials = isClerkCredentials(previousUser?.unsafeMetadata);\n const newCredentials = isClerkCredentials(newUser?.unsafeMetadata);\n\n return previousCredentials === newCredentials;\n}\n","import { AgentSecret } from \"cojson\";\nimport { Account, ID } from \"../internal.js\";\nimport { AuthenticateAccountFunction } from \"../types.js\";\nimport { AuthSecretStorage } from \"./AuthSecretStorage.js\";\nimport { KvStore, KvStoreContext } from \"./KvStoreContext.js\";\n\ntype StorageData = {\n accountID: ID<Account>;\n accountSecret: AgentSecret;\n secretSeed?: number[];\n};\n\n/**\n * `DemoAuth` provides a `JazzAuth` object for demo authentication.\n *\n * Demo authentication is useful for quickly testing your app, as it allows you to create new accounts and log in as existing ones.\n *\n * ```\n * import { DemoAuth } from \"jazz-tools\";\n *\n * const auth = new DemoAuth(jazzContext.authenticate, new AuthSecretStorage());\n * ```\n *\n * @category Auth Providers\n */\nexport class DemoAuth {\n constructor(\n private authenticate: AuthenticateAccountFunction,\n private authSecretStorage: AuthSecretStorage,\n ) {}\n\n logIn = async (username: string) => {\n const existingUsers = await this.getExisitingUsersWithData();\n const storageData = existingUsers[username];\n\n if (!storageData?.accountID) {\n throw new Error(\"User not found\");\n }\n\n await this.authenticate({\n accountID: storageData.accountID,\n accountSecret: storageData.accountSecret,\n });\n\n await this.authSecretStorage.set({\n accountID: storageData.accountID,\n accountSecret: storageData.accountSecret,\n secretSeed: storageData.secretSeed\n ? new Uint8Array(storageData.secretSeed)\n : undefined,\n provider: \"demo\",\n });\n };\n\n signUp = async (username: string) => {\n const existingUsers = await this.getExistingUsers();\n if (existingUsers.includes(username)) {\n throw new Error(\"User already registered\");\n }\n\n const credentials = await this.authSecretStorage.get();\n\n if (!credentials) {\n throw new Error(\"No credentials found\");\n }\n\n const currentAccount = await Account.getMe().ensureLoaded({\n resolve: {\n profile: true,\n },\n });\n\n currentAccount.profile.name = username;\n\n await this.authSecretStorage.set({\n accountID: credentials.accountID,\n accountSecret: credentials.accountSecret,\n secretSeed: credentials.secretSeed\n ? new Uint8Array(credentials.secretSeed)\n : undefined,\n provider: \"demo\",\n });\n\n await this.addToExistingUsers(username, {\n accountID: credentials.accountID,\n accountSecret: credentials.accountSecret,\n secretSeed: credentials.secretSeed\n ? Array.from(credentials.secretSeed)\n : undefined,\n });\n };\n\n private async addToExistingUsers(username: string, data: StorageData) {\n const existingUsers = await this.getExisitingUsersWithData();\n\n if (existingUsers[username]) {\n return;\n }\n\n existingUsers[username] = data;\n\n const kvStore = KvStoreContext.getInstance().getStorage();\n await kvStore.set(\"demo-auth-users\", JSON.stringify(existingUsers));\n }\n\n private async getExisitingUsersWithData() {\n const kvStore = KvStoreContext.getInstance().getStorage();\n await migrateExistingUsers(kvStore);\n\n const existingUsers = await kvStore.get(\"demo-auth-users\");\n return existingUsers ? JSON.parse(existingUsers) : {};\n }\n\n getExistingUsers = async () => {\n return Object.keys(await this.getExisitingUsersWithData());\n };\n}\n\nexport function encodeUsername(username: string) {\n return btoa(username)\n .replace(/=/g, \"-\")\n .replace(/\\+/g, \"_\")\n .replace(/\\//g, \".\");\n}\n\nasync function getStorageVersion(kvStore: KvStore) {\n try {\n const version = await kvStore.get(\"demo-auth-storage-version\");\n return version ? parseInt(version) : 1;\n } catch (error) {\n return 1;\n }\n}\n\nasync function setStorageVersion(kvStore: KvStore, version: number) {\n await kvStore.set(\"demo-auth-storage-version\", version.toString());\n}\n\nasync function getExistingUsersList(kvStore: KvStore) {\n const existingUsers = await kvStore.get(\"demo-auth-existing-users\");\n return existingUsers ? existingUsers.split(\",\") : [];\n}\n\n/**\n * Migrates existing users keys to work with any storage.\n */\nasync function migrateExistingUsers(kvStore: KvStore) {\n if ((await getStorageVersion(kvStore)) < 2) {\n const existingUsers = await getExistingUsersList(kvStore);\n\n for (const username of existingUsers) {\n const legacyKey = `demo-auth-existing-users-${username}`;\n const storageData = await kvStore.get(legacyKey);\n if (storageData) {\n await kvStore.set(\n `demo-auth-existing-users-${encodeUsername(username)}`,\n storageData,\n );\n await kvStore.delete(legacyKey);\n }\n }\n\n await setStorageVersion(kvStore, 2);\n }\n\n if ((await getStorageVersion(kvStore)) < 3) {\n const existingUsersList = await getExistingUsersList(kvStore);\n\n const existingUsers: Record<string, StorageData> = {};\n const keysToDelete: string[] = [\"demo-auth-existing-users\"];\n\n for (const username of existingUsersList) {\n const key = `demo-auth-existing-users-${encodeUsername(username)}`;\n const storageData = await kvStore.get(key);\n if (storageData) {\n existingUsers[username] = JSON.parse(storageData);\n keysToDelete.push(key);\n }\n }\n\n await kvStore.set(\"demo-auth-users\", JSON.stringify(existingUsers));\n\n for (const key of keysToDelete) {\n await kvStore.delete(key);\n }\n\n await setStorageVersion(kvStore, 3);\n }\n}\n","import * as bip39 from \"@scure/bip39\";\nimport { entropyToMnemonic } from \"@scure/bip39\";\nimport { CryptoProvider, cojsonInternals } from \"cojson\";\nimport type { ID } from \"../internal.js\";\nimport { Account } from \"../internal.js\";\nimport type {\n AuthenticateAccountFunction,\n RegisterAccountFunction,\n} from \"../types.js\";\nimport { AuthSecretStorage } from \"./AuthSecretStorage.js\";\n\n/**\n * `PassphraseAuth` provides a `JazzAuth` object for passphrase authentication.\n *\n * ```ts\n * import { PassphraseAuth } from \"jazz-tools\";\n *\n * const auth = new PassphraseAuth(crypto, jazzContext.authenticate, new AuthSecretStorage(), wordlist);\n * ```\n *\n * @category Auth Providers\n */\nexport class PassphraseAuth {\n passphrase: string = \"\";\n\n constructor(\n private crypto: CryptoProvider,\n private authenticate: AuthenticateAccountFunction,\n private register: RegisterAccountFunction,\n private authSecretStorage: AuthSecretStorage,\n public wordlist: string[],\n ) {}\n\n logIn = async (passphrase: string) => {\n const { crypto, authenticate } = this;\n\n let secretSeed;\n\n try {\n secretSeed = bip39.mnemonicToEntropy(passphrase, this.wordlist);\n } catch (e) {\n throw new Error(\"Invalid passphrase\");\n }\n\n const accountSecret = crypto.agentSecretFromSecretSeed(secretSeed);\n\n const accountID = cojsonInternals.idforHeader(\n cojsonInternals.accountHeaderForInitialAgentSecret(accountSecret, crypto),\n crypto,\n ) as ID<Account>;\n\n await authenticate({\n accountID,\n accountSecret,\n });\n\n await this.authSecretStorage.set({\n accountID,\n secretSeed,\n accountSecret,\n provider: \"passphrase\",\n });\n\n this.passphrase = passphrase;\n this.notify();\n };\n\n signUp = async (name?: string) => {\n const credentials = await this.authSecretStorage.get();\n\n if (!credentials || !credentials.secretSeed) {\n throw new Error(\"No credentials found\");\n }\n\n const passphrase = entropyToMnemonic(credentials.secretSeed, this.wordlist);\n\n await this.authSecretStorage.set({\n accountID: credentials.accountID,\n secretSeed: credentials.secretSeed,\n accountSecret: credentials.accountSecret,\n provider: \"passphrase\",\n });\n\n if (name?.trim()) {\n const currentAccount = await Account.getMe().ensureLoaded({\n resolve: {\n profile: true,\n },\n });\n\n currentAccount.profile.name = name;\n }\n\n return passphrase;\n };\n\n registerNewAccount = async (passphrase: string, name: string) => {\n const secretSeed = bip39.mnemonicToEntropy(passphrase, this.wordlist);\n const accountSecret = this.crypto.agentSecretFromSecretSeed(secretSeed);\n const accountID = await this.register(accountSecret, { name });\n\n await this.authSecretStorage.set({\n accountID,\n secretSeed,\n accountSecret,\n provider: \"passphrase\",\n });\n\n return accountID;\n };\n\n getCurrentAccountPassphrase = async () => {\n const credentials = await this.authSecretStorage.get();\n\n if (!credentials || !credentials.secretSeed) {\n throw new Error(\"No credentials found\");\n }\n\n return entropyToMnemonic(credentials.secretSeed, this.wordlist);\n };\n\n generateRandomPassphrase = () => {\n return entropyToMnemonic(this.crypto.newRandomSecretSeed(), this.wordlist);\n };\n\n loadCurrentAccountPassphrase = async () => {\n const passphrase = await this.getCurrentAccountPassphrase();\n this.passphrase = passphrase;\n this.notify();\n };\n\n listeners = new Set<() => void>();\n subscribe = (callback: () => void) => {\n this.listeners.add(callback);\n\n return () => {\n this.listeners.delete(callback);\n };\n };\n\n notify() {\n for (const listener of this.listeners) {\n listener();\n }\n }\n}\n","import { type InviteSecret, cojsonInternals } from \"cojson\";\nimport { Account } from \"../coValues/account.js\";\nimport type {\n CoValue,\n CoValueClass,\n CoValueClassOrSchema,\n ID,\n} from \"../internal.js\";\n\n/** @category Invite Links */\nexport function createInviteLink<C extends CoValue>(\n value: C,\n role: \"reader\" | \"writer\" | \"admin\" | \"writeOnly\",\n baseURL: string,\n valueHint?: string,\n): string {\n const coValueCore = value._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.id\n }/${inviteSecret}`;\n}\n\n/** @category Invite Links */\nexport function parseInviteLink(inviteURL: string):\n | {\n valueID: string;\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: string | 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];\n inviteSecret = parts[4] as InviteSecret;\n } else if (parts.length === 4) {\n valueID = parts[2];\n inviteSecret = parts[3] as InviteSecret;\n }\n\n if (!valueID || !inviteSecret) {\n return undefined;\n }\n return { valueID, inviteSecret, valueHint };\n }\n}\n\n/** @category Invite Links */\nexport function consumeInviteLink<S extends CoValueClassOrSchema>({\n inviteURL,\n as = Account.getMe(),\n forValueHint,\n invitedObjectSchema,\n}: {\n inviteURL: string;\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 return new Promise((resolve, reject) => {\n const result = parseInviteLink(inviteURL);\n\n if (result && result.valueHint === forValueHint) {\n as.acceptInvite(result.valueID, result.inviteSecret, invitedObjectSchema)\n .then(() => {\n resolve(result);\n })\n .catch(reject);\n } else {\n resolve(undefined);\n }\n });\n}\n","import {\n CoValueCore,\n CojsonInternalTypes,\n CryptoProvider,\n RawAccount,\n RawCoMap,\n cojsonInternals,\n} from \"cojson\";\nimport z from \"zod/v4\";\nimport {\n AnyZodOrCoValueSchema,\n CoMap,\n CoMapSchema,\n CoMapSchemaInit,\n CoValueClass,\n CoreCoMapSchema,\n Group,\n Loaded,\n ResolveQuery,\n ResolveQueryStrict,\n Simplify,\n coMapDefiner,\n coValueClassFromCoValueClassOrSchema,\n exportCoValue,\n importContentPieces,\n loadCoValue,\n} from \"../internal.js\";\nimport { isCoValueId } from \"../lib/id.js\";\nimport { Account } from \"./account.js\";\n\ntype MessageShape = Record<string, AnyZodOrCoValueSchema>;\n\ntype RequestSchemaDefinition<\n S extends MessageShape,\n R extends ResolveQuery<CoMapSchema<S>> = true,\n> =\n | S\n | {\n schema: S;\n resolve?: R;\n };\n\n/**\n * Configuration options for defining HTTP request/response schemas in Jazz.\n *\n * This interface defines the structure for creating typed HTTP routes with\n * request and response validation using CoMap schemas.\n *\n * @template RequestShape - The shape of the request message schema (must extend MessageShape)\n * @template RequestResolve - The resolve query type for the request CoMap schema\n * @template ResponseShape - The shape of the response message schema (must extend MessageShape)\n * @template ResponseResolve - The resolve query type for the response CoMap schema\n */\ninterface RequestOptions<\n RequestShape extends MessageShape,\n RequestResolve extends ResolveQuery<CoMapSchema<RequestShape>>,\n ResponseShape extends MessageShape,\n ResponseResolve extends ResolveQuery<CoMapSchema<ResponseShape>>,\n> {\n /**\n * The URL endpoint for the HTTP route.\n * This is used by the client to send requests to the server.\n */\n url: string;\n\n /**\n * The id of the worker Account or Group.\n */\n workerId: string;\n\n /**\n * Schema definition for the request payload.\n * Can be either a direct schema object or an object with schema and optional resolve properties.\n * The schema defines the structure and validation rules for incoming requests.\n */\n request: RequestSchemaDefinition<\n RequestShape,\n ResolveQueryStrict<CoMapSchema<RequestShape>, RequestResolve>\n >;\n\n /**\n * Schema definition for the response payload.\n * Can be either a direct schema object or an object with schema and optional resolve properties.\n * The schema defines the structure and validation rules for outgoing responses.\n */\n response: RequestSchemaDefinition<\n ResponseShape,\n ResolveQueryStrict<CoMapSchema<ResponseShape>, ResponseResolve>\n >;\n}\n\ntype AsNullablePayload<T extends MessageShape> = T extends Record<string, never>\n ? undefined\n : never;\ntype MessageValuePayload<T extends MessageShape> =\n | Simplify<CoMapSchemaInit<T>>\n | AsNullablePayload<T>;\n\nfunction createMessageEnvelope<S extends MessageShape>(\n schema: CoreCoMapSchema,\n value: MessageValuePayload<S>,\n owner: Account,\n sharedWith: Account | Group,\n type: \"request\" | \"response\",\n): Loaded<CoMapSchema<S>> {\n const group = Group.create({ owner });\n\n if (type === \"request\") {\n group.addMember(sharedWith, \"writer\");\n } else {\n group.addMember(sharedWith, \"reader\");\n }\n\n // @ts-expect-error - CoreCoMapSchema doesn't have static methods\n return schema.create(value ?? {}, group);\n}\n\n/**\n * Function that exports the input CoValue in a serializable format and prepares the information\n * required for the other side to safely verify the identity of the sender.\n */\nasync function serializeMessagePayload({\n type,\n schema,\n resolve,\n value,\n owner,\n target,\n}: {\n // Skipping type validation here to avoid excessive type complexity that affects the typecheck performance\n type: \"request\" | \"response\";\n schema: CoreCoMapSchema;\n resolve: any;\n value: any;\n owner: Account;\n target: Account | Group;\n}) {\n const me = owner ?? Account.getMe();\n const node = me._raw.core.node;\n const crypto = node.crypto;\n\n const agent = node.getCurrentAgent();\n const signerID = agent.currentSignerID();\n const signerSecret = agent.currentSignerSecret();\n\n const envelope = createMessageEnvelope(schema, value, me, target, type);\n\n const contentPieces =\n (await exportCoValue(schema, envelope.id, {\n resolve,\n loadAs: me,\n bestEffortResolution: true,\n })) ?? [];\n\n const createdAt = Date.now();\n\n const signPayload = crypto.secureHash({\n contentPieces,\n id: envelope.id,\n createdAt,\n signerID,\n });\n\n const authToken = crypto.sign(signerSecret, signPayload);\n\n return {\n contentPieces,\n id: envelope.id,\n createdAt,\n authToken,\n signerID,\n };\n}\n\nconst requestSchema = z.object({\n contentPieces: z.array(z.json()),\n id: z.custom<`co_z${string}`>(isCoValueId),\n createdAt: z.number(),\n authToken: z.custom<`signature_z${string}`>(\n (value) => typeof value === \"string\" && value.startsWith(\"signature_z\"),\n ),\n signerID: z.custom<`signer_z${string}`>(\n (value) => typeof value === \"string\" && value.startsWith(\"signer_z\"),\n ),\n});\n\n/**\n * Function that parses the message payload, verifies the identity of the sender and loads the data.\n *\n * @returns The data from the message.\n */\nasync function handleMessagePayload({\n type,\n schema,\n resolve,\n request,\n loadAs,\n}: {\n type: \"request\" | \"response\";\n // Skipping type validation here to avoid excessive type complexity that affects the typecheck performance\n schema: CoreCoMapSchema;\n resolve: any;\n request: unknown;\n loadAs: Account;\n}) {\n const node = loadAs._raw.core.node;\n const crypto = node.crypto;\n\n const requestParsed = requestSchema.safeParse(request);\n\n if (!requestParsed.success) {\n throw new JazzRequestError(\n \"Request payload is not valid\",\n 400,\n requestParsed.error,\n );\n }\n\n const requestData = requestParsed.data;\n\n if (type === \"request\") {\n const core = await node.loadCoValueCore(requestData.id, undefined, true);\n\n // Check if the message has already been handled to prevent replay attacks\n if (core.isAvailable()) {\n const content = core.getCurrentContent() as RawCoMap;\n\n if (content.get(\"$handled\") === loadAs.id) {\n throw new JazzRequestError(\"Request payload is already handled\", 400);\n }\n }\n\n // Check if the message is expired as extra protection\n if (requestData.createdAt + 1000 * 60 < Date.now()) {\n throw new JazzRequestError(\"Authentication token is expired\", 401);\n }\n }\n\n // Verify the signature of the message to prevent tampering\n const signPayload = crypto.secureHash({\n contentPieces: requestData.contentPieces,\n id: requestData.id,\n createdAt: requestData.createdAt,\n signerID: requestData.signerID,\n });\n\n if (\n !safeVerifySignature(\n crypto,\n signPayload,\n requestData.signerID,\n requestData.authToken,\n )\n ) {\n throw new JazzRequestError(\"Invalid signature\", 401);\n }\n\n let contentPieces =\n requestData.contentPieces as CojsonInternalTypes.NewContentMessage[];\n\n if (type === \"request\") {\n const coValueContent = contentPieces.find(\n (piece) => piece.id === requestData.id,\n );\n\n if (coValueContent && coValueContent.header) {\n const validValues = cojsonInternals.getDependedOnCoValues(\n coValueContent.header,\n coValueContent,\n );\n validValues.add(requestData.id);\n contentPieces = contentPieces.filter((piece) =>\n validValues.has(piece.id),\n );\n } else {\n contentPieces = [];\n }\n }\n\n importContentPieces(contentPieces, loadAs);\n\n const coValue = await node.loadCoValueCore(requestData.id);\n const accountId = getCoValueCreatorAccountId(coValue);\n\n const madeBy = await Account.load(accountId, {\n loadAs,\n });\n\n if (!madeBy) {\n throw new JazzRequestError(\"Creator account not found\", 400);\n }\n\n const coSchema = coValueClassFromCoValueClassOrSchema(\n schema,\n ) as CoValueClass<CoMap>;\n const value = await loadCoValue<CoMap, true>(coSchema, requestData.id, {\n resolve,\n loadAs,\n });\n\n if (!value) {\n throw new JazzRequestError(\"Value not found\", 400);\n }\n\n if (type === \"request\") {\n value._raw.set(\"$handled\", loadAs.id);\n }\n\n return {\n value: value as unknown,\n madeBy,\n };\n}\n\nfunction parseSchemaAndResolve<\n S extends MessageShape,\n R extends ResolveQuery<CoMapSchema<S>>,\n>(options: RequestSchemaDefinition<S, R>) {\n if (\"schema\" in options) {\n return {\n // Using a type cast to reduce the type complexity\n schema: coMapDefiner(options.schema) as CoreCoMapSchema,\n resolve: options.resolve as any,\n };\n }\n\n return {\n schema: coMapDefiner(options) as CoreCoMapSchema,\n resolve: true as any,\n };\n}\n\nexport class HttpRoute<\n RequestShape extends MessageShape = z.core.$ZodLooseShape,\n RequestResolve extends ResolveQuery<CoMapSchema<RequestShape>> = any,\n ResponseShape extends MessageShape = z.core.$ZodLooseShape,\n ResponseResolve extends ResolveQuery<CoMapSchema<ResponseShape>> = any,\n> {\n private requestDefinition: {\n schema: CoreCoMapSchema;\n resolve: any;\n };\n private responseDefinition: {\n schema: CoreCoMapSchema;\n resolve: any;\n };\n private url: string;\n private workerId: string;\n\n constructor(\n params: RequestOptions<\n RequestShape,\n RequestResolve,\n ResponseShape,\n ResponseResolve\n >,\n ) {\n this.requestDefinition = parseSchemaAndResolve(params.request);\n this.responseDefinition = parseSchemaAndResolve(params.response);\n this.url = params.url;\n this.workerId = params.workerId;\n\n if (params.workerId === undefined) {\n throw new TypeError(\"Worker ID is required\");\n }\n }\n\n async send(\n values: MessageValuePayload<RequestShape>,\n options?: { owner?: Account },\n ): Promise<Loaded<CoMapSchema<ResponseShape>, ResponseResolve>> {\n const as = options?.owner ?? Account.getMe();\n\n const target = await loadWorkerAccountOrGroup(this.workerId, as);\n if (!target) {\n throw new JazzRequestError(\"Worker account not found\", 400);\n }\n\n const response = await fetch(this.url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(\n await serializeMessagePayload({\n type: \"request\",\n schema: this.requestDefinition.schema,\n resolve: true, // export only the envelope\n value: values,\n owner: as,\n target,\n }),\n ),\n });\n\n if (!response.ok) {\n if (response.headers.has(\"X-Jazz-Request-Error\")) {\n const error = await response.json();\n throw new JazzRequestError(error.message, error.code, error.details);\n }\n\n throw new JazzRequestError(\"Request failed\", response.status);\n }\n\n const responseBody = await response.json();\n\n const responseParsed = z\n .object({\n type: z.literal(\"success\"),\n payload: z.any(),\n })\n .safeParse(responseBody);\n\n if (!responseParsed.success) {\n throw new JazzRequestError(\n \"Response payload is not valid\",\n 400,\n responseParsed.error,\n );\n }\n\n const data = await handleMessagePayload({\n type: \"response\",\n schema: this.responseDefinition.schema,\n resolve: this.responseDefinition.resolve,\n request: responseParsed.data.payload,\n loadAs: as,\n });\n\n return data.value as Loaded<CoMapSchema<ResponseShape>, ResponseResolve>;\n }\n\n handle = async (\n request: Request,\n as: Account,\n callback: (\n value: Loaded<CoMapSchema<RequestShape>, RequestResolve>,\n madeBy: Account,\n ) =>\n | Promise<MessageValuePayload<ResponseShape>>\n | MessageValuePayload<ResponseShape>,\n ): Promise<Response> => {\n try {\n const response = await this.executeHandleRequest(request, as, callback);\n return response;\n } catch (error) {\n // Serialize the error to make it possible to handle it on the client side\n if (isJazzRequestError(error)) {\n return new Response(JSON.stringify(error.toJSON()), {\n status: error.code,\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Jazz-Request-Error\": \"true\",\n },\n });\n }\n\n throw error;\n }\n };\n\n executeHandleRequest = async (\n request: Request,\n as: Account,\n callback: (\n value: Loaded<CoMapSchema<RequestShape>, RequestResolve>,\n madeBy: Account,\n ) =>\n | Promise<MessageValuePayload<ResponseShape>>\n | MessageValuePayload<ResponseShape>,\n ): Promise<Response> => {\n const node = as._raw.core.node;\n const body = await request.json();\n const data = await handleMessagePayload({\n type: \"request\",\n schema: this.requestDefinition.schema,\n resolve: this.requestDefinition.resolve,\n request: body,\n loadAs: as,\n });\n\n const tracking = node.syncManager.trackDirtyCoValues();\n\n const responseValue = await callback(\n data.value as Loaded<CoMapSchema<RequestShape>, RequestResolve>,\n data.madeBy,\n );\n\n const responsePayload = await serializeMessagePayload({\n type: \"response\",\n schema: this.responseDefinition.schema,\n resolve: this.responseDefinition.resolve,\n value: responseValue,\n owner: as,\n target: data.madeBy,\n });\n\n const responseBody = JSON.stringify({\n type: \"success\",\n payload: responsePayload,\n });\n\n // TODO: Detect the defer support from the environment\n await Promise.all(\n Array.from(tracking.done(), (id) => node.syncManager.waitForSync(id)),\n );\n\n return new Response(responseBody, {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n };\n\n get requestSchema(): CoMapSchema<RequestShape> {\n return this.requestDefinition.schema as CoMapSchema<RequestShape>;\n }\n\n get responseSchema() {\n return this.responseDefinition.schema as CoMapSchema<ResponseShape>;\n }\n}\n\n/**\n * Define a request route.\n *\n * @param params - The parameters for the request route.\n * @returns The request route.\n *\n * @see {@link https://jazz.tools/docs/react/server-side/http-requests}\n */\nexport function experimental_defineRequest<\n RequestShape extends MessageShape,\n RequestResolve extends ResolveQuery<CoMapSchema<RequestShape>>,\n ResponseShape extends MessageShape,\n ResponseResolve extends ResolveQuery<CoMapSchema<ResponseShape>>,\n>(\n params: RequestOptions<\n RequestShape,\n RequestResolve,\n ResponseShape,\n ResponseResolve\n >,\n) {\n return new HttpRoute(params);\n}\n\nfunction getCoValueCreatorAccountId(coValue: CoValueCore) {\n if (!coValue.isAvailable()) {\n throw new Error(\"Unable to load the request payload\");\n }\n\n const creatorSessionId = coValue.getValidSortedTransactions().at(0)\n ?.txID.sessionID;\n\n if (!creatorSessionId) {\n throw new JazzRequestError(\n \"Request payload is not valid, creator session ID not found\",\n 400,\n );\n }\n\n const accountId =\n cojsonInternals.accountOrAgentIDfromSessionID(creatorSessionId);\n\n if (!isCoValueId(accountId)) {\n throw new JazzRequestError(\n \"Request payload is not valid, the creator is not a valid account\",\n 400,\n );\n }\n\n return accountId;\n}\n\nexport class JazzRequestError {\n public readonly isJazzRequestError = true;\n\n constructor(\n public readonly message: string,\n public readonly code: number,\n public readonly details?: unknown,\n ) {}\n\n toJSON() {\n return { message: this.message, code: this.code, details: this.details };\n }\n}\n\nexport function isJazzRequestError(error: unknown): error is JazzRequestError {\n return (\n error instanceof JazzRequestError ||\n (typeof error === \"object\" &&\n error !== null &&\n \"isJazzRequestError\" in error &&\n Boolean(error.isJazzRequestError))\n );\n}\n\nfunction safeVerifySignature(\n crypto: CryptoProvider,\n signPayload: `hash_z${string}`,\n signerID: `signer_z${string}`,\n authToken: `signature_z${string}`,\n) {\n try {\n return crypto.verify(authToken, signPayload, signerID);\n } catch (error) {\n return false;\n }\n}\n\nasync function loadWorkerAccountOrGroup(id: string, loadAs: Account) {\n const node = loadAs._raw.core.node;\n const coValue = await node.loadCoValueCore(id as `co_z${string}`);\n\n if (!coValue.isAvailable()) {\n return null;\n }\n\n const content = coValue.getCurrentContent();\n\n if (content instanceof RawAccount) {\n return Account.load(content.id, {\n loadAs,\n });\n }\n\n return Group.load(content.id, {\n loadAs,\n });\n}\n","export * from \"./exports.js\";\n\nexport {\n cojsonInternals,\n logger,\n LogLevel,\n} from \"cojson\";\n"],"mappings":"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","names":["Account","AuthSecretStorage","Account","AuthSecretStorage","cojsonInternals","cojsonInternals","cojsonInternals","cojsonInternals","cojsonInternals"]}
|
@@ -80,7 +80,7 @@ var getNewDimensions = (originalWidth, originalHeight, maxSize) => {
|
|
80
80
|
};
|
81
81
|
|
82
82
|
// src/media/utils.ts
|
83
|
-
import { Account as Account2, ImageDefinition as ImageDefinition2 } from "jazz-tools";
|
83
|
+
import { Account as Account2, FileStream as FileStream2, ImageDefinition as ImageDefinition2 } from "jazz-tools";
|
84
84
|
function highestResAvailable(image, wantedWidth, wantedHeight) {
|
85
85
|
const availableSizes = image._raw.keys().filter((key) => /^\d+x\d+$/.test(key)).map((key) => {
|
86
86
|
const [w, h] = key.split("x").map(Number);
|
@@ -152,19 +152,19 @@ async function loadImage(imageOrId) {
|
|
152
152
|
image: image.original
|
153
153
|
};
|
154
154
|
}
|
155
|
-
await imageOrId.ensureLoaded({
|
156
|
-
resolve: {
|
157
|
-
original: true
|
158
|
-
}
|
159
|
-
});
|
160
155
|
if (!imageOrId.original) {
|
161
156
|
console.warn("Unable to find the original image");
|
162
157
|
return null;
|
163
158
|
}
|
159
|
+
const loadedOriginal = await FileStream2.load(imageOrId.original.id);
|
160
|
+
if (!loadedOriginal) {
|
161
|
+
console.warn("Unable to find the original image");
|
162
|
+
return null;
|
163
|
+
}
|
164
164
|
return {
|
165
165
|
width: imageOrId.originalSize[0],
|
166
166
|
height: imageOrId.originalSize[1],
|
167
|
-
image:
|
167
|
+
image: loadedOriginal
|
168
168
|
};
|
169
169
|
}
|
170
170
|
async function loadImageBySize(imageOrId, wantedWidth, wantedHeight) {
|
@@ -187,18 +187,18 @@ async function loadImageBySize(imageOrId, wantedWidth, wantedHeight) {
|
|
187
187
|
match: sizesMatchWanted(size[0], size[1], wantedWidth, wantedHeight)
|
188
188
|
})).sort((a, b) => a.match - b.match);
|
189
189
|
const bestTarget = sortedSizes.find((el) => el.match > 0.95) || sortedSizes.at(-1);
|
190
|
-
const
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
if (
|
190
|
+
const file = image[bestTarget.size[2]];
|
191
|
+
if (!file) {
|
192
|
+
return null;
|
193
|
+
}
|
194
|
+
const loadedFile = await FileStream2.load(file.id);
|
195
|
+
if (!loadedFile) {
|
196
196
|
return null;
|
197
197
|
}
|
198
198
|
return {
|
199
199
|
width: bestTarget.size[0],
|
200
200
|
height: bestTarget.size[1],
|
201
|
-
image:
|
201
|
+
image: loadedFile
|
202
202
|
};
|
203
203
|
}
|
204
204
|
|
@@ -208,4 +208,4 @@ export {
|
|
208
208
|
loadImage,
|
209
209
|
loadImageBySize
|
210
210
|
};
|
211
|
-
//# sourceMappingURL=chunk-
|
211
|
+
//# sourceMappingURL=chunk-JBLT443O.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/media/create-image.ts","../../src/media/utils.ts"],"sourcesContent":["import {\n Account,\n FileStream,\n Group,\n ImageDefinition,\n type Loaded,\n} from \"jazz-tools\";\n\nexport type SourceType = Blob | File | string;\n\nexport type CreateImageOptions = {\n /** The owner of the image. Can be either a Group or Account. If not specified, the current user will be the owner. */\n owner?: Group | Account;\n /**\n * Controls placeholder generation for the image.\n * - `\"blur\"`: Generates a blurred placeholder image (default)\n * - `false`: No placeholder is generated\n * @default \"blur\"\n */\n placeholder?: \"blur\" | false;\n /**\n * Maximum size constraint for the image. The image will be resized to fit within this size while maintaining aspect ratio.\n * If the image is smaller than maxSize in both dimensions, no resizing occurs.\n * @example 1024 // Resizes image to fit within 1024px in the largest dimension\n */\n maxSize?: number; // | [number, number];\n /**\n * The progressive loading pattern is a technique that allows images to load incrementally, starting with a small version and gradually replacing it with a larger version as it becomes available.\n * This is useful for improving the user experience by showing a placeholder while the image is loading.\n *\n * Passing progressive: true to createImage() will create internal smaller versions of the image for future uses.\n *\n * @default false\n */\n progressive?: boolean;\n};\n\nexport type CreateImageImpl = {\n createFileStreamFromSource: (\n imageBlobOrFile: SourceType,\n owner?: Group | Account,\n ) => Promise<FileStream>;\n getImageSize: (\n imageBlobOrFile: SourceType,\n ) => Promise<{ width: number; height: number }>;\n getPlaceholderBase64: (imageBlobOrFile: SourceType) => Promise<string>;\n resize: (\n imageBlobOrFile: SourceType,\n width: number,\n height: number,\n ) => Promise<Blob | string>;\n};\n\nexport function createImageFactory(impl: CreateImageImpl) {\n return (source: SourceType, options: CreateImageOptions) =>\n createImage(source, options, impl);\n}\n\nasync function createImage(\n imageBlobOrFile: SourceType,\n options: CreateImageOptions,\n impl: CreateImageImpl,\n): Promise<Loaded<typeof ImageDefinition, { $each: true }>> {\n // Get the original size of the image\n const { width: originalWidth, height: originalHeight } =\n await impl.getImageSize(imageBlobOrFile);\n\n const def: {\n originalSize: [number, number];\n progressive: boolean;\n placeholderDataURL: string | undefined;\n original?: FileStream;\n files: Record<string, FileStream>;\n } = {\n originalSize: [originalWidth, originalHeight],\n progressive: false,\n placeholderDataURL: undefined,\n files: {},\n };\n\n // Placeholder\n if (options?.placeholder === \"blur\") {\n def.placeholderDataURL = await impl.getPlaceholderBase64(imageBlobOrFile);\n }\n\n /**\n * Original\n *\n * Save the original image.\n * If the maxSize is set, resize the image to the maxSize if needed\n */\n if (options?.maxSize === undefined) {\n def.original = await impl.createFileStreamFromSource(\n imageBlobOrFile,\n options?.owner,\n );\n def.files[`${originalWidth}x${originalHeight}`] = def.original;\n } else if (\n options?.maxSize >= originalWidth &&\n options?.maxSize >= originalHeight\n ) {\n // no resizes required, just return the original image\n def.original = await impl.createFileStreamFromSource(\n imageBlobOrFile,\n options?.owner,\n );\n def.files[`${originalWidth}x${originalHeight}`] = def.original;\n } else {\n const { width, height } = getNewDimensions(\n originalWidth,\n originalHeight,\n options.maxSize,\n );\n\n const blob = await impl.resize(imageBlobOrFile, width, height);\n def.originalSize = [width, height];\n def.original = await impl.createFileStreamFromSource(blob, options?.owner);\n def.files[`${width}x${height}`] = def.original;\n }\n\n const imageCoValue = ImageDefinition.create(\n {\n originalSize: def.originalSize,\n progressive: def.progressive,\n placeholderDataURL: def.placeholderDataURL,\n original: def.original,\n ...def.files,\n },\n options?.owner,\n );\n\n /**\n * Progressive loading\n *\n * Save a set of resized images using three sizes: 256, 1024, 2048\n *\n * On the client side, the image will be loaded progressively, starting from the smallest size and increasing the size until the original size is reached.\n */\n if (options?.progressive) {\n imageCoValue.progressive = true;\n\n const resizes = ([256, 1024, 2048] as const).filter(\n (s) =>\n s <\n Math.max(imageCoValue.originalSize[0], imageCoValue.originalSize[1]),\n );\n\n for (const size of resizes) {\n const { width, height } = getNewDimensions(\n originalWidth,\n originalHeight,\n size,\n );\n\n const blob = await impl.resize(imageBlobOrFile, width, height);\n imageCoValue[`${width}x${height}`] =\n await impl.createFileStreamFromSource(blob, options?.owner);\n }\n }\n\n return imageCoValue;\n}\n\nconst getNewDimensions = (\n originalWidth: number,\n originalHeight: number,\n maxSize: number,\n) => {\n if (originalWidth > originalHeight) {\n return {\n width: maxSize,\n height: Math.round(maxSize * (originalHeight / originalWidth)),\n };\n }\n\n return {\n width: Math.round(maxSize * (originalWidth / originalHeight)),\n height: maxSize,\n };\n};\n","import type { CoID } from \"cojson\";\nimport { Account, FileStream, ImageDefinition } from \"jazz-tools\";\n\nexport function highestResAvailable(\n image: ImageDefinition,\n wantedWidth: number,\n wantedHeight: number,\n): { width: number; height: number; image: FileStream } | null {\n const availableSizes: [number, number, string][] = image._raw\n .keys()\n .filter((key) => /^\\d+x\\d+$/.test(key))\n .map((key) => {\n const [w, h] = key.split(\"x\").map(Number) as [number, number];\n return [w, h, key];\n });\n\n if (availableSizes.length === 0) {\n return image.original\n ? {\n width: image.originalSize[0],\n height: image.originalSize[1],\n image: image.original,\n }\n : null;\n }\n\n const sortedSizes = availableSizes\n .map((size) => {\n return {\n size,\n match: sizesMatchWanted(size[0], size[1], wantedWidth, wantedHeight),\n isLoaded: isLoaded(image._raw.get(size[2]) as CoID<any> | undefined),\n };\n })\n .sort((a, b) => a.match - b.match);\n\n // We try to find the better already loaded image\n // note: `toReversed` is not available in react-native.\n const bestLoaded = [...sortedSizes]\n .reverse()\n .find((el) => el.isLoaded && image[el.size[2]]?.getChunks());\n\n // if I can't find a good match, let's use the highest resolution\n const bestTarget =\n sortedSizes.find((el) => el.match > 0.95) || sortedSizes.at(-1);\n\n // if the best target is already loaded, we are done\n if (image[bestTarget!.size[2]]?.getChunks()) {\n return image[bestTarget!.size[2]]\n ? {\n width: bestTarget!.size[0],\n height: bestTarget!.size[1],\n image: image[bestTarget!.size[2]]!,\n }\n : null;\n }\n\n // if the best already loaded is not the best target\n // let's trigger the load of the best target\n if (bestLoaded) {\n image[bestTarget!.size[2]]?.getChunks();\n return image[bestLoaded.size[2]]\n ? {\n width: bestLoaded.size[0],\n height: bestLoaded.size[1],\n image: image[bestLoaded.size[2]]!,\n }\n : null;\n }\n\n // if nothing is loaded, then start fetching all the images till the best\n for (let size of sortedSizes) {\n if (size.match <= bestTarget!.match) {\n image[size.size[2]]?.getChunks();\n }\n }\n\n return null;\n}\n\nfunction sizesMatchWanted(\n w: number,\n h: number,\n wantedW: number,\n wantedH: number,\n): number {\n const area1 = w * h;\n const area2 = wantedW * wantedH;\n\n const areaRatio = area1 / area2;\n\n // // Below 0.95 means the image is too small, we don't want to upscale it\n // if (areaRatio < 0.95) {\n // return 9999;\n // }\n\n return areaRatio;\n}\n\nfunction isLoaded(id: CoID<any> | null | undefined): boolean {\n if (!id) {\n return false;\n }\n\n return !!Account.getMe()._raw.core.node.getLoaded(id);\n}\n\nexport async function loadImage(\n imageOrId: ImageDefinition | string,\n): Promise<{ width: number; height: number; image: FileStream } | null> {\n if (typeof imageOrId === \"string\") {\n const image = await ImageDefinition.load(imageOrId, {\n resolve: {\n original: true,\n },\n });\n\n if (image === null || image.original === null) {\n return null;\n }\n\n return {\n width: image.originalSize[0],\n height: image.originalSize[1],\n image: image.original,\n };\n }\n\n await imageOrId.ensureLoaded({\n resolve: {\n original: true,\n },\n });\n\n if (!imageOrId.original) {\n console.warn(\"Unable to find the original image\");\n return null;\n }\n\n return {\n width: imageOrId.originalSize[0],\n height: imageOrId.originalSize[1],\n image: imageOrId.original,\n };\n}\n\nexport async function loadImageBySize(\n imageOrId: ImageDefinition | string,\n wantedWidth: number,\n wantedHeight: number,\n): Promise<{ width: number; height: number; image: FileStream } | null> {\n const image =\n typeof imageOrId === \"string\"\n ? await ImageDefinition.load(imageOrId)\n : imageOrId;\n\n if (image === null) {\n return null;\n }\n\n if (image.progressive === false) {\n return loadImage(imageOrId);\n }\n\n const availableSizes: [number, number, string][] = image._raw\n .keys()\n .filter((key) => /^\\d+x\\d+$/.test(key))\n .map((key) => {\n const [w, h] = key.split(\"x\").map(Number) as [number, number];\n return [w, h, key];\n });\n\n if (availableSizes.length === 0) {\n return null;\n }\n\n const sortedSizes = availableSizes\n .map((size) => ({\n size,\n match: sizesMatchWanted(size[0], size[1], wantedWidth, wantedHeight),\n }))\n .sort((a, b) => a.match - b.match);\n\n const bestTarget =\n sortedSizes.find((el) => el.match > 0.95) || sortedSizes.at(-1)!;\n\n const deepLoaded = await ImageDefinition.load(image.id, {\n resolve: {\n [bestTarget.size[2]]: true,\n },\n });\n\n if (deepLoaded === null || deepLoaded[bestTarget.size[2]] === undefined) {\n return null;\n }\n\n return {\n width: bestTarget.size[0],\n height: bestTarget.size[1],\n image: deepLoaded[bestTarget.size[2]]!,\n };\n}\n"],"mappings":"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","names":["Account","ImageDefinition"]}
|
1
|
+
{"version":3,"sources":["../../src/media/create-image.ts","../../src/media/utils.ts"],"sourcesContent":["import {\n Account,\n FileStream,\n Group,\n ImageDefinition,\n type Loaded,\n} from \"jazz-tools\";\n\nexport type SourceType = Blob | File | string;\n\nexport type CreateImageOptions = {\n /** The owner of the image. Can be either a Group or Account. If not specified, the current user will be the owner. */\n owner?: Group | Account;\n /**\n * Controls placeholder generation for the image.\n * - `\"blur\"`: Generates a blurred placeholder image (default)\n * - `false`: No placeholder is generated\n * @default \"blur\"\n */\n placeholder?: \"blur\" | false;\n /**\n * Maximum size constraint for the image. The image will be resized to fit within this size while maintaining aspect ratio.\n * If the image is smaller than maxSize in both dimensions, no resizing occurs.\n * @example 1024 // Resizes image to fit within 1024px in the largest dimension\n */\n maxSize?: number; // | [number, number];\n /**\n * The progressive loading pattern is a technique that allows images to load incrementally, starting with a small version and gradually replacing it with a larger version as it becomes available.\n * This is useful for improving the user experience by showing a placeholder while the image is loading.\n *\n * Passing progressive: true to createImage() will create internal smaller versions of the image for future uses.\n *\n * @default false\n */\n progressive?: boolean;\n};\n\nexport type CreateImageImpl = {\n createFileStreamFromSource: (\n imageBlobOrFile: SourceType,\n owner?: Group | Account,\n ) => Promise<FileStream>;\n getImageSize: (\n imageBlobOrFile: SourceType,\n ) => Promise<{ width: number; height: number }>;\n getPlaceholderBase64: (imageBlobOrFile: SourceType) => Promise<string>;\n resize: (\n imageBlobOrFile: SourceType,\n width: number,\n height: number,\n ) => Promise<Blob | string>;\n};\n\nexport function createImageFactory(impl: CreateImageImpl) {\n return (source: SourceType, options: CreateImageOptions) =>\n createImage(source, options, impl);\n}\n\nasync function createImage(\n imageBlobOrFile: SourceType,\n options: CreateImageOptions,\n impl: CreateImageImpl,\n): Promise<Loaded<typeof ImageDefinition, { $each: true }>> {\n // Get the original size of the image\n const { width: originalWidth, height: originalHeight } =\n await impl.getImageSize(imageBlobOrFile);\n\n const def: {\n originalSize: [number, number];\n progressive: boolean;\n placeholderDataURL: string | undefined;\n original?: FileStream;\n files: Record<string, FileStream>;\n } = {\n originalSize: [originalWidth, originalHeight],\n progressive: false,\n placeholderDataURL: undefined,\n files: {},\n };\n\n // Placeholder\n if (options?.placeholder === \"blur\") {\n def.placeholderDataURL = await impl.getPlaceholderBase64(imageBlobOrFile);\n }\n\n /**\n * Original\n *\n * Save the original image.\n * If the maxSize is set, resize the image to the maxSize if needed\n */\n if (options?.maxSize === undefined) {\n def.original = await impl.createFileStreamFromSource(\n imageBlobOrFile,\n options?.owner,\n );\n def.files[`${originalWidth}x${originalHeight}`] = def.original;\n } else if (\n options?.maxSize >= originalWidth &&\n options?.maxSize >= originalHeight\n ) {\n // no resizes required, just return the original image\n def.original = await impl.createFileStreamFromSource(\n imageBlobOrFile,\n options?.owner,\n );\n def.files[`${originalWidth}x${originalHeight}`] = def.original;\n } else {\n const { width, height } = getNewDimensions(\n originalWidth,\n originalHeight,\n options.maxSize,\n );\n\n const blob = await impl.resize(imageBlobOrFile, width, height);\n def.originalSize = [width, height];\n def.original = await impl.createFileStreamFromSource(blob, options?.owner);\n def.files[`${width}x${height}`] = def.original;\n }\n\n const imageCoValue = ImageDefinition.create(\n {\n originalSize: def.originalSize,\n progressive: def.progressive,\n placeholderDataURL: def.placeholderDataURL,\n original: def.original,\n ...def.files,\n },\n options?.owner,\n );\n\n /**\n * Progressive loading\n *\n * Save a set of resized images using three sizes: 256, 1024, 2048\n *\n * On the client side, the image will be loaded progressively, starting from the smallest size and increasing the size until the original size is reached.\n */\n if (options?.progressive) {\n imageCoValue.progressive = true;\n\n const resizes = ([256, 1024, 2048] as const).filter(\n (s) =>\n s <\n Math.max(imageCoValue.originalSize[0], imageCoValue.originalSize[1]),\n );\n\n for (const size of resizes) {\n const { width, height } = getNewDimensions(\n originalWidth,\n originalHeight,\n size,\n );\n\n const blob = await impl.resize(imageBlobOrFile, width, height);\n imageCoValue[`${width}x${height}`] =\n await impl.createFileStreamFromSource(blob, options?.owner);\n }\n }\n\n return imageCoValue;\n}\n\nconst getNewDimensions = (\n originalWidth: number,\n originalHeight: number,\n maxSize: number,\n) => {\n if (originalWidth > originalHeight) {\n return {\n width: maxSize,\n height: Math.round(maxSize * (originalHeight / originalWidth)),\n };\n }\n\n return {\n width: Math.round(maxSize * (originalWidth / originalHeight)),\n height: maxSize,\n };\n};\n","import type { CoID } from \"cojson\";\nimport { Account, FileStream, ImageDefinition } from \"jazz-tools\";\n\nexport function highestResAvailable(\n image: ImageDefinition,\n wantedWidth: number,\n wantedHeight: number,\n): { width: number; height: number; image: FileStream } | null {\n const availableSizes: [number, number, string][] = image._raw\n .keys()\n .filter((key) => /^\\d+x\\d+$/.test(key))\n .map((key) => {\n const [w, h] = key.split(\"x\").map(Number) as [number, number];\n return [w, h, key];\n });\n\n if (availableSizes.length === 0) {\n return image.original\n ? {\n width: image.originalSize[0],\n height: image.originalSize[1],\n image: image.original,\n }\n : null;\n }\n\n const sortedSizes = availableSizes\n .map((size) => {\n return {\n size,\n match: sizesMatchWanted(size[0], size[1], wantedWidth, wantedHeight),\n isLoaded: isLoaded(image._raw.get(size[2]) as CoID<any> | undefined),\n };\n })\n .sort((a, b) => a.match - b.match);\n\n // We try to find the better already loaded image\n // note: `toReversed` is not available in react-native.\n const bestLoaded = [...sortedSizes]\n .reverse()\n .find((el) => el.isLoaded && image[el.size[2]]?.getChunks());\n\n // if I can't find a good match, let's use the highest resolution\n const bestTarget =\n sortedSizes.find((el) => el.match > 0.95) || sortedSizes.at(-1);\n\n // if the best target is already loaded, we are done\n if (image[bestTarget!.size[2]]?.getChunks()) {\n return image[bestTarget!.size[2]]\n ? {\n width: bestTarget!.size[0],\n height: bestTarget!.size[1],\n image: image[bestTarget!.size[2]]!,\n }\n : null;\n }\n\n // if the best already loaded is not the best target\n // let's trigger the load of the best target\n if (bestLoaded) {\n image[bestTarget!.size[2]]?.getChunks();\n return image[bestLoaded.size[2]]\n ? {\n width: bestLoaded.size[0],\n height: bestLoaded.size[1],\n image: image[bestLoaded.size[2]]!,\n }\n : null;\n }\n\n // if nothing is loaded, then start fetching all the images till the best\n for (let size of sortedSizes) {\n if (size.match <= bestTarget!.match) {\n image[size.size[2]]?.getChunks();\n }\n }\n\n return null;\n}\n\nfunction sizesMatchWanted(\n w: number,\n h: number,\n wantedW: number,\n wantedH: number,\n): number {\n const area1 = w * h;\n const area2 = wantedW * wantedH;\n\n const areaRatio = area1 / area2;\n\n // // Below 0.95 means the image is too small, we don't want to upscale it\n // if (areaRatio < 0.95) {\n // return 9999;\n // }\n\n return areaRatio;\n}\n\nfunction isLoaded(id: CoID<any> | null | undefined): boolean {\n if (!id) {\n return false;\n }\n\n return !!Account.getMe()._raw.core.node.getLoaded(id);\n}\n\nexport async function loadImage(\n imageOrId: ImageDefinition | string,\n): Promise<{ width: number; height: number; image: FileStream } | null> {\n if (typeof imageOrId === \"string\") {\n const image = await ImageDefinition.load(imageOrId, {\n resolve: {\n original: true,\n },\n });\n\n if (image === null || image.original === null) {\n return null;\n }\n\n return {\n width: image.originalSize[0],\n height: image.originalSize[1],\n image: image.original,\n };\n }\n\n if (!imageOrId.original) {\n console.warn(\"Unable to find the original image\");\n return null;\n }\n\n const loadedOriginal = await FileStream.load(imageOrId.original.id);\n\n if (!loadedOriginal) {\n console.warn(\"Unable to find the original image\");\n return null;\n }\n\n return {\n width: imageOrId.originalSize[0],\n height: imageOrId.originalSize[1],\n image: loadedOriginal,\n };\n}\n\nexport async function loadImageBySize(\n imageOrId: ImageDefinition | string,\n wantedWidth: number,\n wantedHeight: number,\n): Promise<{ width: number; height: number; image: FileStream } | null> {\n const image: ImageDefinition | null =\n typeof imageOrId === \"string\"\n ? await ImageDefinition.load(imageOrId)\n : imageOrId;\n\n if (image === null) {\n return null;\n }\n\n if (image.progressive === false) {\n return loadImage(imageOrId);\n }\n\n const availableSizes: [number, number, string][] = image._raw\n .keys()\n .filter((key) => /^\\d+x\\d+$/.test(key))\n .map((key) => {\n const [w, h] = key.split(\"x\").map(Number) as [number, number];\n return [w, h, key];\n });\n\n if (availableSizes.length === 0) {\n return null;\n }\n\n const sortedSizes = availableSizes\n .map((size) => ({\n size,\n match: sizesMatchWanted(size[0], size[1], wantedWidth, wantedHeight),\n }))\n .sort((a, b) => a.match - b.match);\n\n const bestTarget =\n sortedSizes.find((el) => el.match > 0.95) || sortedSizes.at(-1)!;\n\n const file = image[bestTarget.size[2]];\n\n if (!file) {\n return null;\n }\n\n const loadedFile = await FileStream.load(file.id);\n\n if (!loadedFile) {\n return null;\n }\n\n return {\n width: bestTarget.size[0],\n height: bestTarget.size[1],\n image: loadedFile,\n };\n}\n"],"mappings":"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","names":["Account","FileStream","ImageDefinition"]}
|
package/dist/media/index.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.native.d.ts","sourceRoot":"","sources":["../../src/media/index.native.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,
|
1
|
+
{"version":3,"file":"index.native.d.ts","sourceRoot":"","sources":["../../src/media/index.native.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,OAAO,EACL,kBAAkB,EAClB,UAAU,EACV,kBAAkB,EACnB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAI9B,wBAAsB,WAAW,CAC/B,eAAe,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,EACrC,OAAO,CAAC,EAAE,kBAAkB;;;;;;;;;gCAmB7B;AAmFD,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,UAAU,EACpB,KAAK,CAAC,EAAE,OAAO,GAAG,KAAK,GACtB,OAAO,CAAC,UAAU,CAAC,CAarB"}
|