jazz-tools 0.7.23 → 0.7.24

Sign up to get free protection for your applications and to get access to all the features.
@@ -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";