jazz-tools 0.19.19 → 0.19.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.svelte-kit/__package__/client.d.ts.map +1 -1
- package/.svelte-kit/__package__/client.js +3 -1
- package/.svelte-kit/__package__/tests/client.test.js +48 -0
- package/.turbo/turbo-build.log +65 -61
- package/dist/better-auth/auth/client.d.ts.map +1 -1
- package/dist/better-auth/auth/client.js +1 -1
- package/dist/better-auth/auth/client.js.map +1 -1
- package/dist/{chunk-PEHQ7TN2.js → chunk-MI24YFCY.js} +31 -4
- package/dist/chunk-MI24YFCY.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/react-core/hooks.d.ts +2 -2
- package/dist/react-core/hooks.d.ts.map +1 -1
- package/dist/react-core/index.js +4 -78
- package/dist/react-core/index.js.map +1 -1
- package/dist/react-native/chunk-DGUM43GV.js +11 -0
- package/dist/react-native/chunk-DGUM43GV.js.map +1 -0
- package/dist/react-native/crypto.js +2 -0
- package/dist/react-native/crypto.js.map +1 -1
- package/dist/react-native/index.js +540 -29
- package/dist/react-native/index.js.map +1 -1
- package/dist/react-native-core/auth/PasskeyAuth.d.ts +123 -0
- package/dist/react-native-core/auth/PasskeyAuth.d.ts.map +1 -0
- package/dist/react-native-core/auth/PasskeyAuthBasicUI.d.ts +34 -0
- package/dist/react-native-core/auth/PasskeyAuthBasicUI.d.ts.map +1 -0
- package/dist/react-native-core/auth/auth.d.ts +3 -0
- package/dist/react-native-core/auth/auth.d.ts.map +1 -1
- package/dist/react-native-core/auth/passkey-utils.d.ts +16 -0
- package/dist/react-native-core/auth/passkey-utils.d.ts.map +1 -0
- package/dist/react-native-core/auth/usePasskeyAuth.d.ts +48 -0
- package/dist/react-native-core/auth/usePasskeyAuth.d.ts.map +1 -0
- package/dist/react-native-core/chunk-DGUM43GV.js +11 -0
- package/dist/react-native-core/chunk-DGUM43GV.js.map +1 -0
- package/dist/react-native-core/crypto.js +2 -0
- package/dist/react-native-core/crypto.js.map +1 -1
- package/dist/react-native-core/index.js +535 -24
- package/dist/react-native-core/index.js.map +1 -1
- package/dist/react-native-core/tests/PasskeyAuth.test.d.ts +2 -0
- package/dist/react-native-core/tests/PasskeyAuth.test.d.ts.map +1 -0
- package/dist/react-native-core/tests/passkey-utils.test.d.ts +2 -0
- package/dist/react-native-core/tests/passkey-utils.test.d.ts.map +1 -0
- package/dist/testing.js +1 -1
- package/dist/tools/coValues/account.d.ts +5 -1
- package/dist/tools/coValues/account.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts +30 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
- package/dist/tools/testing.d.ts.map +1 -1
- package/package.json +8 -4
- package/src/better-auth/auth/client.ts +3 -1
- package/src/better-auth/auth/tests/client.test.ts +66 -2
- package/src/react-core/hooks.ts +12 -103
- package/src/react-native-core/auth/PasskeyAuth.ts +316 -0
- package/src/react-native-core/auth/PasskeyAuthBasicUI.tsx +284 -0
- package/src/react-native-core/auth/auth.ts +3 -0
- package/src/react-native-core/auth/passkey-utils.ts +47 -0
- package/src/react-native-core/auth/usePasskeyAuth.tsx +85 -0
- package/src/react-native-core/tests/PasskeyAuth.test.ts +463 -0
- package/src/react-native-core/tests/passkey-utils.test.ts +144 -0
- package/src/tools/coValues/account.ts +11 -3
- package/src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts +27 -1
- package/src/tools/tests/account.test.ts +2 -1
- package/testSetup.ts +4 -0
- package/vitest.config.ts +1 -0
- package/dist/chunk-PEHQ7TN2.js.map +0 -1
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__require
|
|
3
|
+
} from "./chunk-DGUM43GV.js";
|
|
4
|
+
|
|
1
5
|
// src/react-native-core/storage/kv-store-context.ts
|
|
2
6
|
var KvStoreContext = class _KvStoreContext {
|
|
3
7
|
constructor() {
|
|
@@ -222,6 +226,507 @@ var styles = StyleSheet.create({
|
|
|
222
226
|
}
|
|
223
227
|
});
|
|
224
228
|
|
|
229
|
+
// src/react-native-core/auth/PasskeyAuth.ts
|
|
230
|
+
import { cojsonInternals } from "cojson";
|
|
231
|
+
import {
|
|
232
|
+
Account
|
|
233
|
+
} from "jazz-tools";
|
|
234
|
+
|
|
235
|
+
// src/react-native-core/auth/passkey-utils.ts
|
|
236
|
+
function uint8ArrayToBase64Url(bytes) {
|
|
237
|
+
let binary = "";
|
|
238
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
239
|
+
binary += String.fromCharCode(bytes[i]);
|
|
240
|
+
}
|
|
241
|
+
const base64 = btoa(binary);
|
|
242
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
243
|
+
}
|
|
244
|
+
function base64UrlToUint8Array(base64url) {
|
|
245
|
+
let base64 = base64url.replace(/-/g, "+").replace(/_/g, "/");
|
|
246
|
+
const padding = base64.length % 4;
|
|
247
|
+
if (padding > 0) {
|
|
248
|
+
base64 += "=".repeat(4 - padding);
|
|
249
|
+
}
|
|
250
|
+
const binary = atob(base64);
|
|
251
|
+
const bytes = new Uint8Array(binary.length);
|
|
252
|
+
for (let i = 0; i < binary.length; i++) {
|
|
253
|
+
bytes[i] = binary.charCodeAt(i);
|
|
254
|
+
}
|
|
255
|
+
return bytes;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// src/react-native-core/auth/PasskeyAuth.ts
|
|
259
|
+
var cachedPasskeyModule = null;
|
|
260
|
+
function getPasskeyModule() {
|
|
261
|
+
if (cachedPasskeyModule) {
|
|
262
|
+
return cachedPasskeyModule;
|
|
263
|
+
}
|
|
264
|
+
try {
|
|
265
|
+
const module = __require("react-native-passkey");
|
|
266
|
+
const passkeyModule = module.Passkey || module.default || module;
|
|
267
|
+
cachedPasskeyModule = passkeyModule;
|
|
268
|
+
return passkeyModule;
|
|
269
|
+
} catch (e) {
|
|
270
|
+
console.error("Failed to load react-native-passkey:", e);
|
|
271
|
+
throw new Error(
|
|
272
|
+
"react-native-passkey is not installed. Please install it to use passkey authentication: npm install react-native-passkey"
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
function setPasskeyModule(module) {
|
|
277
|
+
cachedPasskeyModule = module;
|
|
278
|
+
}
|
|
279
|
+
async function isPasskeySupported() {
|
|
280
|
+
try {
|
|
281
|
+
const module = getPasskeyModule();
|
|
282
|
+
return await module.isSupported();
|
|
283
|
+
} catch {
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
var ReactNativePasskeyAuth = class {
|
|
288
|
+
constructor(crypto, authenticate, authSecretStorage, appName, rpId) {
|
|
289
|
+
this.crypto = crypto;
|
|
290
|
+
this.authenticate = authenticate;
|
|
291
|
+
this.authSecretStorage = authSecretStorage;
|
|
292
|
+
this.appName = appName;
|
|
293
|
+
this.rpId = rpId;
|
|
294
|
+
/**
|
|
295
|
+
* Log in using an existing passkey.
|
|
296
|
+
* This will prompt the user to authenticate with their device biometrics.
|
|
297
|
+
*/
|
|
298
|
+
this.logIn = async () => {
|
|
299
|
+
const { crypto, authenticate } = this;
|
|
300
|
+
const webAuthNCredential = await this.getPasskeyCredentials();
|
|
301
|
+
if (!webAuthNCredential) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
if (!webAuthNCredential.response.userHandle) {
|
|
305
|
+
throw new Error("Passkey credential is missing userHandle");
|
|
306
|
+
}
|
|
307
|
+
const webAuthNCredentialPayload = base64UrlToUint8Array(
|
|
308
|
+
webAuthNCredential.response.userHandle
|
|
309
|
+
);
|
|
310
|
+
const accountSecretSeed = webAuthNCredentialPayload.slice(
|
|
311
|
+
0,
|
|
312
|
+
cojsonInternals.secretSeedLength
|
|
313
|
+
);
|
|
314
|
+
const secret = crypto.agentSecretFromSecretSeed(accountSecretSeed);
|
|
315
|
+
const accountID = cojsonInternals.rawCoIDfromBytes(
|
|
316
|
+
webAuthNCredentialPayload.slice(
|
|
317
|
+
cojsonInternals.secretSeedLength,
|
|
318
|
+
cojsonInternals.secretSeedLength + cojsonInternals.shortHashLength
|
|
319
|
+
)
|
|
320
|
+
);
|
|
321
|
+
await authenticate({
|
|
322
|
+
accountID,
|
|
323
|
+
accountSecret: secret
|
|
324
|
+
});
|
|
325
|
+
await this.authSecretStorage.set({
|
|
326
|
+
accountID,
|
|
327
|
+
secretSeed: accountSecretSeed,
|
|
328
|
+
accountSecret: secret,
|
|
329
|
+
provider: "passkey"
|
|
330
|
+
});
|
|
331
|
+
};
|
|
332
|
+
/**
|
|
333
|
+
* Register a new passkey for the current account.
|
|
334
|
+
* This will create a passkey that stores the account credentials securely on the device.
|
|
335
|
+
*
|
|
336
|
+
* @param username - The display name for the passkey
|
|
337
|
+
*/
|
|
338
|
+
this.signUp = async (username) => {
|
|
339
|
+
const credentials = await this.authSecretStorage.get();
|
|
340
|
+
if (!credentials?.secretSeed) {
|
|
341
|
+
throw new Error(
|
|
342
|
+
"Not enough credentials to register the account with passkey"
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
await this.createPasskeyCredentials({
|
|
346
|
+
accountID: credentials.accountID,
|
|
347
|
+
secretSeed: credentials.secretSeed,
|
|
348
|
+
username
|
|
349
|
+
});
|
|
350
|
+
const currentAccount = await Account.getMe().$jazz.ensureLoaded({
|
|
351
|
+
resolve: {
|
|
352
|
+
profile: true
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
if (username.trim().length !== 0) {
|
|
356
|
+
currentAccount.profile.$jazz.set("name", username);
|
|
357
|
+
}
|
|
358
|
+
await this.authSecretStorage.set({
|
|
359
|
+
accountID: credentials.accountID,
|
|
360
|
+
secretSeed: credentials.secretSeed,
|
|
361
|
+
accountSecret: credentials.accountSecret,
|
|
362
|
+
provider: "passkey"
|
|
363
|
+
});
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
async createPasskeyCredentials({
|
|
367
|
+
accountID,
|
|
368
|
+
secretSeed,
|
|
369
|
+
username
|
|
370
|
+
}) {
|
|
371
|
+
const webAuthNCredentialPayload = new Uint8Array(
|
|
372
|
+
cojsonInternals.secretSeedLength + cojsonInternals.shortHashLength
|
|
373
|
+
);
|
|
374
|
+
webAuthNCredentialPayload.set(secretSeed);
|
|
375
|
+
webAuthNCredentialPayload.set(
|
|
376
|
+
cojsonInternals.rawCoIDtoBytes(accountID),
|
|
377
|
+
cojsonInternals.secretSeedLength
|
|
378
|
+
);
|
|
379
|
+
const challenge = uint8ArrayToBase64Url(
|
|
380
|
+
new Uint8Array(this.crypto.randomBytes(32))
|
|
381
|
+
);
|
|
382
|
+
const userId = uint8ArrayToBase64Url(webAuthNCredentialPayload);
|
|
383
|
+
const passkey = getPasskeyModule();
|
|
384
|
+
try {
|
|
385
|
+
await passkey.create({
|
|
386
|
+
challenge,
|
|
387
|
+
rp: {
|
|
388
|
+
id: this.rpId,
|
|
389
|
+
name: this.appName
|
|
390
|
+
},
|
|
391
|
+
user: {
|
|
392
|
+
id: userId,
|
|
393
|
+
name: `${username} (${(/* @__PURE__ */ new Date()).toLocaleString()})`,
|
|
394
|
+
displayName: username
|
|
395
|
+
},
|
|
396
|
+
pubKeyCredParams: [
|
|
397
|
+
{ alg: -7, type: "public-key" },
|
|
398
|
+
// ES256
|
|
399
|
+
{ alg: -257, type: "public-key" }
|
|
400
|
+
// RS256
|
|
401
|
+
],
|
|
402
|
+
authenticatorSelection: {
|
|
403
|
+
residentKey: "required",
|
|
404
|
+
userVerification: "preferred"
|
|
405
|
+
},
|
|
406
|
+
timeout: 6e4,
|
|
407
|
+
attestation: "none"
|
|
408
|
+
});
|
|
409
|
+
} catch (error) {
|
|
410
|
+
throw new Error("Passkey creation aborted", { cause: error });
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
async getPasskeyCredentials() {
|
|
414
|
+
const challenge = uint8ArrayToBase64Url(
|
|
415
|
+
new Uint8Array(this.crypto.randomBytes(32))
|
|
416
|
+
);
|
|
417
|
+
const passkey = getPasskeyModule();
|
|
418
|
+
try {
|
|
419
|
+
const result = await passkey.get({
|
|
420
|
+
challenge,
|
|
421
|
+
rpId: this.rpId,
|
|
422
|
+
timeout: 6e4,
|
|
423
|
+
userVerification: "preferred"
|
|
424
|
+
});
|
|
425
|
+
return result;
|
|
426
|
+
} catch (error) {
|
|
427
|
+
throw new Error("Passkey authentication aborted", { cause: error });
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
ReactNativePasskeyAuth.id = "passkey";
|
|
432
|
+
|
|
433
|
+
// src/react-native-core/auth/usePasskeyAuth.tsx
|
|
434
|
+
import {
|
|
435
|
+
useAuthSecretStorage,
|
|
436
|
+
useIsAuthenticated,
|
|
437
|
+
useJazzContext
|
|
438
|
+
} from "jazz-tools/react-core";
|
|
439
|
+
import { useMemo } from "react";
|
|
440
|
+
function usePasskeyAuth({
|
|
441
|
+
appName,
|
|
442
|
+
rpId
|
|
443
|
+
}) {
|
|
444
|
+
const context = useJazzContext();
|
|
445
|
+
const authSecretStorage = useAuthSecretStorage();
|
|
446
|
+
if ("guest" in context) {
|
|
447
|
+
throw new Error("Passkey auth is not supported in guest mode");
|
|
448
|
+
}
|
|
449
|
+
const authMethod = useMemo(() => {
|
|
450
|
+
return new ReactNativePasskeyAuth(
|
|
451
|
+
context.node.crypto,
|
|
452
|
+
context.authenticate,
|
|
453
|
+
authSecretStorage,
|
|
454
|
+
appName,
|
|
455
|
+
rpId
|
|
456
|
+
);
|
|
457
|
+
}, [
|
|
458
|
+
appName,
|
|
459
|
+
rpId,
|
|
460
|
+
authSecretStorage,
|
|
461
|
+
context.node.crypto,
|
|
462
|
+
context.authenticate
|
|
463
|
+
]);
|
|
464
|
+
const isAuthenticated = useIsAuthenticated();
|
|
465
|
+
return {
|
|
466
|
+
state: isAuthenticated ? "signedIn" : "anonymous",
|
|
467
|
+
logIn: authMethod.logIn,
|
|
468
|
+
signUp: authMethod.signUp
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// src/react-native-core/auth/PasskeyAuthBasicUI.tsx
|
|
473
|
+
import { useState as useState2 } from "react";
|
|
474
|
+
import {
|
|
475
|
+
StyleSheet as StyleSheet2,
|
|
476
|
+
Text as Text2,
|
|
477
|
+
TextInput as TextInput2,
|
|
478
|
+
TouchableOpacity as TouchableOpacity2,
|
|
479
|
+
View as View2,
|
|
480
|
+
useColorScheme as useColorScheme2
|
|
481
|
+
} from "react-native";
|
|
482
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
483
|
+
var PasskeyAuthBasicUI = ({
|
|
484
|
+
appName,
|
|
485
|
+
rpId,
|
|
486
|
+
children
|
|
487
|
+
}) => {
|
|
488
|
+
const colorScheme = useColorScheme2();
|
|
489
|
+
const darkMode = colorScheme === "dark";
|
|
490
|
+
const [username, setUsername] = useState2("");
|
|
491
|
+
const [errorMessage, setErrorMessage] = useState2(null);
|
|
492
|
+
const auth = usePasskeyAuth({ appName, rpId });
|
|
493
|
+
const handleSignUp = () => {
|
|
494
|
+
setErrorMessage(null);
|
|
495
|
+
auth.signUp(username).catch((error) => {
|
|
496
|
+
if (error.cause instanceof Error) {
|
|
497
|
+
setErrorMessage(error.cause.message);
|
|
498
|
+
} else {
|
|
499
|
+
setErrorMessage(error.message);
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
};
|
|
503
|
+
const handleLogIn = () => {
|
|
504
|
+
setErrorMessage(null);
|
|
505
|
+
auth.logIn().catch((error) => {
|
|
506
|
+
if (error.cause instanceof Error) {
|
|
507
|
+
setErrorMessage(error.cause.message);
|
|
508
|
+
} else {
|
|
509
|
+
setErrorMessage(error.message);
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
};
|
|
513
|
+
if (auth.state === "signedIn") {
|
|
514
|
+
return children;
|
|
515
|
+
}
|
|
516
|
+
return /* @__PURE__ */ jsx2(
|
|
517
|
+
View2,
|
|
518
|
+
{
|
|
519
|
+
style: [
|
|
520
|
+
styles2.container,
|
|
521
|
+
darkMode ? styles2.darkBackground : styles2.lightBackground
|
|
522
|
+
],
|
|
523
|
+
children: /* @__PURE__ */ jsxs2(View2, { style: styles2.formContainer, children: [
|
|
524
|
+
/* @__PURE__ */ jsx2(
|
|
525
|
+
Text2,
|
|
526
|
+
{
|
|
527
|
+
style: [
|
|
528
|
+
styles2.headerText,
|
|
529
|
+
darkMode ? styles2.darkText : styles2.lightText
|
|
530
|
+
],
|
|
531
|
+
children: appName
|
|
532
|
+
}
|
|
533
|
+
),
|
|
534
|
+
errorMessage && /* @__PURE__ */ jsx2(Text2, { style: styles2.errorText, children: errorMessage }),
|
|
535
|
+
/* @__PURE__ */ jsx2(
|
|
536
|
+
TextInput2,
|
|
537
|
+
{
|
|
538
|
+
placeholder: "Display name",
|
|
539
|
+
value: username,
|
|
540
|
+
onChangeText: setUsername,
|
|
541
|
+
placeholderTextColor: darkMode ? "#999" : "#666",
|
|
542
|
+
style: [
|
|
543
|
+
styles2.textInput,
|
|
544
|
+
darkMode ? styles2.darkInput : styles2.lightInput
|
|
545
|
+
],
|
|
546
|
+
autoCapitalize: "words",
|
|
547
|
+
autoCorrect: false
|
|
548
|
+
}
|
|
549
|
+
),
|
|
550
|
+
/* @__PURE__ */ jsx2(
|
|
551
|
+
TouchableOpacity2,
|
|
552
|
+
{
|
|
553
|
+
onPress: handleSignUp,
|
|
554
|
+
style: [
|
|
555
|
+
styles2.button,
|
|
556
|
+
darkMode ? styles2.darkButton : styles2.lightButton
|
|
557
|
+
],
|
|
558
|
+
children: /* @__PURE__ */ jsx2(
|
|
559
|
+
Text2,
|
|
560
|
+
{
|
|
561
|
+
style: darkMode ? styles2.darkButtonText : styles2.lightButtonText,
|
|
562
|
+
children: "Sign Up with Passkey"
|
|
563
|
+
}
|
|
564
|
+
)
|
|
565
|
+
}
|
|
566
|
+
),
|
|
567
|
+
/* @__PURE__ */ jsxs2(View2, { style: styles2.divider, children: [
|
|
568
|
+
/* @__PURE__ */ jsx2(
|
|
569
|
+
View2,
|
|
570
|
+
{
|
|
571
|
+
style: [
|
|
572
|
+
styles2.dividerLine,
|
|
573
|
+
darkMode ? styles2.darkDivider : styles2.lightDivider
|
|
574
|
+
]
|
|
575
|
+
}
|
|
576
|
+
),
|
|
577
|
+
/* @__PURE__ */ jsx2(
|
|
578
|
+
Text2,
|
|
579
|
+
{
|
|
580
|
+
style: [
|
|
581
|
+
styles2.dividerText,
|
|
582
|
+
darkMode ? styles2.darkText : styles2.lightText
|
|
583
|
+
],
|
|
584
|
+
children: "or"
|
|
585
|
+
}
|
|
586
|
+
),
|
|
587
|
+
/* @__PURE__ */ jsx2(
|
|
588
|
+
View2,
|
|
589
|
+
{
|
|
590
|
+
style: [
|
|
591
|
+
styles2.dividerLine,
|
|
592
|
+
darkMode ? styles2.darkDivider : styles2.lightDivider
|
|
593
|
+
]
|
|
594
|
+
}
|
|
595
|
+
)
|
|
596
|
+
] }),
|
|
597
|
+
/* @__PURE__ */ jsx2(
|
|
598
|
+
TouchableOpacity2,
|
|
599
|
+
{
|
|
600
|
+
onPress: handleLogIn,
|
|
601
|
+
style: [
|
|
602
|
+
styles2.secondaryButton,
|
|
603
|
+
darkMode ? styles2.darkSecondaryButton : styles2.lightSecondaryButton
|
|
604
|
+
],
|
|
605
|
+
children: /* @__PURE__ */ jsx2(Text2, { style: darkMode ? styles2.darkText : styles2.lightText, children: "Log In with Existing Passkey" })
|
|
606
|
+
}
|
|
607
|
+
)
|
|
608
|
+
] })
|
|
609
|
+
}
|
|
610
|
+
);
|
|
611
|
+
};
|
|
612
|
+
var styles2 = StyleSheet2.create({
|
|
613
|
+
container: {
|
|
614
|
+
flex: 1,
|
|
615
|
+
justifyContent: "center",
|
|
616
|
+
alignItems: "center",
|
|
617
|
+
padding: 20
|
|
618
|
+
},
|
|
619
|
+
formContainer: {
|
|
620
|
+
width: "80%",
|
|
621
|
+
maxWidth: 300,
|
|
622
|
+
alignItems: "center",
|
|
623
|
+
justifyContent: "center"
|
|
624
|
+
},
|
|
625
|
+
headerText: {
|
|
626
|
+
fontSize: 24,
|
|
627
|
+
fontWeight: "600",
|
|
628
|
+
marginBottom: 30
|
|
629
|
+
},
|
|
630
|
+
errorText: {
|
|
631
|
+
color: "#ff4444",
|
|
632
|
+
marginVertical: 10,
|
|
633
|
+
textAlign: "center",
|
|
634
|
+
fontSize: 14
|
|
635
|
+
},
|
|
636
|
+
textInput: {
|
|
637
|
+
borderWidth: 1,
|
|
638
|
+
padding: 12,
|
|
639
|
+
marginVertical: 10,
|
|
640
|
+
width: "100%",
|
|
641
|
+
borderRadius: 8,
|
|
642
|
+
fontSize: 16
|
|
643
|
+
},
|
|
644
|
+
darkInput: {
|
|
645
|
+
borderColor: "#444",
|
|
646
|
+
backgroundColor: "#1a1a1a",
|
|
647
|
+
color: "#fff"
|
|
648
|
+
},
|
|
649
|
+
lightInput: {
|
|
650
|
+
borderColor: "#ddd",
|
|
651
|
+
backgroundColor: "#fff",
|
|
652
|
+
color: "#000"
|
|
653
|
+
},
|
|
654
|
+
button: {
|
|
655
|
+
paddingVertical: 14,
|
|
656
|
+
paddingHorizontal: 10,
|
|
657
|
+
borderRadius: 8,
|
|
658
|
+
width: "100%",
|
|
659
|
+
marginVertical: 10
|
|
660
|
+
},
|
|
661
|
+
darkButton: {
|
|
662
|
+
backgroundColor: "#0066cc"
|
|
663
|
+
},
|
|
664
|
+
lightButton: {
|
|
665
|
+
backgroundColor: "#007aff"
|
|
666
|
+
},
|
|
667
|
+
darkButtonText: {
|
|
668
|
+
color: "#fff",
|
|
669
|
+
textAlign: "center",
|
|
670
|
+
fontWeight: "600",
|
|
671
|
+
fontSize: 16
|
|
672
|
+
},
|
|
673
|
+
lightButtonText: {
|
|
674
|
+
color: "#fff",
|
|
675
|
+
textAlign: "center",
|
|
676
|
+
fontWeight: "600",
|
|
677
|
+
fontSize: 16
|
|
678
|
+
},
|
|
679
|
+
divider: {
|
|
680
|
+
flexDirection: "row",
|
|
681
|
+
alignItems: "center",
|
|
682
|
+
width: "100%",
|
|
683
|
+
marginVertical: 20
|
|
684
|
+
},
|
|
685
|
+
dividerLine: {
|
|
686
|
+
flex: 1,
|
|
687
|
+
height: 1
|
|
688
|
+
},
|
|
689
|
+
darkDivider: {
|
|
690
|
+
backgroundColor: "#444"
|
|
691
|
+
},
|
|
692
|
+
lightDivider: {
|
|
693
|
+
backgroundColor: "#ddd"
|
|
694
|
+
},
|
|
695
|
+
dividerText: {
|
|
696
|
+
marginHorizontal: 10,
|
|
697
|
+
fontSize: 14
|
|
698
|
+
},
|
|
699
|
+
secondaryButton: {
|
|
700
|
+
paddingVertical: 14,
|
|
701
|
+
paddingHorizontal: 10,
|
|
702
|
+
borderRadius: 8,
|
|
703
|
+
width: "100%",
|
|
704
|
+
borderWidth: 1
|
|
705
|
+
},
|
|
706
|
+
darkSecondaryButton: {
|
|
707
|
+
borderColor: "#444",
|
|
708
|
+
backgroundColor: "transparent"
|
|
709
|
+
},
|
|
710
|
+
lightSecondaryButton: {
|
|
711
|
+
borderColor: "#ddd",
|
|
712
|
+
backgroundColor: "transparent"
|
|
713
|
+
},
|
|
714
|
+
darkText: {
|
|
715
|
+
color: "#fff",
|
|
716
|
+
textAlign: "center"
|
|
717
|
+
},
|
|
718
|
+
lightText: {
|
|
719
|
+
color: "#000",
|
|
720
|
+
textAlign: "center"
|
|
721
|
+
},
|
|
722
|
+
darkBackground: {
|
|
723
|
+
backgroundColor: "#000"
|
|
724
|
+
},
|
|
725
|
+
lightBackground: {
|
|
726
|
+
backgroundColor: "#fff"
|
|
727
|
+
}
|
|
728
|
+
});
|
|
729
|
+
|
|
225
730
|
// src/react-native-core/auth/auth.ts
|
|
226
731
|
function clearUserCredentials() {
|
|
227
732
|
const kvStore = KvStoreContext.getInstance().getStorage();
|
|
@@ -235,16 +740,16 @@ function clearUserCredentials() {
|
|
|
235
740
|
// src/react-native-core/hooks.tsx
|
|
236
741
|
import { useEffect } from "react";
|
|
237
742
|
import { parseInviteLink } from "jazz-tools";
|
|
238
|
-
import { useJazzContext } from "jazz-tools/react-core";
|
|
743
|
+
import { useJazzContext as useJazzContext2 } from "jazz-tools/react-core";
|
|
239
744
|
import { Linking } from "react-native";
|
|
240
745
|
import {
|
|
241
746
|
useCoState,
|
|
242
747
|
experimental_useInboxSender,
|
|
243
748
|
useDemoAuth,
|
|
244
749
|
usePassphraseAuth,
|
|
245
|
-
useJazzContext as
|
|
246
|
-
useAuthSecretStorage,
|
|
247
|
-
useIsAuthenticated,
|
|
750
|
+
useJazzContext as useJazzContext3,
|
|
751
|
+
useAuthSecretStorage as useAuthSecretStorage2,
|
|
752
|
+
useIsAuthenticated as useIsAuthenticated2,
|
|
248
753
|
useAccount,
|
|
249
754
|
useAgent,
|
|
250
755
|
useLogOut,
|
|
@@ -260,7 +765,7 @@ function useAcceptInviteNative({
|
|
|
260
765
|
onAccept,
|
|
261
766
|
forValueHint
|
|
262
767
|
}) {
|
|
263
|
-
const context =
|
|
768
|
+
const context = useJazzContext2();
|
|
264
769
|
if (!("me" in context)) {
|
|
265
770
|
throw new Error(
|
|
266
771
|
"useAcceptInviteNative can't be used in a JazzProvider with auth === 'guest'."
|
|
@@ -293,7 +798,7 @@ function useAcceptInviteNative({
|
|
|
293
798
|
|
|
294
799
|
// src/react-native-core/provider.tsx
|
|
295
800
|
import { JazzContext, JazzContextManagerContext } from "jazz-tools/react-core";
|
|
296
|
-
import
|
|
801
|
+
import React3, { useEffect as useEffect2, useRef } from "react";
|
|
297
802
|
|
|
298
803
|
// src/react-native-core/ReactNativeContextManager.ts
|
|
299
804
|
import {
|
|
@@ -376,8 +881,8 @@ var ReactNativeWebSocketPeerWithReconnection = class extends WebSocketPeerWithRe
|
|
|
376
881
|
}
|
|
377
882
|
};
|
|
378
883
|
async function setupPeers(options) {
|
|
379
|
-
const
|
|
380
|
-
const crypto = await
|
|
884
|
+
const CryptoProvider3 = options.CryptoProvider || PureJSCrypto;
|
|
885
|
+
const crypto = await CryptoProvider3.create();
|
|
381
886
|
let node = void 0;
|
|
382
887
|
const peers = [];
|
|
383
888
|
const storage2 = options.storage && options.storage !== "disabled" ? await getSqliteStorageAsync(options.storage) : void 0;
|
|
@@ -577,7 +1082,7 @@ var ReactNativeContextManager = class extends JazzContextManager {
|
|
|
577
1082
|
};
|
|
578
1083
|
|
|
579
1084
|
// src/react-native-core/provider.tsx
|
|
580
|
-
import { jsx as
|
|
1085
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
581
1086
|
function JazzProviderCore({
|
|
582
1087
|
children,
|
|
583
1088
|
guestMode,
|
|
@@ -589,11 +1094,11 @@ function JazzProviderCore({
|
|
|
589
1094
|
logOutReplacement,
|
|
590
1095
|
onAnonymousAccountDiscarded,
|
|
591
1096
|
kvStore,
|
|
592
|
-
CryptoProvider:
|
|
1097
|
+
CryptoProvider: CryptoProvider3,
|
|
593
1098
|
authSecretStorageKey
|
|
594
1099
|
}) {
|
|
595
1100
|
setupKvStore(kvStore);
|
|
596
|
-
const [contextManager] =
|
|
1101
|
+
const [contextManager] = React3.useState(
|
|
597
1102
|
() => new ReactNativeContextManager({ authSecretStorageKey })
|
|
598
1103
|
);
|
|
599
1104
|
const onLogOutRefCallback = useRefCallback(onLogOut);
|
|
@@ -606,8 +1111,8 @@ function JazzProviderCore({
|
|
|
606
1111
|
const onAnonymousAccountDiscardedEnabled = Boolean(
|
|
607
1112
|
onAnonymousAccountDiscarded
|
|
608
1113
|
);
|
|
609
|
-
const value =
|
|
610
|
-
|
|
1114
|
+
const value = React3.useSyncExternalStore(
|
|
1115
|
+
React3.useCallback(
|
|
611
1116
|
(callback) => {
|
|
612
1117
|
const props = {
|
|
613
1118
|
AccountSchema,
|
|
@@ -618,7 +1123,7 @@ function JazzProviderCore({
|
|
|
618
1123
|
onLogOut: onLogOutRefCallback,
|
|
619
1124
|
logOutReplacement: logoutReplacementActiveRef.current ? logOutReplacementRefCallback : void 0,
|
|
620
1125
|
onAnonymousAccountDiscarded: onAnonymousAccountDiscardedEnabled ? onAnonymousAccountDiscardedRefCallback : void 0,
|
|
621
|
-
CryptoProvider:
|
|
1126
|
+
CryptoProvider: CryptoProvider3
|
|
622
1127
|
};
|
|
623
1128
|
if (contextManager.propsChanged(props)) {
|
|
624
1129
|
contextManager.createContext(props).catch((error) => {
|
|
@@ -639,10 +1144,10 @@ function JazzProviderCore({
|
|
|
639
1144
|
contextManager.done();
|
|
640
1145
|
};
|
|
641
1146
|
}, []);
|
|
642
|
-
return /* @__PURE__ */
|
|
1147
|
+
return /* @__PURE__ */ jsx3(JazzContext.Provider, { value, children: /* @__PURE__ */ jsx3(JazzContextManagerContext.Provider, { value: contextManager, children: value && children }) });
|
|
643
1148
|
}
|
|
644
1149
|
function useRefCallback(callback) {
|
|
645
|
-
const callbackRef =
|
|
1150
|
+
const callbackRef = React3.useRef(callback);
|
|
646
1151
|
callbackRef.current = callback;
|
|
647
1152
|
return useRef(
|
|
648
1153
|
(...args) => callbackRef.current?.(...args)
|
|
@@ -652,17 +1157,17 @@ function useRefCallback(callback) {
|
|
|
652
1157
|
// src/react-native-core/media/image.tsx
|
|
653
1158
|
import { ImageDefinition } from "jazz-tools";
|
|
654
1159
|
import { highestResAvailable } from "jazz-tools/media";
|
|
655
|
-
import { forwardRef, useEffect as useEffect3, useMemo, useState as
|
|
1160
|
+
import { forwardRef, useEffect as useEffect3, useMemo as useMemo2, useState as useState3 } from "react";
|
|
656
1161
|
import { Image as RNImage } from "react-native";
|
|
657
|
-
import { jsx as
|
|
1162
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
658
1163
|
var Image = forwardRef(function Image2({ imageId, width, height, placeholder, ...props }, ref) {
|
|
659
1164
|
const image = useCoState(ImageDefinition, imageId, {
|
|
660
1165
|
select: (image2) => image2.$isLoaded ? image2 : null
|
|
661
1166
|
});
|
|
662
|
-
const [src, setSrc] =
|
|
1167
|
+
const [src, setSrc] = useState3(
|
|
663
1168
|
image?.placeholderDataURL ?? "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="
|
|
664
1169
|
);
|
|
665
|
-
const dimensions =
|
|
1170
|
+
const dimensions = useMemo2(() => {
|
|
666
1171
|
const originalWidth = image?.originalSize?.[0];
|
|
667
1172
|
const originalHeight = image?.originalSize?.[1];
|
|
668
1173
|
if (width === "original" && height === "original") {
|
|
@@ -717,7 +1222,7 @@ var Image = forwardRef(function Image2({ imageId, width, height, placeholder, ..
|
|
|
717
1222
|
if (!src) {
|
|
718
1223
|
return null;
|
|
719
1224
|
}
|
|
720
|
-
return /* @__PURE__ */
|
|
1225
|
+
return /* @__PURE__ */ jsx4(
|
|
721
1226
|
RNImage,
|
|
722
1227
|
{
|
|
723
1228
|
ref,
|
|
@@ -741,7 +1246,7 @@ import { parseInviteLink as parseInviteLink2 } from "jazz-tools";
|
|
|
741
1246
|
import {
|
|
742
1247
|
JazzProviderCore as JazzProviderCore2
|
|
743
1248
|
} from "jazz-tools/react-native-core";
|
|
744
|
-
import { useMemo as
|
|
1249
|
+
import { useMemo as useMemo3 } from "react";
|
|
745
1250
|
|
|
746
1251
|
// src/react-native/storage/mmkv-store-adapter.ts
|
|
747
1252
|
import { MMKV } from "react-native-mmkv";
|
|
@@ -821,15 +1326,15 @@ var OPSQLiteAdapter = class {
|
|
|
821
1326
|
};
|
|
822
1327
|
|
|
823
1328
|
// src/react-native/provider.tsx
|
|
824
|
-
import { jsx as
|
|
1329
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
825
1330
|
function JazzReactNativeProvider(props) {
|
|
826
|
-
const storage2 =
|
|
1331
|
+
const storage2 = useMemo3(() => {
|
|
827
1332
|
return props.storage ?? new OPSQLiteAdapter();
|
|
828
1333
|
}, [props.storage]);
|
|
829
|
-
const kvStore =
|
|
1334
|
+
const kvStore = useMemo3(() => {
|
|
830
1335
|
return props.kvStore ?? new MMKVStore();
|
|
831
1336
|
}, [props.kvStore]);
|
|
832
|
-
return /* @__PURE__ */
|
|
1337
|
+
return /* @__PURE__ */ jsx5(JazzProviderCore2, { ...props, storage: storage2, kvStore });
|
|
833
1338
|
}
|
|
834
1339
|
export {
|
|
835
1340
|
DemoAuthBasicUI,
|
|
@@ -839,26 +1344,32 @@ export {
|
|
|
839
1344
|
KvStoreContext,
|
|
840
1345
|
MMKVStore,
|
|
841
1346
|
OPSQLiteAdapter,
|
|
1347
|
+
PasskeyAuthBasicUI,
|
|
842
1348
|
ReactNativeContextManager,
|
|
1349
|
+
ReactNativePasskeyAuth,
|
|
843
1350
|
SQLiteDatabaseDriverAsync,
|
|
844
1351
|
clearUserCredentials,
|
|
845
1352
|
createAccountSubscriptionContext,
|
|
846
1353
|
createCoValueSubscriptionContext,
|
|
847
1354
|
createInviteLink,
|
|
848
1355
|
experimental_useInboxSender,
|
|
1356
|
+
getPasskeyModule,
|
|
1357
|
+
isPasskeySupported,
|
|
849
1358
|
parseInviteLink2 as parseInviteLink,
|
|
1359
|
+
setPasskeyModule,
|
|
850
1360
|
setupKvStore,
|
|
851
1361
|
useAcceptInviteNative,
|
|
852
1362
|
useAccount,
|
|
853
1363
|
useAccountSubscription,
|
|
854
1364
|
useAgent,
|
|
855
|
-
useAuthSecretStorage,
|
|
1365
|
+
useAuthSecretStorage2 as useAuthSecretStorage,
|
|
856
1366
|
useCoState,
|
|
857
1367
|
useCoValueSubscription,
|
|
858
1368
|
useDemoAuth,
|
|
859
|
-
useIsAuthenticated,
|
|
860
|
-
|
|
1369
|
+
useIsAuthenticated2 as useIsAuthenticated,
|
|
1370
|
+
useJazzContext3 as useJazzContext,
|
|
861
1371
|
useLogOut,
|
|
1372
|
+
usePasskeyAuth,
|
|
862
1373
|
usePassphraseAuth,
|
|
863
1374
|
useSubscriptionSelector,
|
|
864
1375
|
useSuspenseAccount,
|