@confect/js 4.0.0 → 6.0.0
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 +22 -0
- package/dist/HttpClient.d.ts +9 -10
- package/dist/HttpClient.d.ts.map +1 -1
- package/dist/HttpClient.js +16 -43
- package/dist/HttpClient.js.map +1 -1
- package/dist/WebSocketClient.d.ts +50 -0
- package/dist/WebSocketClient.d.ts.map +1 -0
- package/dist/WebSocketClient.js +71 -0
- package/dist/WebSocketClient.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/package.json +2 -2
- package/src/HttpClient.ts +34 -113
- package/src/WebSocketClient.ts +152 -0
- package/src/index.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @confect/js
|
|
2
2
|
|
|
3
|
+
## 6.0.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- df95ce7: Add `Ref.OptionalArgs` type utility to `@confect/core` for conditionally optional function args. `QueryRunner`, `MutationRunner`, and `ActionRunner` now accept optional args for no-arg Confect functions. `useQuery`, `useMutation`, and `useAction` now accept optional args for no-arg Confect functions. `TestConfect` `query`/`mutation`/`action` helpers now accept optional args for no-arg Confect functions.
|
|
8
|
+
- Updated dependencies [df95ce7]
|
|
9
|
+
- Updated dependencies [a8083e8]
|
|
10
|
+
- @confect/core@6.0.0
|
|
11
|
+
|
|
12
|
+
## 5.0.0
|
|
13
|
+
|
|
14
|
+
### Minor Changes
|
|
15
|
+
|
|
16
|
+
- fb17b7e: Add `WebSocketClient`, a WebSocket-based client wrapping Convex's `ConvexClient`. Provides the same `query`, `mutation`, and `action` methods as `HttpClient`, plus `reactiveQuery` which returns a `Stream` of live query results.
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- 2c4b0c9: Fix `HttpClient` to only accept public `Ref`s
|
|
21
|
+
|
|
22
|
+
`HttpClient` query, mutation, and action methods now correctly reject internal `Ref`s at the type level, matching the runtime behavior of Convex browser clients which can only call public functions.
|
|
23
|
+
- @confect/core@5.0.0
|
|
24
|
+
|
|
3
25
|
## 4.0.0
|
|
4
26
|
|
|
5
27
|
### Minor Changes
|
package/dist/HttpClient.d.ts
CHANGED
|
@@ -12,7 +12,6 @@ declare const HttpClientError_base: Schema.TaggedErrorClass<HttpClientError, "Ht
|
|
|
12
12
|
cause: typeof Schema.Unknown;
|
|
13
13
|
}>;
|
|
14
14
|
declare class HttpClientError extends HttpClientError_base {}
|
|
15
|
-
type OptionalArgs<R extends Ref.AnyQuery | Ref.AnyMutation | Ref.AnyAction> = keyof Ref.Args<R> extends never ? [args?: Ref.Args<R>] : [args: Ref.Args<R>];
|
|
16
15
|
/**
|
|
17
16
|
* A Confect client which uses HTTP to communicate with your Convex backend. Works in any JS runtime that supports `fetch`. Wraps [ConvexHttpClient](https://docs.convex.dev/api/classes/browser.ConvexHttpClient).
|
|
18
17
|
*/
|
|
@@ -20,25 +19,25 @@ declare const HttpClient: Context.Tag<{
|
|
|
20
19
|
url: string;
|
|
21
20
|
setAuth: (token: string) => Effect.Effect<void, never, never>;
|
|
22
21
|
clearAuth: Effect.Effect<void, never, never>;
|
|
23
|
-
query: <Query extends Ref.
|
|
24
|
-
mutation: <Mutation extends Ref.
|
|
25
|
-
action: <Action extends Ref.
|
|
22
|
+
query: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Effect.Effect<Ref.Returns<Query>, HttpClientError | ParseResult.ParseError>;
|
|
23
|
+
mutation: <Mutation extends Ref.AnyPublicMutation>(ref: Mutation, ...rest: Ref.OptionalArgs<Mutation>) => Effect.Effect<Ref.Returns<Mutation>, HttpClientError | ParseResult.ParseError>;
|
|
24
|
+
action: <Action extends Ref.AnyPublicAction>(ref: Action, ...rest: Ref.OptionalArgs<Action>) => Effect.Effect<Ref.Returns<Action>, HttpClientError | ParseResult.ParseError>;
|
|
26
25
|
}, {
|
|
27
26
|
url: string;
|
|
28
27
|
setAuth: (token: string) => Effect.Effect<void, never, never>;
|
|
29
28
|
clearAuth: Effect.Effect<void, never, never>;
|
|
30
|
-
query: <Query extends Ref.
|
|
31
|
-
mutation: <Mutation extends Ref.
|
|
32
|
-
action: <Action extends Ref.
|
|
29
|
+
query: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Effect.Effect<Ref.Returns<Query>, HttpClientError | ParseResult.ParseError>;
|
|
30
|
+
mutation: <Mutation extends Ref.AnyPublicMutation>(ref: Mutation, ...rest: Ref.OptionalArgs<Mutation>) => Effect.Effect<Ref.Returns<Mutation>, HttpClientError | ParseResult.ParseError>;
|
|
31
|
+
action: <Action extends Ref.AnyPublicAction>(ref: Action, ...rest: Ref.OptionalArgs<Action>) => Effect.Effect<Ref.Returns<Action>, HttpClientError | ParseResult.ParseError>;
|
|
33
32
|
}>;
|
|
34
33
|
type HttpClient = typeof HttpClient.Identifier;
|
|
35
34
|
declare const layer: (address: string, options?: ConstructorParameters<typeof ConvexHttpClient>[1]) => Layer.Layer<{
|
|
36
35
|
url: string;
|
|
37
36
|
setAuth: (token: string) => Effect.Effect<void, never, never>;
|
|
38
37
|
clearAuth: Effect.Effect<void, never, never>;
|
|
39
|
-
query: <Query extends Ref.
|
|
40
|
-
mutation: <Mutation extends Ref.
|
|
41
|
-
action: <Action extends Ref.
|
|
38
|
+
query: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Effect.Effect<Ref.Returns<Query>, HttpClientError | ParseResult.ParseError>;
|
|
39
|
+
mutation: <Mutation extends Ref.AnyPublicMutation>(ref: Mutation, ...rest: Ref.OptionalArgs<Mutation>) => Effect.Effect<Ref.Returns<Mutation>, HttpClientError | ParseResult.ParseError>;
|
|
40
|
+
action: <Action extends Ref.AnyPublicAction>(ref: Action, ...rest: Ref.OptionalArgs<Action>) => Effect.Effect<Ref.Returns<Action>, HttpClientError | ParseResult.ParseError>;
|
|
42
41
|
}, never, never>;
|
|
43
42
|
//#endregion
|
|
44
43
|
export { HttpClient_d_exports };
|
package/dist/HttpClient.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HttpClient.d.ts","names":[],"sources":["../src/HttpClient.ts"],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"HttpClient.d.ts","names":[],"sources":["../src/HttpClient.ts"],"mappings":";;;;;;;;cAGwD,oBAAA;;;;;cAE3C,eAAA,SAAwB,oBAAA;AAFmB;;;AAAA,cAuF3C,UAAA,EAAU,OAAA,CAAA,GAAA;;8BAtES,MAAA,CAAA,MAAA;;wBASD,GAAA,CAAI,cAAA,EAAc,GAAA,EACxC,KAAA,KAAK,IAAA,EACD,GAAA,CAAI,YAAA,CAAa,KAAA,MACzB,MAAA,CAAO,MAAA,CACR,GAAA,CAAI,OAAA,CAAQ,KAAA,GACZ,eAAA,GAAkB,WAAA,CAAY,UAAA;8BAWG,GAAA,CAAI,iBAAA,EAAiB,GAAA,EACjD,QAAA,KAAQ,IAAA,EACJ,GAAA,CAAI,YAAA,CAAa,QAAA,MACzB,MAAA,CAAO,MAAA,CACR,GAAA,CAAI,OAAA,CAAQ,QAAA,GACZ,eAAA,GAAkB,WAAA,CAAY,UAAA;0BAWD,GAAA,CAAI,eAAA,EAAe,GAAA,EAC3C,MAAA,KAAM,IAAA,EACF,GAAA,CAAI,YAAA,CAAa,MAAA,MACzB,MAAA,CAAO,MAAA,CACR,GAAA,CAAI,OAAA,CAAQ,MAAA,GACZ,eAAA,GAAkB,WAAA,CAAY,UAAA;AAAA;;8BA9CF,MAAA,CAAA,MAAA;;wBASD,GAAA,CAAI,cAAA,EAAc,GAAA,EACxC,KAAA,KAAK,IAAA,EACD,GAAA,CAAI,YAAA,CAAa,KAAA,MACzB,MAAA,CAAO,MAAA,CACR,GAAA,CAAI,OAAA,CAAQ,KAAA,GACZ,eAAA,GAAkB,WAAA,CAAY,UAAA;8BAWG,GAAA,CAAI,iBAAA,EAAiB,GAAA,EACjD,QAAA,KAAQ,IAAA,EACJ,GAAA,CAAI,YAAA,CAAa,QAAA,MACzB,MAAA,CAAO,MAAA,CACR,GAAA,CAAI,OAAA,CAAQ,QAAA,GACZ,eAAA,GAAkB,WAAA,CAAY,UAAA;0BAWD,GAAA,CAAI,eAAA,EAAe,GAAA,EAC3C,MAAA,KAAM,IAAA,EACF,GAAA,CAAI,YAAA,CAAa,MAAA,MACzB,MAAA,CAAO,MAAA,CACR,GAAA,CAAI,OAAA,CAAQ,MAAA,GACZ,eAAA,GAAkB,WAAA,CAAY,UAAA;AAAA;AAAA,KA4BtB,UAAA,UAAoB,UAAA,CAAW,UAAA;AAAA,cAE9B,KAAA,GACX,OAAA,UACA,OAAA,GAAU,qBAAA,QAA6B,gBAAA,SAAoB,KAAA,CAAA,KAAA;;8BA9E7B,MAAA,CAAA,MAAA;;wBASD,GAAA,CAAI,cAAA,EAAc,GAAA,EACxC,KAAA,KAAK,IAAA,EACD,GAAA,CAAI,YAAA,CAAa,KAAA,MACzB,MAAA,CAAO,MAAA,CACR,GAAA,CAAI,OAAA,CAAQ,KAAA,GACZ,eAAA,GAAkB,WAAA,CAAY,UAAA;8BAWG,GAAA,CAAI,iBAAA,EAAiB,GAAA,EACjD,QAAA,KAAQ,IAAA,EACJ,GAAA,CAAI,YAAA,CAAa,QAAA,MACzB,MAAA,CAAO,MAAA,CACR,GAAA,CAAI,OAAA,CAAQ,QAAA,GACZ,eAAA,GAAkB,WAAA,CAAY,UAAA;0BAWD,GAAA,CAAI,eAAA,EAAe,GAAA,EAC3C,MAAA,KAAM,IAAA,EACF,GAAA,CAAI,YAAA,CAAa,MAAA,MACzB,MAAA,CAAO,MAAA,CACR,GAAA,CAAI,OAAA,CAAQ,MAAA,GACZ,eAAA,GAAkB,WAAA,CAAY,UAAA;AAAA"}
|
package/dist/HttpClient.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __exportAll } from "./_virtual/_rolldown/runtime.js";
|
|
2
2
|
import * as Ref from "@confect/core/Ref";
|
|
3
3
|
import { ConvexHttpClient } from "convex/browser";
|
|
4
|
-
import { Context, Effect, Layer,
|
|
4
|
+
import { Context, Effect, Layer, Schema } from "effect";
|
|
5
5
|
|
|
6
6
|
//#region src/HttpClient.ts
|
|
7
7
|
var HttpClient_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -19,54 +19,27 @@ const make = (address, options) => {
|
|
|
19
19
|
const clearAuth = Effect.sync(() => {
|
|
20
20
|
client.clearAuth();
|
|
21
21
|
});
|
|
22
|
-
const query = (ref, ...rest) =>
|
|
22
|
+
const query = (ref, ...rest) => {
|
|
23
23
|
const args = rest[0] ?? {};
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return yield* Match.value(functionSpec.functionProvenance).pipe(Match.tag("Confect", (confectFunctionSpec) => Effect.gen(function* () {
|
|
27
|
-
const encodedArgs = yield* Schema.encode(confectFunctionSpec.args)(args);
|
|
28
|
-
const encodedResult = yield* Effect.tryPromise({
|
|
29
|
-
try: () => client.query(functionName, encodedArgs),
|
|
30
|
-
catch: (cause) => new HttpClientError({ cause })
|
|
31
|
-
});
|
|
32
|
-
return yield* Schema.decode(confectFunctionSpec.returns)(encodedResult);
|
|
33
|
-
})), Match.tag("Convex", () => Effect.tryPromise({
|
|
34
|
-
try: () => client.query(functionName, args),
|
|
24
|
+
return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) => Effect.tryPromise({
|
|
25
|
+
try: () => client.query(functionReference, encodedArgs),
|
|
35
26
|
catch: (cause) => new HttpClientError({ cause })
|
|
36
|
-
}))
|
|
37
|
-
}
|
|
38
|
-
const mutation = (ref, ...rest) =>
|
|
27
|
+
}));
|
|
28
|
+
};
|
|
29
|
+
const mutation = (ref, ...rest) => {
|
|
39
30
|
const args = rest[0] ?? {};
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return yield* Match.value(functionSpec.functionProvenance).pipe(Match.tag("Confect", (confectFunctionSpec) => Effect.gen(function* () {
|
|
43
|
-
const encodedArgs = yield* Schema.encode(confectFunctionSpec.args)(args);
|
|
44
|
-
const encodedResult = yield* Effect.tryPromise({
|
|
45
|
-
try: () => client.mutation(functionName, encodedArgs),
|
|
46
|
-
catch: (cause) => new HttpClientError({ cause })
|
|
47
|
-
});
|
|
48
|
-
return yield* Schema.decode(confectFunctionSpec.returns)(encodedResult);
|
|
49
|
-
})), Match.tag("Convex", () => Effect.tryPromise({
|
|
50
|
-
try: () => client.mutation(functionName, args),
|
|
31
|
+
return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) => Effect.tryPromise({
|
|
32
|
+
try: () => client.mutation(functionReference, encodedArgs),
|
|
51
33
|
catch: (cause) => new HttpClientError({ cause })
|
|
52
|
-
}))
|
|
53
|
-
}
|
|
54
|
-
const action = (ref, ...rest) =>
|
|
34
|
+
}));
|
|
35
|
+
};
|
|
36
|
+
const action = (ref, ...rest) => {
|
|
55
37
|
const args = rest[0] ?? {};
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return yield* Match.value(functionSpec.functionProvenance).pipe(Match.tag("Confect", (confectFunctionSpec) => Effect.gen(function* () {
|
|
59
|
-
const encodedArgs = yield* Schema.encode(confectFunctionSpec.args)(args);
|
|
60
|
-
const encodedResult = yield* Effect.tryPromise({
|
|
61
|
-
try: () => client.action(functionName, encodedArgs),
|
|
62
|
-
catch: (cause) => new HttpClientError({ cause })
|
|
63
|
-
});
|
|
64
|
-
return yield* Schema.decode(confectFunctionSpec.returns)(encodedResult);
|
|
65
|
-
})), Match.tag("Convex", () => Effect.tryPromise({
|
|
66
|
-
try: () => client.action(functionName, args),
|
|
38
|
+
return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) => Effect.tryPromise({
|
|
39
|
+
try: () => client.action(functionReference, encodedArgs),
|
|
67
40
|
catch: (cause) => new HttpClientError({ cause })
|
|
68
|
-
}))
|
|
69
|
-
}
|
|
41
|
+
}));
|
|
42
|
+
};
|
|
70
43
|
return {
|
|
71
44
|
url,
|
|
72
45
|
setAuth,
|
package/dist/HttpClient.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HttpClient.js","names":[],"sources":["../src/HttpClient.ts"],"sourcesContent":["import * as Ref from \"@confect/core/Ref\";\nimport { ConvexHttpClient } from \"convex/browser\";\nimport type {
|
|
1
|
+
{"version":3,"file":"HttpClient.js","names":[],"sources":["../src/HttpClient.ts"],"sourcesContent":["import * as Ref from \"@confect/core/Ref\";\nimport { ConvexHttpClient } from \"convex/browser\";\nimport type { ParseResult } from \"effect\";\nimport { Context, Effect, Layer, Schema } from \"effect\";\n\nexport class HttpClientError extends Schema.TaggedError<HttpClientError>()(\n \"HttpClientError\",\n {\n cause: Schema.Unknown,\n },\n) {}\n\nconst make = (\n address: string,\n options?: ConstructorParameters<typeof ConvexHttpClient>[1],\n) => {\n const client = new ConvexHttpClient(address, options);\n\n const url = client.url;\n\n const setAuth = (token: string) =>\n Effect.sync(() => {\n client.setAuth(token);\n });\n\n const clearAuth = Effect.sync(() => {\n client.clearAuth();\n });\n\n const query = <Query extends Ref.AnyPublicQuery>(\n ref: Query,\n ...rest: Ref.OptionalArgs<Query>\n ): Effect.Effect<\n Ref.Returns<Query>,\n HttpClientError | ParseResult.ParseError\n > => {\n const args = (rest[0] ?? {}) as Ref.Args<Query>;\n return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) =>\n Effect.tryPromise({\n try: () => client.query(functionReference, encodedArgs),\n catch: (cause) => new HttpClientError({ cause }),\n }),\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 HttpClientError | ParseResult.ParseError\n > => {\n const args = (rest[0] ?? {}) as Ref.Args<Mutation>;\n return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) =>\n Effect.tryPromise({\n try: () => client.mutation(functionReference, encodedArgs),\n catch: (cause) => new HttpClientError({ cause }),\n }),\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 HttpClientError | ParseResult.ParseError\n > => {\n const args = (rest[0] ?? {}) as Ref.Args<Action>;\n return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) =>\n Effect.tryPromise({\n try: () => client.action(functionReference, encodedArgs),\n catch: (cause) => new HttpClientError({ cause }),\n }),\n );\n };\n\n return {\n url,\n setAuth,\n clearAuth,\n query,\n mutation,\n action,\n };\n};\n\n/**\n * A Confect client which uses HTTP to communicate with your Convex backend. Works in any JS runtime that supports `fetch`. Wraps [ConvexHttpClient](https://docs.convex.dev/api/classes/browser.ConvexHttpClient).\n */\nexport const HttpClient = Context.GenericTag<ReturnType<typeof make>>(\n \"@confect/js/HttpClient\",\n);\n\nexport type HttpClient = typeof HttpClient.Identifier;\n\nexport const layer = (\n address: string,\n options?: ConstructorParameters<typeof ConvexHttpClient>[1],\n) => Layer.sync(HttpClient, () => make(address, options));\n"],"mappings":";;;;;;;;;;;AAKA,IAAa,kBAAb,cAAqC,OAAO,aAA8B,CACxE,mBACA,EACE,OAAO,OAAO,SACf,CACF,CAAC;AAEF,MAAM,QACJ,SACA,YACG;CACH,MAAM,SAAS,IAAI,iBAAiB,SAAS,QAAQ;CAErD,MAAM,MAAM,OAAO;CAEnB,MAAM,WAAW,UACf,OAAO,WAAW;AAChB,SAAO,QAAQ,MAAM;GACrB;CAEJ,MAAM,YAAY,OAAO,WAAW;AAClC,SAAO,WAAW;GAClB;CAEF,MAAM,SACJ,KACA,GAAG,SAIA;EACH,MAAM,OAAQ,KAAK,MAAM,EAAE;AAC3B,SAAO,IAAI,aAAa,KAAK,OAAO,mBAAmB,gBACrD,OAAO,WAAW;GAChB,WAAW,OAAO,MAAM,mBAAmB,YAAY;GACvD,QAAQ,UAAU,IAAI,gBAAgB,EAAE,OAAO,CAAC;GACjD,CAAC,CACH;;CAGH,MAAM,YACJ,KACA,GAAG,SAIA;EACH,MAAM,OAAQ,KAAK,MAAM,EAAE;AAC3B,SAAO,IAAI,aAAa,KAAK,OAAO,mBAAmB,gBACrD,OAAO,WAAW;GAChB,WAAW,OAAO,SAAS,mBAAmB,YAAY;GAC1D,QAAQ,UAAU,IAAI,gBAAgB,EAAE,OAAO,CAAC;GACjD,CAAC,CACH;;CAGH,MAAM,UACJ,KACA,GAAG,SAIA;EACH,MAAM,OAAQ,KAAK,MAAM,EAAE;AAC3B,SAAO,IAAI,aAAa,KAAK,OAAO,mBAAmB,gBACrD,OAAO,WAAW;GAChB,WAAW,OAAO,OAAO,mBAAmB,YAAY;GACxD,QAAQ,UAAU,IAAI,gBAAgB,EAAE,OAAO,CAAC;GACjD,CAAC,CACH;;AAGH,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACD;;;;;AAMH,MAAa,aAAa,QAAQ,WAChC,yBACD;AAID,MAAa,SACX,SACA,YACG,MAAM,KAAK,kBAAkB,KAAK,SAAS,QAAQ,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as Ref from "@confect/core/Ref";
|
|
2
|
+
import { ConvexClient } from "convex/browser";
|
|
3
|
+
import { Context, Effect, Layer, ParseResult, Schema, Stream } from "effect";
|
|
4
|
+
|
|
5
|
+
//#region src/WebSocketClient.d.ts
|
|
6
|
+
declare namespace WebSocketClient_d_exports {
|
|
7
|
+
export { WebSocketClient, WebSocketClientError, layer };
|
|
8
|
+
}
|
|
9
|
+
declare const WebSocketClientError_base: Schema.TaggedErrorClass<WebSocketClientError, "WebSocketClientError", {
|
|
10
|
+
readonly _tag: Schema.tag<"WebSocketClientError">;
|
|
11
|
+
} & {
|
|
12
|
+
cause: typeof Schema.Unknown;
|
|
13
|
+
}>;
|
|
14
|
+
declare class WebSocketClientError extends WebSocketClientError_base {}
|
|
15
|
+
/**
|
|
16
|
+
* 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).
|
|
17
|
+
*/
|
|
18
|
+
declare const WebSocketClient: Context.Tag<{
|
|
19
|
+
url: string;
|
|
20
|
+
setAuth: (fetchToken: (args: {
|
|
21
|
+
forceRefreshToken: boolean;
|
|
22
|
+
}) => Effect.Effect<string | null | undefined>, onChange?: (isAuthenticated: boolean) => Effect.Effect<void>) => Effect.Effect<void, never, never>;
|
|
23
|
+
query: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Effect.Effect<Ref.Returns<Query>, WebSocketClientError | ParseResult.ParseError>;
|
|
24
|
+
mutation: <Mutation extends Ref.AnyPublicMutation>(ref: Mutation, ...rest: Ref.OptionalArgs<Mutation>) => Effect.Effect<Ref.Returns<Mutation>, WebSocketClientError | ParseResult.ParseError>;
|
|
25
|
+
action: <Action extends Ref.AnyPublicAction>(ref: Action, ...rest: Ref.OptionalArgs<Action>) => Effect.Effect<Ref.Returns<Action>, WebSocketClientError | ParseResult.ParseError>;
|
|
26
|
+
reactiveQuery: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Stream.Stream<Ref.Returns<Query>, WebSocketClientError | ParseResult.ParseError>;
|
|
27
|
+
}, {
|
|
28
|
+
url: string;
|
|
29
|
+
setAuth: (fetchToken: (args: {
|
|
30
|
+
forceRefreshToken: boolean;
|
|
31
|
+
}) => Effect.Effect<string | null | undefined>, onChange?: (isAuthenticated: boolean) => Effect.Effect<void>) => Effect.Effect<void, never, never>;
|
|
32
|
+
query: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Effect.Effect<Ref.Returns<Query>, WebSocketClientError | ParseResult.ParseError>;
|
|
33
|
+
mutation: <Mutation extends Ref.AnyPublicMutation>(ref: Mutation, ...rest: Ref.OptionalArgs<Mutation>) => Effect.Effect<Ref.Returns<Mutation>, WebSocketClientError | ParseResult.ParseError>;
|
|
34
|
+
action: <Action extends Ref.AnyPublicAction>(ref: Action, ...rest: Ref.OptionalArgs<Action>) => Effect.Effect<Ref.Returns<Action>, WebSocketClientError | ParseResult.ParseError>;
|
|
35
|
+
reactiveQuery: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Stream.Stream<Ref.Returns<Query>, WebSocketClientError | ParseResult.ParseError>;
|
|
36
|
+
}>;
|
|
37
|
+
type WebSocketClient = typeof WebSocketClient.Identifier;
|
|
38
|
+
declare const layer: (address: string, options?: ConstructorParameters<typeof ConvexClient>[1]) => Layer.Layer<{
|
|
39
|
+
url: string;
|
|
40
|
+
setAuth: (fetchToken: (args: {
|
|
41
|
+
forceRefreshToken: boolean;
|
|
42
|
+
}) => Effect.Effect<string | null | undefined>, onChange?: (isAuthenticated: boolean) => Effect.Effect<void>) => Effect.Effect<void, never, never>;
|
|
43
|
+
query: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Effect.Effect<Ref.Returns<Query>, WebSocketClientError | ParseResult.ParseError>;
|
|
44
|
+
mutation: <Mutation extends Ref.AnyPublicMutation>(ref: Mutation, ...rest: Ref.OptionalArgs<Mutation>) => Effect.Effect<Ref.Returns<Mutation>, WebSocketClientError | ParseResult.ParseError>;
|
|
45
|
+
action: <Action extends Ref.AnyPublicAction>(ref: Action, ...rest: Ref.OptionalArgs<Action>) => Effect.Effect<Ref.Returns<Action>, WebSocketClientError | ParseResult.ParseError>;
|
|
46
|
+
reactiveQuery: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: Ref.OptionalArgs<Query>) => Stream.Stream<Ref.Returns<Query>, WebSocketClientError | ParseResult.ParseError>;
|
|
47
|
+
}, never, never>;
|
|
48
|
+
//#endregion
|
|
49
|
+
export { WebSocketClient_d_exports };
|
|
50
|
+
//# sourceMappingURL=WebSocketClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebSocketClient.d.ts","names":[],"sources":["../src/WebSocketClient.ts"],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { __exportAll } from "./_virtual/_rolldown/runtime.js";
|
|
2
|
+
import * as Ref from "@confect/core/Ref";
|
|
3
|
+
import { ConvexClient } from "convex/browser";
|
|
4
|
+
import { Context, Effect, Layer, Schema, Stream } from "effect";
|
|
5
|
+
|
|
6
|
+
//#region src/WebSocketClient.ts
|
|
7
|
+
var WebSocketClient_exports = /* @__PURE__ */ __exportAll({
|
|
8
|
+
WebSocketClient: () => WebSocketClient,
|
|
9
|
+
WebSocketClientError: () => WebSocketClientError,
|
|
10
|
+
layer: () => layer
|
|
11
|
+
});
|
|
12
|
+
var WebSocketClientError = class extends Schema.TaggedError()("WebSocketClientError", { cause: Schema.Unknown }) {};
|
|
13
|
+
const make = (address, options) => Effect.acquireRelease(Effect.sync(() => new ConvexClient(address, options)), (convexClient) => Effect.promise(() => convexClient.close())).pipe(Effect.map((convexClient) => {
|
|
14
|
+
const url = address;
|
|
15
|
+
const setAuth = (fetchToken, onChange) => Effect.sync(() => {
|
|
16
|
+
convexClient.setAuth((args) => Effect.runPromise(fetchToken(args)), ...onChange ? [(isAuthenticated) => Effect.runFork(onChange(isAuthenticated))] : []);
|
|
17
|
+
});
|
|
18
|
+
const query = (ref, ...rest) => {
|
|
19
|
+
const args = rest[0] ?? {};
|
|
20
|
+
return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) => Effect.tryPromise({
|
|
21
|
+
try: () => convexClient.query(functionReference, encodedArgs),
|
|
22
|
+
catch: (cause) => new WebSocketClientError({ cause })
|
|
23
|
+
}));
|
|
24
|
+
};
|
|
25
|
+
const mutation = (ref, ...rest) => {
|
|
26
|
+
const args = rest[0] ?? {};
|
|
27
|
+
return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) => Effect.tryPromise({
|
|
28
|
+
try: () => convexClient.mutation(functionReference, encodedArgs),
|
|
29
|
+
catch: (cause) => new WebSocketClientError({ cause })
|
|
30
|
+
}));
|
|
31
|
+
};
|
|
32
|
+
const action = (ref, ...rest) => {
|
|
33
|
+
const args = rest[0] ?? {};
|
|
34
|
+
return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) => Effect.tryPromise({
|
|
35
|
+
try: () => convexClient.action(functionReference, encodedArgs),
|
|
36
|
+
catch: (cause) => new WebSocketClientError({ cause })
|
|
37
|
+
}));
|
|
38
|
+
};
|
|
39
|
+
const reactiveQuery = (ref, ...rest) => {
|
|
40
|
+
const args = rest[0] ?? {};
|
|
41
|
+
const functionReference = Ref.getFunctionReference(ref);
|
|
42
|
+
return Stream.unwrapScoped(Effect.gen(function* () {
|
|
43
|
+
const encodedArgs = yield* Ref.encodeArgs(ref, args);
|
|
44
|
+
return Stream.asyncScoped((emit) => Effect.gen(function* () {
|
|
45
|
+
const unsubscribe = convexClient.onUpdate(functionReference, encodedArgs, (result) => {
|
|
46
|
+
emit.single(result);
|
|
47
|
+
}, (error) => {
|
|
48
|
+
emit.fail(new WebSocketClientError({ cause: error }));
|
|
49
|
+
});
|
|
50
|
+
yield* Effect.addFinalizer(() => Effect.sync(() => unsubscribe()));
|
|
51
|
+
}));
|
|
52
|
+
})).pipe(Stream.mapEffect((encodedReturns) => Ref.decodeReturns(ref, encodedReturns)));
|
|
53
|
+
};
|
|
54
|
+
return {
|
|
55
|
+
url,
|
|
56
|
+
setAuth,
|
|
57
|
+
query,
|
|
58
|
+
mutation,
|
|
59
|
+
action,
|
|
60
|
+
reactiveQuery
|
|
61
|
+
};
|
|
62
|
+
}));
|
|
63
|
+
/**
|
|
64
|
+
* 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).
|
|
65
|
+
*/
|
|
66
|
+
const WebSocketClient = Context.GenericTag("@confect/js/WebSocketClient");
|
|
67
|
+
const layer = (address, options) => Layer.scoped(WebSocketClient, make(address, options));
|
|
68
|
+
|
|
69
|
+
//#endregion
|
|
70
|
+
export { WebSocketClient_exports };
|
|
71
|
+
//# sourceMappingURL=WebSocketClient.js.map
|
|
@@ -0,0 +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 type { ParseResult } from \"effect\";\nimport { Context, Effect, Layer, Schema, Stream } from \"effect\";\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 query = <Query extends Ref.AnyPublicQuery>(\n ref: Query,\n ...rest: Ref.OptionalArgs<Query>\n ): Effect.Effect<\n Ref.Returns<Query>,\n WebSocketClientError | ParseResult.ParseError\n > => {\n const args = (rest[0] ?? {}) as Ref.Args<Query>;\n return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) =>\n Effect.tryPromise({\n try: () => convexClient.query(functionReference, encodedArgs),\n catch: (cause) => new WebSocketClientError({ cause }),\n }),\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 WebSocketClientError | ParseResult.ParseError\n > => {\n const args = (rest[0] ?? {}) as Ref.Args<Mutation>;\n return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) =>\n Effect.tryPromise({\n try: () => convexClient.mutation(functionReference, encodedArgs),\n catch: (cause) => new WebSocketClientError({ cause }),\n }),\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 WebSocketClientError | ParseResult.ParseError\n > => {\n const args = (rest[0] ?? {}) as Ref.Args<Action>;\n return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) =>\n Effect.tryPromise({\n try: () => convexClient.action(functionReference, encodedArgs),\n catch: (cause) => new WebSocketClientError({ cause }),\n }),\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 WebSocketClientError | ParseResult.ParseError\n > => {\n const args = (rest[0] ?? {}) as Ref.Args<Query>;\n const functionReference = Ref.getFunctionReference(ref);\n\n return Stream.unwrapScoped(\n Effect.gen(function* () {\n const encodedArgs = yield* Ref.encodeArgs(ref, args);\n\n return Stream.asyncScoped<unknown, WebSocketClientError>((emit) =>\n Effect.gen(function* () {\n const unsubscribe = convexClient.onUpdate(\n functionReference,\n encodedArgs,\n (result) => {\n emit.single(result);\n },\n (error) => {\n emit.fail(new WebSocketClientError({ cause: 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.GenericTag<\n Effect.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.scoped(WebSocketClient, make(address, options));\n"],"mappings":";;;;;;;;;;;AAKA,IAAa,uBAAb,cAA0C,OAAO,aAAmC,CAClF,wBACA,EACE,OAAO,OAAO,SACf,CACF,CAAC;AAEF,MAAM,QACJ,SACA,YAEA,OAAO,eACL,OAAO,WAAW,IAAI,aAAa,SAAS,QAAQ,CAAC,GACpD,iBAAiB,OAAO,cAAc,aAAa,OAAO,CAAC,CAC7D,CAAC,KACA,OAAO,KAAK,iBAAiB;CAC3B,MAAM,MAAM;CAEZ,MAAM,WACJ,YAGA,aAEA,OAAO,WAAW;AAChB,eAAa,SACV,SAAS,OAAO,WAAW,WAAW,KAAK,CAAC,EAC7C,GAAI,WACA,EACG,oBACC,OAAO,QAAQ,SAAS,gBAAgB,CAAC,CAC5C,GACD,EAAE,CACP;GACD;CAEJ,MAAM,SACJ,KACA,GAAG,SAIA;EACH,MAAM,OAAQ,KAAK,MAAM,EAAE;AAC3B,SAAO,IAAI,aAAa,KAAK,OAAO,mBAAmB,gBACrD,OAAO,WAAW;GAChB,WAAW,aAAa,MAAM,mBAAmB,YAAY;GAC7D,QAAQ,UAAU,IAAI,qBAAqB,EAAE,OAAO,CAAC;GACtD,CAAC,CACH;;CAGH,MAAM,YACJ,KACA,GAAG,SAIA;EACH,MAAM,OAAQ,KAAK,MAAM,EAAE;AAC3B,SAAO,IAAI,aAAa,KAAK,OAAO,mBAAmB,gBACrD,OAAO,WAAW;GAChB,WAAW,aAAa,SAAS,mBAAmB,YAAY;GAChE,QAAQ,UAAU,IAAI,qBAAqB,EAAE,OAAO,CAAC;GACtD,CAAC,CACH;;CAGH,MAAM,UACJ,KACA,GAAG,SAIA;EACH,MAAM,OAAQ,KAAK,MAAM,EAAE;AAC3B,SAAO,IAAI,aAAa,KAAK,OAAO,mBAAmB,gBACrD,OAAO,WAAW;GAChB,WAAW,aAAa,OAAO,mBAAmB,YAAY;GAC9D,QAAQ,UAAU,IAAI,qBAAqB,EAAE,OAAO,CAAC;GACtD,CAAC,CACH;;CAGH,MAAM,iBACJ,KACA,GAAG,SAIA;EACH,MAAM,OAAQ,KAAK,MAAM,EAAE;EAC3B,MAAM,oBAAoB,IAAI,qBAAqB,IAAI;AAEvD,SAAO,OAAO,aACZ,OAAO,IAAI,aAAa;GACtB,MAAM,cAAc,OAAO,IAAI,WAAW,KAAK,KAAK;AAEpD,UAAO,OAAO,aAA4C,SACxD,OAAO,IAAI,aAAa;IACtB,MAAM,cAAc,aAAa,SAC/B,mBACA,cACC,WAAW;AACV,UAAK,OAAO,OAAO;QAEpB,UAAU;AACT,UAAK,KAAK,IAAI,qBAAqB,EAAE,OAAO,OAAO,CAAC,CAAC;MAExD;AACD,WAAO,OAAO,mBACZ,OAAO,WAAW,aAAa,CAAC,CACjC;KACD,CACH;IACD,CACH,CAAC,KACA,OAAO,WAAW,mBAChB,IAAI,cAAc,KAAK,eAAe,CACvC,CACF;;AAGH,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACD;EACD,CACH;;;;AAKH,MAAa,kBAAkB,QAAQ,WAErC,8BAA8B;AAIhC,MAAa,SACX,SACA,YACG,MAAM,OAAO,iBAAiB,KAAK,SAAS,QAAQ,CAAC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@confect/js",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "JavaScript client bindings for any JS runtime",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"convex": "^1.30.0",
|
|
50
50
|
"effect": "^3.19.16",
|
|
51
|
-
"@confect/core": "
|
|
51
|
+
"@confect/core": "6.0.0"
|
|
52
52
|
},
|
|
53
53
|
"engines": {
|
|
54
54
|
"node": ">=22",
|
package/src/HttpClient.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import * as Ref from "@confect/core/Ref";
|
|
2
2
|
import { ConvexHttpClient } from "convex/browser";
|
|
3
|
-
import type { FunctionReference } from "convex/server";
|
|
4
3
|
import type { ParseResult } from "effect";
|
|
5
|
-
import { Context, Effect, Layer,
|
|
4
|
+
import { Context, Effect, Layer, Schema } from "effect";
|
|
6
5
|
|
|
7
6
|
export class HttpClientError extends Schema.TaggedError<HttpClientError>()(
|
|
8
7
|
"HttpClientError",
|
|
@@ -11,9 +10,6 @@ export class HttpClientError extends Schema.TaggedError<HttpClientError>()(
|
|
|
11
10
|
},
|
|
12
11
|
) {}
|
|
13
12
|
|
|
14
|
-
type OptionalArgs<R extends Ref.AnyQuery | Ref.AnyMutation | Ref.AnyAction> =
|
|
15
|
-
keyof Ref.Args<R> extends never ? [args?: Ref.Args<R>] : [args: Ref.Args<R>];
|
|
16
|
-
|
|
17
13
|
const make = (
|
|
18
14
|
address: string,
|
|
19
15
|
options?: ConstructorParameters<typeof ConvexHttpClient>[1],
|
|
@@ -31,128 +27,53 @@ const make = (
|
|
|
31
27
|
client.clearAuth();
|
|
32
28
|
});
|
|
33
29
|
|
|
34
|
-
const query = <Query extends Ref.
|
|
30
|
+
const query = <Query extends Ref.AnyPublicQuery>(
|
|
35
31
|
ref: Query,
|
|
36
|
-
...rest: OptionalArgs<Query>
|
|
32
|
+
...rest: Ref.OptionalArgs<Query>
|
|
37
33
|
): Effect.Effect<
|
|
38
34
|
Ref.Returns<Query>,
|
|
39
35
|
HttpClientError | ParseResult.ParseError
|
|
40
|
-
> =>
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Match.tag("Confect", (confectFunctionSpec) =>
|
|
50
|
-
Effect.gen(function* () {
|
|
51
|
-
const encodedArgs = yield* Schema.encode(confectFunctionSpec.args)(
|
|
52
|
-
args,
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
const encodedResult = yield* Effect.tryPromise({
|
|
56
|
-
try: () => client.query(functionName, encodedArgs),
|
|
57
|
-
catch: (cause) => new HttpClientError({ cause }),
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
return yield* Schema.decode(confectFunctionSpec.returns)(
|
|
61
|
-
encodedResult,
|
|
62
|
-
);
|
|
63
|
-
}),
|
|
64
|
-
),
|
|
65
|
-
Match.tag("Convex", () =>
|
|
66
|
-
Effect.tryPromise({
|
|
67
|
-
try: () => client.query(functionName, args),
|
|
68
|
-
catch: (cause) => new HttpClientError({ cause }),
|
|
69
|
-
}),
|
|
70
|
-
),
|
|
71
|
-
Match.exhaustive,
|
|
72
|
-
);
|
|
73
|
-
});
|
|
36
|
+
> => {
|
|
37
|
+
const args = (rest[0] ?? {}) as Ref.Args<Query>;
|
|
38
|
+
return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) =>
|
|
39
|
+
Effect.tryPromise({
|
|
40
|
+
try: () => client.query(functionReference, encodedArgs),
|
|
41
|
+
catch: (cause) => new HttpClientError({ cause }),
|
|
42
|
+
}),
|
|
43
|
+
);
|
|
44
|
+
};
|
|
74
45
|
|
|
75
|
-
const mutation = <Mutation extends Ref.
|
|
46
|
+
const mutation = <Mutation extends Ref.AnyPublicMutation>(
|
|
76
47
|
ref: Mutation,
|
|
77
|
-
...rest: OptionalArgs<Mutation>
|
|
48
|
+
...rest: Ref.OptionalArgs<Mutation>
|
|
78
49
|
): Effect.Effect<
|
|
79
50
|
Ref.Returns<Mutation>,
|
|
80
51
|
HttpClientError | ParseResult.ParseError
|
|
81
|
-
> =>
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
Match.tag("Confect", (confectFunctionSpec) =>
|
|
91
|
-
Effect.gen(function* () {
|
|
92
|
-
const encodedArgs = yield* Schema.encode(confectFunctionSpec.args)(
|
|
93
|
-
args,
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
const encodedResult = yield* Effect.tryPromise({
|
|
97
|
-
try: () => client.mutation(functionName, encodedArgs),
|
|
98
|
-
catch: (cause) => new HttpClientError({ cause }),
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
return yield* Schema.decode(confectFunctionSpec.returns)(
|
|
102
|
-
encodedResult,
|
|
103
|
-
);
|
|
104
|
-
}),
|
|
105
|
-
),
|
|
106
|
-
Match.tag("Convex", () =>
|
|
107
|
-
Effect.tryPromise({
|
|
108
|
-
try: () => client.mutation(functionName, args),
|
|
109
|
-
catch: (cause) => new HttpClientError({ cause }),
|
|
110
|
-
}),
|
|
111
|
-
),
|
|
112
|
-
Match.exhaustive,
|
|
113
|
-
);
|
|
114
|
-
});
|
|
52
|
+
> => {
|
|
53
|
+
const args = (rest[0] ?? {}) as Ref.Args<Mutation>;
|
|
54
|
+
return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) =>
|
|
55
|
+
Effect.tryPromise({
|
|
56
|
+
try: () => client.mutation(functionReference, encodedArgs),
|
|
57
|
+
catch: (cause) => new HttpClientError({ cause }),
|
|
58
|
+
}),
|
|
59
|
+
);
|
|
60
|
+
};
|
|
115
61
|
|
|
116
|
-
const action = <Action extends Ref.
|
|
62
|
+
const action = <Action extends Ref.AnyPublicAction>(
|
|
117
63
|
ref: Action,
|
|
118
|
-
...rest: OptionalArgs<Action>
|
|
64
|
+
...rest: Ref.OptionalArgs<Action>
|
|
119
65
|
): Effect.Effect<
|
|
120
66
|
Ref.Returns<Action>,
|
|
121
67
|
HttpClientError | ParseResult.ParseError
|
|
122
|
-
> =>
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
Match.tag("Confect", (confectFunctionSpec) =>
|
|
132
|
-
Effect.gen(function* () {
|
|
133
|
-
const encodedArgs = yield* Schema.encode(confectFunctionSpec.args)(
|
|
134
|
-
args,
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
const encodedResult = yield* Effect.tryPromise({
|
|
138
|
-
try: () => client.action(functionName, encodedArgs),
|
|
139
|
-
catch: (cause) => new HttpClientError({ cause }),
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
return yield* Schema.decode(confectFunctionSpec.returns)(
|
|
143
|
-
encodedResult,
|
|
144
|
-
);
|
|
145
|
-
}),
|
|
146
|
-
),
|
|
147
|
-
Match.tag("Convex", () =>
|
|
148
|
-
Effect.tryPromise({
|
|
149
|
-
try: () => client.action(functionName, args),
|
|
150
|
-
catch: (cause) => new HttpClientError({ cause }),
|
|
151
|
-
}),
|
|
152
|
-
),
|
|
153
|
-
Match.exhaustive,
|
|
154
|
-
);
|
|
155
|
-
});
|
|
68
|
+
> => {
|
|
69
|
+
const args = (rest[0] ?? {}) as Ref.Args<Action>;
|
|
70
|
+
return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) =>
|
|
71
|
+
Effect.tryPromise({
|
|
72
|
+
try: () => client.action(functionReference, encodedArgs),
|
|
73
|
+
catch: (cause) => new HttpClientError({ cause }),
|
|
74
|
+
}),
|
|
75
|
+
);
|
|
76
|
+
};
|
|
156
77
|
|
|
157
78
|
return {
|
|
158
79
|
url,
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import * as Ref from "@confect/core/Ref";
|
|
2
|
+
import { ConvexClient } from "convex/browser";
|
|
3
|
+
import type { ParseResult } from "effect";
|
|
4
|
+
import { Context, Effect, Layer, Schema, Stream } from "effect";
|
|
5
|
+
|
|
6
|
+
export class WebSocketClientError extends Schema.TaggedError<WebSocketClientError>()(
|
|
7
|
+
"WebSocketClientError",
|
|
8
|
+
{
|
|
9
|
+
cause: Schema.Unknown,
|
|
10
|
+
},
|
|
11
|
+
) {}
|
|
12
|
+
|
|
13
|
+
const make = (
|
|
14
|
+
address: string,
|
|
15
|
+
options?: ConstructorParameters<typeof ConvexClient>[1],
|
|
16
|
+
) =>
|
|
17
|
+
Effect.acquireRelease(
|
|
18
|
+
Effect.sync(() => new ConvexClient(address, options)),
|
|
19
|
+
(convexClient) => Effect.promise(() => convexClient.close()),
|
|
20
|
+
).pipe(
|
|
21
|
+
Effect.map((convexClient) => {
|
|
22
|
+
const url = address;
|
|
23
|
+
|
|
24
|
+
const setAuth = (
|
|
25
|
+
fetchToken: (args: {
|
|
26
|
+
forceRefreshToken: boolean;
|
|
27
|
+
}) => Effect.Effect<string | null | undefined>,
|
|
28
|
+
onChange?: (isAuthenticated: boolean) => Effect.Effect<void>,
|
|
29
|
+
) =>
|
|
30
|
+
Effect.sync(() => {
|
|
31
|
+
convexClient.setAuth(
|
|
32
|
+
(args) => Effect.runPromise(fetchToken(args)),
|
|
33
|
+
...(onChange
|
|
34
|
+
? [
|
|
35
|
+
(isAuthenticated: boolean) =>
|
|
36
|
+
Effect.runFork(onChange(isAuthenticated)),
|
|
37
|
+
]
|
|
38
|
+
: []),
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const query = <Query extends Ref.AnyPublicQuery>(
|
|
43
|
+
ref: Query,
|
|
44
|
+
...rest: Ref.OptionalArgs<Query>
|
|
45
|
+
): Effect.Effect<
|
|
46
|
+
Ref.Returns<Query>,
|
|
47
|
+
WebSocketClientError | ParseResult.ParseError
|
|
48
|
+
> => {
|
|
49
|
+
const args = (rest[0] ?? {}) as Ref.Args<Query>;
|
|
50
|
+
return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) =>
|
|
51
|
+
Effect.tryPromise({
|
|
52
|
+
try: () => convexClient.query(functionReference, encodedArgs),
|
|
53
|
+
catch: (cause) => new WebSocketClientError({ cause }),
|
|
54
|
+
}),
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const mutation = <Mutation extends Ref.AnyPublicMutation>(
|
|
59
|
+
ref: Mutation,
|
|
60
|
+
...rest: Ref.OptionalArgs<Mutation>
|
|
61
|
+
): Effect.Effect<
|
|
62
|
+
Ref.Returns<Mutation>,
|
|
63
|
+
WebSocketClientError | ParseResult.ParseError
|
|
64
|
+
> => {
|
|
65
|
+
const args = (rest[0] ?? {}) as Ref.Args<Mutation>;
|
|
66
|
+
return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) =>
|
|
67
|
+
Effect.tryPromise({
|
|
68
|
+
try: () => convexClient.mutation(functionReference, encodedArgs),
|
|
69
|
+
catch: (cause) => new WebSocketClientError({ cause }),
|
|
70
|
+
}),
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const action = <Action extends Ref.AnyPublicAction>(
|
|
75
|
+
ref: Action,
|
|
76
|
+
...rest: Ref.OptionalArgs<Action>
|
|
77
|
+
): Effect.Effect<
|
|
78
|
+
Ref.Returns<Action>,
|
|
79
|
+
WebSocketClientError | ParseResult.ParseError
|
|
80
|
+
> => {
|
|
81
|
+
const args = (rest[0] ?? {}) as Ref.Args<Action>;
|
|
82
|
+
return Ref.runWithCodec(ref, args, (functionReference, encodedArgs) =>
|
|
83
|
+
Effect.tryPromise({
|
|
84
|
+
try: () => convexClient.action(functionReference, encodedArgs),
|
|
85
|
+
catch: (cause) => new WebSocketClientError({ cause }),
|
|
86
|
+
}),
|
|
87
|
+
);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const reactiveQuery = <Query extends Ref.AnyPublicQuery>(
|
|
91
|
+
ref: Query,
|
|
92
|
+
...rest: Ref.OptionalArgs<Query>
|
|
93
|
+
): Stream.Stream<
|
|
94
|
+
Ref.Returns<Query>,
|
|
95
|
+
WebSocketClientError | ParseResult.ParseError
|
|
96
|
+
> => {
|
|
97
|
+
const args = (rest[0] ?? {}) as Ref.Args<Query>;
|
|
98
|
+
const functionReference = Ref.getFunctionReference(ref);
|
|
99
|
+
|
|
100
|
+
return Stream.unwrapScoped(
|
|
101
|
+
Effect.gen(function* () {
|
|
102
|
+
const encodedArgs = yield* Ref.encodeArgs(ref, args);
|
|
103
|
+
|
|
104
|
+
return Stream.asyncScoped<unknown, WebSocketClientError>((emit) =>
|
|
105
|
+
Effect.gen(function* () {
|
|
106
|
+
const unsubscribe = convexClient.onUpdate(
|
|
107
|
+
functionReference,
|
|
108
|
+
encodedArgs,
|
|
109
|
+
(result) => {
|
|
110
|
+
emit.single(result);
|
|
111
|
+
},
|
|
112
|
+
(error) => {
|
|
113
|
+
emit.fail(new WebSocketClientError({ cause: error }));
|
|
114
|
+
},
|
|
115
|
+
);
|
|
116
|
+
yield* Effect.addFinalizer(() =>
|
|
117
|
+
Effect.sync(() => unsubscribe()),
|
|
118
|
+
);
|
|
119
|
+
}),
|
|
120
|
+
);
|
|
121
|
+
}),
|
|
122
|
+
).pipe(
|
|
123
|
+
Stream.mapEffect((encodedReturns) =>
|
|
124
|
+
Ref.decodeReturns(ref, encodedReturns),
|
|
125
|
+
),
|
|
126
|
+
);
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
url,
|
|
131
|
+
setAuth,
|
|
132
|
+
query,
|
|
133
|
+
mutation,
|
|
134
|
+
action,
|
|
135
|
+
reactiveQuery,
|
|
136
|
+
};
|
|
137
|
+
}),
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* 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).
|
|
142
|
+
*/
|
|
143
|
+
export const WebSocketClient = Context.GenericTag<
|
|
144
|
+
Effect.Effect.Success<ReturnType<typeof make>>
|
|
145
|
+
>("@confect/js/WebSocketClient");
|
|
146
|
+
|
|
147
|
+
export type WebSocketClient = typeof WebSocketClient.Identifier;
|
|
148
|
+
|
|
149
|
+
export const layer = (
|
|
150
|
+
address: string,
|
|
151
|
+
options?: ConstructorParameters<typeof ConvexClient>[1],
|
|
152
|
+
) => Layer.scoped(WebSocketClient, make(address, options));
|
package/src/index.ts
CHANGED