jazz-tools 0.9.1 → 0.9.9
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 -10
- package/CHANGELOG.md +14 -0
- package/dist/{chunk-7LENDMTN.js → chunk-VQZOWIPU.js} +915 -376
- package/dist/chunk-VQZOWIPU.js.map +1 -0
- package/dist/index.native.js +7 -1
- package/dist/index.native.js.map +1 -1
- package/dist/index.web.js +7 -1
- package/dist/index.web.js.map +1 -1
- package/dist/testing.js +10 -2
- package/dist/testing.js.map +1 -1
- package/package.json +2 -2
- package/src/coValues/account.ts +41 -3
- package/src/coValues/coFeed.ts +112 -20
- package/src/coValues/coList.ts +47 -15
- package/src/coValues/coMap.ts +51 -16
- package/src/coValues/coPlainText.ts +247 -0
- package/src/coValues/coRichText.ts +635 -0
- package/src/coValues/deepLoading.ts +11 -2
- package/src/coValues/group.ts +49 -17
- package/src/coValues/inbox.ts +7 -2
- package/src/coValues/interfaces.ts +112 -9
- package/src/exports.ts +13 -8
- package/src/implementation/activeAccountContext.ts +33 -0
- package/src/implementation/createContext.ts +8 -0
- package/src/internal.ts +4 -4
- package/src/testing.ts +9 -0
- package/src/tests/account.test.ts +1 -0
- package/src/tests/coFeed.test.ts +13 -0
- package/src/tests/coPlainText.test.ts +161 -0
- package/src/tests/coRichText.test.ts +934 -0
- package/src/tests/interfaces.test.ts +90 -0
- package/dist/chunk-7LENDMTN.js.map +0 -1
@@ -1,3 +1,30 @@
|
|
1
|
+
// src/implementation/activeAccountContext.ts
|
2
|
+
var ActiveAccountContext = class {
|
3
|
+
constructor() {
|
4
|
+
this.activeAccount = null;
|
5
|
+
this.guestMode = false;
|
6
|
+
}
|
7
|
+
set(account) {
|
8
|
+
this.activeAccount = account;
|
9
|
+
this.guestMode = false;
|
10
|
+
}
|
11
|
+
setGuestMode() {
|
12
|
+
this.guestMode = true;
|
13
|
+
}
|
14
|
+
get() {
|
15
|
+
if (!this.activeAccount) {
|
16
|
+
if (this.guestMode) {
|
17
|
+
throw new Error(
|
18
|
+
"Something that expects a full active account was called in guest mode."
|
19
|
+
);
|
20
|
+
}
|
21
|
+
throw new Error("No active account");
|
22
|
+
}
|
23
|
+
return this.activeAccount;
|
24
|
+
}
|
25
|
+
};
|
26
|
+
var activeAccountContext = new ActiveAccountContext();
|
27
|
+
|
1
28
|
// src/implementation/anonymousJazzAgent.ts
|
2
29
|
var AnonymousJazzAgent = class {
|
3
30
|
constructor(node) {
|
@@ -9,13 +36,61 @@ var AnonymousJazzAgent = class {
|
|
9
36
|
// src/coValues/interfaces.ts
|
10
37
|
import { RawAccount as RawAccount2 } from "cojson";
|
11
38
|
|
39
|
+
// src/implementation/inspect.ts
|
40
|
+
var inspect = Symbol.for("nodejs.util.inspect.custom");
|
41
|
+
|
12
42
|
// src/implementation/symbols.ts
|
13
43
|
var SchemaInit = Symbol.for("SchemaInit");
|
14
44
|
var ItemsSym = Symbol.for("items");
|
15
45
|
var MembersSym = Symbol.for("members");
|
16
46
|
|
17
|
-
// src/
|
18
|
-
|
47
|
+
// src/coValues/deepLoading.ts
|
48
|
+
function fulfillsDepth(depth, value) {
|
49
|
+
if (value._type === "CoMap" || value._type === "Group" || value._type === "Account") {
|
50
|
+
if (Array.isArray(depth) && depth.length === 1) {
|
51
|
+
return Object.entries(value).every(([key, item]) => {
|
52
|
+
return value._refs[key] ? item && fulfillsDepth(depth[0], item) : value._schema[ItemsSym].optional;
|
53
|
+
});
|
54
|
+
} else {
|
55
|
+
for (const key of Object.keys(depth)) {
|
56
|
+
const map = value;
|
57
|
+
if (!map._refs[key] && map._schema[key].optional) {
|
58
|
+
continue;
|
59
|
+
}
|
60
|
+
if (!map[key]) {
|
61
|
+
return false;
|
62
|
+
}
|
63
|
+
if (!fulfillsDepth(depth[key], map[key])) {
|
64
|
+
return false;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
return true;
|
68
|
+
}
|
69
|
+
} else if (value._type === "CoList") {
|
70
|
+
if (depth.length === 0) {
|
71
|
+
return true;
|
72
|
+
} else {
|
73
|
+
const itemDepth = depth[0];
|
74
|
+
return value.every(
|
75
|
+
(item, i) => value._refs[i] ? item && fulfillsDepth(itemDepth, item) : value._schema[ItemsSym].optional
|
76
|
+
);
|
77
|
+
}
|
78
|
+
} else if (value._type === "CoStream") {
|
79
|
+
if (depth.length === 0) {
|
80
|
+
return true;
|
81
|
+
} else {
|
82
|
+
const itemDepth = depth[0];
|
83
|
+
return Object.values(value.perSession).every(
|
84
|
+
(entry) => entry.ref ? entry.value && fulfillsDepth(itemDepth, entry.value) : value._schema[ItemsSym].optional
|
85
|
+
);
|
86
|
+
}
|
87
|
+
} else if (value._type === "BinaryCoStream" || value._type === "CoPlainText") {
|
88
|
+
return true;
|
89
|
+
} else {
|
90
|
+
console.error(value);
|
91
|
+
throw new Error("Unexpected value type: " + value._type);
|
92
|
+
}
|
93
|
+
}
|
19
94
|
|
20
95
|
// src/lib/cache.ts
|
21
96
|
var weakMap = /* @__PURE__ */ new WeakMap();
|
@@ -329,54 +404,6 @@ var SubscriptionScope = class {
|
|
329
404
|
}
|
330
405
|
};
|
331
406
|
|
332
|
-
// src/coValues/deepLoading.ts
|
333
|
-
function fulfillsDepth(depth, value) {
|
334
|
-
if (value._type === "CoMap" || value._type === "Group" || value._type === "Account") {
|
335
|
-
if (Array.isArray(depth) && depth.length === 1) {
|
336
|
-
return Object.entries(value).every(([key, item]) => {
|
337
|
-
return value._refs[key] ? item && fulfillsDepth(depth[0], item) : value._schema[ItemsSym].optional;
|
338
|
-
});
|
339
|
-
} else {
|
340
|
-
for (const key of Object.keys(depth)) {
|
341
|
-
const map = value;
|
342
|
-
if (!map._refs[key] && map._schema[key].optional) {
|
343
|
-
continue;
|
344
|
-
}
|
345
|
-
if (!map[key]) {
|
346
|
-
return false;
|
347
|
-
}
|
348
|
-
if (!fulfillsDepth(depth[key], map[key])) {
|
349
|
-
return false;
|
350
|
-
}
|
351
|
-
}
|
352
|
-
return true;
|
353
|
-
}
|
354
|
-
} else if (value._type === "CoList") {
|
355
|
-
if (depth.length === 0) {
|
356
|
-
return true;
|
357
|
-
} else {
|
358
|
-
const itemDepth = depth[0];
|
359
|
-
return value.every(
|
360
|
-
(item, i) => value._refs[i] ? item && fulfillsDepth(itemDepth, item) : value._schema[ItemsSym].optional
|
361
|
-
);
|
362
|
-
}
|
363
|
-
} else if (value._type === "CoStream") {
|
364
|
-
if (depth.length === 0) {
|
365
|
-
return true;
|
366
|
-
} else {
|
367
|
-
const itemDepth = depth[0];
|
368
|
-
return Object.values(value.perSession).every(
|
369
|
-
(entry) => entry.ref ? entry.value && fulfillsDepth(itemDepth, entry.value) : value._schema[ItemsSym].optional
|
370
|
-
);
|
371
|
-
}
|
372
|
-
} else if (value._type === "BinaryCoStream") {
|
373
|
-
return true;
|
374
|
-
} else {
|
375
|
-
console.error(value);
|
376
|
-
throw new Error("Unexpected value type: " + value._type);
|
377
|
-
}
|
378
|
-
}
|
379
|
-
|
380
407
|
// src/implementation/createContext.ts
|
381
408
|
import {
|
382
409
|
ControlledAgent,
|
@@ -460,10 +487,12 @@ async function createJazzContext(options) {
|
|
460
487
|
const account2 = new AccountSchema({
|
461
488
|
fromRaw: rawAccount
|
462
489
|
});
|
490
|
+
activeAccountContext.set(account2);
|
463
491
|
await account2.applyMigration(creationProps);
|
464
492
|
}
|
465
493
|
});
|
466
494
|
const account = AccountSchema.fromNode(node);
|
495
|
+
activeAccountContext.set(account);
|
467
496
|
if (authResult.saveCredentials) {
|
468
497
|
await authResult.saveCredentials({
|
469
498
|
accountID: node.account.id,
|
@@ -503,10 +532,12 @@ async function createJazzContext(options) {
|
|
503
532
|
const account2 = new AccountSchema({
|
504
533
|
fromRaw: rawAccount
|
505
534
|
});
|
535
|
+
activeAccountContext.set(account2);
|
506
536
|
await account2.applyMigration(creationProps);
|
507
537
|
}
|
508
538
|
});
|
509
539
|
const account = AccountSchema.fromNode(node);
|
540
|
+
activeAccountContext.set(account);
|
510
541
|
await authResult.saveCredentials({
|
511
542
|
accountID: node.account.id,
|
512
543
|
secret: node.account.agentSecret
|
@@ -542,6 +573,7 @@ async function createAnonymousJazzContext({
|
|
542
573
|
for (const peer of peersToLoadFrom) {
|
543
574
|
node.syncManager.addPeer(peer);
|
544
575
|
}
|
576
|
+
activeAccountContext.setGuestMode();
|
545
577
|
return {
|
546
578
|
agent: new AnonymousJazzAgent(node),
|
547
579
|
done: () => {
|
@@ -685,6 +717,17 @@ var CoValueBase = class {
|
|
685
717
|
return casted;
|
686
718
|
}
|
687
719
|
};
|
720
|
+
function loadCoValueWithoutMe(cls, id, asOrDepth, depth) {
|
721
|
+
if (isAccountInstance(asOrDepth) || isAnonymousAgentInstance(asOrDepth)) {
|
722
|
+
if (!depth) {
|
723
|
+
throw new Error(
|
724
|
+
"Depth is required when loading a CoValue as an Account or AnonymousJazzAgent"
|
725
|
+
);
|
726
|
+
}
|
727
|
+
return loadCoValue(cls, id, asOrDepth, depth);
|
728
|
+
}
|
729
|
+
return loadCoValue(cls, id, activeAccountContext.get(), asOrDepth);
|
730
|
+
}
|
688
731
|
function loadCoValue(cls, id, as, depth) {
|
689
732
|
return new Promise((resolve) => {
|
690
733
|
subscribeToCoValue(
|
@@ -710,6 +753,30 @@ function ensureCoValueLoaded(existing, depth) {
|
|
710
753
|
depth
|
711
754
|
);
|
712
755
|
}
|
756
|
+
function subscribeToCoValueWithoutMe(cls, id, asOrDepth, depthOrListener, listener) {
|
757
|
+
if (isAccountInstance(asOrDepth) || isAnonymousAgentInstance(asOrDepth)) {
|
758
|
+
if (typeof depthOrListener !== "function") {
|
759
|
+
return subscribeToCoValue(
|
760
|
+
cls,
|
761
|
+
id,
|
762
|
+
asOrDepth,
|
763
|
+
depthOrListener,
|
764
|
+
listener
|
765
|
+
);
|
766
|
+
}
|
767
|
+
throw new Error("Invalid arguments");
|
768
|
+
}
|
769
|
+
if (typeof depthOrListener !== "function") {
|
770
|
+
throw new Error("Invalid arguments");
|
771
|
+
}
|
772
|
+
return subscribeToCoValue(
|
773
|
+
cls,
|
774
|
+
id,
|
775
|
+
activeAccountContext.get(),
|
776
|
+
asOrDepth,
|
777
|
+
depthOrListener
|
778
|
+
);
|
779
|
+
}
|
713
780
|
function subscribeToCoValue(cls, id, as, depth, listener, onUnavailable, syncResolution) {
|
714
781
|
const ref2 = new Ref(id, as, { ref: cls, optional: false });
|
715
782
|
let unsubscribed = false;
|
@@ -787,12 +854,40 @@ function subscribeToExistingCoValue(existing, depth, listener) {
|
|
787
854
|
listener
|
788
855
|
);
|
789
856
|
}
|
857
|
+
function isAccountInstance(instance) {
|
858
|
+
if (typeof instance !== "object" || instance === null) {
|
859
|
+
return false;
|
860
|
+
}
|
861
|
+
return "_type" in instance && instance._type === "Account";
|
862
|
+
}
|
863
|
+
function isAnonymousAgentInstance(instance) {
|
864
|
+
if (typeof instance !== "object" || instance === null) {
|
865
|
+
return false;
|
866
|
+
}
|
867
|
+
return "_type" in instance && instance._type === "Anonymous";
|
868
|
+
}
|
790
869
|
function parseCoValueCreateOptions(options) {
|
791
|
-
|
792
|
-
|
793
|
-
|
870
|
+
const Group2 = RegisteredSchemas["Group"];
|
871
|
+
if (!options) {
|
872
|
+
return { owner: Group2.create(), uniqueness: void 0 };
|
873
|
+
}
|
874
|
+
if ("_type" in options) {
|
875
|
+
if (options._type === "Account" || options._type === "Group") {
|
876
|
+
return { owner: options, uniqueness: void 0 };
|
877
|
+
}
|
878
|
+
}
|
879
|
+
const uniqueness = options.unique ? { uniqueness: options.unique } : void 0;
|
880
|
+
return {
|
881
|
+
owner: options.owner ?? Group2.create(),
|
882
|
+
uniqueness
|
794
883
|
};
|
795
884
|
}
|
885
|
+
function parseGroupCreateOptions(options) {
|
886
|
+
if (!options) {
|
887
|
+
return { owner: activeAccountContext.get() };
|
888
|
+
}
|
889
|
+
return "_type" in options && isAccountInstance(options) ? { owner: options } : { owner: options.owner ?? activeAccountContext.get() };
|
890
|
+
}
|
796
891
|
|
797
892
|
// src/coValues/inbox.ts
|
798
893
|
import {
|
@@ -978,6 +1073,7 @@ var InboxSender = class _InboxSender {
|
|
978
1073
|
});
|
979
1074
|
}
|
980
1075
|
static async load(inboxOwnerID, currentAccount) {
|
1076
|
+
currentAccount ||= activeAccountContext.get();
|
981
1077
|
const node = currentAccount._raw.core.node;
|
982
1078
|
const inboxOwnerRaw = await node.load(
|
983
1079
|
inboxOwnerID
|
@@ -1002,6 +1098,7 @@ var InboxSender = class _InboxSender {
|
|
1002
1098
|
}
|
1003
1099
|
};
|
1004
1100
|
async function acceptInvite(invite, account) {
|
1101
|
+
account ||= activeAccountContext.get();
|
1005
1102
|
const id = invite.slice(0, invite.indexOf("/"));
|
1006
1103
|
const inviteSecret = invite.slice(invite.indexOf("/") + 1);
|
1007
1104
|
if (!id?.startsWith("co_z") || !inviteSecret.startsWith("inviteSecret_")) {
|
@@ -1252,62 +1349,20 @@ var _CoMap = class _CoMap extends CoValueBase {
|
|
1252
1349
|
}
|
1253
1350
|
return RecordLikeCoMap;
|
1254
1351
|
}
|
1255
|
-
|
1256
|
-
|
1257
|
-
*
|
1258
|
-
* `depth` specifies which (if any) fields that reference other CoValues to load as well before resolving.
|
1259
|
-
* The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
|
1260
|
-
*
|
1261
|
-
* You can pass `[]` or `{}` for shallowly loading only this CoMap, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues.
|
1262
|
-
*
|
1263
|
-
* Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
|
1264
|
-
*
|
1265
|
-
* @example
|
1266
|
-
* ```ts
|
1267
|
-
* const person = await Person.load(
|
1268
|
-
* "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
|
1269
|
-
* me,
|
1270
|
-
* { pet: {} }
|
1271
|
-
* );
|
1272
|
-
* ```
|
1273
|
-
*
|
1274
|
-
* @category Subscription & Loading
|
1275
|
-
*/
|
1276
|
-
static load(id, as, depth) {
|
1277
|
-
return loadCoValue(this, id, as, depth);
|
1352
|
+
static load(id, asOrDepth, depth) {
|
1353
|
+
return loadCoValueWithoutMe(this, id, asOrDepth, depth);
|
1278
1354
|
}
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
* You can pass `[]` or `{}` for shallowly loading only this CoMap, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues.
|
1288
|
-
*
|
1289
|
-
* Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
|
1290
|
-
*
|
1291
|
-
* Returns an unsubscribe function that you should call when you no longer need updates.
|
1292
|
-
*
|
1293
|
-
* Also see the `useCoState` hook to reactively subscribe to a CoValue in a React component.
|
1294
|
-
*
|
1295
|
-
* @example
|
1296
|
-
* ```ts
|
1297
|
-
* const unsub = Person.subscribe(
|
1298
|
-
* "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
|
1299
|
-
* me,
|
1300
|
-
* { pet: {} },
|
1301
|
-
* (person) => console.log(person)
|
1302
|
-
* );
|
1303
|
-
* ```
|
1304
|
-
*
|
1305
|
-
* @category Subscription & Loading
|
1306
|
-
*/
|
1307
|
-
static subscribe(id, as, depth, listener) {
|
1308
|
-
return subscribeToCoValue(this, id, as, depth, listener);
|
1355
|
+
static subscribe(id, asOrDepth, depthOrListener, listener) {
|
1356
|
+
return subscribeToCoValueWithoutMe(
|
1357
|
+
this,
|
1358
|
+
id,
|
1359
|
+
asOrDepth,
|
1360
|
+
depthOrListener,
|
1361
|
+
listener
|
1362
|
+
);
|
1309
1363
|
}
|
1310
1364
|
static findUnique(unique, ownerID, as) {
|
1365
|
+
as ||= activeAccountContext.get();
|
1311
1366
|
const header = {
|
1312
1367
|
type: "comap",
|
1313
1368
|
ruleset: {
|
@@ -1584,6 +1639,9 @@ var _Account = class _Account extends CoValueBase {
|
|
1584
1639
|
});
|
1585
1640
|
return this.fromNode(node);
|
1586
1641
|
}
|
1642
|
+
static getMe() {
|
1643
|
+
return activeAccountContext.get();
|
1644
|
+
}
|
1587
1645
|
static async createAs(as, options) {
|
1588
1646
|
const connectedPeers = cojsonInternals2.connectedPeers(
|
1589
1647
|
"creatingAccount",
|
@@ -1634,13 +1692,17 @@ var _Account = class _Account extends CoValueBase {
|
|
1634
1692
|
migrate(creationProps) {
|
1635
1693
|
creationProps;
|
1636
1694
|
}
|
1637
|
-
|
1638
|
-
|
1639
|
-
return loadCoValue(this, id, as, depth);
|
1695
|
+
static load(id, asOrDepth, depth) {
|
1696
|
+
return loadCoValueWithoutMe(this, id, asOrDepth, depth);
|
1640
1697
|
}
|
1641
|
-
|
1642
|
-
|
1643
|
-
|
1698
|
+
static subscribe(id, asOrDepth, depthOrListener, listener) {
|
1699
|
+
return subscribeToCoValueWithoutMe(
|
1700
|
+
this,
|
1701
|
+
id,
|
1702
|
+
asOrDepth,
|
1703
|
+
depthOrListener,
|
1704
|
+
listener
|
1705
|
+
);
|
1644
1706
|
}
|
1645
1707
|
/** @category Subscription & Loading */
|
1646
1708
|
ensureLoaded(depth) {
|
@@ -1735,186 +1797,57 @@ function isControlledAccount(account) {
|
|
1735
1797
|
}
|
1736
1798
|
RegisteredSchemas["Account"] = Account;
|
1737
1799
|
|
1738
|
-
// src/coValues/
|
1739
|
-
|
1800
|
+
// src/coValues/coFeed.ts
|
1801
|
+
import { MAX_RECOMMENDED_TX_SIZE, cojsonInternals as cojsonInternals3 } from "cojson";
|
1802
|
+
var _CoFeed = class _CoFeed extends CoValueBase {
|
1803
|
+
/**
|
1804
|
+
* Declare a `CoFeed` by subclassing `CoFeed.Of(...)` and passing the item schema using a `co` primitive or a `co.ref`.
|
1805
|
+
*
|
1806
|
+
* @example
|
1807
|
+
* ```ts
|
1808
|
+
* class ColorFeed extends CoFeed.Of(co.string) {}
|
1809
|
+
* class AnimalFeed extends CoFeed.Of(co.ref(Animal)) {}
|
1810
|
+
* ```
|
1811
|
+
*
|
1812
|
+
* @category Declaration
|
1813
|
+
*/
|
1814
|
+
static Of(item) {
|
1815
|
+
var _a2, _b2;
|
1816
|
+
return class CoFeedOf extends (_b2 = _CoFeed, _a2 = co.items, _b2) {
|
1817
|
+
constructor() {
|
1818
|
+
super(...arguments);
|
1819
|
+
this[_a2] = item;
|
1820
|
+
}
|
1821
|
+
};
|
1822
|
+
}
|
1823
|
+
/** @internal */
|
1740
1824
|
get _schema() {
|
1741
1825
|
return this.constructor._schema;
|
1742
1826
|
}
|
1743
|
-
|
1744
|
-
|
1745
|
-
|
1746
|
-
|
1747
|
-
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
1753
|
-
|
1754
|
-
|
1755
|
-
|
1756
|
-
|
1757
|
-
|
1758
|
-
|
1759
|
-
|
1760
|
-
|
1761
|
-
|
1762
|
-
|
1763
|
-
|
1764
|
-
|
1765
|
-
|
1766
|
-
|
1767
|
-
} else {
|
1768
|
-
const initOwner = options.owner;
|
1769
|
-
if (!initOwner) throw new Error("No owner provided");
|
1770
|
-
if (initOwner._type === "Account" && isControlledAccount(initOwner)) {
|
1771
|
-
const rawOwner = initOwner._raw;
|
1772
|
-
raw = rawOwner.createGroup();
|
1773
|
-
} else {
|
1774
|
-
throw new Error("Can only construct group as a controlled account");
|
1775
|
-
}
|
1776
|
-
}
|
1777
|
-
Object.defineProperties(this, {
|
1778
|
-
id: {
|
1779
|
-
value: raw.id,
|
1780
|
-
enumerable: false
|
1781
|
-
},
|
1782
|
-
_raw: { value: raw, enumerable: false }
|
1783
|
-
});
|
1784
|
-
return new Proxy(this, AccountAndGroupProxyHandler);
|
1785
|
-
}
|
1786
|
-
static create(options) {
|
1787
|
-
return new this(parseCoValueCreateOptions(options));
|
1788
|
-
}
|
1789
|
-
myRole() {
|
1790
|
-
return this._raw.myRole();
|
1791
|
-
}
|
1792
|
-
addMember(member, role) {
|
1793
|
-
this._raw.addMember(member === "everyone" ? member : member._raw, role);
|
1794
|
-
return this;
|
1795
|
-
}
|
1796
|
-
removeMember(member) {
|
1797
|
-
this._raw.removeMember(member === "everyone" ? member : member._raw);
|
1798
|
-
return this;
|
1799
|
-
}
|
1800
|
-
get members() {
|
1801
|
-
return this._raw.keys().filter((key) => {
|
1802
|
-
return key === "everyone" || key.startsWith("co_");
|
1803
|
-
}).map((id) => {
|
1804
|
-
const role = this._raw.get(id);
|
1805
|
-
const accountID = id === "everyone" ? void 0 : id;
|
1806
|
-
const ref2 = accountID && new Ref(
|
1807
|
-
accountID,
|
1808
|
-
this._loadedAs,
|
1809
|
-
this._schema[MembersSym]
|
1810
|
-
);
|
1811
|
-
const accessRef = () => ref2?.accessFrom(this, "members." + id);
|
1812
|
-
return {
|
1813
|
-
id,
|
1814
|
-
role,
|
1815
|
-
ref: ref2,
|
1816
|
-
get account() {
|
1817
|
-
return accessRef();
|
1818
|
-
}
|
1819
|
-
};
|
1820
|
-
});
|
1821
|
-
}
|
1822
|
-
extend(parent) {
|
1823
|
-
this._raw.extend(parent._raw);
|
1824
|
-
return this;
|
1825
|
-
}
|
1826
|
-
/** @category Subscription & Loading */
|
1827
|
-
static load(id, as, depth) {
|
1828
|
-
return loadCoValue(this, id, as, depth);
|
1829
|
-
}
|
1830
|
-
/** @category Subscription & Loading */
|
1831
|
-
static subscribe(id, as, depth, listener) {
|
1832
|
-
return subscribeToCoValue(this, id, as, depth, listener);
|
1833
|
-
}
|
1834
|
-
/** @category Subscription & Loading */
|
1835
|
-
ensureLoaded(depth) {
|
1836
|
-
return ensureCoValueLoaded(this, depth);
|
1837
|
-
}
|
1838
|
-
/** @category Subscription & Loading */
|
1839
|
-
subscribe(depth, listener) {
|
1840
|
-
return subscribeToExistingCoValue(this, depth, listener);
|
1841
|
-
}
|
1842
|
-
/**
|
1843
|
-
* Wait for the `Group` to be uploaded to the other peers.
|
1844
|
-
*
|
1845
|
-
* @category Subscription & Loading
|
1846
|
-
*/
|
1847
|
-
waitForSync(options) {
|
1848
|
-
return this._raw.core.waitForSync(options);
|
1849
|
-
}
|
1850
|
-
};
|
1851
|
-
_Group.prototype._type = "Group";
|
1852
|
-
_Group._schema = {
|
1853
|
-
profile: "json",
|
1854
|
-
root: "json",
|
1855
|
-
[MembersSym]: {
|
1856
|
-
ref: () => RegisteredSchemas["Account"],
|
1857
|
-
optional: false
|
1858
|
-
}
|
1859
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
1860
|
-
};
|
1861
|
-
Object.defineProperty(_Group.prototype, "_schema", {
|
1862
|
-
get: () => _Group._schema
|
1863
|
-
});
|
1864
|
-
var Group = _Group;
|
1865
|
-
RegisteredSchemas["Group"] = Group;
|
1866
|
-
|
1867
|
-
// src/coValues/coFeed.ts
|
1868
|
-
import { MAX_RECOMMENDED_TX_SIZE, cojsonInternals as cojsonInternals3 } from "cojson";
|
1869
|
-
var _CoFeed = class _CoFeed extends CoValueBase {
|
1870
|
-
/**
|
1871
|
-
* Declare a `CoFeed` by subclassing `CoFeed.Of(...)` and passing the item schema using a `co` primitive or a `co.ref`.
|
1872
|
-
*
|
1873
|
-
* @example
|
1874
|
-
* ```ts
|
1875
|
-
* class ColorFeed extends CoFeed.Of(co.string) {}
|
1876
|
-
* class AnimalFeed extends CoFeed.Of(co.ref(Animal)) {}
|
1877
|
-
* ```
|
1878
|
-
*
|
1879
|
-
* @category Declaration
|
1880
|
-
*/
|
1881
|
-
static Of(item) {
|
1882
|
-
var _a2, _b2;
|
1883
|
-
return class CoFeedOf extends (_b2 = _CoFeed, _a2 = co.items, _b2) {
|
1884
|
-
constructor() {
|
1885
|
-
super(...arguments);
|
1886
|
-
this[_a2] = item;
|
1887
|
-
}
|
1888
|
-
};
|
1889
|
-
}
|
1890
|
-
/** @internal */
|
1891
|
-
get _schema() {
|
1892
|
-
return this.constructor._schema;
|
1893
|
-
}
|
1894
|
-
/**
|
1895
|
-
* The current account's view of this `CoFeed`
|
1896
|
-
* @category Content
|
1897
|
-
*/
|
1898
|
-
get byMe() {
|
1899
|
-
if (this._loadedAs._type === "Account") {
|
1900
|
-
return this[this._loadedAs.id];
|
1901
|
-
} else {
|
1902
|
-
return void 0;
|
1903
|
-
}
|
1904
|
-
}
|
1905
|
-
/**
|
1906
|
-
* The current session's view of this `CoFeed`
|
1907
|
-
*
|
1908
|
-
* This is a shortcut for `this.perSession` where the session ID is the current session ID.
|
1909
|
-
*
|
1910
|
-
* @category Content
|
1911
|
-
*/
|
1912
|
-
get inCurrentSession() {
|
1913
|
-
if (this._loadedAs._type === "Account") {
|
1914
|
-
return this.perSession[this._loadedAs.sessionID];
|
1915
|
-
} else {
|
1916
|
-
return void 0;
|
1917
|
-
}
|
1827
|
+
/**
|
1828
|
+
* The current account's view of this `CoFeed`
|
1829
|
+
* @category Content
|
1830
|
+
*/
|
1831
|
+
get byMe() {
|
1832
|
+
if (this._loadedAs._type === "Account") {
|
1833
|
+
return this[this._loadedAs.id];
|
1834
|
+
} else {
|
1835
|
+
return void 0;
|
1836
|
+
}
|
1837
|
+
}
|
1838
|
+
/**
|
1839
|
+
* The current session's view of this `CoFeed`
|
1840
|
+
*
|
1841
|
+
* This is a shortcut for `this.perSession` where the session ID is the current session ID.
|
1842
|
+
*
|
1843
|
+
* @category Content
|
1844
|
+
*/
|
1845
|
+
get inCurrentSession() {
|
1846
|
+
if (this._loadedAs._type === "Account") {
|
1847
|
+
return this.perSession[this._loadedAs.sessionID];
|
1848
|
+
} else {
|
1849
|
+
return void 0;
|
1850
|
+
}
|
1918
1851
|
}
|
1919
1852
|
constructor(options) {
|
1920
1853
|
super();
|
@@ -2017,19 +1950,17 @@ var _CoFeed = class _CoFeed extends CoValueBase {
|
|
2017
1950
|
this._schema ||= {};
|
2018
1951
|
Object.assign(this._schema, def);
|
2019
1952
|
}
|
2020
|
-
|
2021
|
-
|
2022
|
-
* @category Subscription & Loading
|
2023
|
-
*/
|
2024
|
-
static load(id, as, depth) {
|
2025
|
-
return loadCoValue(this, id, as, depth);
|
1953
|
+
static load(id, asOrDepth, depth) {
|
1954
|
+
return loadCoValueWithoutMe(this, id, asOrDepth, depth);
|
2026
1955
|
}
|
2027
|
-
|
2028
|
-
|
2029
|
-
|
2030
|
-
|
2031
|
-
|
2032
|
-
|
1956
|
+
static subscribe(id, asOrDepth, depthOrListener, listener) {
|
1957
|
+
return subscribeToCoValueWithoutMe(
|
1958
|
+
this,
|
1959
|
+
id,
|
1960
|
+
asOrDepth,
|
1961
|
+
depthOrListener,
|
1962
|
+
listener
|
1963
|
+
);
|
2033
1964
|
}
|
2034
1965
|
/**
|
2035
1966
|
* Ensure a `CoFeed` is loaded to the specified depth
|
@@ -2274,12 +2205,9 @@ var FileStream = class extends CoValueBase {
|
|
2274
2205
|
}
|
2275
2206
|
return new Blob(chunks.chunks, { type: chunks.mimeType });
|
2276
2207
|
}
|
2277
|
-
|
2278
|
-
|
2279
|
-
|
2280
|
-
* @category Content
|
2281
|
-
*/
|
2282
|
-
static async loadAsBlob(id, as, options) {
|
2208
|
+
static async loadAsBlob(id, asOrOptions, optionsOrUndefined) {
|
2209
|
+
const as = isAccountInstance(asOrOptions) ? asOrOptions : activeAccountContext.get();
|
2210
|
+
const options = isAccountInstance(asOrOptions) ? optionsOrUndefined : asOrOptions;
|
2283
2211
|
let stream = await this.load(id, as, []);
|
2284
2212
|
if (!options?.allowUnfinished && !stream?.isBinaryStreamEnded()) {
|
2285
2213
|
stream = await new Promise((resolve) => {
|
@@ -2308,7 +2236,7 @@ var FileStream = class extends CoValueBase {
|
|
2308
2236
|
*/
|
2309
2237
|
static async createFromBlob(blob, options) {
|
2310
2238
|
const stream = this.create(options);
|
2311
|
-
const onProgress = "onProgress" in options ? options.onProgress : void 0;
|
2239
|
+
const onProgress = options && "onProgress" in options ? options.onProgress : void 0;
|
2312
2240
|
const start = Date.now();
|
2313
2241
|
const data = new Uint8Array(await blob.arrayBuffer());
|
2314
2242
|
stream.start({
|
@@ -2352,19 +2280,17 @@ var FileStream = class extends CoValueBase {
|
|
2352
2280
|
[inspect]() {
|
2353
2281
|
return this.toJSON();
|
2354
2282
|
}
|
2355
|
-
|
2356
|
-
|
2357
|
-
* @category Subscription & Loading
|
2358
|
-
*/
|
2359
|
-
static load(id, as, depth) {
|
2360
|
-
return loadCoValue(this, id, as, depth);
|
2283
|
+
static load(id, asOrDepth, depth) {
|
2284
|
+
return loadCoValueWithoutMe(this, id, asOrDepth, depth);
|
2361
2285
|
}
|
2362
|
-
|
2363
|
-
|
2364
|
-
|
2365
|
-
|
2366
|
-
|
2367
|
-
|
2286
|
+
static subscribe(id, asOrDepth, depthOrListener, listener) {
|
2287
|
+
return subscribeToCoValueWithoutMe(
|
2288
|
+
this,
|
2289
|
+
id,
|
2290
|
+
asOrDepth,
|
2291
|
+
depthOrListener,
|
2292
|
+
listener
|
2293
|
+
);
|
2368
2294
|
}
|
2369
2295
|
ensureLoaded(depth) {
|
2370
2296
|
return ensureCoValueLoaded(this, depth);
|
@@ -2588,61 +2514,17 @@ var _CoList = class _CoList extends Array {
|
|
2588
2514
|
this._schema ||= {};
|
2589
2515
|
Object.assign(this._schema, def);
|
2590
2516
|
}
|
2591
|
-
|
2592
|
-
|
2593
|
-
*
|
2594
|
-
* `depth` specifies if item CoValue references should be loaded as well before resolving.
|
2595
|
-
* The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
|
2596
|
-
*
|
2597
|
-
* You can pass `[]` or for shallowly loading only this CoList, or `[itemDepth]` for recursively loading referenced CoValues.
|
2598
|
-
*
|
2599
|
-
* Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
|
2600
|
-
*
|
2601
|
-
* @example
|
2602
|
-
* ```ts
|
2603
|
-
* const animalsWithVets =
|
2604
|
-
* await ListOfAnimals.load(
|
2605
|
-
* "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
|
2606
|
-
* me,
|
2607
|
-
* [{ vet: {} }]
|
2608
|
-
* );
|
2609
|
-
* ```
|
2610
|
-
*
|
2611
|
-
* @category Subscription & Loading
|
2612
|
-
*/
|
2613
|
-
static load(id, as, depth) {
|
2614
|
-
return loadCoValue(this, id, as, depth);
|
2517
|
+
static load(id, asOrDepth, depth) {
|
2518
|
+
return loadCoValueWithoutMe(this, id, asOrDepth, depth);
|
2615
2519
|
}
|
2616
|
-
|
2617
|
-
|
2618
|
-
|
2619
|
-
|
2620
|
-
|
2621
|
-
|
2622
|
-
|
2623
|
-
|
2624
|
-
* You can pass `[]` or for shallowly loading only this CoList, or `[itemDepth]` for recursively loading referenced CoValues.
|
2625
|
-
*
|
2626
|
-
* Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
|
2627
|
-
*
|
2628
|
-
* Returns an unsubscribe function that you should call when you no longer need updates.
|
2629
|
-
*
|
2630
|
-
* Also see the `useCoState` hook to reactively subscribe to a CoValue in a React component.
|
2631
|
-
*
|
2632
|
-
* @example
|
2633
|
-
* ```ts
|
2634
|
-
* const unsub = ListOfAnimals.subscribe(
|
2635
|
-
* "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
|
2636
|
-
* me,
|
2637
|
-
* { vet: {} },
|
2638
|
-
* (animalsWithVets) => console.log(animalsWithVets)
|
2639
|
-
* );
|
2640
|
-
* ```
|
2641
|
-
*
|
2642
|
-
* @category Subscription & Loading
|
2643
|
-
*/
|
2644
|
-
static subscribe(id, as, depth, listener) {
|
2645
|
-
return subscribeToCoValue(this, id, as, depth, listener);
|
2520
|
+
static subscribe(id, asOrDepth, depthOrListener, listener) {
|
2521
|
+
return subscribeToCoValueWithoutMe(
|
2522
|
+
this,
|
2523
|
+
id,
|
2524
|
+
asOrDepth,
|
2525
|
+
depthOrListener,
|
2526
|
+
listener
|
2527
|
+
);
|
2646
2528
|
}
|
2647
2529
|
/**
|
2648
2530
|
* Given an already loaded `CoList`, ensure that items are loaded to the specified depth.
|
@@ -2754,6 +2636,659 @@ var CoListProxyHandler = {
|
|
2754
2636
|
}
|
2755
2637
|
};
|
2756
2638
|
|
2639
|
+
// src/coValues/group.ts
|
2640
|
+
var _Group = class _Group extends CoValueBase {
|
2641
|
+
get _schema() {
|
2642
|
+
return this.constructor._schema;
|
2643
|
+
}
|
2644
|
+
get _refs() {
|
2645
|
+
const profileID = this._raw.get("profile");
|
2646
|
+
const rootID = this._raw.get("root");
|
2647
|
+
return {
|
2648
|
+
profile: profileID && new Ref(
|
2649
|
+
profileID,
|
2650
|
+
this._loadedAs,
|
2651
|
+
this._schema.profile
|
2652
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2653
|
+
),
|
2654
|
+
root: rootID && new Ref(
|
2655
|
+
rootID,
|
2656
|
+
this._loadedAs,
|
2657
|
+
this._schema.root
|
2658
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2659
|
+
)
|
2660
|
+
};
|
2661
|
+
}
|
2662
|
+
/** @deprecated Don't use constructor directly, use .create */
|
2663
|
+
constructor(options) {
|
2664
|
+
super();
|
2665
|
+
let raw;
|
2666
|
+
if (options && "fromRaw" in options) {
|
2667
|
+
raw = options.fromRaw;
|
2668
|
+
} else {
|
2669
|
+
const initOwner = options.owner;
|
2670
|
+
if (!initOwner) throw new Error("No owner provided");
|
2671
|
+
if (initOwner._type === "Account" && isControlledAccount(initOwner)) {
|
2672
|
+
const rawOwner = initOwner._raw;
|
2673
|
+
raw = rawOwner.createGroup();
|
2674
|
+
} else {
|
2675
|
+
throw new Error("Can only construct group as a controlled account");
|
2676
|
+
}
|
2677
|
+
}
|
2678
|
+
Object.defineProperties(this, {
|
2679
|
+
id: {
|
2680
|
+
value: raw.id,
|
2681
|
+
enumerable: false
|
2682
|
+
},
|
2683
|
+
_raw: { value: raw, enumerable: false }
|
2684
|
+
});
|
2685
|
+
return new Proxy(this, AccountAndGroupProxyHandler);
|
2686
|
+
}
|
2687
|
+
static create(options) {
|
2688
|
+
return new this(parseGroupCreateOptions(options));
|
2689
|
+
}
|
2690
|
+
myRole() {
|
2691
|
+
return this._raw.myRole();
|
2692
|
+
}
|
2693
|
+
addMember(member, role) {
|
2694
|
+
this._raw.addMember(member === "everyone" ? member : member._raw, role);
|
2695
|
+
return this;
|
2696
|
+
}
|
2697
|
+
removeMember(member) {
|
2698
|
+
this._raw.removeMember(member === "everyone" ? member : member._raw);
|
2699
|
+
return this;
|
2700
|
+
}
|
2701
|
+
get members() {
|
2702
|
+
return this._raw.keys().filter((key) => {
|
2703
|
+
return key === "everyone" || key.startsWith("co_");
|
2704
|
+
}).map((id) => {
|
2705
|
+
const role = this._raw.get(id);
|
2706
|
+
const accountID = id === "everyone" ? void 0 : id;
|
2707
|
+
const ref2 = accountID && new Ref(
|
2708
|
+
accountID,
|
2709
|
+
this._loadedAs,
|
2710
|
+
this._schema[MembersSym]
|
2711
|
+
);
|
2712
|
+
const accessRef = () => ref2?.accessFrom(this, "members." + id);
|
2713
|
+
return {
|
2714
|
+
id,
|
2715
|
+
role,
|
2716
|
+
ref: ref2,
|
2717
|
+
get account() {
|
2718
|
+
return accessRef();
|
2719
|
+
}
|
2720
|
+
};
|
2721
|
+
});
|
2722
|
+
}
|
2723
|
+
extend(parent) {
|
2724
|
+
this._raw.extend(parent._raw);
|
2725
|
+
return this;
|
2726
|
+
}
|
2727
|
+
static load(id, asOrDepth, depth) {
|
2728
|
+
return loadCoValueWithoutMe(this, id, asOrDepth, depth);
|
2729
|
+
}
|
2730
|
+
static subscribe(id, asOrDepth, depthOrListener, listener) {
|
2731
|
+
return subscribeToCoValueWithoutMe(
|
2732
|
+
this,
|
2733
|
+
id,
|
2734
|
+
asOrDepth,
|
2735
|
+
depthOrListener,
|
2736
|
+
listener
|
2737
|
+
);
|
2738
|
+
}
|
2739
|
+
/** @category Subscription & Loading */
|
2740
|
+
ensureLoaded(depth) {
|
2741
|
+
return ensureCoValueLoaded(this, depth);
|
2742
|
+
}
|
2743
|
+
/** @category Subscription & Loading */
|
2744
|
+
subscribe(depth, listener) {
|
2745
|
+
return subscribeToExistingCoValue(this, depth, listener);
|
2746
|
+
}
|
2747
|
+
/**
|
2748
|
+
* Wait for the `Group` to be uploaded to the other peers.
|
2749
|
+
*
|
2750
|
+
* @category Subscription & Loading
|
2751
|
+
*/
|
2752
|
+
waitForSync(options) {
|
2753
|
+
return this._raw.core.waitForSync(options);
|
2754
|
+
}
|
2755
|
+
};
|
2756
|
+
_Group.prototype._type = "Group";
|
2757
|
+
_Group._schema = {
|
2758
|
+
profile: "json",
|
2759
|
+
root: "json",
|
2760
|
+
[MembersSym]: {
|
2761
|
+
ref: () => RegisteredSchemas["Account"],
|
2762
|
+
optional: false
|
2763
|
+
}
|
2764
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2765
|
+
};
|
2766
|
+
Object.defineProperty(_Group.prototype, "_schema", {
|
2767
|
+
get: () => _Group._schema
|
2768
|
+
});
|
2769
|
+
var Group = _Group;
|
2770
|
+
RegisteredSchemas["Group"] = Group;
|
2771
|
+
|
2772
|
+
// src/coValues/coPlainText.ts
|
2773
|
+
import {
|
2774
|
+
RawAccount as RawAccount6,
|
2775
|
+
stringifyOpID
|
2776
|
+
} from "cojson";
|
2777
|
+
var CoPlainText = class extends String {
|
2778
|
+
get _owner() {
|
2779
|
+
return this._raw.group instanceof RawAccount6 ? Account.fromRaw(this._raw.group) : Group.fromRaw(this._raw.group);
|
2780
|
+
}
|
2781
|
+
get _loadedAs() {
|
2782
|
+
return Account.fromNode(this._raw.core.node);
|
2783
|
+
}
|
2784
|
+
constructor(options) {
|
2785
|
+
super();
|
2786
|
+
let raw;
|
2787
|
+
if ("fromRaw" in options) {
|
2788
|
+
raw = options.fromRaw;
|
2789
|
+
} else {
|
2790
|
+
raw = options.owner._raw.createPlainText(options.text);
|
2791
|
+
}
|
2792
|
+
Object.defineProperties(this, {
|
2793
|
+
id: { value: raw.id, enumerable: false },
|
2794
|
+
_type: { value: "CoPlainText", enumerable: false },
|
2795
|
+
_raw: { value: raw, enumerable: false }
|
2796
|
+
});
|
2797
|
+
}
|
2798
|
+
static create(text, options) {
|
2799
|
+
return new this({ text, owner: options.owner });
|
2800
|
+
}
|
2801
|
+
get length() {
|
2802
|
+
return this._raw.toString().length;
|
2803
|
+
}
|
2804
|
+
toString() {
|
2805
|
+
return this._raw.toString();
|
2806
|
+
}
|
2807
|
+
valueOf() {
|
2808
|
+
return this._raw.toString();
|
2809
|
+
}
|
2810
|
+
toJSON() {
|
2811
|
+
return this._raw.toString();
|
2812
|
+
}
|
2813
|
+
[inspect]() {
|
2814
|
+
return this.toJSON();
|
2815
|
+
}
|
2816
|
+
insertAfter(idx, text) {
|
2817
|
+
this._raw.insertAfter(idx, text);
|
2818
|
+
}
|
2819
|
+
deleteRange(range) {
|
2820
|
+
this._raw.deleteRange(range);
|
2821
|
+
}
|
2822
|
+
posBefore(idx) {
|
2823
|
+
return this._raw.mapping.opIDbeforeIdx[idx];
|
2824
|
+
}
|
2825
|
+
posAfter(idx) {
|
2826
|
+
return this._raw.mapping.opIDafterIdx[idx];
|
2827
|
+
}
|
2828
|
+
idxBefore(pos) {
|
2829
|
+
return this._raw.mapping.idxBeforeOpID[stringifyOpID(pos)];
|
2830
|
+
}
|
2831
|
+
idxAfter(pos) {
|
2832
|
+
return this._raw.mapping.idxAfterOpID[stringifyOpID(pos)];
|
2833
|
+
}
|
2834
|
+
static fromRaw(raw) {
|
2835
|
+
return new this({ fromRaw: raw });
|
2836
|
+
}
|
2837
|
+
/**
|
2838
|
+
* Load a `CoPlainText` with a given ID, as a given account.
|
2839
|
+
*
|
2840
|
+
* `depth` specifies which (if any) fields that reference other CoValues to load as well before resolving.
|
2841
|
+
* The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
|
2842
|
+
*
|
2843
|
+
* You can pass `[]` or `{}` for shallowly loading only this CoPlainText, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues.
|
2844
|
+
*
|
2845
|
+
* Check out the `load` methods on `CoMap`/`CoList`/`CoStream`/`Group`/`Account` to see which depth structures are valid to nest.
|
2846
|
+
*
|
2847
|
+
* @example
|
2848
|
+
* ```ts
|
2849
|
+
* const person = await Person.load(
|
2850
|
+
* "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
|
2851
|
+
* me,
|
2852
|
+
* { pet: {} }
|
2853
|
+
* );
|
2854
|
+
* ```
|
2855
|
+
*
|
2856
|
+
* @category Subscription & Loading
|
2857
|
+
*/
|
2858
|
+
static load(id, as) {
|
2859
|
+
return loadCoValue(this, id, as ?? activeAccountContext.get(), []);
|
2860
|
+
}
|
2861
|
+
static subscribe(id, asOrListener, listener) {
|
2862
|
+
if (isAccountInstance(asOrListener)) {
|
2863
|
+
return subscribeToCoValue(this, id, asOrListener, [], listener);
|
2864
|
+
}
|
2865
|
+
return subscribeToCoValue(
|
2866
|
+
this,
|
2867
|
+
id,
|
2868
|
+
activeAccountContext.get(),
|
2869
|
+
[],
|
2870
|
+
listener
|
2871
|
+
);
|
2872
|
+
}
|
2873
|
+
// /**
|
2874
|
+
// * Effectful version of `CoMap.subscribe()` that returns a stream of updates.
|
2875
|
+
// *
|
2876
|
+
// * Needs to be run inside an `AccountCtx` context.
|
2877
|
+
// *
|
2878
|
+
// * @category Subscription & Loading
|
2879
|
+
// */
|
2880
|
+
// static subscribeEf<T extends CoPlainText>(
|
2881
|
+
// this: CoValueClass<T>,
|
2882
|
+
// id: ID<T>,
|
2883
|
+
// ): Stream.Stream<T, UnavailableError, AccountCtx> {
|
2884
|
+
// return subscribeToCoValueEf(this, id, []);
|
2885
|
+
// }
|
2886
|
+
/**
|
2887
|
+
* Given an already loaded `CoPlainText`, subscribe to updates to the `CoPlainText` and ensure that the specified fields are loaded to the specified depth.
|
2888
|
+
*
|
2889
|
+
* Works like `CoPlainText.subscribe()`, but you don't need to pass the ID or the account to load as again.
|
2890
|
+
*
|
2891
|
+
* Returns an unsubscribe function that you should call when you no longer need updates.
|
2892
|
+
*
|
2893
|
+
* @category Subscription & Loading
|
2894
|
+
**/
|
2895
|
+
subscribe(listener) {
|
2896
|
+
return subscribeToExistingCoValue(this, [], listener);
|
2897
|
+
}
|
2898
|
+
};
|
2899
|
+
|
2900
|
+
// src/coValues/coRichText.ts
|
2901
|
+
var Mark = class extends CoMap {
|
2902
|
+
constructor() {
|
2903
|
+
super(...arguments);
|
2904
|
+
this.startAfter = co.json();
|
2905
|
+
this.startBefore = co.json();
|
2906
|
+
this.endAfter = co.json();
|
2907
|
+
this.endBefore = co.json();
|
2908
|
+
this.tag = co.string;
|
2909
|
+
}
|
2910
|
+
/**
|
2911
|
+
* Validates and clamps mark positions to ensure they are in the correct order
|
2912
|
+
* @returns Normalized positions or null if invalid
|
2913
|
+
*/
|
2914
|
+
validatePositions(textLength, idxAfter, idxBefore) {
|
2915
|
+
if (!textLength) {
|
2916
|
+
console.error("Cannot validate positions for empty text");
|
2917
|
+
return null;
|
2918
|
+
}
|
2919
|
+
const positions = {
|
2920
|
+
startAfter: this.startAfter ? idxBefore(this.startAfter) ?? 0 : 0,
|
2921
|
+
startBefore: this.startBefore ? idxAfter(this.startBefore) ?? 0 : 0,
|
2922
|
+
endAfter: this.endAfter ? idxBefore(this.endAfter) ?? textLength : textLength,
|
2923
|
+
endBefore: this.endBefore ? idxAfter(this.endBefore) ?? textLength : textLength
|
2924
|
+
};
|
2925
|
+
return {
|
2926
|
+
startAfter: Math.max(0, positions.startAfter),
|
2927
|
+
startBefore: Math.max(positions.startAfter + 1, positions.startBefore),
|
2928
|
+
endAfter: Math.min(textLength - 1, positions.endAfter),
|
2929
|
+
endBefore: Math.min(textLength, positions.endBefore)
|
2930
|
+
};
|
2931
|
+
}
|
2932
|
+
};
|
2933
|
+
var CoRichText = class extends CoMap {
|
2934
|
+
constructor() {
|
2935
|
+
super(...arguments);
|
2936
|
+
this.text = co.ref(CoPlainText);
|
2937
|
+
this.marks = co.ref(CoList.Of(co.ref(Mark)));
|
2938
|
+
}
|
2939
|
+
/**
|
2940
|
+
* Create a CoRichText from plain text.
|
2941
|
+
*/
|
2942
|
+
static createFromPlainText(text, options) {
|
2943
|
+
return this.create(
|
2944
|
+
{
|
2945
|
+
text: CoPlainText.create(text, { owner: options.owner }),
|
2946
|
+
marks: CoList.Of(co.ref(Mark)).create([], {
|
2947
|
+
owner: options.owner
|
2948
|
+
})
|
2949
|
+
},
|
2950
|
+
{ owner: options.owner }
|
2951
|
+
);
|
2952
|
+
}
|
2953
|
+
/**
|
2954
|
+
* Create a CoRichText from plain text and a mark.
|
2955
|
+
*/
|
2956
|
+
static createFromPlainTextAndMark(text, WrapIn, extraArgs, options) {
|
2957
|
+
const richtext = this.createFromPlainText(text, options);
|
2958
|
+
richtext.insertMark(0, text.length, WrapIn, extraArgs);
|
2959
|
+
return richtext;
|
2960
|
+
}
|
2961
|
+
/**
|
2962
|
+
* Insert text at a specific index.
|
2963
|
+
*/
|
2964
|
+
insertAfter(idx, text) {
|
2965
|
+
if (!this.text)
|
2966
|
+
throw new Error("Cannot insert into a CoRichText without loaded text");
|
2967
|
+
this.text.insertAfter(idx, text);
|
2968
|
+
}
|
2969
|
+
/**
|
2970
|
+
* Delete a range of text.
|
2971
|
+
*/
|
2972
|
+
deleteRange(range) {
|
2973
|
+
if (!this.text)
|
2974
|
+
throw new Error("Cannot delete from a CoRichText without loaded text");
|
2975
|
+
this.text.deleteRange(range);
|
2976
|
+
}
|
2977
|
+
/**
|
2978
|
+
* Get the position of a specific index.
|
2979
|
+
*/
|
2980
|
+
posBefore(idx) {
|
2981
|
+
if (!this.text)
|
2982
|
+
throw new Error(
|
2983
|
+
"Cannot get posBefore in a CoRichText without loaded text"
|
2984
|
+
);
|
2985
|
+
return this.text.posBefore(idx);
|
2986
|
+
}
|
2987
|
+
/**
|
2988
|
+
* Get the position of a specific index.
|
2989
|
+
*/
|
2990
|
+
posAfter(idx) {
|
2991
|
+
if (!this.text)
|
2992
|
+
throw new Error(
|
2993
|
+
"Cannot get posAfter in a CoRichText without loaded text"
|
2994
|
+
);
|
2995
|
+
return this.text.posAfter(idx);
|
2996
|
+
}
|
2997
|
+
/**
|
2998
|
+
* Get the index of a specific position.
|
2999
|
+
*/
|
3000
|
+
idxBefore(pos) {
|
3001
|
+
if (!this.text)
|
3002
|
+
throw new Error(
|
3003
|
+
"Cannot get idxBefore in a CoRichText without loaded text"
|
3004
|
+
);
|
3005
|
+
return this.text.idxBefore(pos);
|
3006
|
+
}
|
3007
|
+
/**
|
3008
|
+
* Get the index of a specific position.
|
3009
|
+
*/
|
3010
|
+
idxAfter(pos) {
|
3011
|
+
if (!this.text)
|
3012
|
+
throw new Error(
|
3013
|
+
"Cannot get idxAfter in a CoRichText without loaded text"
|
3014
|
+
);
|
3015
|
+
return this.text.idxAfter(pos);
|
3016
|
+
}
|
3017
|
+
/**
|
3018
|
+
* Insert a mark at a specific range.
|
3019
|
+
*/
|
3020
|
+
insertMark(start, end, RangeClass, extraArgs, options) {
|
3021
|
+
if (!this.text || !this.marks) {
|
3022
|
+
throw new Error("Cannot insert a range without loaded ranges");
|
3023
|
+
}
|
3024
|
+
const textLength = this.length;
|
3025
|
+
start = Math.max(start, 0);
|
3026
|
+
end = Math.min(end, textLength);
|
3027
|
+
const owner = options?.markOwner || this._owner;
|
3028
|
+
if (!owner) {
|
3029
|
+
throw new Error("No owner specified for mark");
|
3030
|
+
}
|
3031
|
+
const range = RangeClass.create(
|
3032
|
+
{
|
3033
|
+
...extraArgs,
|
3034
|
+
startAfter: this.posBefore(start),
|
3035
|
+
startBefore: this.posAfter(start),
|
3036
|
+
endAfter: this.posBefore(end),
|
3037
|
+
endBefore: this.posAfter(end)
|
3038
|
+
},
|
3039
|
+
{ owner }
|
3040
|
+
);
|
3041
|
+
this.marks.push(range);
|
3042
|
+
}
|
3043
|
+
/**
|
3044
|
+
* Remove a mark at a specific range.
|
3045
|
+
*/
|
3046
|
+
removeMark(start, end, RangeClass, options) {
|
3047
|
+
if (!this.marks) {
|
3048
|
+
throw new Error("Cannot remove marks without loaded marks");
|
3049
|
+
}
|
3050
|
+
const resolvedMarks = this.resolveMarks();
|
3051
|
+
for (const mark of resolvedMarks) {
|
3052
|
+
if (mark.endBefore < start || mark.startAfter > end) {
|
3053
|
+
continue;
|
3054
|
+
}
|
3055
|
+
if (options.tag && mark.sourceMark.tag !== options.tag) {
|
3056
|
+
continue;
|
3057
|
+
}
|
3058
|
+
const markIndex = this.marks.findIndex((m) => m === mark.sourceMark);
|
3059
|
+
if (markIndex === -1) {
|
3060
|
+
continue;
|
3061
|
+
}
|
3062
|
+
if (mark.startBefore >= start && mark.endAfter <= end) {
|
3063
|
+
this.marks.splice(markIndex, 1);
|
3064
|
+
continue;
|
3065
|
+
}
|
3066
|
+
if (mark.startBefore < start && mark.endAfter >= start && mark.endAfter <= end) {
|
3067
|
+
const endAfterPos = this.posBefore(start);
|
3068
|
+
const endBeforePos = this.posBefore(start);
|
3069
|
+
if (endAfterPos && endBeforePos) {
|
3070
|
+
mark.sourceMark.endAfter = endAfterPos;
|
3071
|
+
mark.sourceMark.endBefore = endBeforePos;
|
3072
|
+
}
|
3073
|
+
continue;
|
3074
|
+
}
|
3075
|
+
if (mark.startBefore >= start && mark.startBefore <= end && mark.endAfter > end) {
|
3076
|
+
const startAfterPos = this.posAfter(end);
|
3077
|
+
const startBeforePos = this.posAfter(end);
|
3078
|
+
if (startAfterPos && startBeforePos) {
|
3079
|
+
mark.sourceMark.startAfter = startAfterPos;
|
3080
|
+
mark.sourceMark.startBefore = startBeforePos;
|
3081
|
+
}
|
3082
|
+
continue;
|
3083
|
+
}
|
3084
|
+
if (mark.startBefore <= start && mark.endAfter >= end) {
|
3085
|
+
const endAfterPos = this.posBefore(start);
|
3086
|
+
const endBeforePos = this.posBefore(start);
|
3087
|
+
if (endAfterPos && endBeforePos) {
|
3088
|
+
mark.sourceMark.endAfter = endAfterPos;
|
3089
|
+
mark.sourceMark.endBefore = endBeforePos;
|
3090
|
+
}
|
3091
|
+
this.insertMark(
|
3092
|
+
end + 1,
|
3093
|
+
mark.endBefore,
|
3094
|
+
RangeClass,
|
3095
|
+
{},
|
3096
|
+
{
|
3097
|
+
markOwner: mark.sourceMark._owner || this._owner
|
3098
|
+
}
|
3099
|
+
);
|
3100
|
+
continue;
|
3101
|
+
}
|
3102
|
+
}
|
3103
|
+
}
|
3104
|
+
/**
|
3105
|
+
* Resolve the positions of all marks.
|
3106
|
+
*/
|
3107
|
+
resolveMarks() {
|
3108
|
+
if (!this.text || !this.marks) {
|
3109
|
+
throw new Error("Cannot resolve ranges without loaded text and ranges");
|
3110
|
+
}
|
3111
|
+
const textLength = this.length;
|
3112
|
+
return this.marks.flatMap((mark) => {
|
3113
|
+
if (!mark) return [];
|
3114
|
+
const positions = mark.validatePositions(
|
3115
|
+
textLength,
|
3116
|
+
(pos) => this.idxAfter(pos),
|
3117
|
+
(pos) => this.idxBefore(pos)
|
3118
|
+
);
|
3119
|
+
if (!positions) return [];
|
3120
|
+
return [
|
3121
|
+
{
|
3122
|
+
sourceMark: mark,
|
3123
|
+
...positions,
|
3124
|
+
tag: mark.tag
|
3125
|
+
}
|
3126
|
+
];
|
3127
|
+
});
|
3128
|
+
}
|
3129
|
+
/**
|
3130
|
+
* Resolve and diffuse the positions of all marks.
|
3131
|
+
*/
|
3132
|
+
resolveAndDiffuseMarks() {
|
3133
|
+
return this.resolveMarks().flatMap((range) => [
|
3134
|
+
...range.startAfter < range.startBefore - 1 ? [
|
3135
|
+
{
|
3136
|
+
start: range.startAfter,
|
3137
|
+
end: range.startBefore - 1,
|
3138
|
+
side: "uncertainStart",
|
3139
|
+
sourceMark: range.sourceMark
|
3140
|
+
}
|
3141
|
+
] : [],
|
3142
|
+
{
|
3143
|
+
start: range.startBefore - 1,
|
3144
|
+
end: range.endAfter + 1,
|
3145
|
+
side: "certainMiddle",
|
3146
|
+
sourceMark: range.sourceMark
|
3147
|
+
},
|
3148
|
+
...range.endAfter + 1 < range.endBefore ? [
|
3149
|
+
{
|
3150
|
+
start: range.endAfter + 1,
|
3151
|
+
end: range.endBefore,
|
3152
|
+
side: "uncertainEnd",
|
3153
|
+
sourceMark: range.sourceMark
|
3154
|
+
}
|
3155
|
+
] : []
|
3156
|
+
]);
|
3157
|
+
}
|
3158
|
+
/**
|
3159
|
+
* Resolve, diffuse, and focus the positions of all marks.
|
3160
|
+
*/
|
3161
|
+
resolveAndDiffuseAndFocusMarks() {
|
3162
|
+
return this.resolveAndDiffuseMarks().filter(
|
3163
|
+
(range) => range.side === "certainMiddle"
|
3164
|
+
);
|
3165
|
+
}
|
3166
|
+
/**
|
3167
|
+
* Convert a CoRichText to a tree structure useful for client libraries.
|
3168
|
+
*/
|
3169
|
+
toTree(tagPrecedence) {
|
3170
|
+
const ranges = this.resolveAndDiffuseAndFocusMarks();
|
3171
|
+
const text = this.text?.toString() || "";
|
3172
|
+
let currentNodes = [
|
3173
|
+
{
|
3174
|
+
type: "leaf",
|
3175
|
+
start: 0,
|
3176
|
+
end: text.length
|
3177
|
+
}
|
3178
|
+
];
|
3179
|
+
const rangesSortedLowToHighPrecedence = ranges.sort((a, b) => {
|
3180
|
+
const aPrecedence = tagPrecedence.indexOf(a.sourceMark.tag);
|
3181
|
+
const bPrecedence = tagPrecedence.indexOf(b.sourceMark.tag);
|
3182
|
+
return bPrecedence - aPrecedence;
|
3183
|
+
});
|
3184
|
+
for (const range of rangesSortedLowToHighPrecedence) {
|
3185
|
+
const newNodes = currentNodes.flatMap((node) => {
|
3186
|
+
const [before, inOrAfter] = splitNode(node, range.start);
|
3187
|
+
const [inside, after] = inOrAfter ? splitNode(inOrAfter, range.end) : [void 0, void 0];
|
3188
|
+
return [
|
3189
|
+
...before ? [before] : [],
|
3190
|
+
...inside ? [
|
3191
|
+
{
|
3192
|
+
type: "node",
|
3193
|
+
tag: range.sourceMark.tag,
|
3194
|
+
start: inside.start,
|
3195
|
+
end: inside.end,
|
3196
|
+
children: [inside]
|
3197
|
+
}
|
3198
|
+
] : [],
|
3199
|
+
...after ? [after] : []
|
3200
|
+
];
|
3201
|
+
});
|
3202
|
+
currentNodes = newNodes;
|
3203
|
+
}
|
3204
|
+
return {
|
3205
|
+
type: "node",
|
3206
|
+
tag: "root",
|
3207
|
+
start: 0,
|
3208
|
+
end: text.length,
|
3209
|
+
children: currentNodes
|
3210
|
+
};
|
3211
|
+
}
|
3212
|
+
get length() {
|
3213
|
+
return this.text?.toString().length || 0;
|
3214
|
+
}
|
3215
|
+
/**
|
3216
|
+
* Convert a CoRichText to plain text.
|
3217
|
+
*/
|
3218
|
+
toString() {
|
3219
|
+
if (!this.text) return "";
|
3220
|
+
return this.text.toString();
|
3221
|
+
}
|
3222
|
+
};
|
3223
|
+
function splitNode(node, at) {
|
3224
|
+
if (node.type === "leaf") {
|
3225
|
+
return [
|
3226
|
+
at > node.start ? {
|
3227
|
+
type: "leaf",
|
3228
|
+
start: node.start,
|
3229
|
+
end: Math.min(at, node.end)
|
3230
|
+
} : void 0,
|
3231
|
+
at < node.end ? {
|
3232
|
+
type: "leaf",
|
3233
|
+
start: Math.max(at, node.start),
|
3234
|
+
end: node.end
|
3235
|
+
} : void 0
|
3236
|
+
];
|
3237
|
+
} else {
|
3238
|
+
const children = node.children;
|
3239
|
+
return [
|
3240
|
+
at > node.start ? {
|
3241
|
+
type: "node",
|
3242
|
+
tag: node.tag,
|
3243
|
+
start: node.start,
|
3244
|
+
end: Math.min(at, node.end),
|
3245
|
+
children: children.map((child) => splitNode(child, at)[0]).filter((c) => !!c)
|
3246
|
+
} : void 0,
|
3247
|
+
at < node.end ? {
|
3248
|
+
type: "node",
|
3249
|
+
tag: node.tag,
|
3250
|
+
start: Math.max(at, node.start),
|
3251
|
+
end: node.end,
|
3252
|
+
children: children.map((child) => splitNode(child, at)[1]).filter((c) => !!c)
|
3253
|
+
} : void 0
|
3254
|
+
];
|
3255
|
+
}
|
3256
|
+
}
|
3257
|
+
var Marks = {
|
3258
|
+
Heading: class Heading extends Mark {
|
3259
|
+
constructor() {
|
3260
|
+
super(...arguments);
|
3261
|
+
this.tag = co.literal("heading");
|
3262
|
+
this.level = co.number;
|
3263
|
+
}
|
3264
|
+
},
|
3265
|
+
Paragraph: class Paragraph extends Mark {
|
3266
|
+
constructor() {
|
3267
|
+
super(...arguments);
|
3268
|
+
this.tag = co.literal("paragraph");
|
3269
|
+
}
|
3270
|
+
},
|
3271
|
+
Link: class Link extends Mark {
|
3272
|
+
constructor() {
|
3273
|
+
super(...arguments);
|
3274
|
+
this.tag = co.literal("link");
|
3275
|
+
this.url = co.string;
|
3276
|
+
}
|
3277
|
+
},
|
3278
|
+
Strong: class Strong extends Mark {
|
3279
|
+
constructor() {
|
3280
|
+
super(...arguments);
|
3281
|
+
this.tag = co.literal("strong");
|
3282
|
+
}
|
3283
|
+
},
|
3284
|
+
Em: class Italic extends Mark {
|
3285
|
+
constructor() {
|
3286
|
+
super(...arguments);
|
3287
|
+
this.tag = co.literal("em");
|
3288
|
+
}
|
3289
|
+
}
|
3290
|
+
};
|
3291
|
+
|
2757
3292
|
// src/coValues/extensions/imageDef.ts
|
2758
3293
|
var _a, _b;
|
2759
3294
|
var ImageDefinition = class extends (_b = CoMap, _a = co.items, _b) {
|
@@ -2852,6 +3387,7 @@ var SchemaUnion = class _SchemaUnion extends CoValueBase {
|
|
2852
3387
|
};
|
2853
3388
|
|
2854
3389
|
export {
|
3390
|
+
activeAccountContext,
|
2855
3391
|
AnonymousJazzAgent,
|
2856
3392
|
CoValueBase,
|
2857
3393
|
loadCoValue,
|
@@ -2870,12 +3406,15 @@ export {
|
|
2870
3406
|
Profile,
|
2871
3407
|
Account,
|
2872
3408
|
isControlledAccount,
|
2873
|
-
Group,
|
2874
3409
|
CoFeed,
|
2875
3410
|
FileStream,
|
2876
3411
|
CoList,
|
3412
|
+
Group,
|
3413
|
+
CoPlainText,
|
3414
|
+
CoRichText,
|
3415
|
+
Marks,
|
2877
3416
|
ImageDefinition,
|
2878
3417
|
SchemaUnion
|
2879
3418
|
};
|
2880
3419
|
/* istanbul ignore file -- @preserve */
|
2881
|
-
//# sourceMappingURL=chunk-
|
3420
|
+
//# sourceMappingURL=chunk-VQZOWIPU.js.map
|