jazz-tools 0.9.0 → 0.9.8

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.
@@ -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) {
@@ -369,7 +396,7 @@ function fulfillsDepth(depth, value) {
369
396
  (entry) => entry.ref ? entry.value && fulfillsDepth(itemDepth, entry.value) : value._schema[ItemsSym].optional
370
397
  );
371
398
  }
372
- } else if (value._type === "BinaryCoStream") {
399
+ } else if (value._type === "BinaryCoStream" || value._type === "CoPlainText") {
373
400
  return true;
374
401
  } else {
375
402
  console.error(value);
@@ -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
- return "_type" in options && (options._type === "Account" || options._type === "Group") ? { owner: options, uniqueness: void 0 } : {
792
- owner: options.owner,
793
- uniqueness: options.unique ? { uniqueness: options.unique } : void 0
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
- * Load a `CoMap` with a given ID, as a given account.
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
- * Load and subscribe to a `CoMap` with a given ID, as a given account.
1281
- *
1282
- * Automatically also subscribes to updates to all referenced/nested CoValues as soon as they are accessed in the listener.
1283
- *
1284
- * `depth` specifies which (if any) fields that reference other CoValues to load as well before calling `listener` for the first time.
1285
- * The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
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
- /** @category Subscription & Loading */
1638
- static load(id, as, depth) {
1639
- return loadCoValue(this, id, as, depth);
1695
+ static load(id, asOrDepth, depth) {
1696
+ return loadCoValueWithoutMe(this, id, asOrDepth, depth);
1640
1697
  }
1641
- /** @category Subscription & Loading */
1642
- static subscribe(id, as, depth, listener) {
1643
- return subscribeToCoValue(this, id, as, depth, listener);
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,135 +1797,6 @@ function isControlledAccount(account) {
1735
1797
  }
1736
1798
  RegisteredSchemas["Account"] = Account;
1737
1799
 
1738
- // src/coValues/group.ts
1739
- var _Group = class _Group extends CoValueBase {
1740
- get _schema() {
1741
- return this.constructor._schema;
1742
- }
1743
- get _refs() {
1744
- const profileID = this._raw.get("profile");
1745
- const rootID = this._raw.get("root");
1746
- return {
1747
- profile: profileID && new Ref(
1748
- profileID,
1749
- this._loadedAs,
1750
- this._schema.profile
1751
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1752
- ),
1753
- root: rootID && new Ref(
1754
- rootID,
1755
- this._loadedAs,
1756
- this._schema.root
1757
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1758
- )
1759
- };
1760
- }
1761
- /** @deprecated Don't use constructor directly, use .create */
1762
- constructor(options) {
1763
- super();
1764
- let raw;
1765
- if (options && "fromRaw" in options) {
1766
- raw = options.fromRaw;
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
1800
  // src/coValues/coFeed.ts
1868
1801
  import { MAX_RECOMMENDED_TX_SIZE, cojsonInternals as cojsonInternals3 } from "cojson";
1869
1802
  var _CoFeed = class _CoFeed extends CoValueBase {
@@ -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
- * Load a `CoFeed`
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
- * Subscribe to a `CoFeed`, when you have an ID but don't have a `CoFeed` instance yet
2029
- * @category Subscription & Loading
2030
- */
2031
- static subscribe(id, as, depth, listener) {
2032
- return subscribeToCoValue(this, id, as, depth, listener);
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
- * Load a `FileStream` as a `Blob`
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
- * Load a `FileStream`
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
- * Subscribe to a `FileStream`, when you have an ID but don't have a `FileStream` instance yet
2364
- * @category Subscription & Loading
2365
- */
2366
- static subscribe(id, as, depth, listener) {
2367
- return subscribeToCoValue(this, id, as, depth, listener);
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
- * Load a `CoList` with a given ID, as a given account.
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
- * Load and subscribe to a `CoList` with a given ID, as a given account.
2618
- *
2619
- * Automatically also subscribes to updates to all referenced/nested CoValues as soon as they are accessed in the listener.
2620
- *
2621
- * `depth` specifies if item CoValue references should be loaded as well before calling `listener` for the first time.
2622
- * The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
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,8 +2636,573 @@ var CoListProxyHandler = {
2754
2636
  }
2755
2637
  };
2756
2638
 
2757
- // src/coValues/extensions/imageDef.ts
2758
- var _a, _b;
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
+ toString() {
2802
+ return this._raw.toString();
2803
+ }
2804
+ valueOf() {
2805
+ return this._raw.toString();
2806
+ }
2807
+ toJSON() {
2808
+ return this._raw.toString();
2809
+ }
2810
+ [inspect]() {
2811
+ return this.toJSON();
2812
+ }
2813
+ insertAfter(idx, text) {
2814
+ this._raw.insertAfter(idx, text);
2815
+ }
2816
+ deleteRange(range) {
2817
+ this._raw.deleteRange(range);
2818
+ }
2819
+ posBefore(idx) {
2820
+ return this._raw.mapping.opIDbeforeIdx[idx];
2821
+ }
2822
+ posAfter(idx) {
2823
+ return this._raw.mapping.opIDafterIdx[idx];
2824
+ }
2825
+ idxBefore(pos) {
2826
+ return this._raw.mapping.idxBeforeOpID[stringifyOpID(pos)];
2827
+ }
2828
+ idxAfter(pos) {
2829
+ return this._raw.mapping.idxAfterOpID[stringifyOpID(pos)];
2830
+ }
2831
+ static fromRaw(raw) {
2832
+ return new this({ fromRaw: raw });
2833
+ }
2834
+ /**
2835
+ * Load a `CoPlainText` with a given ID, as a given account.
2836
+ *
2837
+ * `depth` specifies which (if any) fields that reference other CoValues to load as well before resolving.
2838
+ * The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
2839
+ *
2840
+ * You can pass `[]` or `{}` for shallowly loading only this CoPlainText, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues.
2841
+ *
2842
+ * Check out the `load` methods on `CoMap`/`CoList`/`CoStream`/`Group`/`Account` to see which depth structures are valid to nest.
2843
+ *
2844
+ * @example
2845
+ * ```ts
2846
+ * const person = await Person.load(
2847
+ * "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
2848
+ * me,
2849
+ * { pet: {} }
2850
+ * );
2851
+ * ```
2852
+ *
2853
+ * @category Subscription & Loading
2854
+ */
2855
+ static load(id, as) {
2856
+ return loadCoValue(this, id, as ?? activeAccountContext.get(), []);
2857
+ }
2858
+ static subscribe(id, asOrListener, listener) {
2859
+ if (isAccountInstance(asOrListener)) {
2860
+ return subscribeToCoValue(this, id, asOrListener, [], listener);
2861
+ }
2862
+ return subscribeToCoValue(
2863
+ this,
2864
+ id,
2865
+ activeAccountContext.get(),
2866
+ [],
2867
+ listener
2868
+ );
2869
+ }
2870
+ // /**
2871
+ // * Effectful version of `CoMap.subscribe()` that returns a stream of updates.
2872
+ // *
2873
+ // * Needs to be run inside an `AccountCtx` context.
2874
+ // *
2875
+ // * @category Subscription & Loading
2876
+ // */
2877
+ // static subscribeEf<T extends CoPlainText>(
2878
+ // this: CoValueClass<T>,
2879
+ // id: ID<T>,
2880
+ // ): Stream.Stream<T, UnavailableError, AccountCtx> {
2881
+ // return subscribeToCoValueEf(this, id, []);
2882
+ // }
2883
+ /**
2884
+ * Given an already loaded `CoMap`, subscribe to updates to the `CoMap` and ensure that the specified fields are loaded to the specified depth.
2885
+ *
2886
+ * Works like `CoMap.subscribe()`, but you don't need to pass the ID or the account to load as again.
2887
+ *
2888
+ * Returns an unsubscribe function that you should call when you no longer need updates.
2889
+ *
2890
+ * @category Subscription & Loading
2891
+ **/
2892
+ subscribe(listener) {
2893
+ return subscribeToExistingCoValue(this, [], listener);
2894
+ }
2895
+ };
2896
+
2897
+ // src/coValues/coRichText.ts
2898
+ var Mark = class extends CoMap {
2899
+ constructor() {
2900
+ super(...arguments);
2901
+ this.startAfter = co.json();
2902
+ this.startBefore = co.json();
2903
+ this.endAfter = co.json();
2904
+ this.endBefore = co.json();
2905
+ this.tag = co.string;
2906
+ }
2907
+ };
2908
+ var CoRichText = class extends CoMap {
2909
+ constructor() {
2910
+ super(...arguments);
2911
+ this.text = co.ref(CoPlainText);
2912
+ this.marks = co.ref(CoList.Of(co.ref(Mark)));
2913
+ }
2914
+ /**
2915
+ * Create a CoRichText from plain text.
2916
+ */
2917
+ static createFromPlainText(text, options) {
2918
+ return this.create(
2919
+ {
2920
+ text: CoPlainText.create(text, { owner: options.owner }),
2921
+ marks: CoList.Of(co.ref(Mark)).create([], {
2922
+ owner: options.owner
2923
+ })
2924
+ },
2925
+ { owner: options.owner }
2926
+ );
2927
+ }
2928
+ /**
2929
+ * Create a CoRichText from plain text and a mark.
2930
+ */
2931
+ static createFromPlainTextAndMark(text, WrapIn, extraArgs, options) {
2932
+ const richtext = this.createFromPlainText(text, options);
2933
+ richtext.insertMark(0, text.length, WrapIn, extraArgs);
2934
+ return richtext;
2935
+ }
2936
+ /**
2937
+ * Insert text at a specific index.
2938
+ */
2939
+ insertAfter(idx, text) {
2940
+ if (!this.text)
2941
+ throw new Error("Cannot insert into a CoRichText without loaded text");
2942
+ this.text.insertAfter(idx, text);
2943
+ }
2944
+ /**
2945
+ * Delete a range of text.
2946
+ */
2947
+ deleteRange(range) {
2948
+ if (!this.text)
2949
+ throw new Error("Cannot delete from a CoRichText without loaded text");
2950
+ this.text.deleteRange(range);
2951
+ }
2952
+ /**
2953
+ * Get the position of a specific index.
2954
+ */
2955
+ posBefore(idx) {
2956
+ if (!this.text)
2957
+ throw new Error(
2958
+ "Cannot get posBefore in a CoRichText without loaded text"
2959
+ );
2960
+ return this.text.posBefore(idx);
2961
+ }
2962
+ /**
2963
+ * Get the position of a specific index.
2964
+ */
2965
+ posAfter(idx) {
2966
+ if (!this.text)
2967
+ throw new Error(
2968
+ "Cannot get posAfter in a CoRichText without loaded text"
2969
+ );
2970
+ return this.text.posAfter(idx);
2971
+ }
2972
+ /**
2973
+ * Get the index of a specific position.
2974
+ */
2975
+ idxBefore(pos) {
2976
+ if (!this.text)
2977
+ throw new Error(
2978
+ "Cannot get idxBefore in a CoRichText without loaded text"
2979
+ );
2980
+ return this.text.idxBefore(pos);
2981
+ }
2982
+ /**
2983
+ * Get the index of a specific position.
2984
+ */
2985
+ idxAfter(pos) {
2986
+ if (!this.text)
2987
+ throw new Error(
2988
+ "Cannot get idxAfter in a CoRichText without loaded text"
2989
+ );
2990
+ return this.text.idxAfter(pos);
2991
+ }
2992
+ /**
2993
+ * Insert a mark at a specific range.
2994
+ */
2995
+ insertMark(start, end, RangeClass, extraArgs, options) {
2996
+ if (!this.marks) {
2997
+ throw new Error("Cannot insert a range without loaded ranges");
2998
+ }
2999
+ const range = RangeClass.create(
3000
+ {
3001
+ ...extraArgs,
3002
+ startAfter: this.posBefore(start),
3003
+ startBefore: this.posAfter(start),
3004
+ endAfter: this.posBefore(end),
3005
+ endBefore: this.posAfter(end)
3006
+ },
3007
+ { owner: options?.markOwner || this._owner }
3008
+ );
3009
+ this.marks.push(range);
3010
+ }
3011
+ /**
3012
+ * Resolve the positions of all marks.
3013
+ */
3014
+ resolveMarks() {
3015
+ if (!this.text || !this.marks) {
3016
+ throw new Error("Cannot resolve ranges without loaded text and ranges");
3017
+ }
3018
+ const ranges = this.marks.flatMap((mark) => {
3019
+ if (!mark) return [];
3020
+ const startBefore = this.idxAfter(mark.startBefore);
3021
+ const endAfter = this.idxAfter(mark.endAfter);
3022
+ if (startBefore === void 0 || endAfter === void 0) {
3023
+ return [];
3024
+ }
3025
+ const startAfter = mark.startAfter ? this.idxAfter(mark.startAfter) : startBefore - 1;
3026
+ const endBefore = mark.endBefore ? this.idxAfter(mark.endBefore) : endAfter + 1;
3027
+ if (startAfter === void 0 || endBefore === void 0) {
3028
+ return [];
3029
+ }
3030
+ return [
3031
+ {
3032
+ sourceMark: mark,
3033
+ startAfter,
3034
+ startBefore,
3035
+ endAfter,
3036
+ endBefore,
3037
+ tag: mark.tag,
3038
+ from: mark
3039
+ }
3040
+ ];
3041
+ });
3042
+ return ranges;
3043
+ }
3044
+ /**
3045
+ * Resolve and diffuse the positions of all marks.
3046
+ */
3047
+ resolveAndDiffuseMarks() {
3048
+ return this.resolveMarks().flatMap((range) => [
3049
+ ...range.startAfter < range.startBefore - 1 ? [
3050
+ {
3051
+ start: range.startAfter,
3052
+ end: range.startBefore - 1,
3053
+ side: "uncertainStart",
3054
+ sourceMark: range.sourceMark
3055
+ }
3056
+ ] : [],
3057
+ {
3058
+ start: range.startBefore - 1,
3059
+ end: range.endAfter + 1,
3060
+ side: "certainMiddle",
3061
+ sourceMark: range.sourceMark
3062
+ },
3063
+ ...range.endAfter + 1 < range.endBefore ? [
3064
+ {
3065
+ start: range.endAfter + 1,
3066
+ end: range.endBefore,
3067
+ side: "uncertainEnd",
3068
+ sourceMark: range.sourceMark
3069
+ }
3070
+ ] : []
3071
+ ]);
3072
+ }
3073
+ /**
3074
+ * Resolve, diffuse, and focus the positions of all marks.
3075
+ */
3076
+ resolveAndDiffuseAndFocusMarks() {
3077
+ return this.resolveAndDiffuseMarks().filter(
3078
+ (range) => range.side === "certainMiddle"
3079
+ );
3080
+ }
3081
+ /**
3082
+ * Convert a CoRichText to a tree structure useful for client libraries.
3083
+ */
3084
+ toTree(tagPrecedence) {
3085
+ const ranges = this.resolveAndDiffuseAndFocusMarks();
3086
+ const text = this.text?.toString() || "";
3087
+ let currentNodes = [
3088
+ {
3089
+ type: "leaf",
3090
+ start: 0,
3091
+ end: text.length
3092
+ }
3093
+ ];
3094
+ const rangesSortedLowToHighPrecedence = ranges.sort((a, b) => {
3095
+ const aPrecedence = tagPrecedence.indexOf(a.sourceMark.tag);
3096
+ const bPrecedence = tagPrecedence.indexOf(b.sourceMark.tag);
3097
+ return bPrecedence - aPrecedence;
3098
+ });
3099
+ for (const range of rangesSortedLowToHighPrecedence) {
3100
+ const newNodes = currentNodes.flatMap((node) => {
3101
+ const [before, inOrAfter] = splitNode(node, range.start);
3102
+ const [inside, after] = inOrAfter ? splitNode(inOrAfter, range.end) : [void 0, void 0];
3103
+ return [
3104
+ ...before ? [before] : [],
3105
+ ...inside ? [
3106
+ {
3107
+ type: "node",
3108
+ tag: range.sourceMark.tag,
3109
+ start: inside.start,
3110
+ end: inside.end,
3111
+ children: [inside]
3112
+ }
3113
+ ] : [],
3114
+ ...after ? [after] : []
3115
+ ];
3116
+ });
3117
+ currentNodes = newNodes;
3118
+ }
3119
+ return {
3120
+ type: "node",
3121
+ tag: "root",
3122
+ start: 0,
3123
+ end: text.length,
3124
+ children: currentNodes
3125
+ };
3126
+ }
3127
+ /**
3128
+ * Convert a CoRichText to plain text.
3129
+ */
3130
+ toString() {
3131
+ if (!this.text) return "";
3132
+ return this.text.toString();
3133
+ }
3134
+ };
3135
+ function splitNode(node, at) {
3136
+ if (node.type === "leaf") {
3137
+ return [
3138
+ at > node.start ? {
3139
+ type: "leaf",
3140
+ start: node.start,
3141
+ end: Math.min(at, node.end)
3142
+ } : void 0,
3143
+ at < node.end ? {
3144
+ type: "leaf",
3145
+ start: Math.max(at, node.start),
3146
+ end: node.end
3147
+ } : void 0
3148
+ ];
3149
+ } else {
3150
+ const children = node.children;
3151
+ return [
3152
+ at > node.start ? {
3153
+ type: "node",
3154
+ tag: node.tag,
3155
+ start: node.start,
3156
+ end: Math.min(at, node.end),
3157
+ children: children.map((child) => splitNode(child, at)[0]).filter((c) => !!c)
3158
+ } : void 0,
3159
+ at < node.end ? {
3160
+ type: "node",
3161
+ tag: node.tag,
3162
+ start: Math.max(at, node.start),
3163
+ end: node.end,
3164
+ children: children.map((child) => splitNode(child, at)[1]).filter((c) => !!c)
3165
+ } : void 0
3166
+ ];
3167
+ }
3168
+ }
3169
+ var Marks = {
3170
+ Heading: class Heading extends Mark {
3171
+ constructor() {
3172
+ super(...arguments);
3173
+ this.tag = co.literal("heading");
3174
+ this.level = co.number;
3175
+ }
3176
+ },
3177
+ Paragraph: class Paragraph extends Mark {
3178
+ constructor() {
3179
+ super(...arguments);
3180
+ this.tag = co.literal("paragraph");
3181
+ }
3182
+ },
3183
+ Link: class Link extends Mark {
3184
+ constructor() {
3185
+ super(...arguments);
3186
+ this.tag = co.literal("link");
3187
+ this.url = co.string;
3188
+ }
3189
+ },
3190
+ Strong: class Strong extends Mark {
3191
+ constructor() {
3192
+ super(...arguments);
3193
+ this.tag = co.literal("strong");
3194
+ }
3195
+ },
3196
+ Em: class Italic extends Mark {
3197
+ constructor() {
3198
+ super(...arguments);
3199
+ this.tag = co.literal("em");
3200
+ }
3201
+ }
3202
+ };
3203
+
3204
+ // src/coValues/extensions/imageDef.ts
3205
+ var _a, _b;
2759
3206
  var ImageDefinition = class extends (_b = CoMap, _a = co.items, _b) {
2760
3207
  constructor() {
2761
3208
  super(...arguments);
@@ -2852,6 +3299,7 @@ var SchemaUnion = class _SchemaUnion extends CoValueBase {
2852
3299
  };
2853
3300
 
2854
3301
  export {
3302
+ activeAccountContext,
2855
3303
  AnonymousJazzAgent,
2856
3304
  CoValueBase,
2857
3305
  loadCoValue,
@@ -2870,12 +3318,15 @@ export {
2870
3318
  Profile,
2871
3319
  Account,
2872
3320
  isControlledAccount,
2873
- Group,
2874
3321
  CoFeed,
2875
3322
  FileStream,
2876
3323
  CoList,
3324
+ Group,
3325
+ CoPlainText,
3326
+ CoRichText,
3327
+ Marks,
2877
3328
  ImageDefinition,
2878
3329
  SchemaUnion
2879
3330
  };
2880
3331
  /* istanbul ignore file -- @preserve */
2881
- //# sourceMappingURL=chunk-EK2I4C5W.js.map
3332
+ //# sourceMappingURL=chunk-YD32FKHW.js.map