jazz-tools 0.9.23 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +10 -12
- package/CHANGELOG.md +27 -0
- package/dist/{chunk-OJIEP4WE.js → chunk-24EJ3CKA.js} +566 -118
- package/dist/chunk-24EJ3CKA.js.map +1 -0
- package/dist/{index.web.js → index.js} +20 -9
- package/dist/index.js.map +1 -0
- package/dist/testing.js +125 -34
- package/dist/testing.js.map +1 -1
- package/package.json +11 -15
- package/src/auth/AuthSecretStorage.ts +109 -0
- package/src/auth/DemoAuth.ts +188 -0
- package/src/auth/InMemoryKVStore.ts +25 -0
- package/src/auth/KvStoreContext.ts +39 -0
- package/src/auth/PassphraseAuth.ts +113 -0
- package/src/coValues/account.ts +8 -3
- package/src/coValues/coFeed.ts +1 -1
- package/src/coValues/coList.ts +1 -1
- package/src/coValues/coMap.ts +1 -1
- package/src/coValues/group.ts +9 -8
- package/src/coValues/interfaces.ts +14 -5
- package/src/exports.ts +17 -3
- package/src/implementation/ContextManager.ts +178 -0
- package/src/implementation/activeAccountContext.ts +6 -1
- package/src/implementation/createContext.ts +173 -149
- package/src/implementation/schema.ts +3 -3
- package/src/index.ts +3 -0
- package/src/testing.ts +172 -34
- package/src/tests/AuthSecretStorage.test.ts +275 -0
- package/src/tests/ContextManager.test.ts +256 -0
- package/src/tests/DemoAuth.test.ts +269 -0
- package/src/tests/PassphraseAuth.test.ts +152 -0
- package/src/tests/coFeed.test.ts +48 -42
- package/src/tests/coList.test.ts +26 -24
- package/src/tests/coMap.test.ts +25 -23
- package/src/tests/coPlainText.test.ts +25 -23
- package/src/tests/coRichText.test.ts +24 -23
- package/src/tests/createContext.test.ts +339 -0
- package/src/tests/deepLoading.test.ts +44 -45
- package/src/tests/fixtures.ts +2050 -0
- package/src/tests/groupsAndAccounts.test.ts +3 -3
- package/src/tests/schema.test.ts +1 -1
- package/src/tests/schemaUnion.test.ts +2 -2
- package/src/tests/subscribe.test.ts +43 -10
- package/src/tests/testing.test.ts +56 -0
- package/src/tests/utils.ts +13 -13
- package/src/types.ts +54 -0
- package/tsconfig.json +3 -1
- package/tsup.config.ts +1 -2
- package/dist/chunk-OJIEP4WE.js.map +0 -1
- package/dist/index.native.js +0 -75
- package/dist/index.native.js.map +0 -1
- package/dist/index.web.js.map +0 -1
- package/src/index.native.ts +0 -6
- package/src/index.web.ts +0 -3
- package/tsconfig.native.json +0 -5
- package/tsconfig.web.json +0 -5
@@ -9,8 +9,12 @@ var ActiveAccountContext = class {
|
|
9
9
|
this.guestMode = false;
|
10
10
|
}
|
11
11
|
setGuestMode() {
|
12
|
+
this.activeAccount = null;
|
12
13
|
this.guestMode = true;
|
13
14
|
}
|
15
|
+
maybeGet() {
|
16
|
+
return this.activeAccount;
|
17
|
+
}
|
14
18
|
get() {
|
15
19
|
if (!this.activeAccount) {
|
16
20
|
if (this.guestMode) {
|
@@ -414,128 +418,136 @@ import {
|
|
414
418
|
var RegisteredSchemas = {};
|
415
419
|
|
416
420
|
// src/implementation/createContext.ts
|
417
|
-
|
421
|
+
async function randomSessionProvider(accountID, crypto) {
|
418
422
|
return {
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
saveCredentials: async () => {
|
423
|
-
},
|
424
|
-
onSuccess: () => {
|
425
|
-
},
|
426
|
-
onError: () => {
|
427
|
-
},
|
428
|
-
logOut: () => {
|
429
|
-
}
|
430
|
-
})
|
423
|
+
sessionID: crypto.newRandomSessionID(accountID),
|
424
|
+
sessionDone: () => {
|
425
|
+
}
|
431
426
|
};
|
432
|
-
}
|
433
|
-
|
427
|
+
}
|
428
|
+
async function createJazzContextFromExistingCredentials({
|
429
|
+
credentials,
|
430
|
+
peersToLoadFrom,
|
431
|
+
crypto,
|
432
|
+
AccountSchema: PropsAccountSchema,
|
433
|
+
sessionProvider,
|
434
|
+
onLogOut
|
435
|
+
}) {
|
436
|
+
const { sessionID, sessionDone } = await sessionProvider(
|
437
|
+
credentials.accountID,
|
438
|
+
crypto
|
439
|
+
);
|
440
|
+
const CurrentAccountSchema = PropsAccountSchema ?? RegisteredSchemas["Account"];
|
441
|
+
const node = await LocalNode.withLoadedAccount({
|
442
|
+
accountID: credentials.accountID,
|
443
|
+
accountSecret: credentials.secret,
|
444
|
+
sessionID,
|
445
|
+
peersToLoadFrom,
|
446
|
+
crypto
|
447
|
+
});
|
448
|
+
const account = CurrentAccountSchema.fromNode(node);
|
449
|
+
activeAccountContext.set(account);
|
450
|
+
await account.applyMigration();
|
434
451
|
return {
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
})
|
452
|
+
node,
|
453
|
+
account,
|
454
|
+
done: () => {
|
455
|
+
node.gracefulShutdown();
|
456
|
+
sessionDone();
|
457
|
+
},
|
458
|
+
logOut: async () => {
|
459
|
+
node.gracefulShutdown();
|
460
|
+
sessionDone();
|
461
|
+
await onLogOut?.();
|
462
|
+
}
|
447
463
|
};
|
448
|
-
}
|
449
|
-
async function
|
464
|
+
}
|
465
|
+
async function createJazzContextForNewAccount({
|
466
|
+
creationProps,
|
467
|
+
initialAgentSecret,
|
468
|
+
peersToLoadFrom,
|
469
|
+
crypto,
|
470
|
+
AccountSchema: PropsAccountSchema,
|
471
|
+
onLogOut
|
472
|
+
}) {
|
473
|
+
const CurrentAccountSchema = PropsAccountSchema ?? RegisteredSchemas["Account"];
|
474
|
+
const { node } = await LocalNode.withNewlyCreatedAccount({
|
475
|
+
creationProps,
|
476
|
+
peersToLoadFrom,
|
477
|
+
crypto,
|
478
|
+
initialAgentSecret,
|
479
|
+
migration: async (rawAccount, _node, creationProps2) => {
|
480
|
+
const account2 = new CurrentAccountSchema({
|
481
|
+
fromRaw: rawAccount
|
482
|
+
});
|
483
|
+
activeAccountContext.set(account2);
|
484
|
+
await account2.applyMigration(creationProps2);
|
485
|
+
}
|
486
|
+
});
|
487
|
+
const account = CurrentAccountSchema.fromNode(node);
|
488
|
+
activeAccountContext.set(account);
|
450
489
|
return {
|
451
|
-
|
452
|
-
|
490
|
+
node,
|
491
|
+
account,
|
492
|
+
done: () => {
|
493
|
+
node.gracefulShutdown();
|
494
|
+
},
|
495
|
+
logOut: async () => {
|
496
|
+
node.gracefulShutdown();
|
497
|
+
await onLogOut?.();
|
453
498
|
}
|
454
499
|
};
|
455
500
|
}
|
456
501
|
async function createJazzContext(options) {
|
457
|
-
|
458
|
-
|
502
|
+
const crypto = options.crypto;
|
503
|
+
let context;
|
504
|
+
const authSecretStorage = options.authSecretStorage;
|
505
|
+
await authSecretStorage.migrate();
|
506
|
+
const credentials = options.credentials ?? await authSecretStorage.get();
|
507
|
+
if (credentials && !options.newAccountProps) {
|
508
|
+
context = await createJazzContextFromExistingCredentials({
|
509
|
+
credentials: {
|
510
|
+
accountID: credentials.accountID,
|
511
|
+
secret: credentials.accountSecret
|
512
|
+
},
|
459
513
|
peersToLoadFrom: options.peersToLoadFrom,
|
460
|
-
crypto: options.crypto
|
461
|
-
});
|
462
|
-
}
|
463
|
-
const { auth, sessionProvider, peersToLoadFrom, crypto } = options;
|
464
|
-
const AccountSchema = options.AccountSchema ?? RegisteredSchemas["Account"];
|
465
|
-
const authResult = await auth.start(crypto);
|
466
|
-
if (authResult.type === "existing") {
|
467
|
-
const { sessionID, sessionDone } = await sessionProvider(
|
468
|
-
authResult.credentials.accountID,
|
469
|
-
crypto
|
470
|
-
);
|
471
|
-
const node = await LocalNode.withLoadedAccount({
|
472
|
-
accountID: authResult.credentials.accountID,
|
473
|
-
accountSecret: authResult.credentials.secret,
|
474
|
-
sessionID,
|
475
|
-
peersToLoadFrom,
|
476
514
|
crypto,
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
activeAccountContext.set(account2);
|
482
|
-
await account2.applyMigration(creationProps);
|
515
|
+
AccountSchema: options.AccountSchema,
|
516
|
+
sessionProvider: options.sessionProvider,
|
517
|
+
onLogOut: () => {
|
518
|
+
authSecretStorage.clear();
|
483
519
|
}
|
484
520
|
});
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
});
|
492
|
-
}
|
493
|
-
authResult.onSuccess();
|
494
|
-
return {
|
495
|
-
account,
|
496
|
-
done: () => {
|
497
|
-
node.gracefulShutdown();
|
498
|
-
sessionDone();
|
499
|
-
},
|
500
|
-
logOut: () => {
|
501
|
-
node.gracefulShutdown();
|
502
|
-
sessionDone();
|
503
|
-
authResult.logOut();
|
504
|
-
}
|
521
|
+
authSecretStorage.emitUpdate(credentials);
|
522
|
+
} else {
|
523
|
+
const secretSeed = options.crypto.newRandomSecretSeed();
|
524
|
+
const initialAgentSecret = options.newAccountProps?.secret ?? crypto.agentSecretFromSecretSeed(secretSeed);
|
525
|
+
const creationProps = options.newAccountProps?.creationProps ?? {
|
526
|
+
name: options.defaultProfileName ?? "Anonymous user"
|
505
527
|
};
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
peersToLoadFrom,
|
528
|
+
context = await createJazzContextForNewAccount({
|
529
|
+
creationProps,
|
530
|
+
initialAgentSecret,
|
531
|
+
peersToLoadFrom: options.peersToLoadFrom,
|
510
532
|
crypto,
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
fromRaw: rawAccount
|
515
|
-
});
|
516
|
-
activeAccountContext.set(account2);
|
517
|
-
await account2.applyMigration(creationProps);
|
533
|
+
AccountSchema: options.AccountSchema,
|
534
|
+
onLogOut: async () => {
|
535
|
+
await authSecretStorage.clear();
|
518
536
|
}
|
519
537
|
});
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
account,
|
529
|
-
done: () => {
|
530
|
-
node.gracefulShutdown();
|
531
|
-
},
|
532
|
-
logOut: () => {
|
533
|
-
node.gracefulShutdown();
|
534
|
-
authResult.logOut();
|
535
|
-
}
|
536
|
-
};
|
538
|
+
if (!options.newAccountProps) {
|
539
|
+
await authSecretStorage.set({
|
540
|
+
accountID: context.account.id,
|
541
|
+
secretSeed,
|
542
|
+
accountSecret: context.node.account.agentSecret,
|
543
|
+
provider: "anonymous"
|
544
|
+
});
|
545
|
+
}
|
537
546
|
}
|
538
|
-
|
547
|
+
return {
|
548
|
+
...context,
|
549
|
+
authSecretStorage
|
550
|
+
};
|
539
551
|
}
|
540
552
|
async function createAnonymousJazzContext({
|
541
553
|
peersToLoadFrom,
|
@@ -556,7 +568,7 @@ async function createAnonymousJazzContext({
|
|
556
568
|
agent: new AnonymousJazzAgent(node),
|
557
569
|
done: () => {
|
558
570
|
},
|
559
|
-
logOut: () => {
|
571
|
+
logOut: async () => {
|
560
572
|
}
|
561
573
|
};
|
562
574
|
}
|
@@ -723,13 +735,17 @@ function loadCoValue(cls, id, as, depth) {
|
|
723
735
|
);
|
724
736
|
});
|
725
737
|
}
|
726
|
-
function ensureCoValueLoaded(existing, depth) {
|
727
|
-
|
738
|
+
async function ensureCoValueLoaded(existing, depth) {
|
739
|
+
const response = await loadCoValue(
|
728
740
|
existing.constructor,
|
729
741
|
existing.id,
|
730
742
|
existing._loadedAs,
|
731
743
|
depth
|
732
744
|
);
|
745
|
+
if (!response) {
|
746
|
+
throw new Error("Failed to deeply load CoValue " + existing.id);
|
747
|
+
}
|
748
|
+
return response;
|
733
749
|
}
|
734
750
|
function subscribeToCoValueWithoutMe(cls, id, asOrDepth, depthOrListener, listener) {
|
735
751
|
if (isAccountInstance(asOrDepth) || isAnonymousAgentInstance(asOrDepth)) {
|
@@ -806,7 +822,10 @@ function createCoValueObservable(options) {
|
|
806
822
|
currentValue = value;
|
807
823
|
listener();
|
808
824
|
},
|
809
|
-
|
825
|
+
() => {
|
826
|
+
currentValue = null;
|
827
|
+
onUnavailable?.();
|
828
|
+
},
|
810
829
|
options?.syncResolution
|
811
830
|
);
|
812
831
|
return () => {
|
@@ -2699,11 +2718,9 @@ var _Group = class _Group extends CoValueBase {
|
|
2699
2718
|
}
|
2700
2719
|
addMember(member, role) {
|
2701
2720
|
this._raw.addMember(member === "everyone" ? member : member._raw, role);
|
2702
|
-
return this;
|
2703
2721
|
}
|
2704
2722
|
removeMember(member) {
|
2705
|
-
this._raw.removeMember(member === "everyone" ? member : member._raw);
|
2706
|
-
return this;
|
2723
|
+
return this._raw.removeMember(member === "everyone" ? member : member._raw);
|
2707
2724
|
}
|
2708
2725
|
get members() {
|
2709
2726
|
return this._raw.keys().filter((key) => {
|
@@ -2727,8 +2744,8 @@ var _Group = class _Group extends CoValueBase {
|
|
2727
2744
|
};
|
2728
2745
|
});
|
2729
2746
|
}
|
2730
|
-
extend(parent) {
|
2731
|
-
this._raw.extend(parent._raw);
|
2747
|
+
extend(parent, roleMapping) {
|
2748
|
+
this._raw.extend(parent._raw, roleMapping);
|
2732
2749
|
return this;
|
2733
2750
|
}
|
2734
2751
|
static load(id, asOrDepth, depth) {
|
@@ -3378,8 +3395,433 @@ var SchemaUnion = class _SchemaUnion extends CoValueBase {
|
|
3378
3395
|
}
|
3379
3396
|
};
|
3380
3397
|
|
3381
|
-
// src/
|
3398
|
+
// src/auth/KvStoreContext.ts
|
3399
|
+
var KvStoreContext = class _KvStoreContext {
|
3400
|
+
constructor() {
|
3401
|
+
this.storageInstance = null;
|
3402
|
+
}
|
3403
|
+
static getInstance() {
|
3404
|
+
if (!_KvStoreContext.instance) {
|
3405
|
+
_KvStoreContext.instance = new _KvStoreContext();
|
3406
|
+
}
|
3407
|
+
return _KvStoreContext.instance;
|
3408
|
+
}
|
3409
|
+
isInitialized() {
|
3410
|
+
return this.storageInstance !== null;
|
3411
|
+
}
|
3412
|
+
initialize(store) {
|
3413
|
+
if (!this.storageInstance) {
|
3414
|
+
this.storageInstance = store;
|
3415
|
+
}
|
3416
|
+
}
|
3417
|
+
getStorage() {
|
3418
|
+
if (!this.storageInstance) {
|
3419
|
+
throw new Error("Storage instance is not initialized.");
|
3420
|
+
}
|
3421
|
+
return this.storageInstance;
|
3422
|
+
}
|
3423
|
+
};
|
3424
|
+
var KvStoreContext_default = KvStoreContext;
|
3425
|
+
|
3426
|
+
// src/auth/AuthSecretStorage.ts
|
3427
|
+
var STORAGE_KEY = "jazz-logged-in-secret";
|
3428
|
+
var AuthSecretStorage = class {
|
3429
|
+
constructor() {
|
3430
|
+
this.listeners = /* @__PURE__ */ new Set();
|
3431
|
+
this.isAuthenticated = false;
|
3432
|
+
}
|
3433
|
+
async migrate() {
|
3434
|
+
const kvStore = KvStoreContext_default.getInstance().getStorage();
|
3435
|
+
if (!await kvStore.get(STORAGE_KEY)) {
|
3436
|
+
const demoAuthSecret = await kvStore.get("demo-auth-logged-in-secret");
|
3437
|
+
if (demoAuthSecret) {
|
3438
|
+
await kvStore.set(STORAGE_KEY, demoAuthSecret);
|
3439
|
+
await kvStore.delete("demo-auth-logged-in-secret");
|
3440
|
+
}
|
3441
|
+
const clerkAuthSecret = await kvStore.get("jazz-clerk-auth");
|
3442
|
+
if (clerkAuthSecret) {
|
3443
|
+
await kvStore.set(STORAGE_KEY, clerkAuthSecret);
|
3444
|
+
await kvStore.delete("jazz-clerk-auth");
|
3445
|
+
}
|
3446
|
+
}
|
3447
|
+
}
|
3448
|
+
async get() {
|
3449
|
+
const kvStore = KvStoreContext_default.getInstance().getStorage();
|
3450
|
+
const data = await kvStore.get(STORAGE_KEY);
|
3451
|
+
if (!data) return null;
|
3452
|
+
const parsed = JSON.parse(data);
|
3453
|
+
if (!parsed.accountID || !parsed.accountSecret) {
|
3454
|
+
throw new Error("Invalid auth secret storage data");
|
3455
|
+
}
|
3456
|
+
return {
|
3457
|
+
accountID: parsed.accountID,
|
3458
|
+
secretSeed: parsed.secretSeed ? new Uint8Array(parsed.secretSeed) : void 0,
|
3459
|
+
accountSecret: parsed.accountSecret,
|
3460
|
+
provider: parsed.provider
|
3461
|
+
};
|
3462
|
+
}
|
3463
|
+
async set(payload) {
|
3464
|
+
const kvStore = KvStoreContext_default.getInstance().getStorage();
|
3465
|
+
await kvStore.set(
|
3466
|
+
STORAGE_KEY,
|
3467
|
+
JSON.stringify({
|
3468
|
+
accountID: payload.accountID,
|
3469
|
+
secretSeed: payload.secretSeed ? Array.from(payload.secretSeed) : void 0,
|
3470
|
+
accountSecret: payload.accountSecret,
|
3471
|
+
provider: payload.provider
|
3472
|
+
})
|
3473
|
+
);
|
3474
|
+
this.emitUpdate(payload);
|
3475
|
+
}
|
3476
|
+
getIsAuthenticated(data) {
|
3477
|
+
if (!data) return false;
|
3478
|
+
return data.provider !== "anonymous";
|
3479
|
+
}
|
3480
|
+
onUpdate(handler) {
|
3481
|
+
this.listeners.add(handler);
|
3482
|
+
return () => {
|
3483
|
+
this.listeners.delete(handler);
|
3484
|
+
};
|
3485
|
+
}
|
3486
|
+
emitUpdate(data) {
|
3487
|
+
const isAuthenticated = this.getIsAuthenticated(data);
|
3488
|
+
if (this.isAuthenticated === isAuthenticated) return;
|
3489
|
+
this.isAuthenticated = isAuthenticated;
|
3490
|
+
for (const listener of this.listeners) {
|
3491
|
+
listener(this.isAuthenticated);
|
3492
|
+
}
|
3493
|
+
}
|
3494
|
+
async clear() {
|
3495
|
+
const kvStore = KvStoreContext_default.getInstance().getStorage();
|
3496
|
+
await kvStore.delete(STORAGE_KEY);
|
3497
|
+
this.emitUpdate(null);
|
3498
|
+
}
|
3499
|
+
};
|
3500
|
+
|
3501
|
+
// src/auth/InMemoryKVStore.ts
|
3502
|
+
var InMemoryKVStore = class {
|
3503
|
+
constructor() {
|
3504
|
+
this.store = {};
|
3505
|
+
}
|
3506
|
+
async get(key) {
|
3507
|
+
const data = this.store[key];
|
3508
|
+
if (!data) return null;
|
3509
|
+
return data;
|
3510
|
+
}
|
3511
|
+
async set(key, value) {
|
3512
|
+
this.store[key] = value;
|
3513
|
+
}
|
3514
|
+
async delete(key) {
|
3515
|
+
delete this.store[key];
|
3516
|
+
}
|
3517
|
+
async clearAll() {
|
3518
|
+
this.store = {};
|
3519
|
+
}
|
3520
|
+
};
|
3521
|
+
|
3522
|
+
// src/implementation/ContextManager.ts
|
3382
3523
|
import { cojsonInternals as cojsonInternals4 } from "cojson";
|
3524
|
+
var JazzContextManager = class {
|
3525
|
+
constructor() {
|
3526
|
+
this.authSecretStorage = new AuthSecretStorage();
|
3527
|
+
this.authenticating = false;
|
3528
|
+
this.logOut = async () => {
|
3529
|
+
if (!this.context || !this.props) {
|
3530
|
+
return;
|
3531
|
+
}
|
3532
|
+
await this.context.logOut();
|
3533
|
+
this.props.onLogOut?.();
|
3534
|
+
return this.createContext(this.props);
|
3535
|
+
};
|
3536
|
+
this.done = () => {
|
3537
|
+
if (!this.context) {
|
3538
|
+
return;
|
3539
|
+
}
|
3540
|
+
this.context.done();
|
3541
|
+
};
|
3542
|
+
this.authenticate = async (credentials) => {
|
3543
|
+
if (!this.props) {
|
3544
|
+
throw new Error("Props required");
|
3545
|
+
}
|
3546
|
+
const prevContext = this.context;
|
3547
|
+
const prevCredentials = await this.authSecretStorage.get();
|
3548
|
+
const wasAnonymous = this.authSecretStorage.getIsAuthenticated(prevCredentials) === false;
|
3549
|
+
this.authenticating = true;
|
3550
|
+
await this.createContext(this.props, { credentials }).finally(() => {
|
3551
|
+
this.authenticating = false;
|
3552
|
+
});
|
3553
|
+
const currentContext = this.context;
|
3554
|
+
if (prevContext && currentContext && "me" in prevContext && "me" in currentContext && wasAnonymous) {
|
3555
|
+
const [prevAccountAsPeer, currentAccountAsPeer] = cojsonInternals4.connectedPeers(
|
3556
|
+
prevContext.me.id,
|
3557
|
+
currentContext.me.id,
|
3558
|
+
{
|
3559
|
+
peer1role: "client",
|
3560
|
+
peer2role: "server"
|
3561
|
+
}
|
3562
|
+
);
|
3563
|
+
prevContext.node.syncManager.addPeer(currentAccountAsPeer);
|
3564
|
+
currentContext.node.syncManager.addPeer(prevAccountAsPeer);
|
3565
|
+
try {
|
3566
|
+
await this.props.onAnonymousAccountDiscarded?.(prevContext.me);
|
3567
|
+
await prevContext.me.waitForAllCoValuesSync();
|
3568
|
+
} catch (error) {
|
3569
|
+
console.error("Error onAnonymousAccountDiscarded", error);
|
3570
|
+
}
|
3571
|
+
prevAccountAsPeer.outgoing.close();
|
3572
|
+
currentAccountAsPeer.outgoing.close();
|
3573
|
+
}
|
3574
|
+
prevContext?.done();
|
3575
|
+
};
|
3576
|
+
this.listeners = /* @__PURE__ */ new Set();
|
3577
|
+
this.subscribe = (callback) => {
|
3578
|
+
this.listeners.add(callback);
|
3579
|
+
return () => {
|
3580
|
+
this.listeners.delete(callback);
|
3581
|
+
};
|
3582
|
+
};
|
3583
|
+
KvStoreContext.getInstance().initialize(this.getKvStore());
|
3584
|
+
}
|
3585
|
+
getKvStore() {
|
3586
|
+
return new InMemoryKVStore();
|
3587
|
+
}
|
3588
|
+
async createContext(props, authProps) {
|
3589
|
+
props;
|
3590
|
+
authProps;
|
3591
|
+
throw new Error("Not implemented");
|
3592
|
+
}
|
3593
|
+
updateContext(props, context) {
|
3594
|
+
if (!this.authenticating) {
|
3595
|
+
this.context?.done();
|
3596
|
+
}
|
3597
|
+
this.context = context;
|
3598
|
+
this.props = props;
|
3599
|
+
this.value = {
|
3600
|
+
...context,
|
3601
|
+
node: context.node,
|
3602
|
+
authenticate: this.authenticate,
|
3603
|
+
logOut: this.logOut
|
3604
|
+
};
|
3605
|
+
this.notify();
|
3606
|
+
}
|
3607
|
+
propsChanged(props) {
|
3608
|
+
props;
|
3609
|
+
throw new Error("Not implemented");
|
3610
|
+
}
|
3611
|
+
getCurrentValue() {
|
3612
|
+
return this.value;
|
3613
|
+
}
|
3614
|
+
getAuthSecretStorage() {
|
3615
|
+
return this.authSecretStorage;
|
3616
|
+
}
|
3617
|
+
notify() {
|
3618
|
+
for (const listener of this.listeners) {
|
3619
|
+
listener();
|
3620
|
+
}
|
3621
|
+
}
|
3622
|
+
};
|
3623
|
+
|
3624
|
+
// src/auth/DemoAuth.ts
|
3625
|
+
var DemoAuth = class {
|
3626
|
+
constructor(authenticate, authSecretStorage) {
|
3627
|
+
this.authenticate = authenticate;
|
3628
|
+
this.authSecretStorage = authSecretStorage;
|
3629
|
+
this.logIn = async (username) => {
|
3630
|
+
const existingUsers = await this.getExisitingUsersWithData();
|
3631
|
+
const storageData = existingUsers[username];
|
3632
|
+
if (!storageData?.accountID) {
|
3633
|
+
throw new Error("User not found");
|
3634
|
+
}
|
3635
|
+
await this.authenticate({
|
3636
|
+
accountID: storageData.accountID,
|
3637
|
+
accountSecret: storageData.accountSecret
|
3638
|
+
});
|
3639
|
+
await this.authSecretStorage.set({
|
3640
|
+
accountID: storageData.accountID,
|
3641
|
+
accountSecret: storageData.accountSecret,
|
3642
|
+
secretSeed: storageData.secretSeed ? new Uint8Array(storageData.secretSeed) : void 0,
|
3643
|
+
provider: "demo"
|
3644
|
+
});
|
3645
|
+
};
|
3646
|
+
this.signUp = async (username) => {
|
3647
|
+
const existingUsers = await this.getExistingUsers();
|
3648
|
+
if (existingUsers.includes(username)) {
|
3649
|
+
throw new Error("User already registered");
|
3650
|
+
}
|
3651
|
+
const credentials = await this.authSecretStorage.get();
|
3652
|
+
if (!credentials) {
|
3653
|
+
throw new Error("No credentials found");
|
3654
|
+
}
|
3655
|
+
const currentAccount = await Account.getMe().ensureLoaded({
|
3656
|
+
profile: {}
|
3657
|
+
});
|
3658
|
+
currentAccount.profile.name = username;
|
3659
|
+
await this.authSecretStorage.set({
|
3660
|
+
accountID: credentials.accountID,
|
3661
|
+
accountSecret: credentials.accountSecret,
|
3662
|
+
secretSeed: credentials.secretSeed ? new Uint8Array(credentials.secretSeed) : void 0,
|
3663
|
+
provider: "demo"
|
3664
|
+
});
|
3665
|
+
await this.addToExistingUsers(username, {
|
3666
|
+
accountID: credentials.accountID,
|
3667
|
+
accountSecret: credentials.accountSecret,
|
3668
|
+
secretSeed: credentials.secretSeed ? Array.from(credentials.secretSeed) : void 0
|
3669
|
+
});
|
3670
|
+
};
|
3671
|
+
this.getExistingUsers = async () => {
|
3672
|
+
return Object.keys(await this.getExisitingUsersWithData());
|
3673
|
+
};
|
3674
|
+
}
|
3675
|
+
async addToExistingUsers(username, data) {
|
3676
|
+
const existingUsers = await this.getExisitingUsersWithData();
|
3677
|
+
if (existingUsers[username]) {
|
3678
|
+
return;
|
3679
|
+
}
|
3680
|
+
existingUsers[username] = data;
|
3681
|
+
const kvStore = KvStoreContext.getInstance().getStorage();
|
3682
|
+
await kvStore.set("demo-auth-users", JSON.stringify(existingUsers));
|
3683
|
+
}
|
3684
|
+
async getExisitingUsersWithData() {
|
3685
|
+
const kvStore = KvStoreContext.getInstance().getStorage();
|
3686
|
+
await migrateExistingUsers(kvStore);
|
3687
|
+
const existingUsers = await kvStore.get("demo-auth-users");
|
3688
|
+
return existingUsers ? JSON.parse(existingUsers) : {};
|
3689
|
+
}
|
3690
|
+
};
|
3691
|
+
function encodeUsername(username) {
|
3692
|
+
return btoa(username).replace(/=/g, "-").replace(/\+/g, "_").replace(/\//g, ".");
|
3693
|
+
}
|
3694
|
+
async function getStorageVersion(kvStore) {
|
3695
|
+
try {
|
3696
|
+
const version = await kvStore.get("demo-auth-storage-version");
|
3697
|
+
return version ? parseInt(version) : 1;
|
3698
|
+
} catch (error) {
|
3699
|
+
return 1;
|
3700
|
+
}
|
3701
|
+
}
|
3702
|
+
async function setStorageVersion(kvStore, version) {
|
3703
|
+
await kvStore.set("demo-auth-storage-version", version.toString());
|
3704
|
+
}
|
3705
|
+
async function getExistingUsersList(kvStore) {
|
3706
|
+
const existingUsers = await kvStore.get("demo-auth-existing-users");
|
3707
|
+
return existingUsers ? existingUsers.split(",") : [];
|
3708
|
+
}
|
3709
|
+
async function migrateExistingUsers(kvStore) {
|
3710
|
+
if (await getStorageVersion(kvStore) < 2) {
|
3711
|
+
const existingUsers = await getExistingUsersList(kvStore);
|
3712
|
+
for (const username of existingUsers) {
|
3713
|
+
const legacyKey = `demo-auth-existing-users-${username}`;
|
3714
|
+
const storageData = await kvStore.get(legacyKey);
|
3715
|
+
if (storageData) {
|
3716
|
+
await kvStore.set(
|
3717
|
+
`demo-auth-existing-users-${encodeUsername(username)}`,
|
3718
|
+
storageData
|
3719
|
+
);
|
3720
|
+
await kvStore.delete(legacyKey);
|
3721
|
+
}
|
3722
|
+
}
|
3723
|
+
await setStorageVersion(kvStore, 2);
|
3724
|
+
}
|
3725
|
+
if (await getStorageVersion(kvStore) < 3) {
|
3726
|
+
const existingUsersList = await getExistingUsersList(kvStore);
|
3727
|
+
const existingUsers = {};
|
3728
|
+
const keysToDelete = ["demo-auth-existing-users"];
|
3729
|
+
for (const username of existingUsersList) {
|
3730
|
+
const key = `demo-auth-existing-users-${encodeUsername(username)}`;
|
3731
|
+
const storageData = await kvStore.get(key);
|
3732
|
+
if (storageData) {
|
3733
|
+
existingUsers[username] = JSON.parse(storageData);
|
3734
|
+
keysToDelete.push(key);
|
3735
|
+
}
|
3736
|
+
}
|
3737
|
+
await kvStore.set("demo-auth-users", JSON.stringify(existingUsers));
|
3738
|
+
for (const key of keysToDelete) {
|
3739
|
+
await kvStore.delete(key);
|
3740
|
+
}
|
3741
|
+
await setStorageVersion(kvStore, 3);
|
3742
|
+
}
|
3743
|
+
}
|
3744
|
+
|
3745
|
+
// src/auth/PassphraseAuth.ts
|
3746
|
+
import * as bip39 from "@scure/bip39";
|
3747
|
+
import { entropyToMnemonic } from "@scure/bip39";
|
3748
|
+
import { cojsonInternals as cojsonInternals5 } from "cojson";
|
3749
|
+
var PassphraseAuth = class {
|
3750
|
+
constructor(crypto, authenticate, authSecretStorage, wordlist) {
|
3751
|
+
this.crypto = crypto;
|
3752
|
+
this.authenticate = authenticate;
|
3753
|
+
this.authSecretStorage = authSecretStorage;
|
3754
|
+
this.wordlist = wordlist;
|
3755
|
+
this.passphrase = "";
|
3756
|
+
this.logIn = async (passphrase) => {
|
3757
|
+
const { crypto, authenticate } = this;
|
3758
|
+
let secretSeed;
|
3759
|
+
try {
|
3760
|
+
secretSeed = bip39.mnemonicToEntropy(passphrase, this.wordlist);
|
3761
|
+
} catch (e) {
|
3762
|
+
throw new Error("Invalid passphrase");
|
3763
|
+
}
|
3764
|
+
const accountSecret = crypto.agentSecretFromSecretSeed(secretSeed);
|
3765
|
+
const accountID = cojsonInternals5.idforHeader(
|
3766
|
+
cojsonInternals5.accountHeaderForInitialAgentSecret(accountSecret, crypto),
|
3767
|
+
crypto
|
3768
|
+
);
|
3769
|
+
await authenticate({
|
3770
|
+
accountID,
|
3771
|
+
accountSecret
|
3772
|
+
});
|
3773
|
+
await this.authSecretStorage.set({
|
3774
|
+
accountID,
|
3775
|
+
secretSeed,
|
3776
|
+
accountSecret,
|
3777
|
+
provider: "passphrase"
|
3778
|
+
});
|
3779
|
+
this.passphrase = passphrase;
|
3780
|
+
this.notify();
|
3781
|
+
};
|
3782
|
+
this.signUp = async () => {
|
3783
|
+
const credentials = await this.authSecretStorage.get();
|
3784
|
+
if (!credentials || !credentials.secretSeed) {
|
3785
|
+
throw new Error("No credentials found");
|
3786
|
+
}
|
3787
|
+
const passphrase = entropyToMnemonic(credentials.secretSeed, this.wordlist);
|
3788
|
+
await this.authSecretStorage.set({
|
3789
|
+
accountID: credentials.accountID,
|
3790
|
+
secretSeed: credentials.secretSeed,
|
3791
|
+
accountSecret: credentials.accountSecret,
|
3792
|
+
provider: "passphrase"
|
3793
|
+
});
|
3794
|
+
return passphrase;
|
3795
|
+
};
|
3796
|
+
this.getCurrentAccountPassphrase = async () => {
|
3797
|
+
const credentials = await this.authSecretStorage.get();
|
3798
|
+
if (!credentials || !credentials.secretSeed) {
|
3799
|
+
throw new Error("No credentials found");
|
3800
|
+
}
|
3801
|
+
return entropyToMnemonic(credentials.secretSeed, this.wordlist);
|
3802
|
+
};
|
3803
|
+
this.loadCurrentAccountPassphrase = async () => {
|
3804
|
+
const passphrase = await this.getCurrentAccountPassphrase();
|
3805
|
+
this.passphrase = passphrase;
|
3806
|
+
this.notify();
|
3807
|
+
};
|
3808
|
+
this.listeners = /* @__PURE__ */ new Set();
|
3809
|
+
this.subscribe = (callback) => {
|
3810
|
+
this.listeners.add(callback);
|
3811
|
+
return () => {
|
3812
|
+
this.listeners.delete(callback);
|
3813
|
+
};
|
3814
|
+
};
|
3815
|
+
}
|
3816
|
+
notify() {
|
3817
|
+
for (const listener of this.listeners) {
|
3818
|
+
listener();
|
3819
|
+
}
|
3820
|
+
}
|
3821
|
+
};
|
3822
|
+
|
3823
|
+
// src/implementation/invites.ts
|
3824
|
+
import { cojsonInternals as cojsonInternals6 } from "cojson";
|
3383
3825
|
function createInviteLink(value, role, baseURL, valueHint) {
|
3384
3826
|
const coValueCore = value._raw.core;
|
3385
3827
|
let currentCoValue = coValueCore;
|
@@ -3390,7 +3832,7 @@ function createInviteLink(value, role, baseURL, valueHint) {
|
|
3390
3832
|
if (ruleset.type !== "group" || meta?.type === "account") {
|
3391
3833
|
throw new Error("Can't create invite link for object without group");
|
3392
3834
|
}
|
3393
|
-
const group =
|
3835
|
+
const group = cojsonInternals6.expectGroup(currentCoValue.getCurrentContent());
|
3394
3836
|
const inviteSecret = group.createInvite(role);
|
3395
3837
|
return `${baseURL}#/invite/${valueHint ? valueHint + "/" : ""}${value.id}/${inviteSecret}`;
|
3396
3838
|
}
|
@@ -3442,9 +3884,9 @@ export {
|
|
3442
3884
|
createCoValueObservable,
|
3443
3885
|
Encoders,
|
3444
3886
|
co,
|
3445
|
-
fixedCredentialsAuth,
|
3446
|
-
ephemeralCredentialsAuth,
|
3447
3887
|
randomSessionProvider,
|
3888
|
+
createJazzContextFromExistingCredentials,
|
3889
|
+
createJazzContextForNewAccount,
|
3448
3890
|
createJazzContext,
|
3449
3891
|
createAnonymousJazzContext,
|
3450
3892
|
Inbox,
|
@@ -3462,9 +3904,15 @@ export {
|
|
3462
3904
|
Marks,
|
3463
3905
|
ImageDefinition,
|
3464
3906
|
SchemaUnion,
|
3907
|
+
KvStoreContext,
|
3908
|
+
AuthSecretStorage,
|
3909
|
+
InMemoryKVStore,
|
3910
|
+
JazzContextManager,
|
3911
|
+
DemoAuth,
|
3912
|
+
PassphraseAuth,
|
3465
3913
|
createInviteLink,
|
3466
3914
|
parseInviteLink,
|
3467
3915
|
consumeInviteLink
|
3468
3916
|
};
|
3469
3917
|
/* istanbul ignore file -- @preserve */
|
3470
|
-
//# sourceMappingURL=chunk-
|
3918
|
+
//# sourceMappingURL=chunk-24EJ3CKA.js.map
|