jazz-tools 0.7.0-alpha.9 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. package/.eslintrc.cjs +3 -10
  2. package/.prettierrc.js +9 -0
  3. package/.turbo/turbo-build.log +14 -15
  4. package/.turbo/turbo-lint.log +4 -0
  5. package/.turbo/turbo-test.log +140 -0
  6. package/CHANGELOG.md +331 -27
  7. package/LICENSE.txt +1 -1
  8. package/README.md +10 -2
  9. package/dist/coValues/account.js +86 -41
  10. package/dist/coValues/account.js.map +1 -1
  11. package/dist/coValues/coList.js +75 -48
  12. package/dist/coValues/coList.js.map +1 -1
  13. package/dist/coValues/coMap.js +167 -44
  14. package/dist/coValues/coMap.js.map +1 -1
  15. package/dist/coValues/coStream.js +192 -35
  16. package/dist/coValues/coStream.js.map +1 -1
  17. package/dist/coValues/deepLoading.js +60 -0
  18. package/dist/coValues/deepLoading.js.map +1 -0
  19. package/dist/coValues/extensions/imageDef.js +10 -7
  20. package/dist/coValues/extensions/imageDef.js.map +1 -1
  21. package/dist/coValues/group.js +73 -13
  22. package/dist/coValues/group.js.map +1 -1
  23. package/dist/coValues/interfaces.js +58 -35
  24. package/dist/coValues/interfaces.js.map +1 -1
  25. package/dist/implementation/devtoolsFormatters.js +114 -0
  26. package/dist/implementation/devtoolsFormatters.js.map +1 -0
  27. package/dist/implementation/refs.js +58 -18
  28. package/dist/implementation/refs.js.map +1 -1
  29. package/dist/implementation/schema.js +58 -0
  30. package/dist/implementation/schema.js.map +1 -0
  31. package/dist/implementation/subscriptionScope.js +19 -1
  32. package/dist/implementation/subscriptionScope.js.map +1 -1
  33. package/dist/implementation/symbols.js +5 -0
  34. package/dist/implementation/symbols.js.map +1 -0
  35. package/dist/index.js +4 -5
  36. package/dist/index.js.map +1 -1
  37. package/dist/internal.js +5 -2
  38. package/dist/internal.js.map +1 -1
  39. package/dist/tests/coList.test.js +51 -48
  40. package/dist/tests/coList.test.js.map +1 -1
  41. package/dist/tests/coMap.test.js +131 -74
  42. package/dist/tests/coMap.test.js.map +1 -1
  43. package/dist/tests/coStream.test.js +56 -41
  44. package/dist/tests/coStream.test.js.map +1 -1
  45. package/dist/tests/deepLoading.test.js +188 -0
  46. package/dist/tests/deepLoading.test.js.map +1 -0
  47. package/dist/tests/groupsAndAccounts.test.js +83 -0
  48. package/dist/tests/groupsAndAccounts.test.js.map +1 -0
  49. package/package.json +17 -9
  50. package/src/coValues/account.ts +186 -128
  51. package/src/coValues/coList.ts +156 -107
  52. package/src/coValues/coMap.ts +272 -148
  53. package/src/coValues/coStream.ts +388 -87
  54. package/src/coValues/deepLoading.ts +229 -0
  55. package/src/coValues/extensions/imageDef.ts +17 -13
  56. package/src/coValues/group.ts +166 -59
  57. package/src/coValues/interfaces.ts +189 -160
  58. package/src/implementation/devtoolsFormatters.ts +110 -0
  59. package/src/implementation/inspect.ts +1 -1
  60. package/src/implementation/refs.ts +80 -28
  61. package/src/implementation/schema.ts +141 -0
  62. package/src/implementation/subscriptionScope.ts +48 -12
  63. package/src/implementation/symbols.ts +11 -0
  64. package/src/index.ts +19 -8
  65. package/src/internal.ts +7 -3
  66. package/src/tests/coList.test.ts +77 -62
  67. package/src/tests/coMap.test.ts +201 -114
  68. package/src/tests/coStream.test.ts +113 -84
  69. package/src/tests/deepLoading.test.ts +304 -0
  70. package/src/tests/groupsAndAccounts.test.ts +91 -0
  71. package/dist/implementation/encoding.js +0 -26
  72. package/dist/implementation/encoding.js.map +0 -1
  73. package/src/implementation/encoding.ts +0 -105
@@ -0,0 +1,229 @@
1
+ import { SessionID } from "cojson";
2
+ import {
3
+ Account,
4
+ CoList,
5
+ CoStream,
6
+ CoStreamEntry,
7
+ ItemsSym,
8
+ Ref,
9
+ RefEncoded,
10
+ UnCo,
11
+ } from "../internal.js";
12
+ import { CoKeys, CoMap } from "./coMap.js";
13
+ import { CoValue, ID } from "./interfaces.js";
14
+
15
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
+ export function fulfillsDepth(depth: any, value: CoValue): boolean {
17
+ if (
18
+ value._type === "CoMap" ||
19
+ value._type === "Group" ||
20
+ value._type === "Account"
21
+ ) {
22
+ if (Array.isArray(depth) && depth.length === 1) {
23
+ return Object.entries(value).every(([key, item]) => {
24
+ return (
25
+ value as unknown as {
26
+ _refs: { [key: string]: Ref<CoValue> | undefined };
27
+ }
28
+ )._refs[key]
29
+ ? item && fulfillsDepth(depth[0], item)
30
+ : ((value as CoMap)._schema[
31
+ ItemsSym
32
+ ] as RefEncoded<CoValue>)!.optional;
33
+ });
34
+ } else {
35
+ for (const key of Object.keys(depth)) {
36
+ const map = value as unknown as {
37
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
+ [key: string]: any;
39
+ _refs: { [key: string]: Ref<CoValue> | undefined };
40
+ };
41
+ if (!map._refs[key] && map._schema[key].optional) {
42
+ continue;
43
+ }
44
+ if (!map[key]) {
45
+ return false;
46
+ }
47
+ if (!fulfillsDepth(depth[key], map[key])) {
48
+ return false;
49
+ }
50
+ }
51
+ return true;
52
+ }
53
+ } else if (value._type === "CoList") {
54
+ if (depth.length === 0) {
55
+ return true;
56
+ } else {
57
+ const itemDepth = depth[0];
58
+ return (value as CoList).every((item, i) =>
59
+ (value as CoList)._refs[i]
60
+ ? item && fulfillsDepth(itemDepth, item)
61
+ : (
62
+ (value as CoList)._schema[
63
+ ItemsSym
64
+ ] as RefEncoded<CoValue>
65
+ ).optional,
66
+ );
67
+ }
68
+ } else if (value._type === "CoStream") {
69
+ if (depth.length === 0) {
70
+ return true;
71
+ } else {
72
+ const itemDepth = depth[0];
73
+ return Object.values((value as CoStream).perSession).every(
74
+ (entry) =>
75
+ entry.ref
76
+ ? entry.value && fulfillsDepth(itemDepth, entry.value)
77
+ : (
78
+ (value as CoStream)._schema[
79
+ ItemsSym
80
+ ] as RefEncoded<CoValue>
81
+ ).optional,
82
+ );
83
+ }
84
+ } else if (value._type === "BinaryCoStream") {
85
+ return true;
86
+ } else {
87
+ console.error(value);
88
+ throw new Error("Unexpected value type: " + value._type);
89
+ }
90
+ }
91
+
92
+ type UnCoNotNull<T> = UnCo<Exclude<T, null>>;
93
+ type Clean<T> = UnCo<NonNullable<T>>;
94
+
95
+ export type DepthsIn<
96
+ V,
97
+ DepthLimit extends number = 5,
98
+ CurrentDepth extends number[] = [],
99
+ > =
100
+ | (DepthLimit extends CurrentDepth["length"]
101
+ ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
102
+ any
103
+ : // Basically V extends CoList - but if we used that we'd introduce circularity into the definition of CoList itself
104
+ V extends Array<infer Item>
105
+ ?
106
+ | [
107
+ DepthsIn<
108
+ UnCoNotNull<Item>,
109
+ DepthLimit,
110
+ [0, ...CurrentDepth]
111
+ >,
112
+ ]
113
+ | never[]
114
+ : // Basically V extends CoMap | Group | Account - but if we used that we'd introduce circularity into the definition of CoMap itself
115
+ V extends { _type: "CoMap" | "Group" | "Account" }
116
+ ?
117
+ | {
118
+ [Key in CoKeys<V> as Clean<V[Key]> extends CoValue
119
+ ? Key
120
+ : never]?: DepthsIn<
121
+ Clean<V[Key]>,
122
+ DepthLimit,
123
+ [0, ...CurrentDepth]
124
+ >;
125
+ }
126
+ | (ItemsSym extends keyof V
127
+ ? [
128
+ DepthsIn<
129
+ Clean<V[ItemsSym]>,
130
+ DepthLimit,
131
+ [0, ...CurrentDepth]
132
+ >,
133
+ ]
134
+ : never)
135
+ | never[]
136
+ : V extends {
137
+ _type: "CoStream";
138
+ byMe: CoStreamEntry<infer Item> | undefined;
139
+ }
140
+ ?
141
+ | [
142
+ DepthsIn<
143
+ UnCoNotNull<Item>,
144
+ DepthLimit,
145
+ [0, ...CurrentDepth]
146
+ >,
147
+ ]
148
+ | never[]
149
+ : never[])
150
+ | never[];
151
+
152
+ export type DeeplyLoaded<
153
+ V,
154
+ Depth,
155
+ DepthLimit extends number = 5,
156
+ CurrentDepth extends number[] = [],
157
+ > = DepthLimit extends CurrentDepth["length"]
158
+ ? V
159
+ : // Basically V extends CoList - but if we used that we'd introduce circularity into the definition of CoList itself
160
+ [V] extends [Array<infer Item>]
161
+ ? Depth extends never[] // []
162
+ ? V
163
+ : UnCoNotNull<Item> extends CoValue
164
+ ? Depth extends Array<infer ItemDepth> // [item-depth]
165
+ ? (UnCoNotNull<Item> &
166
+ DeeplyLoaded<
167
+ UnCoNotNull<Item>,
168
+ ItemDepth,
169
+ DepthLimit,
170
+ [0, ...CurrentDepth]
171
+ >)[] &
172
+ V
173
+ : never
174
+ : V
175
+ : // Basically V extends CoMap | Group | Account - but if we used that we'd introduce circularity into the definition of CoMap itself
176
+ [V] extends [{ _type: "CoMap" | "Group" | "Account" }]
177
+ ? Depth extends never[]
178
+ ? V
179
+ : Depth extends Array<infer ItemDepth>
180
+ ? ItemsSym extends keyof V
181
+ ? V & {
182
+ [key: string]: DeeplyLoaded<
183
+ Clean<V[ItemsSym]>,
184
+ ItemDepth,
185
+ DepthLimit,
186
+ [0, ...CurrentDepth]
187
+ >;
188
+ }
189
+ : never
190
+ : keyof Depth extends never
191
+ ? V
192
+ : {
193
+ [Key in keyof Depth]-?: Key extends CoKeys<V>
194
+ ? Clean<V[Key]> extends CoValue
195
+ ?
196
+ | DeeplyLoaded<
197
+ Clean<V[Key]>,
198
+ Depth[Key],
199
+ DepthLimit,
200
+ [0, ...CurrentDepth]
201
+ >
202
+ | (undefined extends V[Key]
203
+ ? undefined
204
+ : never)
205
+ : never
206
+ : never;
207
+ } & V
208
+ : [V] extends [
209
+ {
210
+ _type: "CoStream";
211
+ byMe: CoStreamEntry<infer Item> | undefined;
212
+ },
213
+ ]
214
+ ? Depth extends never[]
215
+ ? V
216
+ : V & {
217
+ byMe?: { value: UnCoNotNull<Item> };
218
+ inCurrentSession?: { value: UnCoNotNull<Item> };
219
+ perSession: {
220
+ [key: SessionID]: { value: UnCoNotNull<Item> };
221
+ };
222
+ } & { [key: ID<Account>]: { value: UnCoNotNull<Item> } }
223
+ : [V] extends [
224
+ {
225
+ _type: "BinaryCoStream";
226
+ },
227
+ ]
228
+ ? V
229
+ : never;
@@ -1,28 +1,32 @@
1
1
  import {
2
2
  BinaryCoStream,
3
3
  CoMap,
4
- val,
4
+ co,
5
5
  subscriptionsScopes,
6
6
  } from "../../internal.js";
7
7
 
8
- export class ImageDefinition extends CoMap<ImageDefinition> {
9
- originalSize = val.json<[number, number]>();
10
- placeholderDataURL? = val.string;
8
+ /** @category Media */
9
+ export class ImageDefinition extends CoMap {
10
+ originalSize = co.json<[number, number]>();
11
+ placeholderDataURL? = co.string;
11
12
 
12
- [val.items] = val.ref(() => BinaryCoStream);
13
- [res: `${number}x${number}`]: val<BinaryCoStream | null>;
13
+ [co.items] = co.ref(BinaryCoStream);
14
+ [res: `${number}x${number}`]: co<BinaryCoStream | null>;
14
15
 
15
- get highestResAvailable():
16
- | { res: `${number}x${number}`; stream: BinaryCoStream }
17
- | undefined {
16
+ highestResAvailable(options?: {
17
+ maxWidth?: number;
18
+ }): { res: `${number}x${number}`; stream: BinaryCoStream } | undefined {
18
19
  if (!subscriptionsScopes.get(this)) {
19
20
  console.warn(
20
- "highestResAvailable() only makes sense when used within a subscription."
21
+ "highestResAvailable() only makes sense when used within a subscription.",
21
22
  );
22
23
  }
23
24
 
24
- const resolutions = Object.keys(this).filter((key) =>
25
- key.match(/^\d+x\d+$/)
25
+ const resolutions = Object.keys(this).filter(
26
+ (key) =>
27
+ key.match(/^\d+x\d+$/) &&
28
+ (options?.maxWidth === undefined ||
29
+ Number(key.split("x")[0]) <= options.maxWidth),
26
30
  ) as `${number}x${number}`[];
27
31
 
28
32
  resolutions.sort((a, b) => {
@@ -52,4 +56,4 @@ export class ImageDefinition extends CoMap<ImageDefinition> {
52
56
  }
53
57
  );
54
58
  }
55
- }
59
+ }
@@ -1,71 +1,81 @@
1
- import type { Everyone, RawGroup, Role } from "cojson";
2
- import type { CoValue, ID, JsonEncoded, RefEncoded } from "../internal.js";
1
+ import type { AccountID, Everyone, RawGroup, Role } from "cojson";
2
+ import type {
3
+ CoValue,
4
+ ID,
5
+ RefEncoded,
6
+ Schema,
7
+ AccountCtx,
8
+ CoValueClass,
9
+ DeeplyLoaded,
10
+ DepthsIn,
11
+ UnavailableError,
12
+ } from "../internal.js";
3
13
  import {
4
14
  Account,
5
15
  CoMap,
6
16
  CoValueBase,
7
17
  Ref,
8
- val,
18
+ co,
9
19
  isControlledAccount,
10
20
  AccountAndGroupProxyHandler,
21
+ MembersSym,
22
+ loadCoValue,
23
+ loadCoValueEf,
24
+ subscribeToCoValue,
25
+ subscribeToCoValueEf,
26
+ ensureCoValueLoaded,
27
+ subscribeToExistingCoValue,
11
28
  } from "../internal.js";
29
+ import { Effect, Stream } from "effect";
12
30
 
13
- export class Profile extends CoMap<{ name: val<string> }> {
14
- name = val.string;
31
+ /** @category Identity & Permissions */
32
+ export class Profile extends CoMap {
33
+ name = co.string;
15
34
  }
16
35
 
17
- export class Group<
18
- Def extends { profile: Profile | null; root: CoMap | null } = {
19
- profile: Profile | null;
20
- root: CoMap | null;
21
- },
22
- >
23
- extends CoValueBase
24
- implements CoValue<"Group", RawGroup>
25
- {
26
- id!: ID<this>;
27
- _type!: "Group";
36
+ /** @category Identity & Permissions */
37
+ export class Group extends CoValueBase implements CoValue {
38
+ declare id: ID<this>;
39
+ declare _type: "Group";
28
40
  static {
29
41
  this.prototype._type = "Group";
30
42
  }
31
- _raw!: RawGroup;
32
-
33
- static _encoding: any;
34
- get _encoding(): {
35
- profile: Def["profile"] extends CoValue
36
- ? RefEncoded<Def["profile"]>
37
- : JsonEncoded;
38
- root: Def["root"] extends CoValue
39
- ? RefEncoded<Def["root"]>
40
- : JsonEncoded;
43
+ declare _raw: RawGroup;
44
+
45
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
+ static _schema: any;
47
+ get _schema(): {
48
+ profile: Schema;
49
+ root: Schema;
50
+ [MembersSym]: RefEncoded<Account>;
41
51
  } {
42
- return (this.constructor as typeof Group)._encoding;
52
+ return (this.constructor as typeof Group)._schema;
43
53
  }
44
54
  static {
45
- this._encoding = {
46
- profile: { json: true },
47
- root: { json: true },
55
+ this._schema = {
56
+ profile: "json" satisfies Schema,
57
+ root: "json" satisfies Schema,
58
+ [MembersSym]: {
59
+ ref: () => Account,
60
+ optional: false,
61
+ } satisfies RefEncoded<Account>,
62
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
48
63
  } as any;
49
- Object.defineProperty(this.prototype, "_encoding", {
50
- get: () => this._encoding,
64
+ Object.defineProperty(this.prototype, "_schema", {
65
+ get: () => this._schema,
51
66
  });
52
67
  }
53
68
 
54
- profile!: Def["profile"] extends Profile
55
- ? Def["profile"] | null
56
- : undefined;
57
-
58
- root!: Def["root"] extends CoMap ? Def["root"] | null : undefined;
69
+ declare profile: Profile | null;
70
+ declare root: CoMap | null;
71
+ declare [MembersSym]: Account | null;
59
72
 
60
- get _refs(): {
61
- profile: Def["profile"] extends Profile ? Ref<Def["profile"]> : never;
62
- root: Def["root"] extends CoMap ? Ref<Def["root"]> : never;
63
- } {
73
+ get _refs() {
64
74
  const profileID = this._raw.get("profile") as unknown as
65
- | ID<NonNullable<Def["profile"]>>
75
+ | ID<NonNullable<this["profile"]>>
66
76
  | undefined;
67
77
  const rootID = this._raw.get("root") as unknown as
68
- | ID<NonNullable<Def["root"]>>
78
+ | ID<NonNullable<this["root"]>>
69
79
  | undefined;
70
80
  return {
71
81
  profile:
@@ -73,34 +83,35 @@ export class Group<
73
83
  (new Ref(
74
84
  profileID,
75
85
  this._loadedAs,
76
- this._encoding.profile as RefEncoded<
77
- NonNullable<Def["profile"]>
78
- >
79
- ) as any),
86
+ this._schema.profile as RefEncoded<
87
+ NonNullable<this["profile"]>
88
+ >,
89
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
90
+ ) as any as this["profile"] extends Profile
91
+ ? Ref<this["profile"]>
92
+ : never),
80
93
  root:
81
94
  rootID &&
82
95
  (new Ref(
83
96
  rootID,
84
97
  this._loadedAs,
85
- this._encoding.root as RefEncoded<NonNullable<Def["root"]>>
86
- ) as any),
98
+ this._schema.root as RefEncoded<NonNullable<this["root"]>>,
99
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
100
+ ) as any as this["root"] extends CoMap
101
+ ? Ref<this["root"]>
102
+ : never),
87
103
  };
88
104
  }
89
105
 
90
- constructor(options: { owner: Account | Group });
91
- constructor(init: any, options: { fromRaw: RawGroup });
92
- constructor(init: undefined, options: { owner: Account | Group });
93
- constructor(
94
- init: undefined | { owner: Account | Group },
95
- options?: { fromRaw: RawGroup } | { owner: Account | Group }
96
- ) {
106
+ /** @deprecated Don't use constructor directly, use .create */
107
+ constructor(options: { fromRaw: RawGroup } | { owner: Account | Group }) {
97
108
  super();
98
109
  let raw: RawGroup;
99
110
 
100
111
  if (options && "fromRaw" in options) {
101
112
  raw = options.fromRaw;
102
113
  } else {
103
- const initOwner = options?.owner || init?.owner;
114
+ const initOwner = options.owner;
104
115
  if (!initOwner) throw new Error("No owner provided");
105
116
  if (
106
117
  initOwner instanceof Account &&
@@ -110,7 +121,7 @@ export class Group<
110
121
  raw = rawOwner.createGroup();
111
122
  } else {
112
123
  throw new Error(
113
- "Can only construct group as a controlled account"
124
+ "Can only construct group as a controlled account",
114
125
  );
115
126
  }
116
127
  }
@@ -125,15 +136,111 @@ export class Group<
125
136
 
126
137
  return new Proxy(
127
138
  this,
128
- AccountAndGroupProxyHandler as ProxyHandler<this>
139
+ AccountAndGroupProxyHandler as ProxyHandler<this>,
129
140
  );
130
141
  }
131
142
 
143
+ static create<G extends Group>(
144
+ this: CoValueClass<G>,
145
+ options: { owner: Account },
146
+ ) {
147
+ return new this(options);
148
+ }
149
+
132
150
  myRole(): Role | undefined {
133
151
  return this._raw.myRole();
134
152
  }
135
153
 
136
154
  addMember(member: Everyone | Account, role: Role) {
137
155
  this._raw.addMember(member === "everyone" ? member : member._raw, role);
156
+ return this;
157
+ }
158
+
159
+ get members() {
160
+ return this._raw
161
+ .keys()
162
+ .filter((key) => {
163
+ return key === "everyone" || key.startsWith("co_");
164
+ })
165
+ .map((id) => {
166
+ const role = this._raw.get(id as Everyone | AccountID);
167
+ const accountID =
168
+ id === "everyone"
169
+ ? undefined
170
+ : (id as unknown as ID<Account>);
171
+ const ref =
172
+ accountID &&
173
+ new Ref<NonNullable<this[MembersSym]>>(
174
+ accountID,
175
+ this._loadedAs,
176
+ this._schema[MembersSym],
177
+ );
178
+ const accessRef = () => ref?.accessFrom(this, "members." + id);
179
+
180
+ return {
181
+ id: id as unknown as Everyone | ID<this[MembersSym]>,
182
+ role,
183
+ ref,
184
+ get account() {
185
+ return accessRef();
186
+ },
187
+ };
188
+ });
189
+ }
190
+
191
+ /** @category Subscription & Loading */
192
+ static load<G extends Group, Depth>(
193
+ this: CoValueClass<G>,
194
+ id: ID<G>,
195
+ as: Account,
196
+ depth: Depth & DepthsIn<G>,
197
+ ): Promise<DeeplyLoaded<G, Depth> | undefined> {
198
+ return loadCoValue(this, id, as, depth);
199
+ }
200
+
201
+ /** @category Subscription & Loading */
202
+ static loadEf<G extends Group, Depth>(
203
+ this: CoValueClass<G>,
204
+ id: ID<G>,
205
+ depth: Depth & DepthsIn<G>,
206
+ ): Effect.Effect<DeeplyLoaded<G, Depth>, UnavailableError, AccountCtx> {
207
+ return loadCoValueEf<G, Depth>(this, id, depth);
208
+ }
209
+
210
+ /** @category Subscription & Loading */
211
+ static subscribe<G extends Group, Depth>(
212
+ this: CoValueClass<G>,
213
+ id: ID<G>,
214
+ as: Account,
215
+ depth: Depth & DepthsIn<G>,
216
+ listener: (value: DeeplyLoaded<G, Depth>) => void,
217
+ ): () => void {
218
+ return subscribeToCoValue<G, Depth>(this, id, as, depth, listener);
219
+ }
220
+
221
+ /** @category Subscription & Loading */
222
+ static subscribeEf<G extends Group, Depth>(
223
+ this: CoValueClass<G>,
224
+ id: ID<G>,
225
+ depth: Depth & DepthsIn<G>,
226
+ ): Stream.Stream<DeeplyLoaded<G, Depth>, UnavailableError, AccountCtx> {
227
+ return subscribeToCoValueEf<G, Depth>(this, id, depth);
228
+ }
229
+
230
+ /** @category Subscription & Loading */
231
+ ensureLoaded<G extends Group, Depth>(
232
+ this: G,
233
+ depth: Depth & DepthsIn<G>,
234
+ ): Promise<DeeplyLoaded<G, Depth> | undefined> {
235
+ return ensureCoValueLoaded(this, depth);
236
+ }
237
+
238
+ /** @category Subscription & Loading */
239
+ subscribe<G extends Group, Depth>(
240
+ this: G,
241
+ depth: Depth & DepthsIn<G>,
242
+ listener: (value: DeeplyLoaded<G, Depth>) => void,
243
+ ): () => void {
244
+ return subscribeToExistingCoValue(this, depth, listener);
138
245
  }
139
246
  }