jazz-tools 0.9.1 → 0.9.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,6 +7,7 @@ import {
7
7
  type RawCoMap,
8
8
  cojsonInternals,
9
9
  } from "cojson";
10
+ import { activeAccountContext } from "../implementation/activeAccountContext.js";
10
11
  import type {
11
12
  AnonymousJazzAgent,
12
13
  CoValue,
@@ -28,10 +29,10 @@ import {
28
29
  ensureCoValueLoaded,
29
30
  inspect,
30
31
  isRefEncoded,
31
- loadCoValue,
32
+ loadCoValueWithoutMe,
32
33
  makeRefs,
33
34
  parseCoValueCreateOptions,
34
- subscribeToCoValue,
35
+ subscribeToCoValueWithoutMe,
35
36
  subscribeToExistingCoValue,
36
37
  subscriptionsScopes,
37
38
  } from "../internal.js";
@@ -274,7 +275,7 @@ export class CoMap extends CoValueBase implements CoValue {
274
275
  static create<M extends CoMap>(
275
276
  this: CoValueClass<M>,
276
277
  init: Simplify<CoMapInit<M>>,
277
- options:
278
+ options?:
278
279
  | {
279
280
  owner: Account | Group;
280
281
  unique?: CoValueUniqueness["uniqueness"];
@@ -432,13 +433,24 @@ export class CoMap extends CoValueBase implements CoValue {
432
433
  *
433
434
  * @category Subscription & Loading
434
435
  */
435
- static load<M extends CoMap, Depth>(
436
- this: CoValueClass<M>,
437
- id: ID<M>,
436
+ static load<C extends CoMap, Depth>(
437
+ this: CoValueClass<C>,
438
+ id: ID<C>,
439
+ depth: Depth & DepthsIn<C>,
440
+ ): Promise<DeeplyLoaded<C, Depth> | undefined>;
441
+ static load<C extends CoMap, Depth>(
442
+ this: CoValueClass<C>,
443
+ id: ID<C>,
438
444
  as: Account,
439
- depth: Depth & DepthsIn<M>,
440
- ): Promise<DeeplyLoaded<M, Depth> | undefined> {
441
- return loadCoValue(this, id, as, depth);
445
+ depth: Depth & DepthsIn<C>,
446
+ ): Promise<DeeplyLoaded<C, Depth> | undefined>;
447
+ static load<C extends CoMap, Depth>(
448
+ this: CoValueClass<C>,
449
+ id: ID<C>,
450
+ asOrDepth: Account | (Depth & DepthsIn<C>),
451
+ depth?: Depth & DepthsIn<C>,
452
+ ): Promise<DeeplyLoaded<C, Depth> | undefined> {
453
+ return loadCoValueWithoutMe(this, id, asOrDepth, depth);
442
454
  }
443
455
 
444
456
  /**
@@ -469,22 +481,45 @@ export class CoMap extends CoValueBase implements CoValue {
469
481
  *
470
482
  * @category Subscription & Loading
471
483
  */
472
- static subscribe<M extends CoMap, Depth>(
473
- this: CoValueClass<M>,
474
- id: ID<M>,
484
+ static subscribe<C extends CoMap, Depth>(
485
+ this: CoValueClass<C>,
486
+ id: ID<C>,
487
+ depth: Depth & DepthsIn<C>,
488
+ listener: (value: DeeplyLoaded<C, Depth>) => void,
489
+ ): () => void;
490
+ static subscribe<C extends CoMap, Depth>(
491
+ this: CoValueClass<C>,
492
+ id: ID<C>,
475
493
  as: Account,
476
- depth: Depth & DepthsIn<M>,
477
- listener: (value: DeeplyLoaded<M, Depth>) => void,
494
+ depth: Depth & DepthsIn<C>,
495
+ listener: (value: DeeplyLoaded<C, Depth>) => void,
496
+ ): () => void;
497
+ static subscribe<C extends CoMap, Depth>(
498
+ this: CoValueClass<C>,
499
+ id: ID<C>,
500
+ asOrDepth: Account | (Depth & DepthsIn<C>),
501
+ depthOrListener:
502
+ | (Depth & DepthsIn<C>)
503
+ | ((value: DeeplyLoaded<C, Depth>) => void),
504
+ listener?: (value: DeeplyLoaded<C, Depth>) => void,
478
505
  ): () => void {
479
- return subscribeToCoValue<M, Depth>(this, id, as, depth, listener);
506
+ return subscribeToCoValueWithoutMe<C, Depth>(
507
+ this,
508
+ id,
509
+ asOrDepth,
510
+ depthOrListener,
511
+ listener,
512
+ );
480
513
  }
481
514
 
482
515
  static findUnique<M extends CoMap>(
483
516
  this: CoValueClass<M>,
484
517
  unique: CoValueUniqueness["uniqueness"],
485
518
  ownerID: ID<Account> | ID<Group>,
486
- as: Account | Group | AnonymousJazzAgent,
519
+ as?: Account | Group | AnonymousJazzAgent,
487
520
  ) {
521
+ as ||= activeAccountContext.get();
522
+
488
523
  const header = {
489
524
  type: "comap" as const,
490
525
  ruleset: {
@@ -0,0 +1,247 @@
1
+ import {
2
+ type OpID,
3
+ RawAccount,
4
+ type RawCoPlainText,
5
+ stringifyOpID,
6
+ } from "cojson";
7
+ import { activeAccountContext } from "../implementation/activeAccountContext.js";
8
+ import type { CoValue, CoValueClass, ID } from "../internal.js";
9
+ import {
10
+ inspect,
11
+ isAccountInstance,
12
+ loadCoValue,
13
+ subscribeToCoValue,
14
+ subscribeToExistingCoValue,
15
+ } from "../internal.js";
16
+ import { Account } from "./account.js";
17
+ import { Group } from "./group.js";
18
+
19
+ export type TextPos = OpID;
20
+
21
+ export class CoPlainText extends String implements CoValue {
22
+ declare id: ID<this>;
23
+ declare _type: "CoPlainText";
24
+ declare _raw: RawCoPlainText;
25
+
26
+ get _owner(): Account | Group {
27
+ return this._raw.group instanceof RawAccount
28
+ ? Account.fromRaw(this._raw.group)
29
+ : Group.fromRaw(this._raw.group);
30
+ }
31
+
32
+ get _loadedAs() {
33
+ return Account.fromNode(this._raw.core.node);
34
+ }
35
+
36
+ constructor(
37
+ options:
38
+ | { fromRaw: RawCoPlainText }
39
+ | { text: string; owner: Account | Group },
40
+ ) {
41
+ super();
42
+
43
+ let raw;
44
+
45
+ if ("fromRaw" in options) {
46
+ raw = options.fromRaw;
47
+ } else {
48
+ raw = options.owner._raw.createPlainText(options.text);
49
+ }
50
+
51
+ Object.defineProperties(this, {
52
+ id: { value: raw.id, enumerable: false },
53
+ _type: { value: "CoPlainText", enumerable: false },
54
+ _raw: { value: raw, enumerable: false },
55
+ });
56
+ }
57
+
58
+ static create<T extends CoPlainText>(
59
+ this: CoValueClass<T>,
60
+ text: string,
61
+ options: { owner: Account | Group },
62
+ ) {
63
+ return new this({ text, owner: options.owner });
64
+ }
65
+
66
+ get length() {
67
+ return this._raw.toString().length;
68
+ }
69
+
70
+ toString() {
71
+ return this._raw.toString();
72
+ }
73
+
74
+ valueOf() {
75
+ return this._raw.toString();
76
+ }
77
+
78
+ toJSON(): string {
79
+ return this._raw.toString();
80
+ }
81
+
82
+ [inspect]() {
83
+ return this.toJSON();
84
+ }
85
+
86
+ insertAfter(idx: number, text: string) {
87
+ this._raw.insertAfter(idx, text);
88
+ }
89
+
90
+ deleteRange(range: { from: number; to: number }) {
91
+ this._raw.deleteRange(range);
92
+ }
93
+
94
+ posBefore(idx: number): TextPos | undefined {
95
+ return this._raw.mapping.opIDbeforeIdx[idx];
96
+ }
97
+
98
+ posAfter(idx: number): TextPos | undefined {
99
+ return this._raw.mapping.opIDafterIdx[idx];
100
+ }
101
+
102
+ idxBefore(pos: TextPos): number | undefined {
103
+ return this._raw.mapping.idxBeforeOpID[stringifyOpID(pos)];
104
+ }
105
+
106
+ idxAfter(pos: TextPos): number | undefined {
107
+ return this._raw.mapping.idxAfterOpID[stringifyOpID(pos)];
108
+ }
109
+
110
+ static fromRaw<V extends CoPlainText>(
111
+ this: CoValueClass<V> & typeof CoPlainText,
112
+ raw: RawCoPlainText,
113
+ ) {
114
+ return new this({ fromRaw: raw });
115
+ }
116
+
117
+ /**
118
+ * Load a `CoPlainText` with a given ID, as a given account.
119
+ *
120
+ * `depth` specifies which (if any) fields that reference other CoValues to load as well before resolving.
121
+ * The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
122
+ *
123
+ * You can pass `[]` or `{}` for shallowly loading only this CoPlainText, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues.
124
+ *
125
+ * Check out the `load` methods on `CoMap`/`CoList`/`CoStream`/`Group`/`Account` to see which depth structures are valid to nest.
126
+ *
127
+ * @example
128
+ * ```ts
129
+ * const person = await Person.load(
130
+ * "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
131
+ * me,
132
+ * { pet: {} }
133
+ * );
134
+ * ```
135
+ *
136
+ * @category Subscription & Loading
137
+ */
138
+ static load<T extends CoPlainText>(
139
+ this: CoValueClass<T>,
140
+ id: ID<T>,
141
+ as?: Account,
142
+ ): Promise<T | undefined> {
143
+ return loadCoValue(this, id, as ?? activeAccountContext.get(), []);
144
+ }
145
+
146
+ // /**
147
+ // * Effectful version of `CoMap.load()`.
148
+ // *
149
+ // * Needs to be run inside an `AccountCtx` context.
150
+ // *
151
+ // * @category Subscription & Loading
152
+ // */
153
+ // static loadEf<T extends CoPlainText>(
154
+ // this: CoValueClass<T>,
155
+ // id: ID<T>,
156
+ // ): Effect.Effect<T, UnavailableError, AccountCtx> {
157
+ // return loadCoValueEf(this, id, []);
158
+ // }
159
+
160
+ /**
161
+ * Load and subscribe to a `CoPlainText` with a given ID, as a given account.
162
+ *
163
+ * Automatically also subscribes to updates to all referenced/nested CoValues as soon as they are accessed in the listener.
164
+ *
165
+ * `depth` specifies which (if any) fields that reference other CoValues to load as well before calling `listener` for the first time.
166
+ * The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
167
+ *
168
+ * You can pass `[]` or `{}` for shallowly loading only this CoMap, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues.
169
+ *
170
+ * Check out the `load` methods on `CoMap`/`CoList`/`CoStream`/`Group`/`Account` to see which depth structures are valid to nest.
171
+ *
172
+ * Returns an unsubscribe function that you should call when you no longer need updates.
173
+ *
174
+ * Also see the `useCoState` hook to reactively subscribe to a CoValue in a React component.
175
+ *
176
+ * @example
177
+ * ```ts
178
+ * const unsub = Person.subscribe(
179
+ * "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
180
+ * me,
181
+ * { pet: {} },
182
+ * (person) => console.log(person)
183
+ * );
184
+ * ```
185
+ *
186
+ * @category Subscription & Loading
187
+ */
188
+ static subscribe<T extends CoPlainText>(
189
+ this: CoValueClass<T>,
190
+ id: ID<T>,
191
+ listener: (value: T) => void,
192
+ ): () => void;
193
+ static subscribe<T extends CoPlainText>(
194
+ this: CoValueClass<T>,
195
+ id: ID<T>,
196
+ as: Account,
197
+ listener: (value: T) => void,
198
+ ): () => void;
199
+ static subscribe<T extends CoPlainText>(
200
+ this: CoValueClass<T>,
201
+ id: ID<T>,
202
+ asOrListener: Account | ((value: T) => void),
203
+ listener?: (value: T) => void,
204
+ ): () => void {
205
+ if (isAccountInstance(asOrListener)) {
206
+ return subscribeToCoValue(this, id, asOrListener, [], listener!);
207
+ }
208
+
209
+ return subscribeToCoValue(
210
+ this,
211
+ id,
212
+ activeAccountContext.get(),
213
+ [],
214
+ listener!,
215
+ );
216
+ }
217
+
218
+ // /**
219
+ // * Effectful version of `CoMap.subscribe()` that returns a stream of updates.
220
+ // *
221
+ // * Needs to be run inside an `AccountCtx` context.
222
+ // *
223
+ // * @category Subscription & Loading
224
+ // */
225
+ // static subscribeEf<T extends CoPlainText>(
226
+ // this: CoValueClass<T>,
227
+ // id: ID<T>,
228
+ // ): Stream.Stream<T, UnavailableError, AccountCtx> {
229
+ // return subscribeToCoValueEf(this, id, []);
230
+ // }
231
+
232
+ /**
233
+ * Given an already loaded `CoPlainText`, subscribe to updates to the `CoPlainText` and ensure that the specified fields are loaded to the specified depth.
234
+ *
235
+ * Works like `CoPlainText.subscribe()`, but you don't need to pass the ID or the account to load as again.
236
+ *
237
+ * Returns an unsubscribe function that you should call when you no longer need updates.
238
+ *
239
+ * @category Subscription & Loading
240
+ **/
241
+ subscribe<T extends CoPlainText>(
242
+ this: T,
243
+ listener: (value: T) => void,
244
+ ): () => void {
245
+ return subscribeToExistingCoValue(this, [], listener);
246
+ }
247
+ }