jazz-tools 0.7.23 → 0.7.24

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.
@@ -1,10 +1,8 @@
1
- import { Effect, Option, Sink, Stream } from "effect";
2
1
  import type { CojsonInternalTypes, RawCoValue } from "cojson";
3
2
  import { RawAccount } from "cojson";
4
- import type { DeeplyLoaded, DepthsIn, UnavailableError } from "../internal.js";
3
+ import type { DeeplyLoaded, DepthsIn } from "../internal.js";
5
4
  import {
6
5
  Account,
7
- AccountCtx,
8
6
  Group,
9
7
  SubscriptionScope,
10
8
  Ref,
@@ -134,13 +132,22 @@ export function loadCoValue<V extends CoValue, Depth>(
134
132
  as: Account,
135
133
  depth: Depth & DepthsIn<V>,
136
134
  ): Promise<DeeplyLoaded<V, Depth> | undefined> {
137
- return Effect.runPromise(
138
- loadCoValueEf(cls, id, depth).pipe(
139
- Effect.mapError(() => undefined),
140
- Effect.merge,
141
- Effect.provideService(AccountCtx, as),
142
- ),
143
- );
135
+ return new Promise((resolve) => {
136
+ const unsubscribe = subscribeToCoValue(
137
+ cls,
138
+ id,
139
+ as,
140
+ depth,
141
+ (value) => {
142
+ resolve(value);
143
+ unsubscribe();
144
+ },
145
+ () => {
146
+ resolve(undefined);
147
+ unsubscribe();
148
+ },
149
+ );
150
+ });
144
151
  }
145
152
 
146
153
  export function ensureCoValueLoaded<V extends CoValue, Depth>(
@@ -155,41 +162,46 @@ export function ensureCoValueLoaded<V extends CoValue, Depth>(
155
162
  );
156
163
  }
157
164
 
158
- export function loadCoValueEf<V extends CoValue, Depth>(
159
- cls: CoValueClass<V>,
160
- id: ID<V>,
161
- depth: Depth & DepthsIn<V>,
162
- ): Effect.Effect<DeeplyLoaded<V, Depth>, UnavailableError, AccountCtx> {
163
- return subscribeToCoValueEf(cls, id, depth).pipe(
164
- Stream.runHead,
165
- Effect.andThen(
166
- Effect.mapError((_noSuchElem) => "unavailable" as const),
167
- ),
168
- );
169
- }
170
-
171
165
  export function subscribeToCoValue<V extends CoValue, Depth>(
172
166
  cls: CoValueClass<V>,
173
167
  id: ID<V>,
174
168
  as: Account,
175
169
  depth: Depth & DepthsIn<V>,
176
170
  listener: (value: DeeplyLoaded<V, Depth>) => void,
171
+ onUnavailable?: () => void,
177
172
  ): () => void {
178
- void Effect.runPromise(
179
- Effect.provideService(
180
- subscribeToCoValueEf(cls, id, depth).pipe(
181
- Stream.run(
182
- Sink.forEach((update) =>
183
- Effect.sync(() => listener(update)),
184
- ),
185
- ),
186
- ),
187
- AccountCtx,
188
- as,
189
- ),
190
- );
173
+ const ref = new Ref(id, as, { ref: cls, optional: false });
174
+
175
+ let unsubscribed = false;
176
+ let unsubscribe: (() => void) | undefined;
177
+
178
+ ref.load()
179
+ .then((value) => {
180
+ if (!value) {
181
+ onUnavailable && onUnavailable();
182
+ return;
183
+ }
184
+ if (unsubscribed) return;
185
+ const subscription = new SubscriptionScope(
186
+ value,
187
+ cls as CoValueClass<V> & CoValueFromRaw<V>,
188
+ (update) => {
189
+ if (fulfillsDepth(depth, update)) {
190
+ listener(update as DeeplyLoaded<V, Depth>);
191
+ }
192
+ },
193
+ );
194
+
195
+ unsubscribe = () => subscription.unsubscribeAll();
196
+ })
197
+ .catch((e) => {
198
+ console.error("Failed to load / subscribe to CoValue", e);
199
+ });
191
200
 
192
- return function unsubscribe() {};
201
+ return function unsubscribeAtAnyPoint() {
202
+ unsubscribed = true;
203
+ unsubscribe && unsubscribe();
204
+ };
193
205
  }
194
206
 
195
207
  export function subscribeToExistingCoValue<V extends CoValue, Depth>(
@@ -205,43 +217,3 @@ export function subscribeToExistingCoValue<V extends CoValue, Depth>(
205
217
  listener,
206
218
  );
207
219
  }
208
-
209
- export function subscribeToCoValueEf<V extends CoValue, Depth>(
210
- cls: CoValueClass<V>,
211
- id: ID<V>,
212
- depth: Depth & DepthsIn<V>,
213
- ): Stream.Stream<DeeplyLoaded<V, Depth>, UnavailableError, AccountCtx> {
214
- return AccountCtx.pipe(
215
- Effect.andThen((account) =>
216
- new Ref(id, account, {
217
- ref: cls,
218
- optional: false,
219
- }).loadEf(),
220
- ),
221
- Stream.fromEffect,
222
- Stream.flatMap((value: V) =>
223
- Stream.asyncScoped<V, UnavailableError>((emit) =>
224
- Effect.gen(function* (_) {
225
- const subscription = new SubscriptionScope(
226
- value,
227
- cls as CoValueClass<V> & CoValueFromRaw<V>,
228
- (update) => void emit.single(update as V),
229
- );
230
-
231
- yield* _(
232
- Effect.addFinalizer(() =>
233
- Effect.sync(() => subscription.unsubscribeAll()),
234
- ),
235
- );
236
- }),
237
- ),
238
- ),
239
- Stream.filterMap((update: V) =>
240
- Option.fromNullable(
241
- fulfillsDepth(depth, update)
242
- ? (update as DeeplyLoaded<V, Depth>)
243
- : undefined,
244
- ),
245
- ),
246
- );
247
- }
@@ -1,4 +1,3 @@
1
- import { Effect } from "effect";
2
1
  import type { CoID, RawCoValue } from "cojson";
3
2
  import type {
4
3
  Account,
@@ -6,7 +5,6 @@ import type {
6
5
  ID,
7
6
  RefEncoded,
8
7
  UnCo,
9
- UnavailableError,
10
8
  } from "../internal.js";
11
9
  import {
12
10
  instantiateRefEncoded,
@@ -47,22 +45,6 @@ export class Ref<out V extends CoValue> {
47
45
  }
48
46
  }
49
47
 
50
- loadEf() {
51
- return Effect.async<V, UnavailableError>((fulfill) => {
52
- this.loadHelper()
53
- .then((value) => {
54
- if (value === "unavailable") {
55
- fulfill(Effect.fail<UnavailableError>("unavailable"));
56
- } else {
57
- fulfill(Effect.succeed(value));
58
- }
59
- })
60
- .catch((e) => {
61
- fulfill(Effect.die(e));
62
- });
63
- });
64
- }
65
-
66
48
  private async loadHelper(options?: {
67
49
  onProgress: (p: number) => void;
68
50
  }): Promise<V | "unavailable"> {
@@ -23,7 +23,7 @@ const optional = {
23
23
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
24
  return { [SchemaInit]: "json" satisfies Schema } as any;
25
25
  },
26
- encoded<T>(arg: OptionalEncoder<T>): co<T> {
26
+ encoded<T>(arg: OptionalEncoder<T>): co<T | undefined> {
27
27
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
28
  return { [SchemaInit]: { encoded: arg } satisfies Schema } as any;
29
29
  },
package/src/index.ts CHANGED
@@ -26,9 +26,4 @@ export { ImageDefinition } from "./internal.js";
26
26
  export { CoValueBase, type CoValueClass } from "./internal.js";
27
27
  export type { DepthsIn, DeeplyLoaded } from "./internal.js";
28
28
 
29
- export {
30
- loadCoValue,
31
- loadCoValueEf,
32
- subscribeToCoValue,
33
- subscribeToCoValueEf,
34
- } from "./internal.js";
29
+ export { loadCoValue, subscribeToCoValue } from "./internal.js";
@@ -26,6 +26,7 @@ describe("Simple CoMap operations", async () => {
26
26
  birthday = co.encoded(Encoders.Date);
27
27
  name? = co.string;
28
28
  nullable = co.optional.encoded(Schema.NullishOr(Schema.String));
29
+ optionalDate = co.optional.encoded(Encoders.Date);
29
30
 
30
31
  get roughColor() {
31
32
  return this.color + "ish";