jazz-tools 0.8.44 → 0.8.48

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 +21 -0
  3. package/dist/chunk-6OHBW32Q.js +2853 -0
  4. package/dist/chunk-6OHBW32Q.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 +29 -10
  11. package/src/coValues/coFeed.ts +4 -3
  12. package/src/coValues/coList.ts +8 -5
  13. package/src/coValues/coMap.ts +14 -5
  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 +8 -9
  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 +11 -8
  31. package/src/tests/groupsAndAccounts.test.ts +1 -63
  32. package/src/tests/inbox.test.ts +299 -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,2853 @@
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.applyMigration(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.applyMigration(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 schema = target._schema;
1365
+ if (!schema) {
1366
+ return void 0;
1367
+ }
1368
+ const descriptor = schema[key] || schema[ItemsSym];
1369
+ if (descriptor && typeof key === "string") {
1370
+ const raw = target._raw.get(key);
1371
+ if (descriptor === "json") {
1372
+ return raw;
1373
+ } else if ("encoded" in descriptor) {
1374
+ return raw === void 0 ? void 0 : descriptor.encoded.decode(raw);
1375
+ } else if (isRefEncoded(descriptor)) {
1376
+ return raw === void 0 ? void 0 : new Ref(
1377
+ raw,
1378
+ target._loadedAs,
1379
+ descriptor
1380
+ ).accessFrom(receiver, key);
1381
+ }
1382
+ } else {
1383
+ return void 0;
1384
+ }
1385
+ }
1386
+ },
1387
+ set(target, key, value, receiver) {
1388
+ if ((typeof key === "string" || ItemsSym) && typeof value === "object" && value !== null && SchemaInit in value) {
1389
+ target.constructor._schema ||= {};
1390
+ target.constructor._schema[key] = value[SchemaInit];
1391
+ return true;
1392
+ }
1393
+ const descriptor = target._schema[key] || target._schema[ItemsSym];
1394
+ if (descriptor && typeof key === "string") {
1395
+ if (descriptor === "json") {
1396
+ target._raw.set(key, value);
1397
+ } else if ("encoded" in descriptor) {
1398
+ target._raw.set(key, descriptor.encoded.encode(value));
1399
+ } else if (isRefEncoded(descriptor)) {
1400
+ if (value === null) {
1401
+ if (descriptor.optional) {
1402
+ target._raw.set(key, null);
1403
+ } else {
1404
+ throw new Error(`Cannot set required reference ${key} to null`);
1405
+ }
1406
+ } else {
1407
+ target._raw.set(key, value.id);
1408
+ subscriptionsScopes.get(target)?.onRefAccessedOrSet(target.id, value.id);
1409
+ }
1410
+ }
1411
+ return true;
1412
+ } else {
1413
+ return Reflect.set(target, key, value, receiver);
1414
+ }
1415
+ },
1416
+ defineProperty(target, key, attributes) {
1417
+ if ("value" in attributes && typeof attributes.value === "object" && SchemaInit in attributes.value) {
1418
+ target.constructor._schema ||= {};
1419
+ target.constructor._schema[key] = attributes.value[SchemaInit];
1420
+ return true;
1421
+ } else {
1422
+ return Reflect.defineProperty(target, key, attributes);
1423
+ }
1424
+ },
1425
+ ownKeys(target) {
1426
+ const keys = Reflect.ownKeys(target).filter((k) => k !== ItemsSym);
1427
+ for (const key of target._raw.keys()) {
1428
+ if (!keys.includes(key)) {
1429
+ keys.push(key);
1430
+ }
1431
+ }
1432
+ return keys;
1433
+ },
1434
+ getOwnPropertyDescriptor(target, key) {
1435
+ if (key in target) {
1436
+ return Reflect.getOwnPropertyDescriptor(target, key);
1437
+ } else {
1438
+ const descriptor = target._schema[key] || target._schema[ItemsSym];
1439
+ if (descriptor || key in target._raw.latest) {
1440
+ return {
1441
+ enumerable: true,
1442
+ configurable: true,
1443
+ writable: true
1444
+ };
1445
+ }
1446
+ }
1447
+ },
1448
+ has(target, key) {
1449
+ const descriptor = target._schema?.[key] || target._schema?.[ItemsSym];
1450
+ if (target._raw && typeof key === "string" && descriptor) {
1451
+ return target._raw.get(key) !== void 0;
1452
+ } else {
1453
+ return Reflect.has(target, key);
1454
+ }
1455
+ },
1456
+ deleteProperty(target, key) {
1457
+ const descriptor = target._schema[key] || target._schema[ItemsSym];
1458
+ if (typeof key === "string" && descriptor) {
1459
+ target._raw.delete(key);
1460
+ return true;
1461
+ } else {
1462
+ return Reflect.deleteProperty(target, key);
1463
+ }
1464
+ }
1465
+ };
1466
+ RegisteredSchemas["CoMap"] = CoMap;
1467
+
1468
+ // src/coValues/profile.ts
1469
+ var Profile = class extends CoMap {
1470
+ constructor() {
1471
+ super(...arguments);
1472
+ this.name = co.string;
1473
+ this.inbox = co.optional.json();
1474
+ this.inboxInvite = co.optional.json();
1475
+ }
1476
+ };
1477
+
1478
+ // src/coValues/account.ts
1479
+ import {
1480
+ LocalNode as LocalNode2,
1481
+ RawAccount as RawAccount4,
1482
+ cojsonInternals as cojsonInternals2
1483
+ } from "cojson";
1484
+ var _Account = class _Account extends CoValueBase {
1485
+ get _schema() {
1486
+ return this.constructor._schema;
1487
+ }
1488
+ get _owner() {
1489
+ return this;
1490
+ }
1491
+ get _loadedAs() {
1492
+ if (this.isMe) return this;
1493
+ const rawAccount = this._raw.core.node.account;
1494
+ if (rawAccount instanceof RawAccount4) {
1495
+ return coValuesCache.get(rawAccount, () => _Account.fromRaw(rawAccount));
1496
+ }
1497
+ return new AnonymousJazzAgent(this._raw.core.node);
1498
+ }
1499
+ get _refs() {
1500
+ const profileID = this._raw.get("profile");
1501
+ const rootID = this._raw.get("root");
1502
+ return {
1503
+ profile: profileID && new Ref(
1504
+ profileID,
1505
+ this._loadedAs,
1506
+ this._schema.profile
1507
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1508
+ ),
1509
+ root: rootID && new Ref(
1510
+ rootID,
1511
+ this._loadedAs,
1512
+ this._schema.root
1513
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1514
+ )
1515
+ };
1516
+ }
1517
+ constructor(options) {
1518
+ super();
1519
+ if (!("fromRaw" in options)) {
1520
+ throw new Error("Can only construct account from raw or with .create()");
1521
+ }
1522
+ this.isMe = options.fromRaw.id == options.fromRaw.core.node.account.id;
1523
+ Object.defineProperties(this, {
1524
+ id: {
1525
+ value: options.fromRaw.id,
1526
+ enumerable: false
1527
+ },
1528
+ _raw: { value: options.fromRaw, enumerable: false },
1529
+ _type: { value: "Account", enumerable: false }
1530
+ });
1531
+ if (this.isMe) {
1532
+ this.sessionID = options.fromRaw.core.node.currentSessionID;
1533
+ }
1534
+ return new Proxy(this, AccountAndGroupProxyHandler);
1535
+ }
1536
+ myRole() {
1537
+ if (this.isMe) {
1538
+ return "admin";
1539
+ }
1540
+ }
1541
+ async acceptInvite(valueID, inviteSecret, coValueClass) {
1542
+ if (!this.isMe) {
1543
+ throw new Error("Only a controlled account can accept invites");
1544
+ }
1545
+ await this._raw.acceptInvite(
1546
+ valueID,
1547
+ inviteSecret
1548
+ );
1549
+ return loadCoValue(coValueClass, valueID, this, []);
1550
+ }
1551
+ /** @private */
1552
+ static async create(options) {
1553
+ const { node } = await LocalNode2.withNewlyCreatedAccount({
1554
+ ...options,
1555
+ migration: async (rawAccount, _node, creationProps) => {
1556
+ const account = new this({
1557
+ fromRaw: rawAccount
1558
+ });
1559
+ await account.applyMigration?.(creationProps);
1560
+ }
1561
+ });
1562
+ return this.fromNode(node);
1563
+ }
1564
+ static async createAs(as, options) {
1565
+ const connectedPeers = cojsonInternals2.connectedPeers(
1566
+ "creatingAccount",
1567
+ "createdAccount",
1568
+ { peer1role: "server", peer2role: "client" }
1569
+ );
1570
+ as._raw.core.node.syncManager.addPeer(connectedPeers[1]);
1571
+ return this.create({
1572
+ creationProps: options.creationProps,
1573
+ crypto: as._raw.core.node.crypto,
1574
+ peersToLoadFrom: [connectedPeers[0]]
1575
+ });
1576
+ }
1577
+ static fromNode(node) {
1578
+ return new this({
1579
+ fromRaw: node.account
1580
+ });
1581
+ }
1582
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1583
+ toJSON() {
1584
+ return {
1585
+ id: this.id,
1586
+ _type: this._type
1587
+ };
1588
+ }
1589
+ [inspect]() {
1590
+ return this.toJSON();
1591
+ }
1592
+ async applyMigration(creationProps) {
1593
+ if (creationProps) {
1594
+ const profileGroup = RegisteredSchemas["Group"].create({ owner: this });
1595
+ profileGroup.addMember("everyone", "reader");
1596
+ this.profile = Profile.create(
1597
+ { name: creationProps.name },
1598
+ { owner: profileGroup }
1599
+ );
1600
+ }
1601
+ const node = this._raw.core.node;
1602
+ const profile = node.expectCoValueLoaded(this._raw.get("profile")).getCurrentContent();
1603
+ if (!profile.get("inbox")) {
1604
+ const inboxRoot = createInboxRoot(this);
1605
+ profile.set("inbox", inboxRoot.id);
1606
+ profile.set("inboxInvite", inboxRoot.inviteLink);
1607
+ }
1608
+ await this.migrate(creationProps);
1609
+ }
1610
+ // Placeholder method for subclasses to override
1611
+ migrate(creationProps) {
1612
+ creationProps;
1613
+ }
1614
+ /** @category Subscription & Loading */
1615
+ static load(id, as, depth) {
1616
+ return loadCoValue(this, id, as, depth);
1617
+ }
1618
+ /** @category Subscription & Loading */
1619
+ static subscribe(id, as, depth, listener) {
1620
+ return subscribeToCoValue(this, id, as, depth, listener);
1621
+ }
1622
+ /** @category Subscription & Loading */
1623
+ ensureLoaded(depth) {
1624
+ return ensureCoValueLoaded(this, depth);
1625
+ }
1626
+ /** @category Subscription & Loading */
1627
+ subscribe(depth, listener) {
1628
+ return subscribeToExistingCoValue(this, depth, listener);
1629
+ }
1630
+ /**
1631
+ * Wait for the `Account` to be uploaded to the other peers.
1632
+ *
1633
+ * @category Subscription & Loading
1634
+ */
1635
+ waitForSync(options) {
1636
+ return this._raw.core.waitForSync(options);
1637
+ }
1638
+ /**
1639
+ * Wait for all the available `CoValues` to be uploaded to the other peers.
1640
+ *
1641
+ * @category Subscription & Loading
1642
+ */
1643
+ waitForAllCoValuesSync(options) {
1644
+ return this._raw.core.node.syncManager.waitForAllCoValuesSync(
1645
+ options?.timeout
1646
+ );
1647
+ }
1648
+ };
1649
+ _Account._schema = {
1650
+ profile: {
1651
+ ref: () => Profile,
1652
+ optional: false
1653
+ },
1654
+ root: {
1655
+ ref: () => RegisteredSchemas["CoMap"],
1656
+ optional: true
1657
+ }
1658
+ };
1659
+ var Account = _Account;
1660
+ var AccountAndGroupProxyHandler = {
1661
+ get(target, key, receiver) {
1662
+ if (key === "profile") {
1663
+ const ref2 = target._refs.profile;
1664
+ return ref2 ? ref2.accessFrom(receiver, "profile") : (
1665
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1666
+ void 0
1667
+ );
1668
+ } else if (key === "root") {
1669
+ const ref2 = target._refs.root;
1670
+ return ref2 ? ref2.accessFrom(receiver, "root") : void 0;
1671
+ } else {
1672
+ return Reflect.get(target, key, receiver);
1673
+ }
1674
+ },
1675
+ set(target, key, value, receiver) {
1676
+ if ((key === "profile" || key === "root" || key === MembersSym) && typeof value === "object" && SchemaInit in value) {
1677
+ target.constructor._schema ||= {};
1678
+ target.constructor._schema[key] = value[SchemaInit];
1679
+ return true;
1680
+ } else if (key === "profile") {
1681
+ if (value) {
1682
+ target._raw.set(
1683
+ "profile",
1684
+ value.id,
1685
+ "trusting"
1686
+ );
1687
+ }
1688
+ subscriptionsScopes.get(receiver)?.onRefAccessedOrSet(target.id, value.id);
1689
+ return true;
1690
+ } else if (key === "root") {
1691
+ if (value) {
1692
+ target._raw.set("root", value.id);
1693
+ }
1694
+ subscriptionsScopes.get(receiver)?.onRefAccessedOrSet(target.id, value.id);
1695
+ return true;
1696
+ } else {
1697
+ return Reflect.set(target, key, value, receiver);
1698
+ }
1699
+ },
1700
+ defineProperty(target, key, descriptor) {
1701
+ if ((key === "profile" || key === "root" || key === MembersSym) && typeof descriptor.value === "object" && SchemaInit in descriptor.value) {
1702
+ target.constructor._schema ||= {};
1703
+ target.constructor._schema[key] = descriptor.value[SchemaInit];
1704
+ return true;
1705
+ } else {
1706
+ return Reflect.defineProperty(target, key, descriptor);
1707
+ }
1708
+ }
1709
+ };
1710
+ function isControlledAccount(account) {
1711
+ return account.isMe;
1712
+ }
1713
+ RegisteredSchemas["Account"] = Account;
1714
+
1715
+ // src/coValues/group.ts
1716
+ var _Group = class _Group extends CoValueBase {
1717
+ get _schema() {
1718
+ return this.constructor._schema;
1719
+ }
1720
+ get _refs() {
1721
+ const profileID = this._raw.get("profile");
1722
+ const rootID = this._raw.get("root");
1723
+ return {
1724
+ profile: profileID && new Ref(
1725
+ profileID,
1726
+ this._loadedAs,
1727
+ this._schema.profile
1728
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1729
+ ),
1730
+ root: rootID && new Ref(
1731
+ rootID,
1732
+ this._loadedAs,
1733
+ this._schema.root
1734
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1735
+ )
1736
+ };
1737
+ }
1738
+ /** @deprecated Don't use constructor directly, use .create */
1739
+ constructor(options) {
1740
+ super();
1741
+ let raw;
1742
+ if (options && "fromRaw" in options) {
1743
+ raw = options.fromRaw;
1744
+ } else {
1745
+ const initOwner = options.owner;
1746
+ if (!initOwner) throw new Error("No owner provided");
1747
+ if (initOwner._type === "Account" && isControlledAccount(initOwner)) {
1748
+ const rawOwner = initOwner._raw;
1749
+ raw = rawOwner.createGroup();
1750
+ } else {
1751
+ throw new Error("Can only construct group as a controlled account");
1752
+ }
1753
+ }
1754
+ Object.defineProperties(this, {
1755
+ id: {
1756
+ value: raw.id,
1757
+ enumerable: false
1758
+ },
1759
+ _raw: { value: raw, enumerable: false }
1760
+ });
1761
+ return new Proxy(this, AccountAndGroupProxyHandler);
1762
+ }
1763
+ static create(options) {
1764
+ return new this(options);
1765
+ }
1766
+ myRole() {
1767
+ return this._raw.myRole();
1768
+ }
1769
+ addMember(member, role) {
1770
+ this._raw.addMember(member === "everyone" ? member : member._raw, role);
1771
+ return this;
1772
+ }
1773
+ removeMember(member) {
1774
+ this._raw.removeMember(member === "everyone" ? member : member._raw);
1775
+ return this;
1776
+ }
1777
+ get members() {
1778
+ return this._raw.keys().filter((key) => {
1779
+ return key === "everyone" || key.startsWith("co_");
1780
+ }).map((id) => {
1781
+ const role = this._raw.get(id);
1782
+ const accountID = id === "everyone" ? void 0 : id;
1783
+ const ref2 = accountID && new Ref(
1784
+ accountID,
1785
+ this._loadedAs,
1786
+ this._schema[MembersSym]
1787
+ );
1788
+ const accessRef = () => ref2?.accessFrom(this, "members." + id);
1789
+ return {
1790
+ id,
1791
+ role,
1792
+ ref: ref2,
1793
+ get account() {
1794
+ return accessRef();
1795
+ }
1796
+ };
1797
+ });
1798
+ }
1799
+ extend(parent) {
1800
+ this._raw.extend(parent._raw);
1801
+ return this;
1802
+ }
1803
+ /** @category Subscription & Loading */
1804
+ static load(id, as, depth) {
1805
+ return loadCoValue(this, id, as, depth);
1806
+ }
1807
+ /** @category Subscription & Loading */
1808
+ static subscribe(id, as, depth, listener) {
1809
+ return subscribeToCoValue(this, id, as, depth, listener);
1810
+ }
1811
+ /** @category Subscription & Loading */
1812
+ ensureLoaded(depth) {
1813
+ return ensureCoValueLoaded(this, depth);
1814
+ }
1815
+ /** @category Subscription & Loading */
1816
+ subscribe(depth, listener) {
1817
+ return subscribeToExistingCoValue(this, depth, listener);
1818
+ }
1819
+ /**
1820
+ * Wait for the `Group` to be uploaded to the other peers.
1821
+ *
1822
+ * @category Subscription & Loading
1823
+ */
1824
+ waitForSync(options) {
1825
+ return this._raw.core.waitForSync(options);
1826
+ }
1827
+ };
1828
+ _Group.prototype._type = "Group";
1829
+ _Group._schema = {
1830
+ profile: "json",
1831
+ root: "json",
1832
+ [MembersSym]: {
1833
+ ref: () => RegisteredSchemas["Account"],
1834
+ optional: false
1835
+ }
1836
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1837
+ };
1838
+ Object.defineProperty(_Group.prototype, "_schema", {
1839
+ get: () => _Group._schema
1840
+ });
1841
+ var Group = _Group;
1842
+ RegisteredSchemas["Group"] = Group;
1843
+
1844
+ // src/coValues/coFeed.ts
1845
+ import { MAX_RECOMMENDED_TX_SIZE, cojsonInternals as cojsonInternals3 } from "cojson";
1846
+ var _CoFeed = class _CoFeed extends CoValueBase {
1847
+ /**
1848
+ * Declare a `CoFeed` by subclassing `CoFeed.Of(...)` and passing the item schema using a `co` primitive or a `co.ref`.
1849
+ *
1850
+ * @example
1851
+ * ```ts
1852
+ * class ColorFeed extends CoFeed.Of(co.string) {}
1853
+ * class AnimalFeed extends CoFeed.Of(co.ref(Animal)) {}
1854
+ * ```
1855
+ *
1856
+ * @category Declaration
1857
+ */
1858
+ static Of(item) {
1859
+ var _a2, _b2;
1860
+ return class CoFeedOf extends (_b2 = _CoFeed, _a2 = co.items, _b2) {
1861
+ constructor() {
1862
+ super(...arguments);
1863
+ this[_a2] = item;
1864
+ }
1865
+ };
1866
+ }
1867
+ /** @internal */
1868
+ get _schema() {
1869
+ return this.constructor._schema;
1870
+ }
1871
+ /**
1872
+ * The current account's view of this `CoFeed`
1873
+ * @category Content
1874
+ */
1875
+ get byMe() {
1876
+ if (this._loadedAs._type === "Account") {
1877
+ return this[this._loadedAs.id];
1878
+ } else {
1879
+ return void 0;
1880
+ }
1881
+ }
1882
+ /**
1883
+ * The current session's view of this `CoFeed`
1884
+ *
1885
+ * This is a shortcut for `this.perSession` where the session ID is the current session ID.
1886
+ *
1887
+ * @category Content
1888
+ */
1889
+ get inCurrentSession() {
1890
+ if (this._loadedAs._type === "Account") {
1891
+ return this.perSession[this._loadedAs.sessionID];
1892
+ } else {
1893
+ return void 0;
1894
+ }
1895
+ }
1896
+ constructor(options) {
1897
+ super();
1898
+ if (options && "fromRaw" in options) {
1899
+ Object.defineProperties(this, {
1900
+ id: {
1901
+ value: options.fromRaw.id,
1902
+ enumerable: false
1903
+ },
1904
+ _raw: { value: options.fromRaw, enumerable: false }
1905
+ });
1906
+ }
1907
+ return new Proxy(this, CoStreamProxyHandler);
1908
+ }
1909
+ /**
1910
+ * Create a new `CoFeed`
1911
+ * @category Creation
1912
+ */
1913
+ static create(init, options) {
1914
+ const instance = new this({ init, owner: options.owner });
1915
+ const raw = options.owner._raw.createStream();
1916
+ Object.defineProperties(instance, {
1917
+ id: {
1918
+ value: raw.id,
1919
+ enumerable: false
1920
+ },
1921
+ _raw: { value: raw, enumerable: false }
1922
+ });
1923
+ if (init) {
1924
+ instance.push(...init);
1925
+ }
1926
+ return instance;
1927
+ }
1928
+ /**
1929
+ * Push items to this `CoFeed`
1930
+ *
1931
+ * Items are appended to the current session's log. Each session (tab, device, app instance)
1932
+ * maintains its own append-only log, which is then aggregated into the per-account view.
1933
+ *
1934
+ * @example
1935
+ * ```ts
1936
+ * // Adds items to current session's log
1937
+ * feed.push("item1", "item2");
1938
+ *
1939
+ * // View items from current session
1940
+ * console.log(feed.inCurrentSession);
1941
+ *
1942
+ * // View aggregated items from all sessions for current account
1943
+ * console.log(feed.byMe);
1944
+ * ```
1945
+ *
1946
+ * @category Content
1947
+ */
1948
+ push(...items) {
1949
+ for (const item of items) {
1950
+ this.pushItem(item);
1951
+ }
1952
+ }
1953
+ pushItem(item) {
1954
+ const itemDescriptor = this._schema[ItemsSym];
1955
+ if (itemDescriptor === "json") {
1956
+ this._raw.push(item);
1957
+ } else if ("encoded" in itemDescriptor) {
1958
+ this._raw.push(itemDescriptor.encoded.encode(item));
1959
+ } else if (isRefEncoded(itemDescriptor)) {
1960
+ this._raw.push(item.id);
1961
+ }
1962
+ }
1963
+ /**
1964
+ * Get a JSON representation of the `CoFeed`
1965
+ * @category
1966
+ */
1967
+ toJSON() {
1968
+ const itemDescriptor = this._schema[ItemsSym];
1969
+ const mapper = itemDescriptor === "json" ? (v) => v : "encoded" in itemDescriptor ? itemDescriptor.encoded.encode : (v) => v && v.id;
1970
+ return {
1971
+ id: this.id,
1972
+ _type: this._type,
1973
+ ...Object.fromEntries(
1974
+ Object.entries(this).map(([account, entry]) => [
1975
+ account,
1976
+ mapper(entry.value)
1977
+ ])
1978
+ ),
1979
+ in: Object.fromEntries(
1980
+ Object.entries(this.perSession).map(([session, entry]) => [
1981
+ session,
1982
+ mapper(entry.value)
1983
+ ])
1984
+ )
1985
+ };
1986
+ }
1987
+ /** @internal */
1988
+ [(ItemsSym, inspect)]() {
1989
+ return this.toJSON();
1990
+ }
1991
+ /** @internal */
1992
+ static schema(def) {
1993
+ this._schema ||= {};
1994
+ Object.assign(this._schema, def);
1995
+ }
1996
+ /**
1997
+ * Load a `CoFeed`
1998
+ * @category Subscription & Loading
1999
+ */
2000
+ static load(id, as, depth) {
2001
+ return loadCoValue(this, id, as, depth);
2002
+ }
2003
+ /**
2004
+ * Subscribe to a `CoFeed`, when you have an ID but don't have a `CoFeed` instance yet
2005
+ * @category Subscription & Loading
2006
+ */
2007
+ static subscribe(id, as, depth, listener) {
2008
+ return subscribeToCoValue(this, id, as, depth, listener);
2009
+ }
2010
+ /**
2011
+ * Ensure a `CoFeed` is loaded to the specified depth
2012
+ *
2013
+ * @returns A new instance of the same CoFeed that's loaded to the specified depth,
2014
+ * or undefined if it cannot be loaded that deeply
2015
+ * @category Subscription & Loading
2016
+ */
2017
+ ensureLoaded(depth) {
2018
+ return ensureCoValueLoaded(this, depth);
2019
+ }
2020
+ /**
2021
+ * An instance method to subscribe to an existing `CoFeed`
2022
+ *
2023
+ * No need to provide an ID or Account since they're already part of the instance.
2024
+ * @category Subscription & Loading
2025
+ */
2026
+ subscribe(depth, listener) {
2027
+ return subscribeToExistingCoValue(this, depth, listener);
2028
+ }
2029
+ /**
2030
+ * Wait for the `CoFeed` to be uploaded to the other peers.
2031
+ *
2032
+ * @category Subscription & Loading
2033
+ */
2034
+ waitForSync(options) {
2035
+ return this._raw.core.waitForSync(options);
2036
+ }
2037
+ };
2038
+ _CoFeed.prototype._type = "CoStream";
2039
+ var CoFeed = _CoFeed;
2040
+ function entryFromRawEntry(accessFrom, rawEntry, loadedAs, accountID, itemField) {
2041
+ return {
2042
+ get value() {
2043
+ if (itemField === "json") {
2044
+ return rawEntry.value;
2045
+ } else if ("encoded" in itemField) {
2046
+ return itemField.encoded.decode(rawEntry.value);
2047
+ } else if (isRefEncoded(itemField)) {
2048
+ return this.ref?.accessFrom(
2049
+ accessFrom,
2050
+ rawEntry.by + rawEntry.tx.sessionID + rawEntry.tx.txIndex + ".value"
2051
+ );
2052
+ } else {
2053
+ throw new Error("Invalid item field schema");
2054
+ }
2055
+ },
2056
+ get ref() {
2057
+ if (itemField !== "json" && isRefEncoded(itemField)) {
2058
+ const rawId = rawEntry.value;
2059
+ return new Ref(
2060
+ rawId,
2061
+ loadedAs,
2062
+ itemField
2063
+ );
2064
+ } else {
2065
+ return void 0;
2066
+ }
2067
+ },
2068
+ get by() {
2069
+ return accountID && new Ref(accountID, loadedAs, {
2070
+ ref: RegisteredSchemas["Account"],
2071
+ optional: false
2072
+ })?.accessFrom(
2073
+ accessFrom,
2074
+ rawEntry.by + rawEntry.tx.sessionID + rawEntry.tx.txIndex + ".by"
2075
+ );
2076
+ },
2077
+ madeAt: rawEntry.at,
2078
+ tx: rawEntry.tx
2079
+ };
2080
+ }
2081
+ var CoStreamProxyHandler = {
2082
+ get(target, key, receiver) {
2083
+ if (typeof key === "string" && key.startsWith("co_")) {
2084
+ const rawEntry = target._raw.lastItemBy(key);
2085
+ if (!rawEntry) return;
2086
+ const entry = entryFromRawEntry(
2087
+ receiver,
2088
+ rawEntry,
2089
+ target._loadedAs,
2090
+ key,
2091
+ target._schema[ItemsSym]
2092
+ );
2093
+ Object.defineProperty(entry, "all", {
2094
+ get: () => {
2095
+ const allRawEntries = target._raw.itemsBy(key);
2096
+ return function* () {
2097
+ while (true) {
2098
+ const rawEntry2 = allRawEntries.next();
2099
+ if (rawEntry2.done) return;
2100
+ yield entryFromRawEntry(
2101
+ receiver,
2102
+ rawEntry2.value,
2103
+ target._loadedAs,
2104
+ key,
2105
+ target._schema[ItemsSym]
2106
+ );
2107
+ }
2108
+ }();
2109
+ }
2110
+ });
2111
+ return entry;
2112
+ } else if (key === "perSession") {
2113
+ return new Proxy({}, CoStreamPerSessionProxyHandler(target, receiver));
2114
+ } else {
2115
+ return Reflect.get(target, key, receiver);
2116
+ }
2117
+ },
2118
+ set(target, key, value, receiver) {
2119
+ if (key === ItemsSym && typeof value === "object" && SchemaInit in value) {
2120
+ target.constructor._schema ||= {};
2121
+ target.constructor._schema[ItemsSym] = value[SchemaInit];
2122
+ return true;
2123
+ } else {
2124
+ return Reflect.set(target, key, value, receiver);
2125
+ }
2126
+ },
2127
+ defineProperty(target, key, descriptor) {
2128
+ if (descriptor.value && key === ItemsSym && typeof descriptor.value === "object" && SchemaInit in descriptor.value) {
2129
+ target.constructor._schema ||= {};
2130
+ target.constructor._schema[ItemsSym] = descriptor.value[SchemaInit];
2131
+ return true;
2132
+ } else {
2133
+ return Reflect.defineProperty(target, key, descriptor);
2134
+ }
2135
+ },
2136
+ ownKeys(target) {
2137
+ const keys = Reflect.ownKeys(target);
2138
+ for (const accountID of target._raw.accounts()) {
2139
+ keys.push(accountID);
2140
+ }
2141
+ return keys;
2142
+ },
2143
+ getOwnPropertyDescriptor(target, key) {
2144
+ if (typeof key === "string" && key.startsWith("co_")) {
2145
+ return {
2146
+ configurable: true,
2147
+ enumerable: true,
2148
+ writable: false
2149
+ };
2150
+ } else {
2151
+ return Reflect.getOwnPropertyDescriptor(target, key);
2152
+ }
2153
+ }
2154
+ };
2155
+ var CoStreamPerSessionProxyHandler = (innerTarget, accessFrom) => ({
2156
+ get(_target, key, receiver) {
2157
+ if (typeof key === "string" && key.includes("session")) {
2158
+ const sessionID = key;
2159
+ const rawEntry = innerTarget._raw.lastItemIn(sessionID);
2160
+ if (!rawEntry) return;
2161
+ const by = cojsonInternals3.accountOrAgentIDfromSessionID(sessionID);
2162
+ const entry = entryFromRawEntry(
2163
+ accessFrom,
2164
+ rawEntry,
2165
+ innerTarget._loadedAs,
2166
+ cojsonInternals3.isAccountID(by) ? by : void 0,
2167
+ innerTarget._schema[ItemsSym]
2168
+ );
2169
+ Object.defineProperty(entry, "all", {
2170
+ get: () => {
2171
+ const allRawEntries = innerTarget._raw.itemsIn(sessionID);
2172
+ return function* () {
2173
+ while (true) {
2174
+ const rawEntry2 = allRawEntries.next();
2175
+ if (rawEntry2.done) return;
2176
+ yield entryFromRawEntry(
2177
+ accessFrom,
2178
+ rawEntry2.value,
2179
+ innerTarget._loadedAs,
2180
+ cojsonInternals3.isAccountID(by) ? by : void 0,
2181
+ innerTarget._schema[ItemsSym]
2182
+ );
2183
+ }
2184
+ }();
2185
+ }
2186
+ });
2187
+ return entry;
2188
+ } else {
2189
+ return Reflect.get(innerTarget, key, receiver);
2190
+ }
2191
+ },
2192
+ ownKeys() {
2193
+ return innerTarget._raw.sessions();
2194
+ },
2195
+ getOwnPropertyDescriptor(target, key) {
2196
+ if (typeof key === "string" && key.startsWith("co_")) {
2197
+ return {
2198
+ configurable: true,
2199
+ enumerable: true,
2200
+ writable: false
2201
+ };
2202
+ } else {
2203
+ return Reflect.getOwnPropertyDescriptor(target, key);
2204
+ }
2205
+ }
2206
+ });
2207
+ var FileStream = class extends CoValueBase {
2208
+ constructor(options) {
2209
+ super();
2210
+ let raw;
2211
+ if ("fromRaw" in options) {
2212
+ raw = options.fromRaw;
2213
+ } else {
2214
+ const rawOwner = options.owner._raw;
2215
+ raw = rawOwner.createBinaryStream();
2216
+ }
2217
+ Object.defineProperties(this, {
2218
+ id: {
2219
+ value: raw.id,
2220
+ enumerable: false
2221
+ },
2222
+ _type: { value: "BinaryCoStream", enumerable: false },
2223
+ _raw: { value: raw, enumerable: false }
2224
+ });
2225
+ }
2226
+ static create(options) {
2227
+ return new this(options);
2228
+ }
2229
+ getChunks(options) {
2230
+ return this._raw.getBinaryChunks(options?.allowUnfinished);
2231
+ }
2232
+ isBinaryStreamEnded() {
2233
+ return this._raw.isBinaryStreamEnded();
2234
+ }
2235
+ start(options) {
2236
+ this._raw.startBinaryStream(options);
2237
+ }
2238
+ push(data) {
2239
+ this._raw.pushBinaryStreamChunk(data);
2240
+ }
2241
+ end() {
2242
+ this._raw.endBinaryStream();
2243
+ }
2244
+ toBlob(options) {
2245
+ const chunks = this.getChunks({
2246
+ allowUnfinished: options?.allowUnfinished
2247
+ });
2248
+ if (!chunks) {
2249
+ return void 0;
2250
+ }
2251
+ return new Blob(chunks.chunks, { type: chunks.mimeType });
2252
+ }
2253
+ /**
2254
+ * Load a `FileStream` as a `Blob`
2255
+ *
2256
+ * @category Content
2257
+ */
2258
+ static async loadAsBlob(id, as, options) {
2259
+ let stream = await this.load(id, as, []);
2260
+ if (!options?.allowUnfinished && !stream?.isBinaryStreamEnded()) {
2261
+ stream = await new Promise((resolve) => {
2262
+ const unsubscribe = subscribeToCoValue(this, id, as, [], (value) => {
2263
+ if (value.isBinaryStreamEnded()) {
2264
+ unsubscribe();
2265
+ resolve(value);
2266
+ }
2267
+ });
2268
+ });
2269
+ }
2270
+ return stream?.toBlob({
2271
+ allowUnfinished: options?.allowUnfinished
2272
+ });
2273
+ }
2274
+ /**
2275
+ * Create a `FileStream` from a `Blob` or `File`
2276
+ *
2277
+ * @example
2278
+ * ```ts
2279
+ * import { co, FileStream } from "jazz-tools";
2280
+ *
2281
+ * const fileStream = await FileStream.createFromBlob(file, {owner: group})
2282
+ * ```
2283
+ * @category Content
2284
+ */
2285
+ static async createFromBlob(blob, options) {
2286
+ const stream = this.create({ owner: options.owner });
2287
+ const start = Date.now();
2288
+ const data = new Uint8Array(await blob.arrayBuffer());
2289
+ stream.start({
2290
+ mimeType: blob.type,
2291
+ totalSizeBytes: blob.size,
2292
+ fileName: blob instanceof File ? blob.name : void 0
2293
+ });
2294
+ const chunkSize = MAX_RECOMMENDED_TX_SIZE;
2295
+ let lastProgressUpdate = Date.now();
2296
+ for (let idx = 0; idx < data.length; idx += chunkSize) {
2297
+ stream.push(data.slice(idx, idx + chunkSize));
2298
+ if (Date.now() - lastProgressUpdate > 100) {
2299
+ options.onProgress?.(idx / data.length);
2300
+ lastProgressUpdate = Date.now();
2301
+ }
2302
+ await new Promise((resolve) => setTimeout(resolve, 0));
2303
+ }
2304
+ stream.end();
2305
+ const end = Date.now();
2306
+ console.debug(
2307
+ "Finished creating binary stream in",
2308
+ (end - start) / 1e3,
2309
+ "s - Throughput in MB/s",
2310
+ 1e3 * (blob.size / (end - start)) / (1024 * 1024)
2311
+ );
2312
+ options.onProgress?.(1);
2313
+ return stream;
2314
+ }
2315
+ /**
2316
+ * Get a JSON representation of the `FileStream`
2317
+ * @category Content
2318
+ */
2319
+ toJSON() {
2320
+ return {
2321
+ id: this.id,
2322
+ _type: this._type,
2323
+ ...this.getChunks()
2324
+ };
2325
+ }
2326
+ /** @internal */
2327
+ [inspect]() {
2328
+ return this.toJSON();
2329
+ }
2330
+ /**
2331
+ * Load a `FileStream`
2332
+ * @category Subscription & Loading
2333
+ */
2334
+ static load(id, as, depth) {
2335
+ return loadCoValue(this, id, as, depth);
2336
+ }
2337
+ /**
2338
+ * Subscribe to a `FileStream`, when you have an ID but don't have a `FileStream` instance yet
2339
+ * @category Subscription & Loading
2340
+ */
2341
+ static subscribe(id, as, depth, listener) {
2342
+ return subscribeToCoValue(this, id, as, depth, listener);
2343
+ }
2344
+ ensureLoaded(depth) {
2345
+ return ensureCoValueLoaded(this, depth);
2346
+ }
2347
+ /**
2348
+ * An instance method to subscribe to an existing `FileStream`
2349
+ * @category Subscription & Loading
2350
+ */
2351
+ subscribe(depth, listener) {
2352
+ return subscribeToExistingCoValue(this, depth, listener);
2353
+ }
2354
+ /**
2355
+ * Wait for the `FileStream` to be uploaded to the other peers.
2356
+ *
2357
+ * @category Subscription & Loading
2358
+ */
2359
+ waitForSync(options) {
2360
+ return this._raw.core.waitForSync(options);
2361
+ }
2362
+ };
2363
+
2364
+ // src/coValues/coList.ts
2365
+ import { RawAccount as RawAccount5 } from "cojson";
2366
+ var _CoList = class _CoList extends Array {
2367
+ /**
2368
+ * Declare a `CoList` by subclassing `CoList.Of(...)` and passing the item schema using `co`.
2369
+ *
2370
+ * @example
2371
+ * ```ts
2372
+ * class ColorList extends CoList.Of(
2373
+ * co.string
2374
+ * ) {}
2375
+ * class AnimalList extends CoList.Of(
2376
+ * co.ref(Animal)
2377
+ * ) {}
2378
+ * ```
2379
+ *
2380
+ * @category Declaration
2381
+ */
2382
+ static Of(item) {
2383
+ var _a2, _b2;
2384
+ return class CoListOf extends (_b2 = _CoList, _a2 = co.items, _b2) {
2385
+ constructor() {
2386
+ super(...arguments);
2387
+ this[_a2] = item;
2388
+ }
2389
+ };
2390
+ }
2391
+ /**
2392
+ * @ignore
2393
+ * @deprecated Use UPPERCASE `CoList.Of` instead! */
2394
+ static of(..._args) {
2395
+ throw new Error("Can't use Array.of with CoLists");
2396
+ }
2397
+ /** @internal */
2398
+ get _schema() {
2399
+ return this.constructor._schema;
2400
+ }
2401
+ /** @category Collaboration */
2402
+ get _owner() {
2403
+ return this._raw.group instanceof RawAccount5 ? RegisteredSchemas["Account"].fromRaw(this._raw.group) : RegisteredSchemas["Group"].fromRaw(this._raw.group);
2404
+ }
2405
+ /**
2406
+ * If a `CoList`'s items are a `co.ref(...)`, you can use `coList._refs[i]` to access
2407
+ * the `Ref` instead of the potentially loaded/null value.
2408
+ *
2409
+ * This allows you to always get the ID or load the value manually.
2410
+ *
2411
+ * @example
2412
+ * ```ts
2413
+ * animals._refs[0].id; // => ID<Animal>
2414
+ * animals._refs[0].value;
2415
+ * // => Animal | null
2416
+ * const animal = await animals._refs[0].load();
2417
+ * ```
2418
+ *
2419
+ * @category Content
2420
+ **/
2421
+ get _refs() {
2422
+ return makeRefs(
2423
+ (idx) => this._raw.get(idx),
2424
+ () => Array.from({ length: this._raw.entries().length }, (_, idx) => idx),
2425
+ this._loadedAs,
2426
+ (_idx) => this._schema[ItemsSym]
2427
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2428
+ );
2429
+ }
2430
+ get _edits() {
2431
+ throw new Error("Not implemented");
2432
+ }
2433
+ get _loadedAs() {
2434
+ const rawAccount = this._raw.core.node.account;
2435
+ if (rawAccount instanceof RawAccount5) {
2436
+ return coValuesCache.get(
2437
+ rawAccount,
2438
+ () => RegisteredSchemas["Account"].fromRaw(rawAccount)
2439
+ );
2440
+ }
2441
+ return new AnonymousJazzAgent(this._raw.core.node);
2442
+ }
2443
+ static get [(ItemsSym, Symbol.species)]() {
2444
+ return Array;
2445
+ }
2446
+ constructor(options) {
2447
+ super();
2448
+ Object.defineProperty(this, "_instanceID", {
2449
+ value: `instance-${Math.random().toString(36).slice(2)}`,
2450
+ enumerable: false
2451
+ });
2452
+ if (options && "fromRaw" in options) {
2453
+ Object.defineProperties(this, {
2454
+ id: {
2455
+ value: options.fromRaw.id,
2456
+ enumerable: false
2457
+ },
2458
+ _raw: { value: options.fromRaw, enumerable: false }
2459
+ });
2460
+ }
2461
+ return new Proxy(this, CoListProxyHandler);
2462
+ }
2463
+ /**
2464
+ * Create a new CoList with the given initial values and owner.
2465
+ *
2466
+ * The owner (a Group or Account) determines access rights to the CoMap.
2467
+ *
2468
+ * The CoList will immediately be persisted and synced to connected peers.
2469
+ *
2470
+ * @example
2471
+ * ```ts
2472
+ * const colours = ColorList.create(
2473
+ * ["red", "green", "blue"],
2474
+ * { owner: me }
2475
+ * );
2476
+ * const animals = AnimalList.create(
2477
+ * [cat, dog, fish],
2478
+ * { owner: me }
2479
+ * );
2480
+ * ```
2481
+ *
2482
+ * @category Creation
2483
+ **/
2484
+ static create(items, options) {
2485
+ const instance = new this({ init: items, owner: options.owner });
2486
+ const raw = options.owner._raw.createList(
2487
+ toRawItems(items, instance._schema[ItemsSym])
2488
+ );
2489
+ Object.defineProperties(instance, {
2490
+ id: {
2491
+ value: raw.id,
2492
+ enumerable: false
2493
+ },
2494
+ _raw: { value: raw, enumerable: false }
2495
+ });
2496
+ return instance;
2497
+ }
2498
+ push(...items) {
2499
+ for (const item of toRawItems(items, this._schema[ItemsSym])) {
2500
+ this._raw.append(item);
2501
+ }
2502
+ return this._raw.entries().length;
2503
+ }
2504
+ unshift(...items) {
2505
+ for (const item of toRawItems(items, this._schema[ItemsSym])) {
2506
+ this._raw.prepend(item);
2507
+ }
2508
+ return this._raw.entries().length;
2509
+ }
2510
+ pop() {
2511
+ const last = this[this.length - 1];
2512
+ this._raw.delete(this.length - 1);
2513
+ return last;
2514
+ }
2515
+ shift() {
2516
+ const first = this[0];
2517
+ this._raw.delete(0);
2518
+ return first;
2519
+ }
2520
+ splice(start, deleteCount, ...items) {
2521
+ const deleted = this.slice(start, start + deleteCount);
2522
+ for (let idxToDelete = start + deleteCount - 1; idxToDelete >= start; idxToDelete--) {
2523
+ this._raw.delete(idxToDelete);
2524
+ }
2525
+ let appendAfter = Math.max(start - 1, 0);
2526
+ for (const item of toRawItems(items, this._schema[ItemsSym])) {
2527
+ console.log(this._raw.asArray(), appendAfter);
2528
+ this._raw.append(item, appendAfter);
2529
+ appendAfter++;
2530
+ }
2531
+ return deleted;
2532
+ }
2533
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2534
+ toJSON(_key, seenAbove) {
2535
+ const itemDescriptor = this._schema[ItemsSym];
2536
+ if (itemDescriptor === "json") {
2537
+ return this._raw.asArray();
2538
+ } else if ("encoded" in itemDescriptor) {
2539
+ return this._raw.asArray().map((e) => itemDescriptor.encoded.encode(e));
2540
+ } else if (isRefEncoded(itemDescriptor)) {
2541
+ return this.map(
2542
+ (item, idx) => seenAbove?.includes(item?.id) ? { _circular: item.id } : item?.toJSON(idx + "", [
2543
+ ...seenAbove || [],
2544
+ this.id
2545
+ ])
2546
+ );
2547
+ } else {
2548
+ return [];
2549
+ }
2550
+ }
2551
+ [inspect]() {
2552
+ return this.toJSON();
2553
+ }
2554
+ /** @category Internals */
2555
+ static fromRaw(raw) {
2556
+ return new this({ fromRaw: raw });
2557
+ }
2558
+ /** @internal */
2559
+ static schema(def) {
2560
+ this._schema ||= {};
2561
+ Object.assign(this._schema, def);
2562
+ }
2563
+ /**
2564
+ * Load a `CoList` with a given ID, as a given account.
2565
+ *
2566
+ * `depth` specifies if item CoValue references should be loaded as well before resolving.
2567
+ * The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
2568
+ *
2569
+ * You can pass `[]` or for shallowly loading only this CoList, or `[itemDepth]` for recursively loading referenced CoValues.
2570
+ *
2571
+ * Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
2572
+ *
2573
+ * @example
2574
+ * ```ts
2575
+ * const animalsWithVets =
2576
+ * await ListOfAnimals.load(
2577
+ * "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
2578
+ * me,
2579
+ * [{ vet: {} }]
2580
+ * );
2581
+ * ```
2582
+ *
2583
+ * @category Subscription & Loading
2584
+ */
2585
+ static load(id, as, depth) {
2586
+ return loadCoValue(this, id, as, depth);
2587
+ }
2588
+ /**
2589
+ * Load and subscribe to a `CoList` with a given ID, as a given account.
2590
+ *
2591
+ * Automatically also subscribes to updates to all referenced/nested CoValues as soon as they are accessed in the listener.
2592
+ *
2593
+ * `depth` specifies if item CoValue references should be loaded as well before calling `listener` for the first time.
2594
+ * The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
2595
+ *
2596
+ * You can pass `[]` or for shallowly loading only this CoList, or `[itemDepth]` for recursively loading referenced CoValues.
2597
+ *
2598
+ * Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
2599
+ *
2600
+ * Returns an unsubscribe function that you should call when you no longer need updates.
2601
+ *
2602
+ * Also see the `useCoState` hook to reactively subscribe to a CoValue in a React component.
2603
+ *
2604
+ * @example
2605
+ * ```ts
2606
+ * const unsub = ListOfAnimals.subscribe(
2607
+ * "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
2608
+ * me,
2609
+ * { vet: {} },
2610
+ * (animalsWithVets) => console.log(animalsWithVets)
2611
+ * );
2612
+ * ```
2613
+ *
2614
+ * @category Subscription & Loading
2615
+ */
2616
+ static subscribe(id, as, depth, listener) {
2617
+ return subscribeToCoValue(this, id, as, depth, listener);
2618
+ }
2619
+ /**
2620
+ * Given an already loaded `CoList`, ensure that items are loaded to the specified depth.
2621
+ *
2622
+ * Works like `CoList.load()`, but you don't need to pass the ID or the account to load as again.
2623
+ *
2624
+ * @category Subscription & Loading
2625
+ */
2626
+ ensureLoaded(depth) {
2627
+ return ensureCoValueLoaded(this, depth);
2628
+ }
2629
+ /**
2630
+ * Given an already loaded `CoList`, subscribe to updates to the `CoList` and ensure that items are loaded to the specified depth.
2631
+ *
2632
+ * Works like `CoList.subscribe()`, but you don't need to pass the ID or the account to load as again.
2633
+ *
2634
+ * Returns an unsubscribe function that you should call when you no longer need updates.
2635
+ *
2636
+ * @category Subscription & Loading
2637
+ **/
2638
+ subscribe(depth, listener) {
2639
+ return subscribeToExistingCoValue(this, depth, listener);
2640
+ }
2641
+ /** @category Type Helpers */
2642
+ castAs(cl) {
2643
+ const casted = cl.fromRaw(this._raw);
2644
+ const subscriptionScope = subscriptionsScopes.get(this);
2645
+ if (subscriptionScope) {
2646
+ subscriptionsScopes.set(casted, subscriptionScope);
2647
+ }
2648
+ return casted;
2649
+ }
2650
+ /**
2651
+ * Wait for the `CoList` to be uploaded to the other peers.
2652
+ *
2653
+ * @category Subscription & Loading
2654
+ */
2655
+ waitForSync(options) {
2656
+ return this._raw.core.waitForSync(options);
2657
+ }
2658
+ };
2659
+ _CoList.prototype._type = "CoList";
2660
+ var CoList = _CoList;
2661
+ function toRawItems(items, itemDescriptor) {
2662
+ const rawItems = itemDescriptor === "json" ? items : "encoded" in itemDescriptor ? items?.map((e) => itemDescriptor.encoded.encode(e)) : isRefEncoded(itemDescriptor) ? items?.map((v) => v.id) : (() => {
2663
+ throw new Error("Invalid element descriptor");
2664
+ })();
2665
+ return rawItems;
2666
+ }
2667
+ var CoListProxyHandler = {
2668
+ get(target, key, receiver) {
2669
+ if (typeof key === "string" && !isNaN(+key)) {
2670
+ const itemDescriptor = target._schema[ItemsSym];
2671
+ const rawValue = target._raw.get(Number(key));
2672
+ if (itemDescriptor === "json") {
2673
+ return rawValue;
2674
+ } else if ("encoded" in itemDescriptor) {
2675
+ return rawValue === void 0 ? void 0 : itemDescriptor.encoded.decode(rawValue);
2676
+ } else if (isRefEncoded(itemDescriptor)) {
2677
+ return rawValue === void 0 ? void 0 : new Ref(
2678
+ rawValue,
2679
+ target._loadedAs,
2680
+ itemDescriptor
2681
+ ).accessFrom(receiver, Number(key));
2682
+ }
2683
+ } else if (key === "length") {
2684
+ return target._raw.entries().length;
2685
+ } else {
2686
+ return Reflect.get(target, key, receiver);
2687
+ }
2688
+ },
2689
+ set(target, key, value, receiver) {
2690
+ if (key === ItemsSym && typeof value === "object" && SchemaInit in value) {
2691
+ target.constructor._schema ||= {};
2692
+ target.constructor._schema[ItemsSym] = value[SchemaInit];
2693
+ return true;
2694
+ }
2695
+ if (typeof key === "string" && !isNaN(+key)) {
2696
+ const itemDescriptor = target._schema[ItemsSym];
2697
+ let rawValue;
2698
+ if (itemDescriptor === "json") {
2699
+ rawValue = value;
2700
+ } else if ("encoded" in itemDescriptor) {
2701
+ rawValue = itemDescriptor.encoded.encode(value);
2702
+ } else if (isRefEncoded(itemDescriptor)) {
2703
+ rawValue = value.id;
2704
+ }
2705
+ target._raw.replace(Number(key), rawValue);
2706
+ return true;
2707
+ } else {
2708
+ return Reflect.set(target, key, value, receiver);
2709
+ }
2710
+ },
2711
+ defineProperty(target, key, descriptor) {
2712
+ if (descriptor.value && key === ItemsSym && typeof descriptor.value === "object" && SchemaInit in descriptor.value) {
2713
+ target.constructor._schema ||= {};
2714
+ target.constructor._schema[ItemsSym] = descriptor.value[SchemaInit];
2715
+ return true;
2716
+ } else {
2717
+ return Reflect.defineProperty(target, key, descriptor);
2718
+ }
2719
+ },
2720
+ has(target, key) {
2721
+ if (typeof key === "string" && !isNaN(+key)) {
2722
+ return Number(key) < target._raw.entries().length;
2723
+ } else {
2724
+ return Reflect.has(target, key);
2725
+ }
2726
+ }
2727
+ };
2728
+
2729
+ // src/coValues/extensions/imageDef.ts
2730
+ var _a, _b;
2731
+ var ImageDefinition = class extends (_b = CoMap, _a = co.items, _b) {
2732
+ constructor() {
2733
+ super(...arguments);
2734
+ this.originalSize = co.json();
2735
+ this.placeholderDataURL = co.string;
2736
+ this[_a] = co.ref(FileStream);
2737
+ }
2738
+ highestResAvailable(options) {
2739
+ if (!subscriptionsScopes.get(this)) {
2740
+ console.warn(
2741
+ "highestResAvailable() only makes sense when used within a subscription."
2742
+ );
2743
+ }
2744
+ const resolutions = Object.keys(this).filter(
2745
+ (key) => key.match(/^\d+x\d+$/) && (options?.maxWidth === void 0 || Number(key.split("x")[0]) <= options.maxWidth)
2746
+ );
2747
+ resolutions.sort((a, b) => {
2748
+ const aWidth = Number(a.split("x")[0]);
2749
+ const bWidth = Number(b.split("x")[0]);
2750
+ return aWidth - bWidth;
2751
+ });
2752
+ let highestAvailableResolution;
2753
+ for (const resolution of resolutions) {
2754
+ if (this[resolution] && this[resolution]?.getChunks()) {
2755
+ highestAvailableResolution = resolution;
2756
+ } else {
2757
+ return highestAvailableResolution && {
2758
+ res: highestAvailableResolution,
2759
+ stream: this[highestAvailableResolution]
2760
+ };
2761
+ }
2762
+ }
2763
+ return highestAvailableResolution && {
2764
+ res: highestAvailableResolution,
2765
+ stream: this[highestAvailableResolution]
2766
+ };
2767
+ }
2768
+ };
2769
+
2770
+ // src/coValues/schemaUnion.ts
2771
+ var SchemaUnion = class _SchemaUnion extends CoValueBase {
2772
+ /**
2773
+ * Create a new union type from a discriminator function.
2774
+ *
2775
+ * The discriminator function receives the raw data and should return the appropriate concrete class to use for that data.
2776
+ *
2777
+ * When loading a SchemaUnion, the correct subclass will be instantiated based on the discriminator.
2778
+ *
2779
+ * @param discriminator - Function that determines which concrete type to use
2780
+ * @returns A new class that can create/load instances of the union type
2781
+ *
2782
+ * @example
2783
+ * ```ts
2784
+ * const WidgetUnion = SchemaUnion.Of<BaseWidget>((raw) => {
2785
+ * switch (raw.get("type")) {
2786
+ * case "button": return ButtonWidget;
2787
+ * case "slider": return SliderWidget;
2788
+ * default: throw new Error("Unknown widget type");
2789
+ * }
2790
+ * });
2791
+ *
2792
+ * const widget = await loadCoValue(WidgetUnion, id, me, {});
2793
+ *
2794
+ * // You can narrow the returned instance to a subclass by using `instanceof`
2795
+ * if (widget instanceof ButtonWidget) {
2796
+ * console.log(widget.label);
2797
+ * } else if (widget instanceof SliderWidget) {
2798
+ * console.log(widget.min, widget.max);
2799
+ * }
2800
+ * ```
2801
+ *
2802
+ * @category Declaration
2803
+ **/
2804
+ static Of(discriminator) {
2805
+ return class SchemaUnionClass extends _SchemaUnion {
2806
+ static fromRaw(raw) {
2807
+ const ResolvedClass = discriminator(
2808
+ raw
2809
+ );
2810
+ return ResolvedClass.fromRaw(raw);
2811
+ }
2812
+ };
2813
+ }
2814
+ /**
2815
+ * Create an instance from raw data. This is called internally and should not be used directly.
2816
+ * Use {@link SchemaUnion.Of} to create a union type instead.
2817
+ *
2818
+ * @internal
2819
+ */
2820
+ // @ts-ignore
2821
+ static fromRaw(raw) {
2822
+ throw new Error("Not implemented");
2823
+ }
2824
+ };
2825
+
2826
+ export {
2827
+ AnonymousJazzAgent,
2828
+ CoValueBase,
2829
+ loadCoValue,
2830
+ subscribeToCoValue,
2831
+ createCoValueObservable,
2832
+ Encoders,
2833
+ co,
2834
+ fixedCredentialsAuth,
2835
+ ephemeralCredentialsAuth,
2836
+ randomSessionProvider,
2837
+ createJazzContext,
2838
+ createAnonymousJazzContext,
2839
+ Inbox,
2840
+ InboxSender,
2841
+ CoMap,
2842
+ Profile,
2843
+ Account,
2844
+ isControlledAccount,
2845
+ Group,
2846
+ CoFeed,
2847
+ FileStream,
2848
+ CoList,
2849
+ ImageDefinition,
2850
+ SchemaUnion
2851
+ };
2852
+ /* istanbul ignore file -- @preserve */
2853
+ //# sourceMappingURL=chunk-6OHBW32Q.js.map