jazz-tools 0.7.0-alpha.9 → 0.7.3

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.
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
  }