@confect/js 10.0.0-next.17 → 10.0.0-next.19

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,69 @@
1
1
  # @confect/js
2
2
 
3
+ ## 10.0.0-next.19
4
+
5
+ ### Minor Changes
6
+
7
+ - c1087eb: Add `@confect/foldkit` — client-side bindings for [Foldkit](https://foldkit.dev) apps. The package maps Confect's client surface onto Foldkit's integration seams: `Client.layer` provides the scoped WebSocket client and pagination-session allocator through an application's `resources`, `Subscription.reactiveQuery` builds a subscription entry that opens, re-opens, and closes a reactive query as `Option`-wrapped args derived from the Model change, and `Command.query` / `Command.mutation` / `Command.action` build Command definitions whose args are the ref's args and whose Messages are declared with the same `messages` field Foldkit's own `Command.define` takes. Every failure is folded into a Message via the required `onError` handler, so Command and Subscription error channels stay `never` as Foldkit requires.
8
+
9
+ ```ts
10
+ import * as Confect from "@confect/foldkit";
11
+ import * as Schema from "effect/Schema";
12
+ import * as Subscription from "foldkit/subscription";
13
+
14
+ const SaveNote = Confect.Command.mutation(
15
+ "SaveNote",
16
+ refs.public.notes.insert,
17
+ {
18
+ messages: [SucceededSaveNote, FailedSaveNote],
19
+ onSuccess: (noteId) => SucceededSaveNote({ noteId }),
20
+ onError: (error) => FailedSaveNote({ message: String(error) }),
21
+ },
22
+ );
23
+
24
+ const subscriptions = Subscription.make<
25
+ Model,
26
+ Message,
27
+ Confect.Client.Client
28
+ >()(() => ({
29
+ note: Confect.Subscription.reactiveQuery<Model>()(refs.public.notes.get, {
30
+ args: (model) => Option.map(model.noteId, (noteId) => ({ noteId })),
31
+ onSuccess: (note) => SucceededGetNote({ note }),
32
+ onError: (error) => FailedGetNote({ message: String(error) }),
33
+ }),
34
+ }));
35
+ ```
36
+
37
+ The Command factories accept Foldkit's `interrupt` option — `true` keys invocations by the Command name, `{ keyFields, toKey }` by a part derived from the ref's args — and the returned definition gains the `Interrupt` constructor for stopping in-flight invocations. Factory-built definitions instantiate Foldkit's own definition interfaces, so they are accepted wherever Foldkit accepts a Command definition — including Story/Scene `Command.resolve` and `expectExact` matchers. `Command.queryEffect`, `Command.mutationEffect`, and `Command.actionEffect` return execute bodies for hand-written `Command.define` calls (custom args schemas, multi-call Commands), and `Subscription.reactiveQueryStream` is the `dependenciesToStream` escape hatch for hand-written subscription entries.
38
+
39
+ `PaginatedQuery` navigates a paginated query one page at a time over Convex's cursor pagination. `PaginatedQuery.make(ref)` returns the Model and settlement schemas. Its states use Foldkit `AsyncData`'s vocabulary and semantics: `Idle`, `Loading`, `Refreshing`, `Success`, `Failure`, and `Stale`. Failed settlements preserve the complete error contract: declared function and middleware errors are wrapped as `FunctionError`, Convex's invalid-cursor pseudo-error is normalized to the new `@confect/core/PaginationError.InvalidCursor`, and `WebSocketClientError` and `SchemaError` are carried directly. `settle` accepts a request-bound `Result`, turns a failed refresh into `Stale`, automatically resets an invalid cursor, and ignores successes or failures from superseded requests. All machine operations (`init`, `reinitialize`, `reset`, `close`, `next`, `prev`, and `first`) remain pure.
40
+
41
+ `Subscription.paginatedQuery` keeps exactly one live, reactive page subscription in sync with the machine and emits one `onSettled` Message shape for either outcome. It allocates Convex's pagination `id` internally and returns it with the first settlement, so session allocation is not a separate Command or application Message. Installing that id is keep-alive-equivalent and does not restart the subscription. Query errors are emitted as values without closing the underlying Convex subscription, allowing a later successful result to recover naturally. Each request supports `maximumRowsRead` and `maximumBytesRead` and uses `initialNumItems` for the initial page and split heuristic. Page splits remain transparent, the last complete page stays visible during navigation and after refresh failure, and an empty terminal page automatically retreats to the preceding page.
42
+
43
+ ```ts
44
+ const Notes = Confect.PaginatedQuery.make(refs.public.notes.paginate);
45
+
46
+ // Model: notes: Notes.schema
47
+ // Initial Model value: notes: Notes.idle
48
+ // Message: settlement: Notes.settlement
49
+ // update after matching Idle: Notes.init(idle, { channel }, { initialNumItems: 20 })
50
+
51
+ const subscriptions = Subscription.make<
52
+ Model,
53
+ Message,
54
+ Confect.Client.Client
55
+ >()(() => ({
56
+ notesPage: Confect.Subscription.paginatedQuery<Model>()(Notes, {
57
+ state: (model) => model.notes,
58
+ onSettled: (settlement) => SettledGetNotesPage({ settlement }),
59
+ }),
60
+ }));
61
+ ```
62
+
63
+ - aa7d903: Add per-module subpath exports to `@confect/js`, so `import * as WebSocketClient from "@confect/js/WebSocketClient"` and `import * as HttpClient from "@confect/js/HttpClient"` now resolve. The root import (`import { HttpClient, WebSocketClient } from "@confect/js"`) is unchanged.
64
+
65
+ ## 10.0.0-next.18
66
+
3
67
  ## 10.0.0-next.17
4
68
 
5
69
  ### Patch Changes
@@ -1,14 +1,14 @@
1
1
  import * as Ref from "@confect/core/Ref";
2
2
  import { ConvexClient } from "convex/browser";
3
- import * as Cause from "effect/Cause";
4
3
  import * as Context from "effect/Context";
5
4
  import * as Effect from "effect/Effect";
6
5
  import * as Layer from "effect/Layer";
6
+ import * as Result from "effect/Result";
7
7
  import * as Schema from "effect/Schema";
8
8
  import * as Stream from "effect/Stream";
9
9
  declare const WebSocketClientError_base: Schema.Class<WebSocketClientError, Schema.TaggedStruct<"WebSocketClientError", {
10
- readonly cause: Schema.Unknown;
11
- }>, Cause.YieldableError>;
10
+ readonly cause: Schema.Defect;
11
+ }>, import("effect/Cause").YieldableError>;
12
12
  export declare class WebSocketClientError extends WebSocketClientError_base {
13
13
  }
14
14
  /**
@@ -22,7 +22,8 @@ export declare const WebSocketClient: Context.Service<{
22
22
  query: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Effect.Effect<Ref.Returns<Query>, Ref.Error<Query> | WebSocketClientError | Schema.SchemaError>;
23
23
  mutation: <Mutation extends Ref.AnyPublicMutation>(ref: Mutation, ...rest: Ref.OptionalArgs<Mutation>) => Effect.Effect<Ref.Returns<Mutation>, Ref.Error<Mutation> | WebSocketClientError | Schema.SchemaError>;
24
24
  action: <Action extends Ref.AnyPublicAction>(ref: Action, ...rest: Ref.OptionalArgs<Action>) => Effect.Effect<Ref.Returns<Action>, Ref.Error<Action> | WebSocketClientError | Schema.SchemaError>;
25
- reactiveQuery: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Stream.Stream<Ref.Returns<Query>, Ref.Error<Query> | WebSocketClientError | Schema.SchemaError>;
25
+ reactiveQuery: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Stream.Stream<Ref.Returns<Query>, Schema.SchemaError | WebSocketClientError | Ref.Error<Query>>;
26
+ reactiveQueryResult: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Stream.Stream<Result.Result<Ref.Returns<Query>, Schema.SchemaError | WebSocketClientError | Ref.Error<Query>>>;
26
27
  }, {
27
28
  url: string;
28
29
  setAuth: (fetchToken: (args: {
@@ -31,7 +32,8 @@ export declare const WebSocketClient: Context.Service<{
31
32
  query: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Effect.Effect<Ref.Returns<Query>, Ref.Error<Query> | WebSocketClientError | Schema.SchemaError>;
32
33
  mutation: <Mutation extends Ref.AnyPublicMutation>(ref: Mutation, ...rest: Ref.OptionalArgs<Mutation>) => Effect.Effect<Ref.Returns<Mutation>, Ref.Error<Mutation> | WebSocketClientError | Schema.SchemaError>;
33
34
  action: <Action extends Ref.AnyPublicAction>(ref: Action, ...rest: Ref.OptionalArgs<Action>) => Effect.Effect<Ref.Returns<Action>, Ref.Error<Action> | WebSocketClientError | Schema.SchemaError>;
34
- reactiveQuery: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Stream.Stream<Ref.Returns<Query>, Ref.Error<Query> | WebSocketClientError | Schema.SchemaError>;
35
+ reactiveQuery: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Stream.Stream<Ref.Returns<Query>, Schema.SchemaError | WebSocketClientError | Ref.Error<Query>>;
36
+ reactiveQueryResult: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Stream.Stream<Result.Result<Ref.Returns<Query>, Schema.SchemaError | WebSocketClientError | Ref.Error<Query>>>;
35
37
  }>;
36
38
  export type WebSocketClient = typeof WebSocketClient.Identifier;
37
39
  export declare const layer: (address: string, options?: ConstructorParameters<typeof ConvexClient>[1]) => Layer.Layer<{
@@ -42,7 +44,8 @@ export declare const layer: (address: string, options?: ConstructorParameters<ty
42
44
  query: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Effect.Effect<Ref.Returns<Query>, Ref.Error<Query> | WebSocketClientError | Schema.SchemaError>;
43
45
  mutation: <Mutation extends Ref.AnyPublicMutation>(ref: Mutation, ...rest: Ref.OptionalArgs<Mutation>) => Effect.Effect<Ref.Returns<Mutation>, Ref.Error<Mutation> | WebSocketClientError | Schema.SchemaError>;
44
46
  action: <Action extends Ref.AnyPublicAction>(ref: Action, ...rest: Ref.OptionalArgs<Action>) => Effect.Effect<Ref.Returns<Action>, Ref.Error<Action> | WebSocketClientError | Schema.SchemaError>;
45
- reactiveQuery: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Stream.Stream<Ref.Returns<Query>, Ref.Error<Query> | WebSocketClientError | Schema.SchemaError>;
47
+ reactiveQuery: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Stream.Stream<Ref.Returns<Query>, Schema.SchemaError | WebSocketClientError | Ref.Error<Query>>;
48
+ reactiveQueryResult: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Stream.Stream<Result.Result<Ref.Returns<Query>, Schema.SchemaError | WebSocketClientError | Ref.Error<Query>>>;
46
49
  }, never, never>;
47
50
  export {};
48
51
  //# sourceMappingURL=WebSocketClient.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WebSocketClient.d.ts","sourceRoot":"","sources":["../src/WebSocketClient.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"WebSocketClient.d.ts","sourceRoot":"","sources":["../src/WebSocketClient.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,11 @@
1
1
  import { __exportAll } from "./_virtual/_rolldown/runtime.js";
2
2
  import * as Ref from "@confect/core/Ref";
3
3
  import { ConvexClient } from "convex/browser";
4
- import * as Cause from "effect/Cause";
5
4
  import * as Context from "effect/Context";
6
5
  import * as Effect from "effect/Effect";
7
6
  import * as Layer from "effect/Layer";
8
7
  import * as Queue from "effect/Queue";
8
+ import * as Result from "effect/Result";
9
9
  import * as Schema from "effect/Schema";
10
10
  import * as Stream from "effect/Stream";
11
11
  //#region src/WebSocketClient.ts
@@ -14,7 +14,7 @@ var WebSocketClient_exports = /* @__PURE__ */ __exportAll({
14
14
  WebSocketClientError: () => WebSocketClientError,
15
15
  layer: () => layer
16
16
  });
17
- var WebSocketClientError = class extends Schema.TaggedError()("WebSocketClientError", { cause: Schema.Unknown }) {};
17
+ var WebSocketClientError = class extends Schema.TaggedError()("WebSocketClientError", { cause: Schema.Defect() }) {};
18
18
  const make = (address, options) => Effect.acquireRelease(Effect.sync(() => new ConvexClient(address, options)), (convexClient) => Effect.promise(() => convexClient.close())).pipe(Effect.map((convexClient) => {
19
19
  const url = address;
20
20
  const setAuth = (fetchToken, onChange) => Effect.sync(() => {
@@ -33,29 +33,40 @@ const make = (address, options) => Effect.acquireRelease(Effect.sync(() => new C
33
33
  const args = rest[0] ?? {};
34
34
  return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) => convexClient.action(functionReference, encodedArgs), mapUnknownError);
35
35
  };
36
- const reactiveQuery = (ref, ...rest) => {
36
+ const reactiveQueryResult = (ref, ...rest) => {
37
37
  const args = rest[0] ?? {};
38
38
  const functionReference = Ref.getFunctionReference(ref);
39
39
  const onError = Ref.decodeErrorOrElse(ref, mapUnknownError);
40
- return Stream.unwrap(Effect.gen(function* () {
41
- const encodedArgs = yield* Ref.encodeArgs(ref, args);
42
- return Stream.callback((queue) => Effect.gen(function* () {
40
+ return Stream.unwrap(Effect.match(Ref.encodeArgs(ref, args), {
41
+ onFailure: (error) => Stream.succeed(Result.fail(error)),
42
+ onSuccess: (encodedArgs) => Stream.callback((queue) => Effect.gen(function* () {
43
43
  const unsubscribe = convexClient.onUpdate(functionReference, encodedArgs, (result) => {
44
- Queue.offerUnsafe(queue, result);
44
+ Queue.offerUnsafe(queue, Result.succeed(result));
45
45
  }, (error) => {
46
- Queue.failCauseUnsafe(queue, Cause.fail(onError(error)));
46
+ Queue.offerUnsafe(queue, Result.fail(onError(error)));
47
47
  });
48
48
  yield* Effect.addFinalizer(() => Effect.sync(() => unsubscribe()));
49
- }));
50
- })).pipe(Stream.mapEffect((encodedReturns) => Ref.decodeReturns(ref, encodedReturns)));
49
+ }))
50
+ })).pipe(Stream.mapEffect((result) => Result.match(result, {
51
+ onFailure: (error) => Effect.succeed(Result.fail(error)),
52
+ onSuccess: (encodedReturns) => Effect.match(Ref.decodeReturns(ref, encodedReturns), {
53
+ onFailure: Result.fail,
54
+ onSuccess: Result.succeed
55
+ })
56
+ })));
51
57
  };
58
+ const reactiveQuery = (ref, ...rest) => reactiveQueryResult(ref, ...rest).pipe(Stream.mapEffect(Result.match({
59
+ onFailure: Effect.fail,
60
+ onSuccess: Effect.succeed
61
+ })));
52
62
  return {
53
63
  url,
54
64
  setAuth,
55
65
  query,
56
66
  mutation,
57
67
  action,
58
- reactiveQuery
68
+ reactiveQuery,
69
+ reactiveQueryResult
59
70
  };
60
71
  }));
61
72
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"WebSocketClient.js","names":[],"sources":["../src/WebSocketClient.ts"],"sourcesContent":["import * as Ref from \"@confect/core/Ref\";\nimport { ConvexClient } from \"convex/browser\";\nimport * as Cause from \"effect/Cause\";\nimport * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Queue from \"effect/Queue\";\nimport * as Schema from \"effect/Schema\";\nimport * as Stream from \"effect/Stream\";\n\nexport class WebSocketClientError extends Schema.TaggedError<WebSocketClientError>()(\n \"WebSocketClientError\",\n {\n cause: Schema.Unknown,\n },\n) {}\n\nconst make = (\n address: string,\n options?: ConstructorParameters<typeof ConvexClient>[1],\n) =>\n Effect.acquireRelease(\n Effect.sync(() => new ConvexClient(address, options)),\n (convexClient) => Effect.promise(() => convexClient.close()),\n ).pipe(\n Effect.map((convexClient) => {\n const url = address;\n\n const setAuth = (\n fetchToken: (args: {\n forceRefreshToken: boolean;\n }) => Effect.Effect<string | null | undefined>,\n onChange?: (isAuthenticated: boolean) => Effect.Effect<void>,\n ) =>\n Effect.sync(() => {\n convexClient.setAuth(\n (args) => Effect.runPromise(fetchToken(args)),\n ...(onChange\n ? [\n (isAuthenticated: boolean) =>\n Effect.runFork(onChange(isAuthenticated)),\n ]\n : []),\n );\n });\n\n const mapUnknownError = (cause: unknown) =>\n new WebSocketClientError({ cause });\n\n const query = <Query extends Ref.AnyPublicQuery>(\n ref: Query,\n ...rest: Ref.OptionalArgs<Query>\n ): Effect.Effect<\n Ref.Returns<Query>,\n Ref.Error<Query> | WebSocketClientError | Schema.SchemaError\n > => {\n const args = (rest[0] ?? {}) as Ref.Args<Query>;\n return Ref.runWithCodec(\n ref,\n args,\n (functionReference, encodedArgs) =>\n convexClient.query(functionReference, encodedArgs),\n mapUnknownError,\n );\n };\n\n const mutation = <Mutation extends Ref.AnyPublicMutation>(\n ref: Mutation,\n ...rest: Ref.OptionalArgs<Mutation>\n ): Effect.Effect<\n Ref.Returns<Mutation>,\n Ref.Error<Mutation> | WebSocketClientError | Schema.SchemaError\n > => {\n const args = (rest[0] ?? {}) as Ref.Args<Mutation>;\n return Ref.runWithCodec(\n ref,\n args,\n (functionReference, encodedArgs) =>\n convexClient.mutation(functionReference, encodedArgs),\n mapUnknownError,\n );\n };\n\n const action = <Action extends Ref.AnyPublicAction>(\n ref: Action,\n ...rest: Ref.OptionalArgs<Action>\n ): Effect.Effect<\n Ref.Returns<Action>,\n Ref.Error<Action> | WebSocketClientError | Schema.SchemaError\n > => {\n const args = (rest[0] ?? {}) as Ref.Args<Action>;\n return Ref.runWithCodec(\n ref,\n args,\n (functionReference, encodedArgs) =>\n convexClient.action(functionReference, encodedArgs),\n mapUnknownError,\n );\n };\n\n const reactiveQuery = <Query extends Ref.AnyPublicQuery>(\n ref: Query,\n ...rest: Ref.OptionalArgs<Query>\n ): Stream.Stream<\n Ref.Returns<Query>,\n Ref.Error<Query> | WebSocketClientError | Schema.SchemaError\n > => {\n const args = (rest[0] ?? {}) as Ref.Args<Query>;\n const functionReference = Ref.getFunctionReference(ref);\n const onError = Ref.decodeErrorOrElse(ref, mapUnknownError);\n\n return Stream.unwrap(\n Effect.gen(function* () {\n const encodedArgs = yield* Ref.encodeArgs(ref, args);\n\n return Stream.callback<\n unknown,\n Ref.Error<Query> | WebSocketClientError\n >((queue) =>\n Effect.gen(function* () {\n const unsubscribe = convexClient.onUpdate(\n functionReference,\n encodedArgs,\n (result) => {\n Queue.offerUnsafe(queue, result);\n },\n (error) => {\n Queue.failCauseUnsafe(queue, Cause.fail(onError(error)));\n },\n );\n yield* Effect.addFinalizer(() =>\n Effect.sync(() => unsubscribe()),\n );\n }),\n );\n }),\n ).pipe(\n Stream.mapEffect((encodedReturns) =>\n Ref.decodeReturns(ref, encodedReturns),\n ),\n );\n };\n\n return {\n url,\n setAuth,\n query,\n mutation,\n action,\n reactiveQuery,\n };\n }),\n );\n\n/**\n * A Confect client which uses a WebSocket to communicate with your Convex backend and supports reactive query subscriptions. The WebSocket connection is managed by the layer's scope and closed automatically when the scope ends. Wraps [ConvexClient](https://docs.convex.dev/api/classes/browser.ConvexClient).\n */\nexport const WebSocketClient = Context.Service<\n Effect.Success<ReturnType<typeof make>>\n>(\"@confect/js/WebSocketClient\");\n\nexport type WebSocketClient = typeof WebSocketClient.Identifier;\n\nexport const layer = (\n address: string,\n options?: ConstructorParameters<typeof ConvexClient>[1],\n) => Layer.effect(WebSocketClient, make(address, options));\n"],"mappings":";;;;;;;;;;;;;;;;AAUA,IAAa,uBAAb,cAA0C,OAAO,YAAkC,CAAC,CAClF,wBACA,EACE,OAAO,OAAO,QAChB,CACF,CAAC,CAAC,CAAC;AAEH,MAAM,QACJ,SACA,YAEA,OAAO,eACL,OAAO,WAAW,IAAI,aAAa,SAAS,OAAO,CAAC,IACnD,iBAAiB,OAAO,cAAc,aAAa,MAAM,CAAC,CAC7D,CAAC,CAAC,KACA,OAAO,KAAK,iBAAiB;CAC3B,MAAM,MAAM;CAEZ,MAAM,WACJ,YAGA,aAEA,OAAO,WAAW;EAChB,aAAa,SACV,SAAS,OAAO,WAAW,WAAW,IAAI,CAAC,GAC5C,GAAI,WACA,EACG,oBACC,OAAO,QAAQ,SAAS,eAAe,CAAC,CAC5C,IACA,CAAC,CACP;CACF,CAAC;CAEH,MAAM,mBAAmB,UACvB,IAAI,qBAAqB,EAAE,MAAM,CAAC;CAEpC,MAAM,SACJ,KACA,GAAG,SAIA;EACH,MAAM,OAAQ,KAAK,MAAM,CAAC;EAC1B,OAAO,IAAI,aACT,KACA,OACC,mBAAmB,gBAClB,aAAa,MAAM,mBAAmB,WAAW,GACnD,eACF;CACF;CAEA,MAAM,YACJ,KACA,GAAG,SAIA;EACH,MAAM,OAAQ,KAAK,MAAM,CAAC;EAC1B,OAAO,IAAI,aACT,KACA,OACC,mBAAmB,gBAClB,aAAa,SAAS,mBAAmB,WAAW,GACtD,eACF;CACF;CAEA,MAAM,UACJ,KACA,GAAG,SAIA;EACH,MAAM,OAAQ,KAAK,MAAM,CAAC;EAC1B,OAAO,IAAI,aACT,KACA,OACC,mBAAmB,gBAClB,aAAa,OAAO,mBAAmB,WAAW,GACpD,eACF;CACF;CAEA,MAAM,iBACJ,KACA,GAAG,SAIA;EACH,MAAM,OAAQ,KAAK,MAAM,CAAC;EAC1B,MAAM,oBAAoB,IAAI,qBAAqB,GAAG;EACtD,MAAM,UAAU,IAAI,kBAAkB,KAAK,eAAe;EAE1D,OAAO,OAAO,OACZ,OAAO,IAAI,aAAa;GACtB,MAAM,cAAc,OAAO,IAAI,WAAW,KAAK,IAAI;GAEnD,OAAO,OAAO,UAGX,UACD,OAAO,IAAI,aAAa;IACtB,MAAM,cAAc,aAAa,SAC/B,mBACA,cACC,WAAW;KACV,MAAM,YAAY,OAAO,MAAM;IACjC,IACC,UAAU;KACT,MAAM,gBAAgB,OAAO,MAAM,KAAK,QAAQ,KAAK,CAAC,CAAC;IACzD,CACF;IACA,OAAO,OAAO,mBACZ,OAAO,WAAW,YAAY,CAAC,CACjC;GACF,CAAC,CACH;EACF,CAAC,CACH,CAAC,CAAC,KACA,OAAO,WAAW,mBAChB,IAAI,cAAc,KAAK,cAAc,CACvC,CACF;CACF;CAEA,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;CACF;AACF,CAAC,CACH;;;;AAKF,MAAa,kBAAkB,QAAQ,QAErC,6BAA6B;AAI/B,MAAa,SACX,SACA,YACG,MAAM,OAAO,iBAAiB,KAAK,SAAS,OAAO,CAAC"}
1
+ {"version":3,"file":"WebSocketClient.js","names":[],"sources":["../src/WebSocketClient.ts"],"sourcesContent":["import * as Ref from \"@confect/core/Ref\";\nimport { ConvexClient } from \"convex/browser\";\nimport * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Queue from \"effect/Queue\";\nimport * as Result from \"effect/Result\";\nimport * as Schema from \"effect/Schema\";\nimport * as Stream from \"effect/Stream\";\n\nexport class WebSocketClientError extends Schema.TaggedError<WebSocketClientError>()(\n \"WebSocketClientError\",\n {\n cause: Schema.Defect(),\n },\n) {}\n\nconst make = (\n address: string,\n options?: ConstructorParameters<typeof ConvexClient>[1],\n) =>\n Effect.acquireRelease(\n Effect.sync(() => new ConvexClient(address, options)),\n (convexClient) => Effect.promise(() => convexClient.close()),\n ).pipe(\n Effect.map((convexClient) => {\n const url = address;\n\n const setAuth = (\n fetchToken: (args: {\n forceRefreshToken: boolean;\n }) => Effect.Effect<string | null | undefined>,\n onChange?: (isAuthenticated: boolean) => Effect.Effect<void>,\n ) =>\n Effect.sync(() => {\n convexClient.setAuth(\n (args) => Effect.runPromise(fetchToken(args)),\n ...(onChange\n ? [\n (isAuthenticated: boolean) =>\n Effect.runFork(onChange(isAuthenticated)),\n ]\n : []),\n );\n });\n\n const mapUnknownError = (cause: unknown) =>\n new WebSocketClientError({ cause });\n\n const query = <Query extends Ref.AnyPublicQuery>(\n ref: Query,\n ...rest: Ref.OptionalArgs<Query>\n ): Effect.Effect<\n Ref.Returns<Query>,\n Ref.Error<Query> | WebSocketClientError | Schema.SchemaError\n > => {\n const args = (rest[0] ?? {}) as Ref.Args<Query>;\n return Ref.runWithCodec(\n ref,\n args,\n (functionReference, encodedArgs) =>\n convexClient.query(functionReference, encodedArgs),\n mapUnknownError,\n );\n };\n\n const mutation = <Mutation extends Ref.AnyPublicMutation>(\n ref: Mutation,\n ...rest: Ref.OptionalArgs<Mutation>\n ): Effect.Effect<\n Ref.Returns<Mutation>,\n Ref.Error<Mutation> | WebSocketClientError | Schema.SchemaError\n > => {\n const args = (rest[0] ?? {}) as Ref.Args<Mutation>;\n return Ref.runWithCodec(\n ref,\n args,\n (functionReference, encodedArgs) =>\n convexClient.mutation(functionReference, encodedArgs),\n mapUnknownError,\n );\n };\n\n const action = <Action extends Ref.AnyPublicAction>(\n ref: Action,\n ...rest: Ref.OptionalArgs<Action>\n ): Effect.Effect<\n Ref.Returns<Action>,\n Ref.Error<Action> | WebSocketClientError | Schema.SchemaError\n > => {\n const args = (rest[0] ?? {}) as Ref.Args<Action>;\n return Ref.runWithCodec(\n ref,\n args,\n (functionReference, encodedArgs) =>\n convexClient.action(functionReference, encodedArgs),\n mapUnknownError,\n );\n };\n\n type ReactiveQueryError<Query extends Ref.AnyPublicQuery> =\n | Ref.Error<Query>\n | WebSocketClientError\n | Schema.SchemaError;\n\n const reactiveQueryResult = <Query extends Ref.AnyPublicQuery>(\n ref: Query,\n ...rest: Ref.OptionalArgs<Query>\n ): Stream.Stream<\n Result.Result<Ref.Returns<Query>, ReactiveQueryError<Query>>\n > => {\n type QueryResult = Result.Result<\n Ref.Returns<Query>,\n ReactiveQueryError<Query>\n >;\n const args = (rest[0] ?? {}) as Ref.Args<Query>;\n const functionReference = Ref.getFunctionReference(ref);\n const onError = Ref.decodeErrorOrElse(ref, mapUnknownError);\n\n return Stream.unwrap(\n Effect.match(Ref.encodeArgs(ref, args), {\n onFailure: (error) =>\n Stream.succeed<QueryResult>(Result.fail(error)),\n onSuccess: (encodedArgs) =>\n Stream.callback<\n Result.Result<unknown, ReactiveQueryError<Query>>\n >((queue) =>\n Effect.gen(function* () {\n const unsubscribe = convexClient.onUpdate(\n functionReference,\n encodedArgs,\n (result) => {\n Queue.offerUnsafe(queue, Result.succeed(result));\n },\n (error) => {\n Queue.offerUnsafe(queue, Result.fail(onError(error)));\n },\n );\n yield* Effect.addFinalizer(() =>\n Effect.sync(() => unsubscribe()),\n );\n }),\n ),\n }),\n ).pipe(\n Stream.mapEffect((result): Effect.Effect<QueryResult> =>\n Result.match(result, {\n onFailure: (error) => Effect.succeed(Result.fail(error)),\n onSuccess: (encodedReturns) =>\n Effect.match(Ref.decodeReturns(ref, encodedReturns), {\n onFailure: Result.fail,\n onSuccess: Result.succeed,\n }),\n }),\n ),\n );\n };\n\n const reactiveQuery = <Query extends Ref.AnyPublicQuery>(\n ref: Query,\n ...rest: Ref.OptionalArgs<Query>\n ): Stream.Stream<Ref.Returns<Query>, ReactiveQueryError<Query>> =>\n reactiveQueryResult(ref, ...rest).pipe(\n Stream.mapEffect(\n Result.match({\n onFailure: Effect.fail,\n onSuccess: Effect.succeed,\n }),\n ),\n );\n\n return {\n url,\n setAuth,\n query,\n mutation,\n action,\n reactiveQuery,\n reactiveQueryResult,\n };\n }),\n );\n\n/**\n * A Confect client which uses a WebSocket to communicate with your Convex backend and supports reactive query subscriptions. The WebSocket connection is managed by the layer's scope and closed automatically when the scope ends. Wraps [ConvexClient](https://docs.convex.dev/api/classes/browser.ConvexClient).\n */\nexport const WebSocketClient = Context.Service<\n Effect.Success<ReturnType<typeof make>>\n>(\"@confect/js/WebSocketClient\");\n\nexport type WebSocketClient = typeof WebSocketClient.Identifier;\n\nexport const layer = (\n address: string,\n options?: ConstructorParameters<typeof ConvexClient>[1],\n) => Layer.effect(WebSocketClient, make(address, options));\n"],"mappings":";;;;;;;;;;;;;;;;AAUA,IAAa,uBAAb,cAA0C,OAAO,YAAkC,CAAC,CAClF,wBACA,EACE,OAAO,OAAO,OAAO,EACvB,CACF,CAAC,CAAC,CAAC;AAEH,MAAM,QACJ,SACA,YAEA,OAAO,eACL,OAAO,WAAW,IAAI,aAAa,SAAS,OAAO,CAAC,IACnD,iBAAiB,OAAO,cAAc,aAAa,MAAM,CAAC,CAC7D,CAAC,CAAC,KACA,OAAO,KAAK,iBAAiB;CAC3B,MAAM,MAAM;CAEZ,MAAM,WACJ,YAGA,aAEA,OAAO,WAAW;EAChB,aAAa,SACV,SAAS,OAAO,WAAW,WAAW,IAAI,CAAC,GAC5C,GAAI,WACA,EACG,oBACC,OAAO,QAAQ,SAAS,eAAe,CAAC,CAC5C,IACA,CAAC,CACP;CACF,CAAC;CAEH,MAAM,mBAAmB,UACvB,IAAI,qBAAqB,EAAE,MAAM,CAAC;CAEpC,MAAM,SACJ,KACA,GAAG,SAIA;EACH,MAAM,OAAQ,KAAK,MAAM,CAAC;EAC1B,OAAO,IAAI,aACT,KACA,OACC,mBAAmB,gBAClB,aAAa,MAAM,mBAAmB,WAAW,GACnD,eACF;CACF;CAEA,MAAM,YACJ,KACA,GAAG,SAIA;EACH,MAAM,OAAQ,KAAK,MAAM,CAAC;EAC1B,OAAO,IAAI,aACT,KACA,OACC,mBAAmB,gBAClB,aAAa,SAAS,mBAAmB,WAAW,GACtD,eACF;CACF;CAEA,MAAM,UACJ,KACA,GAAG,SAIA;EACH,MAAM,OAAQ,KAAK,MAAM,CAAC;EAC1B,OAAO,IAAI,aACT,KACA,OACC,mBAAmB,gBAClB,aAAa,OAAO,mBAAmB,WAAW,GACpD,eACF;CACF;CAOA,MAAM,uBACJ,KACA,GAAG,SAGA;EAKH,MAAM,OAAQ,KAAK,MAAM,CAAC;EAC1B,MAAM,oBAAoB,IAAI,qBAAqB,GAAG;EACtD,MAAM,UAAU,IAAI,kBAAkB,KAAK,eAAe;EAE1D,OAAO,OAAO,OACZ,OAAO,MAAM,IAAI,WAAW,KAAK,IAAI,GAAG;GACtC,YAAY,UACV,OAAO,QAAqB,OAAO,KAAK,KAAK,CAAC;GAChD,YAAY,gBACV,OAAO,UAEJ,UACD,OAAO,IAAI,aAAa;IACtB,MAAM,cAAc,aAAa,SAC/B,mBACA,cACC,WAAW;KACV,MAAM,YAAY,OAAO,OAAO,QAAQ,MAAM,CAAC;IACjD,IACC,UAAU;KACT,MAAM,YAAY,OAAO,OAAO,KAAK,QAAQ,KAAK,CAAC,CAAC;IACtD,CACF;IACA,OAAO,OAAO,mBACZ,OAAO,WAAW,YAAY,CAAC,CACjC;GACF,CAAC,CACH;EACJ,CAAC,CACH,CAAC,CAAC,KACA,OAAO,WAAW,WAChB,OAAO,MAAM,QAAQ;GACnB,YAAY,UAAU,OAAO,QAAQ,OAAO,KAAK,KAAK,CAAC;GACvD,YAAY,mBACV,OAAO,MAAM,IAAI,cAAc,KAAK,cAAc,GAAG;IACnD,WAAW,OAAO;IAClB,WAAW,OAAO;GACpB,CAAC;EACL,CAAC,CACH,CACF;CACF;CAEA,MAAM,iBACJ,KACA,GAAG,SAEH,oBAAoB,KAAK,GAAG,IAAI,CAAC,CAAC,KAChC,OAAO,UACL,OAAO,MAAM;EACX,WAAW,OAAO;EAClB,WAAW,OAAO;CACpB,CAAC,CACH,CACF;CAEF,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF,CAAC,CACH;;;;AAKF,MAAa,kBAAkB,QAAQ,QAErC,6BAA6B;AAI/B,MAAa,SACX,SACA,YACG,MAAM,OAAO,iBAAiB,KAAK,SAAS,OAAO,CAAC"}
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@confect/js",
3
3
  "description": "JavaScript client bindings for any JS runtime",
4
- "version": "10.0.0-next.17",
4
+ "version": "10.0.0-next.19",
5
5
  "author": "RJ Dellecese",
6
6
  "bugs": {
7
7
  "url": "https://github.com/rjdellecese/confect/issues"
8
8
  },
9
9
  "devDependencies": {
10
- "@effect/vitest": "4.0.0-rc.111",
10
+ "@effect/vitest": "4.0.0-rc.112",
11
11
  "@types/node": "22.20.1",
12
- "effect": "4.0.0-rc.111",
12
+ "effect": "4.0.0-rc.112",
13
13
  "tsdown": "0.22.14",
14
14
  "typescript": "7.0.2",
15
15
  "unrun": "0.3.1",
@@ -23,6 +23,10 @@
23
23
  "types": "./dist/index.d.ts",
24
24
  "default": "./dist/index.js"
25
25
  },
26
+ "./*": {
27
+ "types": "./dist/*.d.ts",
28
+ "default": "./dist/*.js"
29
+ },
26
30
  "./package.json": "./package.json"
27
31
  },
28
32
  "files": [
@@ -44,8 +48,8 @@
44
48
  "module": "./dist/index.js",
45
49
  "peerDependencies": {
46
50
  "convex": "^1.32.0",
47
- "effect": "^4.0.0-rc.111",
48
- "@confect/core": "^10.0.0-next.17"
51
+ "effect": "^4.0.0-rc.112",
52
+ "@confect/core": "^10.0.0-next.19"
49
53
  },
50
54
  "repository": {
51
55
  "type": "git",
@@ -1,17 +1,17 @@
1
1
  import * as Ref from "@confect/core/Ref";
2
2
  import { ConvexClient } from "convex/browser";
3
- import * as Cause from "effect/Cause";
4
3
  import * as Context from "effect/Context";
5
4
  import * as Effect from "effect/Effect";
6
5
  import * as Layer from "effect/Layer";
7
6
  import * as Queue from "effect/Queue";
7
+ import * as Result from "effect/Result";
8
8
  import * as Schema from "effect/Schema";
9
9
  import * as Stream from "effect/Stream";
10
10
 
11
11
  export class WebSocketClientError extends Schema.TaggedError<WebSocketClientError>()(
12
12
  "WebSocketClientError",
13
13
  {
14
- cause: Schema.Unknown,
14
+ cause: Schema.Defect(),
15
15
  },
16
16
  ) {}
17
17
 
@@ -98,49 +98,77 @@ const make = (
98
98
  );
99
99
  };
100
100
 
101
- const reactiveQuery = <Query extends Ref.AnyPublicQuery>(
101
+ type ReactiveQueryError<Query extends Ref.AnyPublicQuery> =
102
+ | Ref.Error<Query>
103
+ | WebSocketClientError
104
+ | Schema.SchemaError;
105
+
106
+ const reactiveQueryResult = <Query extends Ref.AnyPublicQuery>(
102
107
  ref: Query,
103
108
  ...rest: Ref.OptionalArgs<Query>
104
109
  ): Stream.Stream<
105
- Ref.Returns<Query>,
106
- Ref.Error<Query> | WebSocketClientError | Schema.SchemaError
110
+ Result.Result<Ref.Returns<Query>, ReactiveQueryError<Query>>
107
111
  > => {
112
+ type QueryResult = Result.Result<
113
+ Ref.Returns<Query>,
114
+ ReactiveQueryError<Query>
115
+ >;
108
116
  const args = (rest[0] ?? {}) as Ref.Args<Query>;
109
117
  const functionReference = Ref.getFunctionReference(ref);
110
118
  const onError = Ref.decodeErrorOrElse(ref, mapUnknownError);
111
119
 
112
120
  return Stream.unwrap(
113
- Effect.gen(function* () {
114
- const encodedArgs = yield* Ref.encodeArgs(ref, args);
115
-
116
- return Stream.callback<
117
- unknown,
118
- Ref.Error<Query> | WebSocketClientError
119
- >((queue) =>
120
- Effect.gen(function* () {
121
- const unsubscribe = convexClient.onUpdate(
122
- functionReference,
123
- encodedArgs,
124
- (result) => {
125
- Queue.offerUnsafe(queue, result);
126
- },
127
- (error) => {
128
- Queue.failCauseUnsafe(queue, Cause.fail(onError(error)));
129
- },
130
- );
131
- yield* Effect.addFinalizer(() =>
132
- Effect.sync(() => unsubscribe()),
133
- );
134
- }),
135
- );
121
+ Effect.match(Ref.encodeArgs(ref, args), {
122
+ onFailure: (error) =>
123
+ Stream.succeed<QueryResult>(Result.fail(error)),
124
+ onSuccess: (encodedArgs) =>
125
+ Stream.callback<
126
+ Result.Result<unknown, ReactiveQueryError<Query>>
127
+ >((queue) =>
128
+ Effect.gen(function* () {
129
+ const unsubscribe = convexClient.onUpdate(
130
+ functionReference,
131
+ encodedArgs,
132
+ (result) => {
133
+ Queue.offerUnsafe(queue, Result.succeed(result));
134
+ },
135
+ (error) => {
136
+ Queue.offerUnsafe(queue, Result.fail(onError(error)));
137
+ },
138
+ );
139
+ yield* Effect.addFinalizer(() =>
140
+ Effect.sync(() => unsubscribe()),
141
+ );
142
+ }),
143
+ ),
136
144
  }),
137
145
  ).pipe(
138
- Stream.mapEffect((encodedReturns) =>
139
- Ref.decodeReturns(ref, encodedReturns),
146
+ Stream.mapEffect((result): Effect.Effect<QueryResult> =>
147
+ Result.match(result, {
148
+ onFailure: (error) => Effect.succeed(Result.fail(error)),
149
+ onSuccess: (encodedReturns) =>
150
+ Effect.match(Ref.decodeReturns(ref, encodedReturns), {
151
+ onFailure: Result.fail,
152
+ onSuccess: Result.succeed,
153
+ }),
154
+ }),
140
155
  ),
141
156
  );
142
157
  };
143
158
 
159
+ const reactiveQuery = <Query extends Ref.AnyPublicQuery>(
160
+ ref: Query,
161
+ ...rest: Ref.OptionalArgs<Query>
162
+ ): Stream.Stream<Ref.Returns<Query>, ReactiveQueryError<Query>> =>
163
+ reactiveQueryResult(ref, ...rest).pipe(
164
+ Stream.mapEffect(
165
+ Result.match({
166
+ onFailure: Effect.fail,
167
+ onSuccess: Effect.succeed,
168
+ }),
169
+ ),
170
+ );
171
+
144
172
  return {
145
173
  url,
146
174
  setAuth,
@@ -148,6 +176,7 @@ const make = (
148
176
  mutation,
149
177
  action,
150
178
  reactiveQuery,
179
+ reactiveQueryResult,
151
180
  };
152
181
  }),
153
182
  );