jazz-tools 0.8.44 → 0.8.45

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. package/.turbo/turbo-build.log +16 -10
  2. package/CHANGELOG.md +12 -0
  3. package/dist/chunk-5WLKIDKU.js +2844 -0
  4. package/dist/chunk-5WLKIDKU.js.map +1 -0
  5. package/dist/index.native.js +63 -0
  6. package/dist/index.native.js.map +1 -0
  7. package/dist/index.web.js +61 -0
  8. package/dist/index.web.js.map +1 -0
  9. package/package.json +9 -12
  10. package/src/coValues/account.ts +21 -9
  11. package/src/coValues/coFeed.ts +4 -3
  12. package/src/coValues/coList.ts +8 -5
  13. package/src/coValues/coMap.ts +6 -3
  14. package/src/coValues/deepLoading.ts +6 -12
  15. package/src/coValues/extensions/imageDef.ts +3 -1
  16. package/src/coValues/group.ts +8 -11
  17. package/src/coValues/inbox.ts +377 -0
  18. package/src/coValues/interfaces.ts +9 -6
  19. package/src/coValues/profile.ts +11 -0
  20. package/src/coValues/registeredSchemas.ts +12 -0
  21. package/src/exports.ts +21 -15
  22. package/src/implementation/anonymousJazzAgent.ts +6 -0
  23. package/src/implementation/createContext.ts +6 -7
  24. package/src/implementation/refs.ts +1 -1
  25. package/src/implementation/subscriptionScope.ts +1 -1
  26. package/src/index.native.ts +0 -1
  27. package/src/internal.ts +1 -9
  28. package/src/tests/account.test.ts +2 -2
  29. package/src/tests/coFeed.test.ts +0 -9
  30. package/src/tests/coMap.test.ts +2 -2
  31. package/src/tests/groupsAndAccounts.test.ts +1 -1
  32. package/src/tests/inbox.test.ts +256 -0
  33. package/src/tests/schemaUnion.test.ts +1 -1
  34. package/src/tests/utils.ts +14 -0
  35. package/tsup.config.ts +13 -0
  36. package/dist/native/coValues/account.js +0 -221
  37. package/dist/native/coValues/account.js.map +0 -1
  38. package/dist/native/coValues/coFeed.js +0 -571
  39. package/dist/native/coValues/coFeed.js.map +0 -1
  40. package/dist/native/coValues/coList.js +0 -404
  41. package/dist/native/coValues/coList.js.map +0 -1
  42. package/dist/native/coValues/coMap.js +0 -537
  43. package/dist/native/coValues/coMap.js.map +0 -1
  44. package/dist/native/coValues/deepLoading.js +0 -63
  45. package/dist/native/coValues/deepLoading.js.map +0 -1
  46. package/dist/native/coValues/extensions/imageDef.js +0 -42
  47. package/dist/native/coValues/extensions/imageDef.js.map +0 -1
  48. package/dist/native/coValues/group.js +0 -136
  49. package/dist/native/coValues/group.js.map +0 -1
  50. package/dist/native/coValues/interfaces.js +0 -135
  51. package/dist/native/coValues/interfaces.js.map +0 -1
  52. package/dist/native/coValues/schemaUnion.js +0 -89
  53. package/dist/native/coValues/schemaUnion.js.map +0 -1
  54. package/dist/native/exports.js +0 -5
  55. package/dist/native/exports.js.map +0 -1
  56. package/dist/native/implementation/createContext.js +0 -157
  57. package/dist/native/implementation/createContext.js.map +0 -1
  58. package/dist/native/implementation/devtoolsFormatters.js +0 -95
  59. package/dist/native/implementation/devtoolsFormatters.js.map +0 -1
  60. package/dist/native/implementation/errors.js +0 -2
  61. package/dist/native/implementation/errors.js.map +0 -1
  62. package/dist/native/implementation/inspect.js +0 -2
  63. package/dist/native/implementation/inspect.js.map +0 -1
  64. package/dist/native/implementation/refs.js +0 -115
  65. package/dist/native/implementation/refs.js.map +0 -1
  66. package/dist/native/implementation/schema.js +0 -96
  67. package/dist/native/implementation/schema.js.map +0 -1
  68. package/dist/native/implementation/subscriptionScope.js +0 -91
  69. package/dist/native/implementation/subscriptionScope.js.map +0 -1
  70. package/dist/native/implementation/symbols.js +0 -4
  71. package/dist/native/implementation/symbols.js.map +0 -1
  72. package/dist/native/index.native.js +0 -3
  73. package/dist/native/index.native.js.map +0 -1
  74. package/dist/native/internal.js +0 -18
  75. package/dist/native/internal.js.map +0 -1
  76. package/dist/native/lib/cache.js +0 -13
  77. package/dist/native/lib/cache.js.map +0 -1
  78. package/dist/native/lib/cache.test.js +0 -52
  79. package/dist/native/lib/cache.test.js.map +0 -1
  80. package/dist/web/coValues/account.js +0 -221
  81. package/dist/web/coValues/account.js.map +0 -1
  82. package/dist/web/coValues/coFeed.js +0 -571
  83. package/dist/web/coValues/coFeed.js.map +0 -1
  84. package/dist/web/coValues/coList.js +0 -404
  85. package/dist/web/coValues/coList.js.map +0 -1
  86. package/dist/web/coValues/coMap.js +0 -537
  87. package/dist/web/coValues/coMap.js.map +0 -1
  88. package/dist/web/coValues/deepLoading.js +0 -63
  89. package/dist/web/coValues/deepLoading.js.map +0 -1
  90. package/dist/web/coValues/extensions/imageDef.js +0 -42
  91. package/dist/web/coValues/extensions/imageDef.js.map +0 -1
  92. package/dist/web/coValues/group.js +0 -136
  93. package/dist/web/coValues/group.js.map +0 -1
  94. package/dist/web/coValues/interfaces.js +0 -135
  95. package/dist/web/coValues/interfaces.js.map +0 -1
  96. package/dist/web/coValues/schemaUnion.js +0 -89
  97. package/dist/web/coValues/schemaUnion.js.map +0 -1
  98. package/dist/web/exports.js +0 -5
  99. package/dist/web/exports.js.map +0 -1
  100. package/dist/web/implementation/createContext.js +0 -157
  101. package/dist/web/implementation/createContext.js.map +0 -1
  102. package/dist/web/implementation/devtoolsFormatters.js +0 -95
  103. package/dist/web/implementation/devtoolsFormatters.js.map +0 -1
  104. package/dist/web/implementation/errors.js +0 -2
  105. package/dist/web/implementation/errors.js.map +0 -1
  106. package/dist/web/implementation/inspect.js +0 -2
  107. package/dist/web/implementation/inspect.js.map +0 -1
  108. package/dist/web/implementation/refs.js +0 -115
  109. package/dist/web/implementation/refs.js.map +0 -1
  110. package/dist/web/implementation/schema.js +0 -96
  111. package/dist/web/implementation/schema.js.map +0 -1
  112. package/dist/web/implementation/subscriptionScope.js +0 -91
  113. package/dist/web/implementation/subscriptionScope.js.map +0 -1
  114. package/dist/web/implementation/symbols.js +0 -4
  115. package/dist/web/implementation/symbols.js.map +0 -1
  116. package/dist/web/index.web.js +0 -3
  117. package/dist/web/index.web.js.map +0 -1
  118. package/dist/web/internal.js +0 -18
  119. package/dist/web/internal.js.map +0 -1
  120. package/dist/web/lib/cache.js +0 -13
  121. package/dist/web/lib/cache.js.map +0 -1
  122. package/dist/web/lib/cache.test.js +0 -52
  123. package/dist/web/lib/cache.test.js.map +0 -1
@@ -0,0 +1,2844 @@
1
+ // src/implementation/anonymousJazzAgent.ts
2
+ var AnonymousJazzAgent = class {
3
+ constructor(node) {
4
+ this.node = node;
5
+ this._type = "Anonymous";
6
+ }
7
+ };
8
+
9
+ // src/coValues/interfaces.ts
10
+ import { RawAccount as RawAccount2 } from "cojson";
11
+
12
+ // src/implementation/symbols.ts
13
+ var SchemaInit = Symbol.for("SchemaInit");
14
+ var ItemsSym = Symbol.for("items");
15
+ var MembersSym = Symbol.for("members");
16
+
17
+ // src/implementation/inspect.ts
18
+ var inspect = Symbol.for("nodejs.util.inspect.custom");
19
+
20
+ // src/lib/cache.ts
21
+ var weakMap = /* @__PURE__ */ new WeakMap();
22
+ var coValuesCache = {
23
+ get: (raw, compute) => {
24
+ const cached = weakMap.get(raw);
25
+ if (cached) {
26
+ return cached;
27
+ }
28
+ const computed = compute();
29
+ weakMap.set(raw, computed);
30
+ return computed;
31
+ }
32
+ };
33
+
34
+ // src/implementation/refs.ts
35
+ var TRACE_ACCESSES = false;
36
+ var Ref = class _Ref {
37
+ constructor(id, controlledAccount, schema) {
38
+ this.id = id;
39
+ this.controlledAccount = controlledAccount;
40
+ this.schema = schema;
41
+ if (!isRefEncoded(schema)) {
42
+ throw new Error("Ref must be constructed with a ref schema");
43
+ }
44
+ }
45
+ get value() {
46
+ const node = "node" in this.controlledAccount ? this.controlledAccount.node : this.controlledAccount._raw.core.node;
47
+ const raw = node.getLoaded(this.id);
48
+ if (raw) {
49
+ return coValuesCache.get(
50
+ raw,
51
+ () => instantiateRefEncoded(this.schema, raw)
52
+ );
53
+ } else {
54
+ return null;
55
+ }
56
+ }
57
+ async loadHelper() {
58
+ const node = "node" in this.controlledAccount ? this.controlledAccount.node : this.controlledAccount._raw.core.node;
59
+ const raw = await node.load(this.id);
60
+ if (raw === "unavailable") {
61
+ return "unavailable";
62
+ } else {
63
+ return new _Ref(this.id, this.controlledAccount, this.schema).value;
64
+ }
65
+ }
66
+ async load() {
67
+ const result = await this.loadHelper();
68
+ if (result === "unavailable") {
69
+ return void 0;
70
+ } else {
71
+ return result;
72
+ }
73
+ }
74
+ accessFrom(fromScopeValue, key) {
75
+ const subScope = subscriptionsScopes.get(fromScopeValue);
76
+ subScope?.onRefAccessedOrSet(fromScopeValue.id, this.id);
77
+ TRACE_ACCESSES && console.log(subScope?.scopeID, "accessing", fromScopeValue, key, this.id);
78
+ if (this.value && subScope) {
79
+ subscriptionsScopes.set(this.value, subScope);
80
+ }
81
+ if (subScope) {
82
+ const cached = subScope.cachedValues[this.id];
83
+ if (cached) {
84
+ TRACE_ACCESSES && console.log("cached", cached);
85
+ return cached;
86
+ } else if (this.value !== null) {
87
+ const freshValueInstance = instantiateRefEncoded(
88
+ this.schema,
89
+ this.value?._raw
90
+ );
91
+ TRACE_ACCESSES && console.log("freshValueInstance", freshValueInstance);
92
+ subScope.cachedValues[this.id] = freshValueInstance;
93
+ subscriptionsScopes.set(freshValueInstance, subScope);
94
+ return freshValueInstance;
95
+ } else {
96
+ return null;
97
+ }
98
+ } else {
99
+ return this.value;
100
+ }
101
+ }
102
+ };
103
+ function makeRefs(getIdForKey, getKeysWithIds, controlledAccount, refSchemaForKey) {
104
+ const refs = {};
105
+ return new Proxy(refs, {
106
+ get(_target, key) {
107
+ if (key === Symbol.iterator) {
108
+ return function* () {
109
+ for (const key2 of getKeysWithIds()) {
110
+ yield new Ref(
111
+ getIdForKey(key2),
112
+ controlledAccount,
113
+ refSchemaForKey(key2)
114
+ );
115
+ }
116
+ };
117
+ }
118
+ if (typeof key === "symbol") return void 0;
119
+ if (key === "length") {
120
+ return getKeysWithIds().length;
121
+ }
122
+ const id = getIdForKey(key);
123
+ if (!id) return void 0;
124
+ return new Ref(
125
+ id,
126
+ controlledAccount,
127
+ refSchemaForKey(key)
128
+ );
129
+ },
130
+ ownKeys() {
131
+ return getKeysWithIds().map((key) => key.toString());
132
+ },
133
+ getOwnPropertyDescriptor(target, key) {
134
+ const id = getIdForKey(key);
135
+ if (id) {
136
+ return {
137
+ enumerable: true,
138
+ configurable: true,
139
+ writable: true
140
+ };
141
+ } else {
142
+ return Reflect.getOwnPropertyDescriptor(target, key);
143
+ }
144
+ }
145
+ });
146
+ }
147
+
148
+ // src/implementation/schema.ts
149
+ var Encoders = {
150
+ Date: {
151
+ encode: (value) => value.toISOString(),
152
+ decode: (value) => new Date(value)
153
+ }
154
+ };
155
+ var optional = {
156
+ ref: optionalRef,
157
+ json() {
158
+ return { [SchemaInit]: "json" };
159
+ },
160
+ encoded(arg) {
161
+ return { [SchemaInit]: { encoded: arg } };
162
+ },
163
+ string: {
164
+ [SchemaInit]: "json"
165
+ },
166
+ number: {
167
+ [SchemaInit]: "json"
168
+ },
169
+ boolean: {
170
+ [SchemaInit]: "json"
171
+ },
172
+ null: {
173
+ [SchemaInit]: "json"
174
+ },
175
+ Date: {
176
+ [SchemaInit]: { encoded: Encoders.Date }
177
+ },
178
+ literal(..._lit) {
179
+ return { [SchemaInit]: "json" };
180
+ }
181
+ };
182
+ var co = {
183
+ string: {
184
+ [SchemaInit]: "json"
185
+ },
186
+ number: {
187
+ [SchemaInit]: "json"
188
+ },
189
+ boolean: {
190
+ [SchemaInit]: "json"
191
+ },
192
+ null: {
193
+ [SchemaInit]: "json"
194
+ },
195
+ Date: {
196
+ [SchemaInit]: { encoded: Encoders.Date }
197
+ },
198
+ literal(..._lit) {
199
+ return { [SchemaInit]: "json" };
200
+ },
201
+ json() {
202
+ return { [SchemaInit]: "json" };
203
+ },
204
+ encoded(arg) {
205
+ return { [SchemaInit]: { encoded: arg } };
206
+ },
207
+ ref,
208
+ items: ItemsSym,
209
+ members: MembersSym,
210
+ optional
211
+ };
212
+ function optionalRef(arg) {
213
+ return ref(arg, { optional: true });
214
+ }
215
+ function ref(arg, options) {
216
+ return {
217
+ [SchemaInit]: {
218
+ ref: arg,
219
+ optional: options?.optional || false
220
+ }
221
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
222
+ };
223
+ }
224
+ function isRefEncoded(schema) {
225
+ return typeof schema === "object" && "ref" in schema && "optional" in schema && typeof schema.ref === "function";
226
+ }
227
+ function instantiateRefEncoded(schema, raw) {
228
+ return isCoValueClass(schema.ref) ? schema.ref.fromRaw(raw) : schema.ref(
229
+ raw
230
+ ).fromRaw(raw);
231
+ }
232
+
233
+ // src/implementation/subscriptionScope.ts
234
+ var subscriptionsScopes = /* @__PURE__ */ new WeakMap();
235
+ var TRACE_INVALIDATIONS = false;
236
+ var SubscriptionScope = class {
237
+ constructor(root, rootSchema, onUpdate) {
238
+ this.scopeID = `scope-${Math.random().toString(36).slice(2)}`;
239
+ this.entries = /* @__PURE__ */ new Map();
240
+ this.scheduledUpdate = false;
241
+ this.cachedValues = {};
242
+ this.parents = {};
243
+ this.rootEntry = {
244
+ state: "loaded",
245
+ value: root._raw,
246
+ rawUnsub: () => {
247
+ }
248
+ // placeholder
249
+ };
250
+ this.entries.set(root.id, this.rootEntry);
251
+ subscriptionsScopes.set(root, this);
252
+ this.subscriber = root._loadedAs;
253
+ this.scheduleUpdate = () => {
254
+ const value = rootSchema.fromRaw(this.rootEntry.value);
255
+ subscriptionsScopes.set(value, this);
256
+ onUpdate(value);
257
+ };
258
+ this.rootEntry.rawUnsub = root._raw.core.subscribe(
259
+ (rawUpdate) => {
260
+ if (!rawUpdate) return;
261
+ this.rootEntry.value = rawUpdate;
262
+ this.scheduleUpdate();
263
+ }
264
+ );
265
+ }
266
+ onRefAccessedOrSet(fromId, accessedOrSetId) {
267
+ if (!accessedOrSetId) {
268
+ return;
269
+ }
270
+ this.parents[accessedOrSetId] = this.parents[accessedOrSetId] || /* @__PURE__ */ new Set();
271
+ this.parents[accessedOrSetId].add(fromId);
272
+ if (!this.entries.has(accessedOrSetId)) {
273
+ const loadingEntry = {
274
+ state: "loading",
275
+ immediatelyUnsub: false
276
+ };
277
+ this.entries.set(accessedOrSetId, loadingEntry);
278
+ const node = this.subscriber._type === "Account" ? this.subscriber._raw.core.node : this.subscriber.node;
279
+ void node.loadCoValueCore(accessedOrSetId).then((core) => {
280
+ if (loadingEntry.state === "loading" && loadingEntry.immediatelyUnsub) {
281
+ return;
282
+ }
283
+ if (core !== "unavailable") {
284
+ const entry = {
285
+ state: "loaded",
286
+ rawUnsub: () => {
287
+ }
288
+ // placeholder
289
+ };
290
+ this.entries.set(accessedOrSetId, entry);
291
+ const rawUnsub = core.subscribe((rawUpdate) => {
292
+ if (!rawUpdate) return;
293
+ this.invalidate(accessedOrSetId);
294
+ this.scheduleUpdate();
295
+ });
296
+ entry.rawUnsub = rawUnsub;
297
+ }
298
+ });
299
+ }
300
+ }
301
+ invalidate(id, fromChild, seen = /* @__PURE__ */ new Set()) {
302
+ if (seen.has(id)) return;
303
+ TRACE_INVALIDATIONS && console.log("invalidating", fromChild, "->", id, this.cachedValues[id]);
304
+ delete this.cachedValues[id];
305
+ seen.add(id);
306
+ for (const parent of this.parents[id] || []) {
307
+ this.invalidate(parent, id, seen);
308
+ }
309
+ }
310
+ unsubscribeAll() {
311
+ for (const entry of this.entries.values()) {
312
+ if (entry.state === "loaded") {
313
+ entry.rawUnsub();
314
+ } else {
315
+ entry.immediatelyUnsub = true;
316
+ }
317
+ }
318
+ this.entries.clear();
319
+ }
320
+ };
321
+
322
+ // src/coValues/deepLoading.ts
323
+ function fulfillsDepth(depth, value) {
324
+ if (value._type === "CoMap" || value._type === "Group" || value._type === "Account") {
325
+ if (Array.isArray(depth) && depth.length === 1) {
326
+ return Object.entries(value).every(([key, item]) => {
327
+ return value._refs[key] ? item && fulfillsDepth(depth[0], item) : value._schema[ItemsSym].optional;
328
+ });
329
+ } else {
330
+ for (const key of Object.keys(depth)) {
331
+ const map = value;
332
+ if (!map._refs[key] && map._schema[key].optional) {
333
+ continue;
334
+ }
335
+ if (!map[key]) {
336
+ return false;
337
+ }
338
+ if (!fulfillsDepth(depth[key], map[key])) {
339
+ return false;
340
+ }
341
+ }
342
+ return true;
343
+ }
344
+ } else if (value._type === "CoList") {
345
+ if (depth.length === 0) {
346
+ return true;
347
+ } else {
348
+ const itemDepth = depth[0];
349
+ return value.every(
350
+ (item, i) => value._refs[i] ? item && fulfillsDepth(itemDepth, item) : value._schema[ItemsSym].optional
351
+ );
352
+ }
353
+ } else if (value._type === "CoStream") {
354
+ if (depth.length === 0) {
355
+ return true;
356
+ } else {
357
+ const itemDepth = depth[0];
358
+ return Object.values(value.perSession).every(
359
+ (entry) => entry.ref ? entry.value && fulfillsDepth(itemDepth, entry.value) : value._schema[ItemsSym].optional
360
+ );
361
+ }
362
+ } else if (value._type === "BinaryCoStream") {
363
+ return true;
364
+ } else {
365
+ console.error(value);
366
+ throw new Error("Unexpected value type: " + value._type);
367
+ }
368
+ }
369
+
370
+ // src/implementation/createContext.ts
371
+ import {
372
+ ControlledAgent,
373
+ LocalNode
374
+ } from "cojson";
375
+
376
+ // src/coValues/registeredSchemas.ts
377
+ var RegisteredSchemas = {};
378
+
379
+ // src/implementation/createContext.ts
380
+ var fixedCredentialsAuth = (credentials) => {
381
+ return {
382
+ start: async () => ({
383
+ type: "existing",
384
+ credentials,
385
+ saveCredentials: async () => {
386
+ },
387
+ onSuccess: () => {
388
+ },
389
+ onError: () => {
390
+ },
391
+ logOut: () => {
392
+ }
393
+ })
394
+ };
395
+ };
396
+ var ephemeralCredentialsAuth = () => {
397
+ return {
398
+ start: async () => ({
399
+ type: "new",
400
+ creationProps: { name: "Ephemeral" },
401
+ saveCredentials: async () => {
402
+ },
403
+ onSuccess: () => {
404
+ },
405
+ onError: () => {
406
+ },
407
+ logOut: () => {
408
+ }
409
+ })
410
+ };
411
+ };
412
+ async function randomSessionProvider(accountID, crypto) {
413
+ return {
414
+ sessionID: crypto.newRandomSessionID(accountID),
415
+ sessionDone: () => {
416
+ }
417
+ };
418
+ }
419
+ async function createJazzContext(options) {
420
+ while (true) {
421
+ if (!("auth" in options)) {
422
+ return createAnonymousJazzContext({
423
+ peersToLoadFrom: options.peersToLoadFrom,
424
+ crypto: options.crypto
425
+ });
426
+ }
427
+ const { auth, sessionProvider, peersToLoadFrom, crypto } = options;
428
+ const AccountSchema = options.AccountSchema ?? RegisteredSchemas["Account"];
429
+ let authResult;
430
+ try {
431
+ authResult = await auth.start(crypto);
432
+ } catch (e) {
433
+ console.error("error", e);
434
+ throw e;
435
+ }
436
+ if (authResult.type === "existing") {
437
+ try {
438
+ const { sessionID, sessionDone } = await sessionProvider(
439
+ authResult.credentials.accountID,
440
+ crypto
441
+ );
442
+ try {
443
+ const node = await LocalNode.withLoadedAccount({
444
+ accountID: authResult.credentials.accountID,
445
+ accountSecret: authResult.credentials.secret,
446
+ sessionID,
447
+ peersToLoadFrom,
448
+ crypto,
449
+ migration: async (rawAccount, _node, creationProps) => {
450
+ const account2 = new AccountSchema({
451
+ fromRaw: rawAccount
452
+ });
453
+ await account2.migrate?.(creationProps);
454
+ }
455
+ });
456
+ const account = AccountSchema.fromNode(node);
457
+ if (authResult.saveCredentials) {
458
+ await authResult.saveCredentials({
459
+ accountID: node.account.id,
460
+ secret: node.account.agentSecret
461
+ });
462
+ }
463
+ authResult.onSuccess();
464
+ return {
465
+ account,
466
+ done: () => {
467
+ node.gracefulShutdown();
468
+ sessionDone();
469
+ },
470
+ logOut: () => {
471
+ node.gracefulShutdown();
472
+ sessionDone();
473
+ authResult.logOut();
474
+ }
475
+ };
476
+ } catch (e) {
477
+ authResult.onError(new Error("Error loading account", { cause: e }));
478
+ sessionDone();
479
+ }
480
+ } catch (e) {
481
+ authResult.onError(
482
+ new Error("Error acquiring sessionID", { cause: e })
483
+ );
484
+ }
485
+ } else if (authResult.type === "new") {
486
+ try {
487
+ const { node } = await LocalNode.withNewlyCreatedAccount({
488
+ creationProps: authResult.creationProps,
489
+ peersToLoadFrom,
490
+ crypto,
491
+ initialAgentSecret: authResult.initialSecret,
492
+ migration: async (rawAccount, _node, creationProps) => {
493
+ const account2 = new AccountSchema({
494
+ fromRaw: rawAccount
495
+ });
496
+ await account2.migrate?.(creationProps);
497
+ }
498
+ });
499
+ const account = AccountSchema.fromNode(node);
500
+ await authResult.saveCredentials({
501
+ accountID: node.account.id,
502
+ secret: node.account.agentSecret
503
+ });
504
+ authResult.onSuccess();
505
+ return {
506
+ account,
507
+ done: () => {
508
+ node.gracefulShutdown();
509
+ },
510
+ logOut: () => {
511
+ node.gracefulShutdown();
512
+ authResult.logOut();
513
+ }
514
+ };
515
+ } catch (e) {
516
+ authResult.onError(new Error("Error creating account", { cause: e }));
517
+ }
518
+ }
519
+ }
520
+ }
521
+ async function createAnonymousJazzContext({
522
+ peersToLoadFrom,
523
+ crypto
524
+ }) {
525
+ const agentSecret = crypto.newRandomAgentSecret();
526
+ const rawAgent = new ControlledAgent(agentSecret, crypto);
527
+ const node = new LocalNode(
528
+ rawAgent,
529
+ crypto.newRandomSessionID(rawAgent.id),
530
+ crypto
531
+ );
532
+ for (const peer of peersToLoadFrom) {
533
+ node.syncManager.addPeer(peer);
534
+ }
535
+ return {
536
+ agent: new AnonymousJazzAgent(node),
537
+ done: () => {
538
+ },
539
+ logOut: () => {
540
+ }
541
+ };
542
+ }
543
+
544
+ // src/implementation/devtoolsFormatters.ts
545
+ globalThis.devtoolsFormatters = [
546
+ {
547
+ header: (object) => {
548
+ if (object._type === "CoMap") {
549
+ return ["div", {}, ["span", {}, object.constructor.name]];
550
+ } else if (object._type === "CoList") {
551
+ return [
552
+ "div",
553
+ {},
554
+ ["span", {}, object.constructor.name + "(" + object.length + ") "]
555
+ ];
556
+ } else if (object._type === "Account") {
557
+ return [
558
+ "div",
559
+ {},
560
+ [
561
+ "span",
562
+ {},
563
+ object.constructor.name + "(" + object._refs.profile.value?.name + (object.isMe ? " ME" : "") + ")"
564
+ ]
565
+ ];
566
+ } else {
567
+ return null;
568
+ }
569
+ },
570
+ hasBody: function() {
571
+ return true;
572
+ },
573
+ body: function(object) {
574
+ if (object._type === "CoMap" || object._type === "Account") {
575
+ return [
576
+ "div",
577
+ { style: "margin-left: 15px" },
578
+ ["div", "id: ", ["object", { object: object.id }]],
579
+ ...Object.entries(object).map(([k, v]) => [
580
+ "div",
581
+ { style: "white-space: nowrap;" },
582
+ ["span", { style: "font-weight: bold; opacity: 0.6" }, k, ": "],
583
+ ["object", { object: v }],
584
+ ...typeof object._schema[k] === "function" ? v === null ? [
585
+ [
586
+ "span",
587
+ { style: "opacity: 0.5" },
588
+ ` (pending ${object._schema[k].name} `,
589
+ ["object", { object: object._refs[k] }],
590
+ ")"
591
+ ]
592
+ ] : [] : []
593
+ ])
594
+ ];
595
+ } else if (object._type === "CoList") {
596
+ return [
597
+ "div",
598
+ { style: "margin-left: 15px" },
599
+ ["div", "id: ", ["object", { object: object.id }]],
600
+ ...object.map((v, i) => [
601
+ "div",
602
+ { style: "white-space: nowrap;" },
603
+ ["span", { style: "font-weight: bold; opacity: 0.6" }, i, ": "],
604
+ ["object", { object: v }],
605
+ ...typeof object._schema[ItemsSym] === "function" ? v === null ? [
606
+ [
607
+ "span",
608
+ { style: "opacity: 0.5" },
609
+ ` (pending ${object._schema[ItemsSym].name} `,
610
+ ["object", { object: object._refs[i] }],
611
+ ")"
612
+ ]
613
+ ] : [] : []
614
+ ])
615
+ ];
616
+ }
617
+ }
618
+ }
619
+ ];
620
+
621
+ // src/coValues/interfaces.ts
622
+ function isCoValueClass(value) {
623
+ return typeof value === "function" && value.fromRaw !== void 0;
624
+ }
625
+ var CoValueBase = class {
626
+ get _owner() {
627
+ const owner = this._raw.group instanceof RawAccount2 ? RegisteredSchemas["Account"].fromRaw(this._raw.group) : RegisteredSchemas["Group"].fromRaw(this._raw.group);
628
+ const subScope = subscriptionsScopes.get(this);
629
+ if (subScope) {
630
+ subScope.onRefAccessedOrSet(this.id, owner.id);
631
+ subscriptionsScopes.set(owner, subScope);
632
+ }
633
+ return owner;
634
+ }
635
+ /** @private */
636
+ get _loadedAs() {
637
+ const rawAccount = this._raw.core.node.account;
638
+ if (rawAccount instanceof RawAccount2) {
639
+ return coValuesCache.get(
640
+ rawAccount,
641
+ () => RegisteredSchemas["Account"].fromRaw(rawAccount)
642
+ );
643
+ }
644
+ return new AnonymousJazzAgent(this._raw.core.node);
645
+ }
646
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
647
+ constructor(..._args) {
648
+ Object.defineProperty(this, "_instanceID", {
649
+ value: `instance-${Math.random().toString(36).slice(2)}`,
650
+ enumerable: false
651
+ });
652
+ }
653
+ /** @category Internals */
654
+ static fromRaw(raw) {
655
+ return new this({ fromRaw: raw });
656
+ }
657
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
658
+ toJSON() {
659
+ return {
660
+ id: this.id,
661
+ type: this._type,
662
+ error: "unknown CoValue class"
663
+ };
664
+ }
665
+ [inspect]() {
666
+ return this.toJSON();
667
+ }
668
+ /** @category Type Helpers */
669
+ castAs(cl) {
670
+ const casted = cl.fromRaw(this._raw);
671
+ const subscriptionScope = subscriptionsScopes.get(this);
672
+ if (subscriptionScope) {
673
+ subscriptionsScopes.set(casted, subscriptionScope);
674
+ }
675
+ return casted;
676
+ }
677
+ };
678
+ function loadCoValue(cls, id, as, depth) {
679
+ return new Promise((resolve) => {
680
+ const unsubscribe = subscribeToCoValue(
681
+ cls,
682
+ id,
683
+ as,
684
+ depth,
685
+ (value) => {
686
+ resolve(value);
687
+ unsubscribe();
688
+ },
689
+ () => {
690
+ resolve(void 0);
691
+ unsubscribe();
692
+ }
693
+ );
694
+ });
695
+ }
696
+ function ensureCoValueLoaded(existing, depth) {
697
+ return loadCoValue(
698
+ existing.constructor,
699
+ existing.id,
700
+ existing._loadedAs,
701
+ depth
702
+ );
703
+ }
704
+ function subscribeToCoValue(cls, id, as, depth, listener, onUnavailable) {
705
+ const ref2 = new Ref(id, as, { ref: cls, optional: false });
706
+ let unsubscribed = false;
707
+ let unsubscribe;
708
+ ref2.load().then((value) => {
709
+ if (!value) {
710
+ onUnavailable && onUnavailable();
711
+ return;
712
+ }
713
+ if (unsubscribed) return;
714
+ const subscription = new SubscriptionScope(
715
+ value,
716
+ cls,
717
+ (update) => {
718
+ if (fulfillsDepth(depth, update)) {
719
+ listener(update);
720
+ }
721
+ }
722
+ );
723
+ unsubscribe = () => subscription.unsubscribeAll();
724
+ }).catch((e) => {
725
+ console.error("Failed to load / subscribe to CoValue", e);
726
+ });
727
+ return function unsubscribeAtAnyPoint() {
728
+ unsubscribed = true;
729
+ unsubscribe && unsubscribe();
730
+ };
731
+ }
732
+ function createCoValueObservable() {
733
+ let currentValue = void 0;
734
+ let subscriberCount = 0;
735
+ function subscribe(cls, id, as, depth, listener, onUnavailable) {
736
+ subscriberCount++;
737
+ const unsubscribe = subscribeToCoValue(
738
+ cls,
739
+ id,
740
+ as,
741
+ depth,
742
+ (value) => {
743
+ currentValue = value;
744
+ listener();
745
+ },
746
+ onUnavailable
747
+ );
748
+ return () => {
749
+ unsubscribe();
750
+ subscriberCount--;
751
+ if (subscriberCount === 0) {
752
+ currentValue = void 0;
753
+ }
754
+ };
755
+ }
756
+ const observable = {
757
+ getCurrentValue: () => currentValue,
758
+ subscribe
759
+ };
760
+ return observable;
761
+ }
762
+ function subscribeToExistingCoValue(existing, depth, listener) {
763
+ return subscribeToCoValue(
764
+ existing.constructor,
765
+ existing.id,
766
+ existing._loadedAs,
767
+ depth,
768
+ listener
769
+ );
770
+ }
771
+
772
+ // src/coValues/inbox.ts
773
+ import {
774
+ RawAccount as RawAccount3
775
+ } from "cojson";
776
+ function createInboxRoot(account) {
777
+ if (!account.isMe) {
778
+ throw new Error("Account is not controlled");
779
+ }
780
+ const rawAccount = account._raw;
781
+ const group = rawAccount.createGroup();
782
+ const messagesFeed = group.createStream();
783
+ const inboxRoot = rawAccount.createMap();
784
+ const processedFeed = rawAccount.createStream();
785
+ const failedFeed = rawAccount.createStream();
786
+ const inviteLink = `${messagesFeed.id}/${group.createInvite("writeOnly")}`;
787
+ inboxRoot.set("messages", messagesFeed.id);
788
+ inboxRoot.set("processed", processedFeed.id);
789
+ inboxRoot.set("failed", failedFeed.id);
790
+ return {
791
+ id: inboxRoot.id,
792
+ inviteLink
793
+ };
794
+ }
795
+ function createInboxMessage(payload, inboxOwner) {
796
+ const group = payload._raw.group;
797
+ if (group instanceof RawAccount3) {
798
+ throw new Error("Inbox messages should be owned by a group");
799
+ }
800
+ group.addMember(inboxOwner, "writer");
801
+ const message = group.createMap({
802
+ payload: payload.id,
803
+ result: void 0,
804
+ processed: false,
805
+ error: void 0
806
+ });
807
+ return message;
808
+ }
809
+ var Inbox = class _Inbox {
810
+ constructor(account, root, messages, processed, failed) {
811
+ this.processing = /* @__PURE__ */ new Set();
812
+ this.account = account;
813
+ this.root = root;
814
+ this.messages = messages;
815
+ this.processed = processed;
816
+ this.failed = failed;
817
+ }
818
+ subscribe(Schema, callback, options = {}) {
819
+ const processed = /* @__PURE__ */ new Set();
820
+ const failed = /* @__PURE__ */ new Map();
821
+ const node = this.account._raw.core.node;
822
+ this.processed.subscribe((stream) => {
823
+ for (const items of Object.values(stream.items)) {
824
+ for (const item of items) {
825
+ processed.add(item.value);
826
+ }
827
+ }
828
+ });
829
+ const { account } = this;
830
+ const { retries = 3 } = options;
831
+ let failTimer = void 0;
832
+ const clearFailTimer = () => {
833
+ clearTimeout(failTimer);
834
+ failTimer = void 0;
835
+ };
836
+ const handleNewMessages = (stream) => {
837
+ clearFailTimer();
838
+ for (const [sessionID, items] of Object.entries(stream.items)) {
839
+ const accountID = getAccountIDfromSessionID(sessionID);
840
+ if (!accountID) {
841
+ console.warn("Received message from unknown account", sessionID);
842
+ continue;
843
+ }
844
+ for (const item of items) {
845
+ const txKey = `${sessionID}/${item.tx.txIndex}`;
846
+ if (!processed.has(txKey) && !this.processing.has(txKey)) {
847
+ this.processing.add(txKey);
848
+ const id = item.value;
849
+ node.load(id).then((message) => {
850
+ if (message === "unavailable") {
851
+ return Promise.reject(
852
+ new Error("Unable to load inbox message " + id)
853
+ );
854
+ }
855
+ return loadCoValue(
856
+ Schema,
857
+ message.get("payload"),
858
+ account,
859
+ []
860
+ );
861
+ }).then((value) => {
862
+ if (!value) {
863
+ return Promise.reject(
864
+ new Error("Unable to load inbox message " + id)
865
+ );
866
+ }
867
+ return callback(value, accountID);
868
+ }).then((result) => {
869
+ const inboxMessage = node.expectCoValueLoaded(item.value).getCurrentContent();
870
+ if (result) {
871
+ inboxMessage.set("result", result.id);
872
+ }
873
+ inboxMessage.set("processed", true);
874
+ this.processed.push(txKey);
875
+ this.processing.delete(txKey);
876
+ }).catch((error) => {
877
+ console.error("Error processing inbox message", error);
878
+ this.processing.delete(txKey);
879
+ const errors = failed.get(txKey) ?? [];
880
+ const stringifiedError = String(error);
881
+ errors.push(stringifiedError);
882
+ const inboxMessage = node.expectCoValueLoaded(item.value).getCurrentContent();
883
+ inboxMessage.set("error", stringifiedError);
884
+ if (errors.length > retries) {
885
+ inboxMessage.set("processed", true);
886
+ this.processed.push(txKey);
887
+ this.failed.push({ errors, value: item.value });
888
+ } else {
889
+ failed.set(txKey, errors);
890
+ if (!failTimer) {
891
+ failTimer = setTimeout(
892
+ () => handleNewMessages(stream),
893
+ 100
894
+ );
895
+ }
896
+ }
897
+ });
898
+ }
899
+ }
900
+ }
901
+ };
902
+ return this.messages.subscribe(handleNewMessages);
903
+ }
904
+ static async load(account) {
905
+ const profile = account.profile;
906
+ if (!profile) {
907
+ throw new Error("Account profile should already be loaded");
908
+ }
909
+ if (!profile.inbox) {
910
+ throw new Error("The account has not set up their inbox");
911
+ }
912
+ const node = account._raw.core.node;
913
+ const root = await node.load(profile.inbox);
914
+ if (root === "unavailable") {
915
+ throw new Error("Inbox not found");
916
+ }
917
+ const [messages, processed, failed] = await Promise.all([
918
+ node.load(root.get("messages")),
919
+ node.load(root.get("processed")),
920
+ node.load(root.get("failed"))
921
+ ]);
922
+ if (messages === "unavailable" || processed === "unavailable" || failed === "unavailable") {
923
+ throw new Error("Inbox not found");
924
+ }
925
+ return new _Inbox(account, root, messages, processed, failed);
926
+ }
927
+ };
928
+ var InboxSender = class _InboxSender {
929
+ constructor(currentAccount, owner, messages) {
930
+ this.currentAccount = currentAccount;
931
+ this.owner = owner;
932
+ this.messages = messages;
933
+ }
934
+ getOwnerAccount() {
935
+ return this.owner;
936
+ }
937
+ sendMessage(message) {
938
+ const inboxMessage = createInboxMessage(message, this.owner);
939
+ this.messages.push(inboxMessage.id);
940
+ return new Promise((resolve, reject) => {
941
+ inboxMessage.subscribe((message2) => {
942
+ if (message2.get("processed")) {
943
+ const error = message2.get("error");
944
+ if (error) {
945
+ reject(new Error(error));
946
+ } else {
947
+ resolve(
948
+ message2.get("result")
949
+ );
950
+ }
951
+ }
952
+ });
953
+ });
954
+ }
955
+ static async load(inboxOwnerID, currentAccount) {
956
+ const node = currentAccount._raw.core.node;
957
+ const inboxOwnerRaw = await node.load(
958
+ inboxOwnerID
959
+ );
960
+ if (inboxOwnerRaw === "unavailable") {
961
+ throw new Error("Failed to load the inbox owner");
962
+ }
963
+ const inboxOwnerProfileRaw = await node.load(inboxOwnerRaw.get("profile"));
964
+ if (inboxOwnerProfileRaw === "unavailable") {
965
+ throw new Error("Failed to load the inbox owner profile");
966
+ }
967
+ const inboxInvite = inboxOwnerProfileRaw.get("inboxInvite");
968
+ if (!inboxInvite) {
969
+ throw new Error("The user has not set up their inbox");
970
+ }
971
+ const id = await acceptInvite(inboxInvite, currentAccount);
972
+ const messages = await node.load(id);
973
+ if (messages === "unavailable") {
974
+ throw new Error("Inbox not found");
975
+ }
976
+ return new _InboxSender(currentAccount, inboxOwnerRaw, messages);
977
+ }
978
+ };
979
+ async function acceptInvite(invite, account) {
980
+ const id = invite.slice(0, invite.indexOf("/"));
981
+ const inviteSecret = invite.slice(invite.indexOf("/") + 1);
982
+ if (!id?.startsWith("co_z") || !inviteSecret.startsWith("inviteSecret_")) {
983
+ throw new Error("Invalid inbox ticket");
984
+ }
985
+ if (!account.isMe) {
986
+ throw new Error("Account is not controlled");
987
+ }
988
+ await account._raw.acceptInvite(id, inviteSecret);
989
+ return id;
990
+ }
991
+ function getAccountIDfromSessionID(sessionID) {
992
+ const until = sessionID.indexOf("_session");
993
+ const accountID = sessionID.slice(0, until);
994
+ if (accountID.startsWith("co_z")) {
995
+ return accountID;
996
+ }
997
+ return;
998
+ }
999
+
1000
+ // src/coValues/coMap.ts
1001
+ import {
1002
+ cojsonInternals
1003
+ } from "cojson";
1004
+ var _CoMap = class _CoMap extends CoValueBase {
1005
+ /** @internal */
1006
+ get _schema() {
1007
+ return this.constructor._schema;
1008
+ }
1009
+ /**
1010
+ * If property `prop` is a `co.ref(...)`, you can use `coMaps._refs.prop` to access
1011
+ * the `Ref` instead of the potentially loaded/null value.
1012
+ *
1013
+ * This allows you to always get the ID or load the value manually.
1014
+ *
1015
+ * @example
1016
+ * ```ts
1017
+ * person._refs.pet.id; // => ID<Animal>
1018
+ * person._refs.pet.value;
1019
+ * // => Animal | null
1020
+ * const pet = await person._refs.pet.load();
1021
+ * ```
1022
+ *
1023
+ * @category Content
1024
+ **/
1025
+ get _refs() {
1026
+ return makeRefs(
1027
+ (key) => this._raw.get(key),
1028
+ () => {
1029
+ const keys = this._raw.keys().filter((key) => {
1030
+ const schema = this._schema[key] || this._schema[ItemsSym];
1031
+ return schema && schema !== "json" && isRefEncoded(schema);
1032
+ });
1033
+ return keys;
1034
+ },
1035
+ this._loadedAs,
1036
+ (key) => this._schema[key] || this._schema[ItemsSym]
1037
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1038
+ );
1039
+ }
1040
+ /** @internal */
1041
+ getEditFromRaw(target, rawEdit, descriptor, key) {
1042
+ return {
1043
+ value: descriptor === "json" ? rawEdit.value : "encoded" in descriptor ? rawEdit.value === null || rawEdit.value === void 0 ? rawEdit.value : descriptor.encoded.decode(rawEdit.value) : new Ref(
1044
+ rawEdit.value,
1045
+ target._loadedAs,
1046
+ descriptor
1047
+ ).accessFrom(target, "_edits." + key + ".value"),
1048
+ ref: descriptor !== "json" && isRefEncoded(descriptor) ? new Ref(rawEdit.value, target._loadedAs, descriptor) : void 0,
1049
+ by: rawEdit.by && new Ref(rawEdit.by, target._loadedAs, {
1050
+ ref: RegisteredSchemas["Account"],
1051
+ optional: false
1052
+ }).accessFrom(target, "_edits." + key + ".by"),
1053
+ madeAt: rawEdit.at
1054
+ };
1055
+ }
1056
+ /** @category Collaboration */
1057
+ get _edits() {
1058
+ const map = this;
1059
+ return new Proxy(
1060
+ {},
1061
+ {
1062
+ get(_target, key) {
1063
+ const rawEdit = map._raw.lastEditAt(key);
1064
+ if (!rawEdit) return void 0;
1065
+ const descriptor = map._schema[key];
1066
+ return {
1067
+ ...map.getEditFromRaw(map, rawEdit, descriptor, key),
1068
+ get all() {
1069
+ return [...map._raw.editsAt(key)].map(
1070
+ (rawEdit2) => map.getEditFromRaw(map, rawEdit2, descriptor, key)
1071
+ );
1072
+ }
1073
+ };
1074
+ },
1075
+ ownKeys(_target) {
1076
+ return map._raw.keys();
1077
+ },
1078
+ getOwnPropertyDescriptor(target, key) {
1079
+ return {
1080
+ value: Reflect.get(target, key),
1081
+ writable: false,
1082
+ enumerable: true,
1083
+ configurable: true
1084
+ };
1085
+ }
1086
+ }
1087
+ );
1088
+ }
1089
+ /** @internal */
1090
+ constructor(options) {
1091
+ super();
1092
+ if (options) {
1093
+ if ("fromRaw" in options) {
1094
+ Object.defineProperties(this, {
1095
+ id: {
1096
+ value: options.fromRaw.id,
1097
+ enumerable: false
1098
+ },
1099
+ _raw: { value: options.fromRaw, enumerable: false }
1100
+ });
1101
+ } else {
1102
+ throw new Error("Invalid CoMap constructor arguments");
1103
+ }
1104
+ }
1105
+ return new Proxy(this, CoMapProxyHandler);
1106
+ }
1107
+ /**
1108
+ * Create a new CoMap with the given initial values and owner.
1109
+ *
1110
+ * The owner (a Group or Account) determines access rights to the CoMap.
1111
+ *
1112
+ * The CoMap will immediately be persisted and synced to connected peers.
1113
+ *
1114
+ * @example
1115
+ * ```ts
1116
+ * const person = Person.create({
1117
+ * name: "Alice",
1118
+ * age: 42,
1119
+ * pet: cat,
1120
+ * }, { owner: friendGroup });
1121
+ * ```
1122
+ *
1123
+ * @category Creation
1124
+ **/
1125
+ static create(init, options) {
1126
+ const instance = new this();
1127
+ const raw = instance.rawFromInit(
1128
+ init,
1129
+ options.owner,
1130
+ options.unique === void 0 ? void 0 : { uniqueness: options.unique }
1131
+ );
1132
+ Object.defineProperties(instance, {
1133
+ id: {
1134
+ value: raw.id,
1135
+ enumerable: false
1136
+ },
1137
+ _raw: { value: raw, enumerable: false }
1138
+ });
1139
+ return instance;
1140
+ }
1141
+ /**
1142
+ * Return a JSON representation of the `CoMap`
1143
+ * @category Content
1144
+ */
1145
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1146
+ toJSON(_key, seenAbove) {
1147
+ const jsonedFields = this._raw.keys().map((key) => {
1148
+ const tKey = key;
1149
+ const descriptor = this._schema[tKey] || this._schema[ItemsSym];
1150
+ if (descriptor == "json" || "encode" in descriptor) {
1151
+ return [key, this._raw.get(key)];
1152
+ } else if (isRefEncoded(descriptor)) {
1153
+ if (seenAbove?.includes(this[tKey]?.id)) {
1154
+ return [key, { _circular: this[tKey]?.id }];
1155
+ }
1156
+ const jsonedRef = this[tKey]?.toJSON(tKey, [
1157
+ ...seenAbove || [],
1158
+ this.id
1159
+ ]);
1160
+ return [key, jsonedRef];
1161
+ } else {
1162
+ return [key, void 0];
1163
+ }
1164
+ });
1165
+ return {
1166
+ id: this.id,
1167
+ _type: this._type,
1168
+ ...Object.fromEntries(jsonedFields)
1169
+ };
1170
+ }
1171
+ [inspect]() {
1172
+ return this.toJSON();
1173
+ }
1174
+ /**
1175
+ * Create a new `RawCoMap` from an initialization object
1176
+ * @internal
1177
+ */
1178
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1179
+ rawFromInit(init, owner, uniqueness) {
1180
+ const rawOwner = owner._raw;
1181
+ const rawInit = {};
1182
+ if (init)
1183
+ for (const key of Object.keys(init)) {
1184
+ const initValue = init[key];
1185
+ const descriptor = this._schema[key] || this._schema[ItemsSym];
1186
+ if (!descriptor) {
1187
+ continue;
1188
+ }
1189
+ if (descriptor === "json") {
1190
+ rawInit[key] = initValue;
1191
+ } else if (isRefEncoded(descriptor)) {
1192
+ if (initValue) {
1193
+ rawInit[key] = initValue.id;
1194
+ }
1195
+ } else if ("encoded" in descriptor) {
1196
+ rawInit[key] = descriptor.encoded.encode(
1197
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1198
+ initValue
1199
+ );
1200
+ }
1201
+ }
1202
+ return rawOwner.createMap(rawInit, null, "private", uniqueness);
1203
+ }
1204
+ /**
1205
+ * Declare a Record-like CoMap schema, by extending `CoMap.Record(...)` and passing the value schema using `co`. Keys are always `string`.
1206
+ *
1207
+ * @example
1208
+ * ```ts
1209
+ * import { co, CoMap } from "jazz-tools";
1210
+ *
1211
+ * class ColorToFruitMap extends CoMap.Record(
1212
+ * co.ref(Fruit)
1213
+ * ) {}
1214
+ *
1215
+ * // assume we have map: ColorToFruitMap
1216
+ * // and strawberry: Fruit
1217
+ * map["red"] = strawberry;
1218
+ * ```
1219
+ *
1220
+ * @category Declaration
1221
+ */
1222
+ static Record(value) {
1223
+ var _a2, _b2;
1224
+ class RecordLikeCoMap extends (_b2 = _CoMap, _a2 = ItemsSym, _b2) {
1225
+ constructor() {
1226
+ super(...arguments);
1227
+ this[_a2] = value;
1228
+ }
1229
+ }
1230
+ return RecordLikeCoMap;
1231
+ }
1232
+ /**
1233
+ * Load a `CoMap` with a given ID, as a given account.
1234
+ *
1235
+ * `depth` specifies which (if any) fields that reference other CoValues to load as well before resolving.
1236
+ * The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
1237
+ *
1238
+ * You can pass `[]` or `{}` for shallowly loading only this CoMap, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues.
1239
+ *
1240
+ * Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
1241
+ *
1242
+ * @example
1243
+ * ```ts
1244
+ * const person = await Person.load(
1245
+ * "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
1246
+ * me,
1247
+ * { pet: {} }
1248
+ * );
1249
+ * ```
1250
+ *
1251
+ * @category Subscription & Loading
1252
+ */
1253
+ static load(id, as, depth) {
1254
+ return loadCoValue(this, id, as, depth);
1255
+ }
1256
+ /**
1257
+ * Load and subscribe to a `CoMap` with a given ID, as a given account.
1258
+ *
1259
+ * Automatically also subscribes to updates to all referenced/nested CoValues as soon as they are accessed in the listener.
1260
+ *
1261
+ * `depth` specifies which (if any) fields that reference other CoValues to load as well before calling `listener` for the first time.
1262
+ * The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
1263
+ *
1264
+ * You can pass `[]` or `{}` for shallowly loading only this CoMap, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues.
1265
+ *
1266
+ * Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
1267
+ *
1268
+ * Returns an unsubscribe function that you should call when you no longer need updates.
1269
+ *
1270
+ * Also see the `useCoState` hook to reactively subscribe to a CoValue in a React component.
1271
+ *
1272
+ * @example
1273
+ * ```ts
1274
+ * const unsub = Person.subscribe(
1275
+ * "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
1276
+ * me,
1277
+ * { pet: {} },
1278
+ * (person) => console.log(person)
1279
+ * );
1280
+ * ```
1281
+ *
1282
+ * @category Subscription & Loading
1283
+ */
1284
+ static subscribe(id, as, depth, listener) {
1285
+ return subscribeToCoValue(this, id, as, depth, listener);
1286
+ }
1287
+ static findUnique(unique, ownerID, as) {
1288
+ const header = {
1289
+ type: "comap",
1290
+ ruleset: {
1291
+ type: "ownedByGroup",
1292
+ group: ownerID
1293
+ },
1294
+ meta: null,
1295
+ uniqueness: unique
1296
+ };
1297
+ const crypto = as._type === "Anonymous" ? as.node.crypto : as._raw.core.crypto;
1298
+ return cojsonInternals.idforHeader(header, crypto);
1299
+ }
1300
+ /**
1301
+ * Given an already loaded `CoMap`, ensure that the specified fields are loaded to the specified depth.
1302
+ *
1303
+ * Works like `CoMap.load()`, but you don't need to pass the ID or the account to load as again.
1304
+ *
1305
+ * @category Subscription & Loading
1306
+ */
1307
+ ensureLoaded(depth) {
1308
+ return ensureCoValueLoaded(this, depth);
1309
+ }
1310
+ /**
1311
+ * Given an already loaded `CoMap`, subscribe to updates to the `CoMap` and ensure that the specified fields are loaded to the specified depth.
1312
+ *
1313
+ * Works like `CoMap.subscribe()`, but you don't need to pass the ID or the account to load as again.
1314
+ *
1315
+ * Returns an unsubscribe function that you should call when you no longer need updates.
1316
+ *
1317
+ * @category Subscription & Loading
1318
+ **/
1319
+ subscribe(depth, listener) {
1320
+ return subscribeToExistingCoValue(this, depth, listener);
1321
+ }
1322
+ applyDiff(newValues) {
1323
+ for (const key in newValues) {
1324
+ if (Object.prototype.hasOwnProperty.call(newValues, key)) {
1325
+ const tKey = key;
1326
+ const descriptor = this._schema[tKey] || this._schema[ItemsSym];
1327
+ if (tKey in this._schema) {
1328
+ const newValue = newValues[tKey];
1329
+ const currentValue = this[tKey];
1330
+ if (descriptor === "json" || "encoded" in descriptor) {
1331
+ if (currentValue !== newValue) {
1332
+ this[tKey] = newValue;
1333
+ }
1334
+ } else if (isRefEncoded(descriptor)) {
1335
+ const currentId = currentValue?.id;
1336
+ const newId = newValue?.id;
1337
+ if (currentId !== newId) {
1338
+ this[tKey] = newValue;
1339
+ }
1340
+ }
1341
+ }
1342
+ }
1343
+ }
1344
+ return this;
1345
+ }
1346
+ /**
1347
+ * Wait for the `CoMap` to be uploaded to the other peers.
1348
+ *
1349
+ * @category Subscription & Loading
1350
+ */
1351
+ waitForSync(options) {
1352
+ return this._raw.core.waitForSync(options);
1353
+ }
1354
+ };
1355
+ _CoMap.prototype._type = "CoMap";
1356
+ var CoMap = _CoMap;
1357
+ var CoMapProxyHandler = {
1358
+ get(target, key, receiver) {
1359
+ if (key === "_schema") {
1360
+ return Reflect.get(target, key);
1361
+ } else if (key in target) {
1362
+ return Reflect.get(target, key, receiver);
1363
+ } else {
1364
+ const descriptor = target._schema[key] || target._schema[ItemsSym];
1365
+ if (descriptor && typeof key === "string") {
1366
+ const raw = target._raw.get(key);
1367
+ if (descriptor === "json") {
1368
+ return raw;
1369
+ } else if ("encoded" in descriptor) {
1370
+ return raw === void 0 ? void 0 : descriptor.encoded.decode(raw);
1371
+ } else if (isRefEncoded(descriptor)) {
1372
+ return raw === void 0 ? void 0 : new Ref(
1373
+ raw,
1374
+ target._loadedAs,
1375
+ descriptor
1376
+ ).accessFrom(receiver, key);
1377
+ }
1378
+ } else {
1379
+ return void 0;
1380
+ }
1381
+ }
1382
+ },
1383
+ set(target, key, value, receiver) {
1384
+ if ((typeof key === "string" || ItemsSym) && typeof value === "object" && value !== null && SchemaInit in value) {
1385
+ target.constructor._schema ||= {};
1386
+ target.constructor._schema[key] = value[SchemaInit];
1387
+ return true;
1388
+ }
1389
+ const descriptor = target._schema[key] || target._schema[ItemsSym];
1390
+ if (descriptor && typeof key === "string") {
1391
+ if (descriptor === "json") {
1392
+ target._raw.set(key, value);
1393
+ } else if ("encoded" in descriptor) {
1394
+ target._raw.set(key, descriptor.encoded.encode(value));
1395
+ } else if (isRefEncoded(descriptor)) {
1396
+ if (value === null) {
1397
+ if (descriptor.optional) {
1398
+ target._raw.set(key, null);
1399
+ } else {
1400
+ throw new Error(`Cannot set required reference ${key} to null`);
1401
+ }
1402
+ } else {
1403
+ target._raw.set(key, value.id);
1404
+ subscriptionsScopes.get(target)?.onRefAccessedOrSet(target.id, value.id);
1405
+ }
1406
+ }
1407
+ return true;
1408
+ } else {
1409
+ return Reflect.set(target, key, value, receiver);
1410
+ }
1411
+ },
1412
+ defineProperty(target, key, attributes) {
1413
+ if ("value" in attributes && typeof attributes.value === "object" && SchemaInit in attributes.value) {
1414
+ target.constructor._schema ||= {};
1415
+ target.constructor._schema[key] = attributes.value[SchemaInit];
1416
+ return true;
1417
+ } else {
1418
+ return Reflect.defineProperty(target, key, attributes);
1419
+ }
1420
+ },
1421
+ ownKeys(target) {
1422
+ const keys = Reflect.ownKeys(target).filter((k) => k !== ItemsSym);
1423
+ for (const key of target._raw.keys()) {
1424
+ if (!keys.includes(key)) {
1425
+ keys.push(key);
1426
+ }
1427
+ }
1428
+ return keys;
1429
+ },
1430
+ getOwnPropertyDescriptor(target, key) {
1431
+ if (key in target) {
1432
+ return Reflect.getOwnPropertyDescriptor(target, key);
1433
+ } else {
1434
+ const descriptor = target._schema[key] || target._schema[ItemsSym];
1435
+ if (descriptor || key in target._raw.latest) {
1436
+ return {
1437
+ enumerable: true,
1438
+ configurable: true,
1439
+ writable: true
1440
+ };
1441
+ }
1442
+ }
1443
+ },
1444
+ has(target, key) {
1445
+ const descriptor = target._schema?.[key] || target._schema?.[ItemsSym];
1446
+ if (target._raw && typeof key === "string" && descriptor) {
1447
+ return target._raw.get(key) !== void 0;
1448
+ } else {
1449
+ return Reflect.has(target, key);
1450
+ }
1451
+ },
1452
+ deleteProperty(target, key) {
1453
+ const descriptor = target._schema[key] || target._schema[ItemsSym];
1454
+ if (typeof key === "string" && descriptor) {
1455
+ target._raw.delete(key);
1456
+ return true;
1457
+ } else {
1458
+ return Reflect.deleteProperty(target, key);
1459
+ }
1460
+ }
1461
+ };
1462
+ RegisteredSchemas["CoMap"] = CoMap;
1463
+
1464
+ // src/coValues/profile.ts
1465
+ var Profile = class extends CoMap {
1466
+ constructor() {
1467
+ super(...arguments);
1468
+ this.name = co.string;
1469
+ this.inbox = co.optional.json();
1470
+ this.inboxInvite = co.optional.json();
1471
+ }
1472
+ };
1473
+
1474
+ // src/coValues/account.ts
1475
+ import {
1476
+ LocalNode as LocalNode2,
1477
+ RawAccount as RawAccount4,
1478
+ cojsonInternals as cojsonInternals2
1479
+ } from "cojson";
1480
+ var _Account = class _Account extends CoValueBase {
1481
+ get _schema() {
1482
+ return this.constructor._schema;
1483
+ }
1484
+ get _owner() {
1485
+ return this;
1486
+ }
1487
+ get _loadedAs() {
1488
+ if (this.isMe) return this;
1489
+ const rawAccount = this._raw.core.node.account;
1490
+ if (rawAccount instanceof RawAccount4) {
1491
+ return coValuesCache.get(rawAccount, () => _Account.fromRaw(rawAccount));
1492
+ }
1493
+ return new AnonymousJazzAgent(this._raw.core.node);
1494
+ }
1495
+ get _refs() {
1496
+ const profileID = this._raw.get("profile");
1497
+ const rootID = this._raw.get("root");
1498
+ return {
1499
+ profile: profileID && new Ref(
1500
+ profileID,
1501
+ this._loadedAs,
1502
+ this._schema.profile
1503
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1504
+ ),
1505
+ root: rootID && new Ref(
1506
+ rootID,
1507
+ this._loadedAs,
1508
+ this._schema.root
1509
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1510
+ )
1511
+ };
1512
+ }
1513
+ constructor(options) {
1514
+ super();
1515
+ if (!("fromRaw" in options)) {
1516
+ throw new Error("Can only construct account from raw or with .create()");
1517
+ }
1518
+ this.isMe = options.fromRaw.id == options.fromRaw.core.node.account.id;
1519
+ Object.defineProperties(this, {
1520
+ id: {
1521
+ value: options.fromRaw.id,
1522
+ enumerable: false
1523
+ },
1524
+ _raw: { value: options.fromRaw, enumerable: false },
1525
+ _type: { value: "Account", enumerable: false }
1526
+ });
1527
+ if (this.isMe) {
1528
+ this.sessionID = options.fromRaw.core.node.currentSessionID;
1529
+ }
1530
+ return new Proxy(this, AccountAndGroupProxyHandler);
1531
+ }
1532
+ myRole() {
1533
+ if (this.isMe) {
1534
+ return "admin";
1535
+ }
1536
+ }
1537
+ async acceptInvite(valueID, inviteSecret, coValueClass) {
1538
+ if (!this.isMe) {
1539
+ throw new Error("Only a controlled account can accept invites");
1540
+ }
1541
+ await this._raw.acceptInvite(
1542
+ valueID,
1543
+ inviteSecret
1544
+ );
1545
+ return loadCoValue(coValueClass, valueID, this, []);
1546
+ }
1547
+ /** @private */
1548
+ static async create(options) {
1549
+ const { node } = await LocalNode2.withNewlyCreatedAccount({
1550
+ ...options,
1551
+ migration: async (rawAccount, _node, creationProps) => {
1552
+ const account = new this({
1553
+ fromRaw: rawAccount
1554
+ });
1555
+ await account.migrate?.(creationProps);
1556
+ }
1557
+ });
1558
+ return this.fromNode(node);
1559
+ }
1560
+ static async createAs(as, options) {
1561
+ const connectedPeers = cojsonInternals2.connectedPeers(
1562
+ "creatingAccount",
1563
+ "createdAccount",
1564
+ { peer1role: "server", peer2role: "client" }
1565
+ );
1566
+ as._raw.core.node.syncManager.addPeer(connectedPeers[1]);
1567
+ return this.create({
1568
+ creationProps: options.creationProps,
1569
+ crypto: as._raw.core.node.crypto,
1570
+ peersToLoadFrom: [connectedPeers[0]]
1571
+ });
1572
+ }
1573
+ static fromNode(node) {
1574
+ return new this({
1575
+ fromRaw: node.account
1576
+ });
1577
+ }
1578
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1579
+ toJSON() {
1580
+ return {
1581
+ id: this.id,
1582
+ _type: this._type
1583
+ };
1584
+ }
1585
+ [inspect]() {
1586
+ return this.toJSON();
1587
+ }
1588
+ migrate(creationProps) {
1589
+ if (creationProps) {
1590
+ const profileGroup = RegisteredSchemas["Group"].create({ owner: this });
1591
+ profileGroup.addMember("everyone", "reader");
1592
+ this.profile = Profile.create(
1593
+ { name: creationProps.name },
1594
+ { owner: profileGroup }
1595
+ );
1596
+ }
1597
+ const node = this._raw.core.node;
1598
+ const profile = node.expectCoValueLoaded(this._raw.get("profile")).getCurrentContent();
1599
+ if (!profile.get("inbox")) {
1600
+ const inboxRoot = createInboxRoot(this);
1601
+ profile.set("inbox", inboxRoot.id);
1602
+ profile.set("inboxInvite", inboxRoot.inviteLink);
1603
+ }
1604
+ }
1605
+ /** @category Subscription & Loading */
1606
+ static load(id, as, depth) {
1607
+ return loadCoValue(this, id, as, depth);
1608
+ }
1609
+ /** @category Subscription & Loading */
1610
+ static subscribe(id, as, depth, listener) {
1611
+ return subscribeToCoValue(this, id, as, depth, listener);
1612
+ }
1613
+ /** @category Subscription & Loading */
1614
+ ensureLoaded(depth) {
1615
+ return ensureCoValueLoaded(this, depth);
1616
+ }
1617
+ /** @category Subscription & Loading */
1618
+ subscribe(depth, listener) {
1619
+ return subscribeToExistingCoValue(this, depth, listener);
1620
+ }
1621
+ /**
1622
+ * Wait for the `Account` to be uploaded to the other peers.
1623
+ *
1624
+ * @category Subscription & Loading
1625
+ */
1626
+ waitForSync(options) {
1627
+ return this._raw.core.waitForSync(options);
1628
+ }
1629
+ /**
1630
+ * Wait for all the available `CoValues` to be uploaded to the other peers.
1631
+ *
1632
+ * @category Subscription & Loading
1633
+ */
1634
+ waitForAllCoValuesSync(options) {
1635
+ return this._raw.core.node.syncManager.waitForAllCoValuesSync(
1636
+ options?.timeout
1637
+ );
1638
+ }
1639
+ };
1640
+ _Account._schema = {
1641
+ profile: {
1642
+ ref: () => Profile,
1643
+ optional: false
1644
+ },
1645
+ root: {
1646
+ ref: () => RegisteredSchemas["CoMap"],
1647
+ optional: true
1648
+ }
1649
+ };
1650
+ var Account = _Account;
1651
+ var AccountAndGroupProxyHandler = {
1652
+ get(target, key, receiver) {
1653
+ if (key === "profile") {
1654
+ const ref2 = target._refs.profile;
1655
+ return ref2 ? ref2.accessFrom(receiver, "profile") : (
1656
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1657
+ void 0
1658
+ );
1659
+ } else if (key === "root") {
1660
+ const ref2 = target._refs.root;
1661
+ return ref2 ? ref2.accessFrom(receiver, "root") : void 0;
1662
+ } else {
1663
+ return Reflect.get(target, key, receiver);
1664
+ }
1665
+ },
1666
+ set(target, key, value, receiver) {
1667
+ if ((key === "profile" || key === "root" || key === MembersSym) && typeof value === "object" && SchemaInit in value) {
1668
+ target.constructor._schema ||= {};
1669
+ target.constructor._schema[key] = value[SchemaInit];
1670
+ return true;
1671
+ } else if (key === "profile") {
1672
+ if (value) {
1673
+ target._raw.set(
1674
+ "profile",
1675
+ value.id,
1676
+ "trusting"
1677
+ );
1678
+ }
1679
+ subscriptionsScopes.get(receiver)?.onRefAccessedOrSet(target.id, value.id);
1680
+ return true;
1681
+ } else if (key === "root") {
1682
+ if (value) {
1683
+ target._raw.set("root", value.id);
1684
+ }
1685
+ subscriptionsScopes.get(receiver)?.onRefAccessedOrSet(target.id, value.id);
1686
+ return true;
1687
+ } else {
1688
+ return Reflect.set(target, key, value, receiver);
1689
+ }
1690
+ },
1691
+ defineProperty(target, key, descriptor) {
1692
+ if ((key === "profile" || key === "root" || key === MembersSym) && typeof descriptor.value === "object" && SchemaInit in descriptor.value) {
1693
+ target.constructor._schema ||= {};
1694
+ target.constructor._schema[key] = descriptor.value[SchemaInit];
1695
+ return true;
1696
+ } else {
1697
+ return Reflect.defineProperty(target, key, descriptor);
1698
+ }
1699
+ }
1700
+ };
1701
+ function isControlledAccount(account) {
1702
+ return account.isMe;
1703
+ }
1704
+ RegisteredSchemas["Account"] = Account;
1705
+
1706
+ // src/coValues/group.ts
1707
+ var _Group = class _Group extends CoValueBase {
1708
+ get _schema() {
1709
+ return this.constructor._schema;
1710
+ }
1711
+ get _refs() {
1712
+ const profileID = this._raw.get("profile");
1713
+ const rootID = this._raw.get("root");
1714
+ return {
1715
+ profile: profileID && new Ref(
1716
+ profileID,
1717
+ this._loadedAs,
1718
+ this._schema.profile
1719
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1720
+ ),
1721
+ root: rootID && new Ref(
1722
+ rootID,
1723
+ this._loadedAs,
1724
+ this._schema.root
1725
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1726
+ )
1727
+ };
1728
+ }
1729
+ /** @deprecated Don't use constructor directly, use .create */
1730
+ constructor(options) {
1731
+ super();
1732
+ let raw;
1733
+ if (options && "fromRaw" in options) {
1734
+ raw = options.fromRaw;
1735
+ } else {
1736
+ const initOwner = options.owner;
1737
+ if (!initOwner) throw new Error("No owner provided");
1738
+ if (initOwner._type === "Account" && isControlledAccount(initOwner)) {
1739
+ const rawOwner = initOwner._raw;
1740
+ raw = rawOwner.createGroup();
1741
+ } else {
1742
+ throw new Error("Can only construct group as a controlled account");
1743
+ }
1744
+ }
1745
+ Object.defineProperties(this, {
1746
+ id: {
1747
+ value: raw.id,
1748
+ enumerable: false
1749
+ },
1750
+ _raw: { value: raw, enumerable: false }
1751
+ });
1752
+ return new Proxy(this, AccountAndGroupProxyHandler);
1753
+ }
1754
+ static create(options) {
1755
+ return new this(options);
1756
+ }
1757
+ myRole() {
1758
+ return this._raw.myRole();
1759
+ }
1760
+ addMember(member, role) {
1761
+ this._raw.addMember(member === "everyone" ? member : member._raw, role);
1762
+ return this;
1763
+ }
1764
+ removeMember(member) {
1765
+ this._raw.removeMember(member === "everyone" ? member : member._raw);
1766
+ return this;
1767
+ }
1768
+ get members() {
1769
+ return this._raw.keys().filter((key) => {
1770
+ return key === "everyone" || key.startsWith("co_");
1771
+ }).map((id) => {
1772
+ const role = this._raw.get(id);
1773
+ const accountID = id === "everyone" ? void 0 : id;
1774
+ const ref2 = accountID && new Ref(
1775
+ accountID,
1776
+ this._loadedAs,
1777
+ this._schema[MembersSym]
1778
+ );
1779
+ const accessRef = () => ref2?.accessFrom(this, "members." + id);
1780
+ return {
1781
+ id,
1782
+ role,
1783
+ ref: ref2,
1784
+ get account() {
1785
+ return accessRef();
1786
+ }
1787
+ };
1788
+ });
1789
+ }
1790
+ extend(parent) {
1791
+ this._raw.extend(parent._raw);
1792
+ return this;
1793
+ }
1794
+ /** @category Subscription & Loading */
1795
+ static load(id, as, depth) {
1796
+ return loadCoValue(this, id, as, depth);
1797
+ }
1798
+ /** @category Subscription & Loading */
1799
+ static subscribe(id, as, depth, listener) {
1800
+ return subscribeToCoValue(this, id, as, depth, listener);
1801
+ }
1802
+ /** @category Subscription & Loading */
1803
+ ensureLoaded(depth) {
1804
+ return ensureCoValueLoaded(this, depth);
1805
+ }
1806
+ /** @category Subscription & Loading */
1807
+ subscribe(depth, listener) {
1808
+ return subscribeToExistingCoValue(this, depth, listener);
1809
+ }
1810
+ /**
1811
+ * Wait for the `Group` to be uploaded to the other peers.
1812
+ *
1813
+ * @category Subscription & Loading
1814
+ */
1815
+ waitForSync(options) {
1816
+ return this._raw.core.waitForSync(options);
1817
+ }
1818
+ };
1819
+ _Group.prototype._type = "Group";
1820
+ _Group._schema = {
1821
+ profile: "json",
1822
+ root: "json",
1823
+ [MembersSym]: {
1824
+ ref: () => RegisteredSchemas["Account"],
1825
+ optional: false
1826
+ }
1827
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1828
+ };
1829
+ Object.defineProperty(_Group.prototype, "_schema", {
1830
+ get: () => _Group._schema
1831
+ });
1832
+ var Group = _Group;
1833
+ RegisteredSchemas["Group"] = Group;
1834
+
1835
+ // src/coValues/coFeed.ts
1836
+ import { MAX_RECOMMENDED_TX_SIZE, cojsonInternals as cojsonInternals3 } from "cojson";
1837
+ var _CoFeed = class _CoFeed extends CoValueBase {
1838
+ /**
1839
+ * Declare a `CoFeed` by subclassing `CoFeed.Of(...)` and passing the item schema using a `co` primitive or a `co.ref`.
1840
+ *
1841
+ * @example
1842
+ * ```ts
1843
+ * class ColorFeed extends CoFeed.Of(co.string) {}
1844
+ * class AnimalFeed extends CoFeed.Of(co.ref(Animal)) {}
1845
+ * ```
1846
+ *
1847
+ * @category Declaration
1848
+ */
1849
+ static Of(item) {
1850
+ var _a2, _b2;
1851
+ return class CoFeedOf extends (_b2 = _CoFeed, _a2 = co.items, _b2) {
1852
+ constructor() {
1853
+ super(...arguments);
1854
+ this[_a2] = item;
1855
+ }
1856
+ };
1857
+ }
1858
+ /** @internal */
1859
+ get _schema() {
1860
+ return this.constructor._schema;
1861
+ }
1862
+ /**
1863
+ * The current account's view of this `CoFeed`
1864
+ * @category Content
1865
+ */
1866
+ get byMe() {
1867
+ if (this._loadedAs._type === "Account") {
1868
+ return this[this._loadedAs.id];
1869
+ } else {
1870
+ return void 0;
1871
+ }
1872
+ }
1873
+ /**
1874
+ * The current session's view of this `CoFeed`
1875
+ *
1876
+ * This is a shortcut for `this.perSession` where the session ID is the current session ID.
1877
+ *
1878
+ * @category Content
1879
+ */
1880
+ get inCurrentSession() {
1881
+ if (this._loadedAs._type === "Account") {
1882
+ return this.perSession[this._loadedAs.sessionID];
1883
+ } else {
1884
+ return void 0;
1885
+ }
1886
+ }
1887
+ constructor(options) {
1888
+ super();
1889
+ if (options && "fromRaw" in options) {
1890
+ Object.defineProperties(this, {
1891
+ id: {
1892
+ value: options.fromRaw.id,
1893
+ enumerable: false
1894
+ },
1895
+ _raw: { value: options.fromRaw, enumerable: false }
1896
+ });
1897
+ }
1898
+ return new Proxy(this, CoStreamProxyHandler);
1899
+ }
1900
+ /**
1901
+ * Create a new `CoFeed`
1902
+ * @category Creation
1903
+ */
1904
+ static create(init, options) {
1905
+ const instance = new this({ init, owner: options.owner });
1906
+ const raw = options.owner._raw.createStream();
1907
+ Object.defineProperties(instance, {
1908
+ id: {
1909
+ value: raw.id,
1910
+ enumerable: false
1911
+ },
1912
+ _raw: { value: raw, enumerable: false }
1913
+ });
1914
+ if (init) {
1915
+ instance.push(...init);
1916
+ }
1917
+ return instance;
1918
+ }
1919
+ /**
1920
+ * Push items to this `CoFeed`
1921
+ *
1922
+ * Items are appended to the current session's log. Each session (tab, device, app instance)
1923
+ * maintains its own append-only log, which is then aggregated into the per-account view.
1924
+ *
1925
+ * @example
1926
+ * ```ts
1927
+ * // Adds items to current session's log
1928
+ * feed.push("item1", "item2");
1929
+ *
1930
+ * // View items from current session
1931
+ * console.log(feed.inCurrentSession);
1932
+ *
1933
+ * // View aggregated items from all sessions for current account
1934
+ * console.log(feed.byMe);
1935
+ * ```
1936
+ *
1937
+ * @category Content
1938
+ */
1939
+ push(...items) {
1940
+ for (const item of items) {
1941
+ this.pushItem(item);
1942
+ }
1943
+ }
1944
+ pushItem(item) {
1945
+ const itemDescriptor = this._schema[ItemsSym];
1946
+ if (itemDescriptor === "json") {
1947
+ this._raw.push(item);
1948
+ } else if ("encoded" in itemDescriptor) {
1949
+ this._raw.push(itemDescriptor.encoded.encode(item));
1950
+ } else if (isRefEncoded(itemDescriptor)) {
1951
+ this._raw.push(item.id);
1952
+ }
1953
+ }
1954
+ /**
1955
+ * Get a JSON representation of the `CoFeed`
1956
+ * @category
1957
+ */
1958
+ toJSON() {
1959
+ const itemDescriptor = this._schema[ItemsSym];
1960
+ const mapper = itemDescriptor === "json" ? (v) => v : "encoded" in itemDescriptor ? itemDescriptor.encoded.encode : (v) => v && v.id;
1961
+ return {
1962
+ id: this.id,
1963
+ _type: this._type,
1964
+ ...Object.fromEntries(
1965
+ Object.entries(this).map(([account, entry]) => [
1966
+ account,
1967
+ mapper(entry.value)
1968
+ ])
1969
+ ),
1970
+ in: Object.fromEntries(
1971
+ Object.entries(this.perSession).map(([session, entry]) => [
1972
+ session,
1973
+ mapper(entry.value)
1974
+ ])
1975
+ )
1976
+ };
1977
+ }
1978
+ /** @internal */
1979
+ [(ItemsSym, inspect)]() {
1980
+ return this.toJSON();
1981
+ }
1982
+ /** @internal */
1983
+ static schema(def) {
1984
+ this._schema ||= {};
1985
+ Object.assign(this._schema, def);
1986
+ }
1987
+ /**
1988
+ * Load a `CoFeed`
1989
+ * @category Subscription & Loading
1990
+ */
1991
+ static load(id, as, depth) {
1992
+ return loadCoValue(this, id, as, depth);
1993
+ }
1994
+ /**
1995
+ * Subscribe to a `CoFeed`, when you have an ID but don't have a `CoFeed` instance yet
1996
+ * @category Subscription & Loading
1997
+ */
1998
+ static subscribe(id, as, depth, listener) {
1999
+ return subscribeToCoValue(this, id, as, depth, listener);
2000
+ }
2001
+ /**
2002
+ * Ensure a `CoFeed` is loaded to the specified depth
2003
+ *
2004
+ * @returns A new instance of the same CoFeed that's loaded to the specified depth,
2005
+ * or undefined if it cannot be loaded that deeply
2006
+ * @category Subscription & Loading
2007
+ */
2008
+ ensureLoaded(depth) {
2009
+ return ensureCoValueLoaded(this, depth);
2010
+ }
2011
+ /**
2012
+ * An instance method to subscribe to an existing `CoFeed`
2013
+ *
2014
+ * No need to provide an ID or Account since they're already part of the instance.
2015
+ * @category Subscription & Loading
2016
+ */
2017
+ subscribe(depth, listener) {
2018
+ return subscribeToExistingCoValue(this, depth, listener);
2019
+ }
2020
+ /**
2021
+ * Wait for the `CoFeed` to be uploaded to the other peers.
2022
+ *
2023
+ * @category Subscription & Loading
2024
+ */
2025
+ waitForSync(options) {
2026
+ return this._raw.core.waitForSync(options);
2027
+ }
2028
+ };
2029
+ _CoFeed.prototype._type = "CoStream";
2030
+ var CoFeed = _CoFeed;
2031
+ function entryFromRawEntry(accessFrom, rawEntry, loadedAs, accountID, itemField) {
2032
+ return {
2033
+ get value() {
2034
+ if (itemField === "json") {
2035
+ return rawEntry.value;
2036
+ } else if ("encoded" in itemField) {
2037
+ return itemField.encoded.decode(rawEntry.value);
2038
+ } else if (isRefEncoded(itemField)) {
2039
+ return this.ref?.accessFrom(
2040
+ accessFrom,
2041
+ rawEntry.by + rawEntry.tx.sessionID + rawEntry.tx.txIndex + ".value"
2042
+ );
2043
+ } else {
2044
+ throw new Error("Invalid item field schema");
2045
+ }
2046
+ },
2047
+ get ref() {
2048
+ if (itemField !== "json" && isRefEncoded(itemField)) {
2049
+ const rawId = rawEntry.value;
2050
+ return new Ref(
2051
+ rawId,
2052
+ loadedAs,
2053
+ itemField
2054
+ );
2055
+ } else {
2056
+ return void 0;
2057
+ }
2058
+ },
2059
+ get by() {
2060
+ return accountID && new Ref(accountID, loadedAs, {
2061
+ ref: RegisteredSchemas["Account"],
2062
+ optional: false
2063
+ })?.accessFrom(
2064
+ accessFrom,
2065
+ rawEntry.by + rawEntry.tx.sessionID + rawEntry.tx.txIndex + ".by"
2066
+ );
2067
+ },
2068
+ madeAt: rawEntry.at,
2069
+ tx: rawEntry.tx
2070
+ };
2071
+ }
2072
+ var CoStreamProxyHandler = {
2073
+ get(target, key, receiver) {
2074
+ if (typeof key === "string" && key.startsWith("co_")) {
2075
+ const rawEntry = target._raw.lastItemBy(key);
2076
+ if (!rawEntry) return;
2077
+ const entry = entryFromRawEntry(
2078
+ receiver,
2079
+ rawEntry,
2080
+ target._loadedAs,
2081
+ key,
2082
+ target._schema[ItemsSym]
2083
+ );
2084
+ Object.defineProperty(entry, "all", {
2085
+ get: () => {
2086
+ const allRawEntries = target._raw.itemsBy(key);
2087
+ return function* () {
2088
+ while (true) {
2089
+ const rawEntry2 = allRawEntries.next();
2090
+ if (rawEntry2.done) return;
2091
+ yield entryFromRawEntry(
2092
+ receiver,
2093
+ rawEntry2.value,
2094
+ target._loadedAs,
2095
+ key,
2096
+ target._schema[ItemsSym]
2097
+ );
2098
+ }
2099
+ }();
2100
+ }
2101
+ });
2102
+ return entry;
2103
+ } else if (key === "perSession") {
2104
+ return new Proxy({}, CoStreamPerSessionProxyHandler(target, receiver));
2105
+ } else {
2106
+ return Reflect.get(target, key, receiver);
2107
+ }
2108
+ },
2109
+ set(target, key, value, receiver) {
2110
+ if (key === ItemsSym && typeof value === "object" && SchemaInit in value) {
2111
+ target.constructor._schema ||= {};
2112
+ target.constructor._schema[ItemsSym] = value[SchemaInit];
2113
+ return true;
2114
+ } else {
2115
+ return Reflect.set(target, key, value, receiver);
2116
+ }
2117
+ },
2118
+ defineProperty(target, key, descriptor) {
2119
+ if (descriptor.value && key === ItemsSym && typeof descriptor.value === "object" && SchemaInit in descriptor.value) {
2120
+ target.constructor._schema ||= {};
2121
+ target.constructor._schema[ItemsSym] = descriptor.value[SchemaInit];
2122
+ return true;
2123
+ } else {
2124
+ return Reflect.defineProperty(target, key, descriptor);
2125
+ }
2126
+ },
2127
+ ownKeys(target) {
2128
+ const keys = Reflect.ownKeys(target);
2129
+ for (const accountID of target._raw.accounts()) {
2130
+ keys.push(accountID);
2131
+ }
2132
+ return keys;
2133
+ },
2134
+ getOwnPropertyDescriptor(target, key) {
2135
+ if (typeof key === "string" && key.startsWith("co_")) {
2136
+ return {
2137
+ configurable: true,
2138
+ enumerable: true,
2139
+ writable: false
2140
+ };
2141
+ } else {
2142
+ return Reflect.getOwnPropertyDescriptor(target, key);
2143
+ }
2144
+ }
2145
+ };
2146
+ var CoStreamPerSessionProxyHandler = (innerTarget, accessFrom) => ({
2147
+ get(_target, key, receiver) {
2148
+ if (typeof key === "string" && key.includes("session")) {
2149
+ const sessionID = key;
2150
+ const rawEntry = innerTarget._raw.lastItemIn(sessionID);
2151
+ if (!rawEntry) return;
2152
+ const by = cojsonInternals3.accountOrAgentIDfromSessionID(sessionID);
2153
+ const entry = entryFromRawEntry(
2154
+ accessFrom,
2155
+ rawEntry,
2156
+ innerTarget._loadedAs,
2157
+ cojsonInternals3.isAccountID(by) ? by : void 0,
2158
+ innerTarget._schema[ItemsSym]
2159
+ );
2160
+ Object.defineProperty(entry, "all", {
2161
+ get: () => {
2162
+ const allRawEntries = innerTarget._raw.itemsIn(sessionID);
2163
+ return function* () {
2164
+ while (true) {
2165
+ const rawEntry2 = allRawEntries.next();
2166
+ if (rawEntry2.done) return;
2167
+ yield entryFromRawEntry(
2168
+ accessFrom,
2169
+ rawEntry2.value,
2170
+ innerTarget._loadedAs,
2171
+ cojsonInternals3.isAccountID(by) ? by : void 0,
2172
+ innerTarget._schema[ItemsSym]
2173
+ );
2174
+ }
2175
+ }();
2176
+ }
2177
+ });
2178
+ return entry;
2179
+ } else {
2180
+ return Reflect.get(innerTarget, key, receiver);
2181
+ }
2182
+ },
2183
+ ownKeys() {
2184
+ return innerTarget._raw.sessions();
2185
+ },
2186
+ getOwnPropertyDescriptor(target, key) {
2187
+ if (typeof key === "string" && key.startsWith("co_")) {
2188
+ return {
2189
+ configurable: true,
2190
+ enumerable: true,
2191
+ writable: false
2192
+ };
2193
+ } else {
2194
+ return Reflect.getOwnPropertyDescriptor(target, key);
2195
+ }
2196
+ }
2197
+ });
2198
+ var FileStream = class extends CoValueBase {
2199
+ constructor(options) {
2200
+ super();
2201
+ let raw;
2202
+ if ("fromRaw" in options) {
2203
+ raw = options.fromRaw;
2204
+ } else {
2205
+ const rawOwner = options.owner._raw;
2206
+ raw = rawOwner.createBinaryStream();
2207
+ }
2208
+ Object.defineProperties(this, {
2209
+ id: {
2210
+ value: raw.id,
2211
+ enumerable: false
2212
+ },
2213
+ _type: { value: "BinaryCoStream", enumerable: false },
2214
+ _raw: { value: raw, enumerable: false }
2215
+ });
2216
+ }
2217
+ static create(options) {
2218
+ return new this(options);
2219
+ }
2220
+ getChunks(options) {
2221
+ return this._raw.getBinaryChunks(options?.allowUnfinished);
2222
+ }
2223
+ isBinaryStreamEnded() {
2224
+ return this._raw.isBinaryStreamEnded();
2225
+ }
2226
+ start(options) {
2227
+ this._raw.startBinaryStream(options);
2228
+ }
2229
+ push(data) {
2230
+ this._raw.pushBinaryStreamChunk(data);
2231
+ }
2232
+ end() {
2233
+ this._raw.endBinaryStream();
2234
+ }
2235
+ toBlob(options) {
2236
+ const chunks = this.getChunks({
2237
+ allowUnfinished: options?.allowUnfinished
2238
+ });
2239
+ if (!chunks) {
2240
+ return void 0;
2241
+ }
2242
+ return new Blob(chunks.chunks, { type: chunks.mimeType });
2243
+ }
2244
+ /**
2245
+ * Load a `FileStream` as a `Blob`
2246
+ *
2247
+ * @category Content
2248
+ */
2249
+ static async loadAsBlob(id, as, options) {
2250
+ let stream = await this.load(id, as, []);
2251
+ if (!options?.allowUnfinished && !stream?.isBinaryStreamEnded()) {
2252
+ stream = await new Promise((resolve) => {
2253
+ const unsubscribe = subscribeToCoValue(this, id, as, [], (value) => {
2254
+ if (value.isBinaryStreamEnded()) {
2255
+ unsubscribe();
2256
+ resolve(value);
2257
+ }
2258
+ });
2259
+ });
2260
+ }
2261
+ return stream?.toBlob({
2262
+ allowUnfinished: options?.allowUnfinished
2263
+ });
2264
+ }
2265
+ /**
2266
+ * Create a `FileStream` from a `Blob` or `File`
2267
+ *
2268
+ * @example
2269
+ * ```ts
2270
+ * import { co, FileStream } from "jazz-tools";
2271
+ *
2272
+ * const fileStream = await FileStream.createFromBlob(file, {owner: group})
2273
+ * ```
2274
+ * @category Content
2275
+ */
2276
+ static async createFromBlob(blob, options) {
2277
+ const stream = this.create({ owner: options.owner });
2278
+ const start = Date.now();
2279
+ const data = new Uint8Array(await blob.arrayBuffer());
2280
+ stream.start({
2281
+ mimeType: blob.type,
2282
+ totalSizeBytes: blob.size,
2283
+ fileName: blob instanceof File ? blob.name : void 0
2284
+ });
2285
+ const chunkSize = MAX_RECOMMENDED_TX_SIZE;
2286
+ let lastProgressUpdate = Date.now();
2287
+ for (let idx = 0; idx < data.length; idx += chunkSize) {
2288
+ stream.push(data.slice(idx, idx + chunkSize));
2289
+ if (Date.now() - lastProgressUpdate > 100) {
2290
+ options.onProgress?.(idx / data.length);
2291
+ lastProgressUpdate = Date.now();
2292
+ }
2293
+ await new Promise((resolve) => setTimeout(resolve, 0));
2294
+ }
2295
+ stream.end();
2296
+ const end = Date.now();
2297
+ console.debug(
2298
+ "Finished creating binary stream in",
2299
+ (end - start) / 1e3,
2300
+ "s - Throughput in MB/s",
2301
+ 1e3 * (blob.size / (end - start)) / (1024 * 1024)
2302
+ );
2303
+ options.onProgress?.(1);
2304
+ return stream;
2305
+ }
2306
+ /**
2307
+ * Get a JSON representation of the `FileStream`
2308
+ * @category Content
2309
+ */
2310
+ toJSON() {
2311
+ return {
2312
+ id: this.id,
2313
+ _type: this._type,
2314
+ ...this.getChunks()
2315
+ };
2316
+ }
2317
+ /** @internal */
2318
+ [inspect]() {
2319
+ return this.toJSON();
2320
+ }
2321
+ /**
2322
+ * Load a `FileStream`
2323
+ * @category Subscription & Loading
2324
+ */
2325
+ static load(id, as, depth) {
2326
+ return loadCoValue(this, id, as, depth);
2327
+ }
2328
+ /**
2329
+ * Subscribe to a `FileStream`, when you have an ID but don't have a `FileStream` instance yet
2330
+ * @category Subscription & Loading
2331
+ */
2332
+ static subscribe(id, as, depth, listener) {
2333
+ return subscribeToCoValue(this, id, as, depth, listener);
2334
+ }
2335
+ ensureLoaded(depth) {
2336
+ return ensureCoValueLoaded(this, depth);
2337
+ }
2338
+ /**
2339
+ * An instance method to subscribe to an existing `FileStream`
2340
+ * @category Subscription & Loading
2341
+ */
2342
+ subscribe(depth, listener) {
2343
+ return subscribeToExistingCoValue(this, depth, listener);
2344
+ }
2345
+ /**
2346
+ * Wait for the `FileStream` to be uploaded to the other peers.
2347
+ *
2348
+ * @category Subscription & Loading
2349
+ */
2350
+ waitForSync(options) {
2351
+ return this._raw.core.waitForSync(options);
2352
+ }
2353
+ };
2354
+
2355
+ // src/coValues/coList.ts
2356
+ import { RawAccount as RawAccount5 } from "cojson";
2357
+ var _CoList = class _CoList extends Array {
2358
+ /**
2359
+ * Declare a `CoList` by subclassing `CoList.Of(...)` and passing the item schema using `co`.
2360
+ *
2361
+ * @example
2362
+ * ```ts
2363
+ * class ColorList extends CoList.Of(
2364
+ * co.string
2365
+ * ) {}
2366
+ * class AnimalList extends CoList.Of(
2367
+ * co.ref(Animal)
2368
+ * ) {}
2369
+ * ```
2370
+ *
2371
+ * @category Declaration
2372
+ */
2373
+ static Of(item) {
2374
+ var _a2, _b2;
2375
+ return class CoListOf extends (_b2 = _CoList, _a2 = co.items, _b2) {
2376
+ constructor() {
2377
+ super(...arguments);
2378
+ this[_a2] = item;
2379
+ }
2380
+ };
2381
+ }
2382
+ /**
2383
+ * @ignore
2384
+ * @deprecated Use UPPERCASE `CoList.Of` instead! */
2385
+ static of(..._args) {
2386
+ throw new Error("Can't use Array.of with CoLists");
2387
+ }
2388
+ /** @internal */
2389
+ get _schema() {
2390
+ return this.constructor._schema;
2391
+ }
2392
+ /** @category Collaboration */
2393
+ get _owner() {
2394
+ return this._raw.group instanceof RawAccount5 ? RegisteredSchemas["Account"].fromRaw(this._raw.group) : RegisteredSchemas["Group"].fromRaw(this._raw.group);
2395
+ }
2396
+ /**
2397
+ * If a `CoList`'s items are a `co.ref(...)`, you can use `coList._refs[i]` to access
2398
+ * the `Ref` instead of the potentially loaded/null value.
2399
+ *
2400
+ * This allows you to always get the ID or load the value manually.
2401
+ *
2402
+ * @example
2403
+ * ```ts
2404
+ * animals._refs[0].id; // => ID<Animal>
2405
+ * animals._refs[0].value;
2406
+ * // => Animal | null
2407
+ * const animal = await animals._refs[0].load();
2408
+ * ```
2409
+ *
2410
+ * @category Content
2411
+ **/
2412
+ get _refs() {
2413
+ return makeRefs(
2414
+ (idx) => this._raw.get(idx),
2415
+ () => Array.from({ length: this._raw.entries().length }, (_, idx) => idx),
2416
+ this._loadedAs,
2417
+ (_idx) => this._schema[ItemsSym]
2418
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2419
+ );
2420
+ }
2421
+ get _edits() {
2422
+ throw new Error("Not implemented");
2423
+ }
2424
+ get _loadedAs() {
2425
+ const rawAccount = this._raw.core.node.account;
2426
+ if (rawAccount instanceof RawAccount5) {
2427
+ return coValuesCache.get(
2428
+ rawAccount,
2429
+ () => RegisteredSchemas["Account"].fromRaw(rawAccount)
2430
+ );
2431
+ }
2432
+ return new AnonymousJazzAgent(this._raw.core.node);
2433
+ }
2434
+ static get [(ItemsSym, Symbol.species)]() {
2435
+ return Array;
2436
+ }
2437
+ constructor(options) {
2438
+ super();
2439
+ Object.defineProperty(this, "_instanceID", {
2440
+ value: `instance-${Math.random().toString(36).slice(2)}`,
2441
+ enumerable: false
2442
+ });
2443
+ if (options && "fromRaw" in options) {
2444
+ Object.defineProperties(this, {
2445
+ id: {
2446
+ value: options.fromRaw.id,
2447
+ enumerable: false
2448
+ },
2449
+ _raw: { value: options.fromRaw, enumerable: false }
2450
+ });
2451
+ }
2452
+ return new Proxy(this, CoListProxyHandler);
2453
+ }
2454
+ /**
2455
+ * Create a new CoList with the given initial values and owner.
2456
+ *
2457
+ * The owner (a Group or Account) determines access rights to the CoMap.
2458
+ *
2459
+ * The CoList will immediately be persisted and synced to connected peers.
2460
+ *
2461
+ * @example
2462
+ * ```ts
2463
+ * const colours = ColorList.create(
2464
+ * ["red", "green", "blue"],
2465
+ * { owner: me }
2466
+ * );
2467
+ * const animals = AnimalList.create(
2468
+ * [cat, dog, fish],
2469
+ * { owner: me }
2470
+ * );
2471
+ * ```
2472
+ *
2473
+ * @category Creation
2474
+ **/
2475
+ static create(items, options) {
2476
+ const instance = new this({ init: items, owner: options.owner });
2477
+ const raw = options.owner._raw.createList(
2478
+ toRawItems(items, instance._schema[ItemsSym])
2479
+ );
2480
+ Object.defineProperties(instance, {
2481
+ id: {
2482
+ value: raw.id,
2483
+ enumerable: false
2484
+ },
2485
+ _raw: { value: raw, enumerable: false }
2486
+ });
2487
+ return instance;
2488
+ }
2489
+ push(...items) {
2490
+ for (const item of toRawItems(items, this._schema[ItemsSym])) {
2491
+ this._raw.append(item);
2492
+ }
2493
+ return this._raw.entries().length;
2494
+ }
2495
+ unshift(...items) {
2496
+ for (const item of toRawItems(items, this._schema[ItemsSym])) {
2497
+ this._raw.prepend(item);
2498
+ }
2499
+ return this._raw.entries().length;
2500
+ }
2501
+ pop() {
2502
+ const last = this[this.length - 1];
2503
+ this._raw.delete(this.length - 1);
2504
+ return last;
2505
+ }
2506
+ shift() {
2507
+ const first = this[0];
2508
+ this._raw.delete(0);
2509
+ return first;
2510
+ }
2511
+ splice(start, deleteCount, ...items) {
2512
+ const deleted = this.slice(start, start + deleteCount);
2513
+ for (let idxToDelete = start + deleteCount - 1; idxToDelete >= start; idxToDelete--) {
2514
+ this._raw.delete(idxToDelete);
2515
+ }
2516
+ let appendAfter = Math.max(start - 1, 0);
2517
+ for (const item of toRawItems(items, this._schema[ItemsSym])) {
2518
+ console.log(this._raw.asArray(), appendAfter);
2519
+ this._raw.append(item, appendAfter);
2520
+ appendAfter++;
2521
+ }
2522
+ return deleted;
2523
+ }
2524
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2525
+ toJSON(_key, seenAbove) {
2526
+ const itemDescriptor = this._schema[ItemsSym];
2527
+ if (itemDescriptor === "json") {
2528
+ return this._raw.asArray();
2529
+ } else if ("encoded" in itemDescriptor) {
2530
+ return this._raw.asArray().map((e) => itemDescriptor.encoded.encode(e));
2531
+ } else if (isRefEncoded(itemDescriptor)) {
2532
+ return this.map(
2533
+ (item, idx) => seenAbove?.includes(item?.id) ? { _circular: item.id } : item?.toJSON(idx + "", [
2534
+ ...seenAbove || [],
2535
+ this.id
2536
+ ])
2537
+ );
2538
+ } else {
2539
+ return [];
2540
+ }
2541
+ }
2542
+ [inspect]() {
2543
+ return this.toJSON();
2544
+ }
2545
+ /** @category Internals */
2546
+ static fromRaw(raw) {
2547
+ return new this({ fromRaw: raw });
2548
+ }
2549
+ /** @internal */
2550
+ static schema(def) {
2551
+ this._schema ||= {};
2552
+ Object.assign(this._schema, def);
2553
+ }
2554
+ /**
2555
+ * Load a `CoList` with a given ID, as a given account.
2556
+ *
2557
+ * `depth` specifies if item CoValue references should be loaded as well before resolving.
2558
+ * The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
2559
+ *
2560
+ * You can pass `[]` or for shallowly loading only this CoList, or `[itemDepth]` for recursively loading referenced CoValues.
2561
+ *
2562
+ * Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
2563
+ *
2564
+ * @example
2565
+ * ```ts
2566
+ * const animalsWithVets =
2567
+ * await ListOfAnimals.load(
2568
+ * "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
2569
+ * me,
2570
+ * [{ vet: {} }]
2571
+ * );
2572
+ * ```
2573
+ *
2574
+ * @category Subscription & Loading
2575
+ */
2576
+ static load(id, as, depth) {
2577
+ return loadCoValue(this, id, as, depth);
2578
+ }
2579
+ /**
2580
+ * Load and subscribe to a `CoList` with a given ID, as a given account.
2581
+ *
2582
+ * Automatically also subscribes to updates to all referenced/nested CoValues as soon as they are accessed in the listener.
2583
+ *
2584
+ * `depth` specifies if item CoValue references should be loaded as well before calling `listener` for the first time.
2585
+ * The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
2586
+ *
2587
+ * You can pass `[]` or for shallowly loading only this CoList, or `[itemDepth]` for recursively loading referenced CoValues.
2588
+ *
2589
+ * Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
2590
+ *
2591
+ * Returns an unsubscribe function that you should call when you no longer need updates.
2592
+ *
2593
+ * Also see the `useCoState` hook to reactively subscribe to a CoValue in a React component.
2594
+ *
2595
+ * @example
2596
+ * ```ts
2597
+ * const unsub = ListOfAnimals.subscribe(
2598
+ * "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
2599
+ * me,
2600
+ * { vet: {} },
2601
+ * (animalsWithVets) => console.log(animalsWithVets)
2602
+ * );
2603
+ * ```
2604
+ *
2605
+ * @category Subscription & Loading
2606
+ */
2607
+ static subscribe(id, as, depth, listener) {
2608
+ return subscribeToCoValue(this, id, as, depth, listener);
2609
+ }
2610
+ /**
2611
+ * Given an already loaded `CoList`, ensure that items are loaded to the specified depth.
2612
+ *
2613
+ * Works like `CoList.load()`, but you don't need to pass the ID or the account to load as again.
2614
+ *
2615
+ * @category Subscription & Loading
2616
+ */
2617
+ ensureLoaded(depth) {
2618
+ return ensureCoValueLoaded(this, depth);
2619
+ }
2620
+ /**
2621
+ * Given an already loaded `CoList`, subscribe to updates to the `CoList` and ensure that items are loaded to the specified depth.
2622
+ *
2623
+ * Works like `CoList.subscribe()`, but you don't need to pass the ID or the account to load as again.
2624
+ *
2625
+ * Returns an unsubscribe function that you should call when you no longer need updates.
2626
+ *
2627
+ * @category Subscription & Loading
2628
+ **/
2629
+ subscribe(depth, listener) {
2630
+ return subscribeToExistingCoValue(this, depth, listener);
2631
+ }
2632
+ /** @category Type Helpers */
2633
+ castAs(cl) {
2634
+ const casted = cl.fromRaw(this._raw);
2635
+ const subscriptionScope = subscriptionsScopes.get(this);
2636
+ if (subscriptionScope) {
2637
+ subscriptionsScopes.set(casted, subscriptionScope);
2638
+ }
2639
+ return casted;
2640
+ }
2641
+ /**
2642
+ * Wait for the `CoList` to be uploaded to the other peers.
2643
+ *
2644
+ * @category Subscription & Loading
2645
+ */
2646
+ waitForSync(options) {
2647
+ return this._raw.core.waitForSync(options);
2648
+ }
2649
+ };
2650
+ _CoList.prototype._type = "CoList";
2651
+ var CoList = _CoList;
2652
+ function toRawItems(items, itemDescriptor) {
2653
+ const rawItems = itemDescriptor === "json" ? items : "encoded" in itemDescriptor ? items?.map((e) => itemDescriptor.encoded.encode(e)) : isRefEncoded(itemDescriptor) ? items?.map((v) => v.id) : (() => {
2654
+ throw new Error("Invalid element descriptor");
2655
+ })();
2656
+ return rawItems;
2657
+ }
2658
+ var CoListProxyHandler = {
2659
+ get(target, key, receiver) {
2660
+ if (typeof key === "string" && !isNaN(+key)) {
2661
+ const itemDescriptor = target._schema[ItemsSym];
2662
+ const rawValue = target._raw.get(Number(key));
2663
+ if (itemDescriptor === "json") {
2664
+ return rawValue;
2665
+ } else if ("encoded" in itemDescriptor) {
2666
+ return rawValue === void 0 ? void 0 : itemDescriptor.encoded.decode(rawValue);
2667
+ } else if (isRefEncoded(itemDescriptor)) {
2668
+ return rawValue === void 0 ? void 0 : new Ref(
2669
+ rawValue,
2670
+ target._loadedAs,
2671
+ itemDescriptor
2672
+ ).accessFrom(receiver, Number(key));
2673
+ }
2674
+ } else if (key === "length") {
2675
+ return target._raw.entries().length;
2676
+ } else {
2677
+ return Reflect.get(target, key, receiver);
2678
+ }
2679
+ },
2680
+ set(target, key, value, receiver) {
2681
+ if (key === ItemsSym && typeof value === "object" && SchemaInit in value) {
2682
+ target.constructor._schema ||= {};
2683
+ target.constructor._schema[ItemsSym] = value[SchemaInit];
2684
+ return true;
2685
+ }
2686
+ if (typeof key === "string" && !isNaN(+key)) {
2687
+ const itemDescriptor = target._schema[ItemsSym];
2688
+ let rawValue;
2689
+ if (itemDescriptor === "json") {
2690
+ rawValue = value;
2691
+ } else if ("encoded" in itemDescriptor) {
2692
+ rawValue = itemDescriptor.encoded.encode(value);
2693
+ } else if (isRefEncoded(itemDescriptor)) {
2694
+ rawValue = value.id;
2695
+ }
2696
+ target._raw.replace(Number(key), rawValue);
2697
+ return true;
2698
+ } else {
2699
+ return Reflect.set(target, key, value, receiver);
2700
+ }
2701
+ },
2702
+ defineProperty(target, key, descriptor) {
2703
+ if (descriptor.value && key === ItemsSym && typeof descriptor.value === "object" && SchemaInit in descriptor.value) {
2704
+ target.constructor._schema ||= {};
2705
+ target.constructor._schema[ItemsSym] = descriptor.value[SchemaInit];
2706
+ return true;
2707
+ } else {
2708
+ return Reflect.defineProperty(target, key, descriptor);
2709
+ }
2710
+ },
2711
+ has(target, key) {
2712
+ if (typeof key === "string" && !isNaN(+key)) {
2713
+ return Number(key) < target._raw.entries().length;
2714
+ } else {
2715
+ return Reflect.has(target, key);
2716
+ }
2717
+ }
2718
+ };
2719
+
2720
+ // src/coValues/extensions/imageDef.ts
2721
+ var _a, _b;
2722
+ var ImageDefinition = class extends (_b = CoMap, _a = co.items, _b) {
2723
+ constructor() {
2724
+ super(...arguments);
2725
+ this.originalSize = co.json();
2726
+ this.placeholderDataURL = co.string;
2727
+ this[_a] = co.ref(FileStream);
2728
+ }
2729
+ highestResAvailable(options) {
2730
+ if (!subscriptionsScopes.get(this)) {
2731
+ console.warn(
2732
+ "highestResAvailable() only makes sense when used within a subscription."
2733
+ );
2734
+ }
2735
+ const resolutions = Object.keys(this).filter(
2736
+ (key) => key.match(/^\d+x\d+$/) && (options?.maxWidth === void 0 || Number(key.split("x")[0]) <= options.maxWidth)
2737
+ );
2738
+ resolutions.sort((a, b) => {
2739
+ const aWidth = Number(a.split("x")[0]);
2740
+ const bWidth = Number(b.split("x")[0]);
2741
+ return aWidth - bWidth;
2742
+ });
2743
+ let highestAvailableResolution;
2744
+ for (const resolution of resolutions) {
2745
+ if (this[resolution] && this[resolution]?.getChunks()) {
2746
+ highestAvailableResolution = resolution;
2747
+ } else {
2748
+ return highestAvailableResolution && {
2749
+ res: highestAvailableResolution,
2750
+ stream: this[highestAvailableResolution]
2751
+ };
2752
+ }
2753
+ }
2754
+ return highestAvailableResolution && {
2755
+ res: highestAvailableResolution,
2756
+ stream: this[highestAvailableResolution]
2757
+ };
2758
+ }
2759
+ };
2760
+
2761
+ // src/coValues/schemaUnion.ts
2762
+ var SchemaUnion = class _SchemaUnion extends CoValueBase {
2763
+ /**
2764
+ * Create a new union type from a discriminator function.
2765
+ *
2766
+ * The discriminator function receives the raw data and should return the appropriate concrete class to use for that data.
2767
+ *
2768
+ * When loading a SchemaUnion, the correct subclass will be instantiated based on the discriminator.
2769
+ *
2770
+ * @param discriminator - Function that determines which concrete type to use
2771
+ * @returns A new class that can create/load instances of the union type
2772
+ *
2773
+ * @example
2774
+ * ```ts
2775
+ * const WidgetUnion = SchemaUnion.Of<BaseWidget>((raw) => {
2776
+ * switch (raw.get("type")) {
2777
+ * case "button": return ButtonWidget;
2778
+ * case "slider": return SliderWidget;
2779
+ * default: throw new Error("Unknown widget type");
2780
+ * }
2781
+ * });
2782
+ *
2783
+ * const widget = await loadCoValue(WidgetUnion, id, me, {});
2784
+ *
2785
+ * // You can narrow the returned instance to a subclass by using `instanceof`
2786
+ * if (widget instanceof ButtonWidget) {
2787
+ * console.log(widget.label);
2788
+ * } else if (widget instanceof SliderWidget) {
2789
+ * console.log(widget.min, widget.max);
2790
+ * }
2791
+ * ```
2792
+ *
2793
+ * @category Declaration
2794
+ **/
2795
+ static Of(discriminator) {
2796
+ return class SchemaUnionClass extends _SchemaUnion {
2797
+ static fromRaw(raw) {
2798
+ const ResolvedClass = discriminator(
2799
+ raw
2800
+ );
2801
+ return ResolvedClass.fromRaw(raw);
2802
+ }
2803
+ };
2804
+ }
2805
+ /**
2806
+ * Create an instance from raw data. This is called internally and should not be used directly.
2807
+ * Use {@link SchemaUnion.Of} to create a union type instead.
2808
+ *
2809
+ * @internal
2810
+ */
2811
+ // @ts-ignore
2812
+ static fromRaw(raw) {
2813
+ throw new Error("Not implemented");
2814
+ }
2815
+ };
2816
+
2817
+ export {
2818
+ AnonymousJazzAgent,
2819
+ CoValueBase,
2820
+ loadCoValue,
2821
+ subscribeToCoValue,
2822
+ createCoValueObservable,
2823
+ Encoders,
2824
+ co,
2825
+ fixedCredentialsAuth,
2826
+ ephemeralCredentialsAuth,
2827
+ randomSessionProvider,
2828
+ createJazzContext,
2829
+ createAnonymousJazzContext,
2830
+ Inbox,
2831
+ InboxSender,
2832
+ CoMap,
2833
+ Profile,
2834
+ Account,
2835
+ isControlledAccount,
2836
+ Group,
2837
+ CoFeed,
2838
+ FileStream,
2839
+ CoList,
2840
+ ImageDefinition,
2841
+ SchemaUnion
2842
+ };
2843
+ /* istanbul ignore file -- @preserve */
2844
+ //# sourceMappingURL=chunk-5WLKIDKU.js.map