@confect/server 5.0.0 → 7.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 +145 -1
- package/dist/ActionRunner.d.ts +3 -5
- package/dist/ActionRunner.d.ts.map +1 -1
- package/dist/ActionRunner.js +1 -1
- package/dist/ActionRunner.js.map +1 -1
- package/dist/CronJob.d.ts +1 -2
- package/dist/CronJob.d.ts.map +1 -1
- package/dist/CronJob.js.map +1 -1
- package/dist/DatabaseReader.d.ts +5 -5
- package/dist/DatabaseWriter.d.ts +4 -4
- package/dist/DatabaseWriter.d.ts.map +1 -1
- package/dist/Handler.d.ts +1 -1
- package/dist/Handler.d.ts.map +1 -1
- package/dist/Handler.js.map +1 -1
- package/dist/MutationRunner.d.ts +5 -16
- package/dist/MutationRunner.d.ts.map +1 -1
- package/dist/MutationRunner.js +3 -13
- package/dist/MutationRunner.js.map +1 -1
- package/dist/QueryInitializer.d.ts +1 -1
- package/dist/QueryInitializer.d.ts.map +1 -1
- package/dist/QueryRunner.d.ts +3 -5
- package/dist/QueryRunner.d.ts.map +1 -1
- package/dist/QueryRunner.js +1 -1
- package/dist/QueryRunner.js.map +1 -1
- package/dist/RegisteredConvexFunction.d.ts +8 -8
- package/dist/RegisteredConvexFunction.d.ts.map +1 -1
- package/dist/RegisteredConvexFunction.js +41 -9
- package/dist/RegisteredConvexFunction.js.map +1 -1
- package/dist/RegisteredFunction.d.ts +26 -7
- package/dist/RegisteredFunction.d.ts.map +1 -1
- package/dist/RegisteredFunction.js +34 -5
- package/dist/RegisteredFunction.js.map +1 -1
- package/dist/RegisteredNodeFunction.js +3 -1
- package/dist/RegisteredNodeFunction.js.map +1 -1
- package/dist/Scheduler.d.ts +6 -7
- package/dist/Scheduler.d.ts.map +1 -1
- package/dist/Scheduler.js.map +1 -1
- package/package.json +5 -5
- package/src/ActionRunner.ts +13 -3
- package/src/CronJob.ts +1 -4
- package/src/Handler.ts +5 -1
- package/src/MutationRunner.ts +12 -19
- package/src/QueryRunner.ts +13 -3
- package/src/RegisteredConvexFunction.ts +121 -65
- package/src/RegisteredFunction.ts +67 -22
- package/src/RegisteredNodeFunction.ts +4 -0
- package/src/Scheduler.ts +2 -7
package/src/MutationRunner.ts
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import * as Ref from "@confect/core/Ref";
|
|
2
2
|
import { type GenericMutationCtx } from "convex/server";
|
|
3
|
-
import {
|
|
3
|
+
import type { ParseResult, Effect } from "effect";
|
|
4
|
+
import { Context, Layer } from "effect";
|
|
4
5
|
|
|
5
6
|
const make =
|
|
6
7
|
(runMutation: GenericMutationCtx<any>["runMutation"]) =>
|
|
7
8
|
<Mutation extends Ref.AnyMutation>(
|
|
8
9
|
mutation: Mutation,
|
|
9
|
-
args: Ref.
|
|
10
|
-
)
|
|
11
|
-
Ref.
|
|
12
|
-
|
|
10
|
+
...args: Ref.OptionalArgs<Mutation>
|
|
11
|
+
): Effect.Effect<
|
|
12
|
+
Ref.Returns<Mutation>,
|
|
13
|
+
Ref.Error<Mutation> | ParseResult.ParseError
|
|
14
|
+
> =>
|
|
15
|
+
Ref.runWithCodec(
|
|
16
|
+
mutation,
|
|
17
|
+
(args[0] ?? {}) as Ref.Args<Mutation>,
|
|
18
|
+
(functionReference, encodedArgs) =>
|
|
19
|
+
runMutation(functionReference, encodedArgs),
|
|
13
20
|
);
|
|
14
21
|
|
|
15
22
|
export const MutationRunner = Context.GenericTag<ReturnType<typeof make>>(
|
|
@@ -19,17 +26,3 @@ export type MutationRunner = typeof MutationRunner.Identifier;
|
|
|
19
26
|
|
|
20
27
|
export const layer = (runMutation: GenericMutationCtx<any>["runMutation"]) =>
|
|
21
28
|
Layer.succeed(MutationRunner, make(runMutation));
|
|
22
|
-
|
|
23
|
-
export class MutationRollback extends Schema.TaggedError<MutationRollback>()(
|
|
24
|
-
"MutationRollback",
|
|
25
|
-
{
|
|
26
|
-
mutationName: Schema.String,
|
|
27
|
-
error: Schema.Unknown,
|
|
28
|
-
},
|
|
29
|
-
) {
|
|
30
|
-
/* v8 ignore start */
|
|
31
|
-
override get message(): string {
|
|
32
|
-
return `Mutation ${this.mutationName} failed and was rolled back.\n\n${this.error}`;
|
|
33
|
-
}
|
|
34
|
-
/* v8 ignore stop */
|
|
35
|
-
}
|
package/src/QueryRunner.ts
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import * as Ref from "@confect/core/Ref";
|
|
2
2
|
import { type GenericQueryCtx } from "convex/server";
|
|
3
|
+
import type { ParseResult, Effect } from "effect";
|
|
3
4
|
import { Context, Layer } from "effect";
|
|
4
5
|
|
|
5
6
|
const make =
|
|
6
7
|
(runQuery: GenericQueryCtx<any>["runQuery"]) =>
|
|
7
|
-
<Query extends Ref.AnyQuery>(
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
<Query extends Ref.AnyQuery>(
|
|
9
|
+
query: Query,
|
|
10
|
+
...args: Ref.OptionalArgs<Query>
|
|
11
|
+
): Effect.Effect<
|
|
12
|
+
Ref.Returns<Query>,
|
|
13
|
+
Ref.Error<Query> | ParseResult.ParseError
|
|
14
|
+
> =>
|
|
15
|
+
Ref.runWithCodec(
|
|
16
|
+
query,
|
|
17
|
+
(args[0] ?? {}) as Ref.Args<Query>,
|
|
18
|
+
(functionReference, encodedArgs) =>
|
|
19
|
+
runQuery(functionReference, encodedArgs),
|
|
10
20
|
);
|
|
11
21
|
|
|
12
22
|
export const QueryRunner = Context.GenericTag<ReturnType<typeof make>>(
|
|
@@ -10,7 +10,8 @@ import {
|
|
|
10
10
|
mutationGeneric,
|
|
11
11
|
queryGeneric,
|
|
12
12
|
} from "convex/server";
|
|
13
|
-
import {
|
|
13
|
+
import type { Value } from "convex/values";
|
|
14
|
+
import { Clock, Effect, Layer, Match, pipe, Schema } from "effect";
|
|
14
15
|
import type * as Api from "./Api";
|
|
15
16
|
import * as Auth from "./Auth";
|
|
16
17
|
import * as ConvexConfigProvider from "./ConvexConfigProvider";
|
|
@@ -49,9 +50,11 @@ export const make = <Api_ extends Api.AnyWithPropsWithRuntime<"Convex">>(
|
|
|
49
50
|
);
|
|
50
51
|
|
|
51
52
|
return genericFunction(
|
|
52
|
-
queryFunction(
|
|
53
|
+
queryFunction({
|
|
54
|
+
databaseSchema: api.databaseSchema,
|
|
53
55
|
args: functionProvenance.args,
|
|
54
56
|
returns: functionProvenance.returns,
|
|
57
|
+
error: functionProvenance.error,
|
|
55
58
|
handler: handler as Handler.AnyConfectProvenance,
|
|
56
59
|
}),
|
|
57
60
|
);
|
|
@@ -64,9 +67,11 @@ export const make = <Api_ extends Api.AnyWithPropsWithRuntime<"Convex">>(
|
|
|
64
67
|
);
|
|
65
68
|
|
|
66
69
|
return genericFunction(
|
|
67
|
-
mutationFunction(
|
|
70
|
+
mutationFunction({
|
|
71
|
+
databaseSchema: api.databaseSchema,
|
|
68
72
|
args: functionProvenance.args,
|
|
69
73
|
returns: functionProvenance.returns,
|
|
74
|
+
error: functionProvenance.error,
|
|
70
75
|
handler: handler as Handler.AnyConfectProvenance,
|
|
71
76
|
}),
|
|
72
77
|
);
|
|
@@ -82,6 +87,7 @@ export const make = <Api_ extends Api.AnyWithPropsWithRuntime<"Convex">>(
|
|
|
82
87
|
convexActionFunction(api.databaseSchema, {
|
|
83
88
|
args: functionProvenance.args,
|
|
84
89
|
returns: functionProvenance.returns,
|
|
90
|
+
error: functionProvenance.error,
|
|
85
91
|
handler: handler as Handler.AnyConfectProvenance,
|
|
86
92
|
}),
|
|
87
93
|
);
|
|
@@ -92,6 +98,43 @@ export const make = <Api_ extends Api.AnyWithPropsWithRuntime<"Convex">>(
|
|
|
92
98
|
Match.exhaustive,
|
|
93
99
|
);
|
|
94
100
|
|
|
101
|
+
// Convex's query cache is invalidated by any Date.now() call during handler
|
|
102
|
+
// execution. Effect's unsafeFork calls Date.now() when constructing a
|
|
103
|
+
// FiberId.Runtime, which trips the cache for every confect-wrapped query. We
|
|
104
|
+
// stub Date.now to 0 for the span of the handler; queries are forbidden from
|
|
105
|
+
// relying on real time for correctness anyway.
|
|
106
|
+
//
|
|
107
|
+
// Users who explicitly want the real timestamp can still reach it via Effect's
|
|
108
|
+
// Clock service (Clock.currentTimeMillis/Clock.currentTimeNanos). We provide
|
|
109
|
+
// a Clock layer whose methods close over the *original* Date.now, so opting in
|
|
110
|
+
// to Clock is an opt-in to worse caching—but caching is not broken by default.
|
|
111
|
+
const unpatchedClock = (realDateNow: () => number): Clock.Clock => {
|
|
112
|
+
const bigint1e6 = BigInt(1_000_000);
|
|
113
|
+
const unsafeCurrentTimeMillis = () => realDateNow();
|
|
114
|
+
const unsafeCurrentTimeNanos = () => BigInt(realDateNow()) * bigint1e6;
|
|
115
|
+
const defaultClock = Clock.make();
|
|
116
|
+
return {
|
|
117
|
+
...defaultClock,
|
|
118
|
+
unsafeCurrentTimeMillis,
|
|
119
|
+
unsafeCurrentTimeNanos,
|
|
120
|
+
currentTimeMillis: Effect.sync(unsafeCurrentTimeMillis),
|
|
121
|
+
currentTimeNanos: Effect.sync(unsafeCurrentTimeNanos),
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const withStubbedDateNow = async <T>(
|
|
126
|
+
queryHandler: (clock: Clock.Clock) => Promise<T>,
|
|
127
|
+
): Promise<T> => {
|
|
128
|
+
const realDateNow = Date.now;
|
|
129
|
+
const clock = unpatchedClock(realDateNow);
|
|
130
|
+
Date.now = () => 0;
|
|
131
|
+
try {
|
|
132
|
+
return await queryHandler(clock);
|
|
133
|
+
} finally {
|
|
134
|
+
Date.now = realDateNow;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
95
138
|
const queryFunction = <
|
|
96
139
|
DatabaseSchema_ extends DatabaseSchema.AnyWithProps,
|
|
97
140
|
Args,
|
|
@@ -99,30 +142,31 @@ const queryFunction = <
|
|
|
99
142
|
Returns,
|
|
100
143
|
ConvexReturns,
|
|
101
144
|
E,
|
|
102
|
-
>(
|
|
103
|
-
databaseSchema
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
145
|
+
>({
|
|
146
|
+
databaseSchema,
|
|
147
|
+
args,
|
|
148
|
+
returns,
|
|
149
|
+
error,
|
|
150
|
+
handler,
|
|
151
|
+
}: {
|
|
152
|
+
databaseSchema: DatabaseSchema_;
|
|
153
|
+
args: Schema.Schema<Args, ConvexArgs>;
|
|
154
|
+
returns: Schema.Schema<Returns, ConvexReturns>;
|
|
155
|
+
error: Schema.Schema<Error, Value> | undefined;
|
|
156
|
+
handler: (
|
|
157
|
+
a: Args,
|
|
158
|
+
) => Effect.Effect<
|
|
159
|
+
Returns,
|
|
160
|
+
E,
|
|
161
|
+
| DatabaseReader.DatabaseReader<DatabaseSchema_>
|
|
162
|
+
| Auth.Auth
|
|
163
|
+
| StorageReader
|
|
164
|
+
| QueryRunner.QueryRunner
|
|
165
|
+
| QueryCtx.QueryCtx<
|
|
166
|
+
DataModel.ToConvex<DataModel.FromSchema<DatabaseSchema_>>
|
|
167
|
+
>
|
|
168
|
+
>;
|
|
169
|
+
}) => ({
|
|
126
170
|
args: SchemaToValidator.compileArgsSchema(args),
|
|
127
171
|
returns: SchemaToValidator.compileReturnsSchema(returns),
|
|
128
172
|
handler: (
|
|
@@ -131,13 +175,14 @@ const queryFunction = <
|
|
|
131
175
|
>,
|
|
132
176
|
actualArgs: ConvexArgs,
|
|
133
177
|
): Promise<ConvexReturns> =>
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
178
|
+
withStubbedDateNow((clock) =>
|
|
179
|
+
Effect.gen(function* () {
|
|
180
|
+
const decodedArgs = yield* pipe(
|
|
181
|
+
actualArgs,
|
|
182
|
+
Schema.decode(args),
|
|
183
|
+
Effect.orDie,
|
|
184
|
+
);
|
|
185
|
+
const decodedReturns = yield* handler(decodedArgs).pipe(
|
|
141
186
|
Effect.provide(
|
|
142
187
|
Layer.mergeAll(
|
|
143
188
|
DatabaseReader.layer(databaseSchema, ctx.db),
|
|
@@ -153,12 +198,16 @@ const queryFunction = <
|
|
|
153
198
|
Layer.setConfigProvider(ConvexConfigProvider.make()),
|
|
154
199
|
),
|
|
155
200
|
),
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
201
|
+
);
|
|
202
|
+
return yield* pipe(
|
|
203
|
+
decodedReturns,
|
|
204
|
+
Schema.encode(returns),
|
|
205
|
+
Effect.orDie,
|
|
206
|
+
);
|
|
207
|
+
}).pipe(
|
|
208
|
+
Effect.withClock(clock),
|
|
209
|
+
RegisteredFunction.runHandlerPromise(error),
|
|
160
210
|
),
|
|
161
|
-
Effect.runPromise,
|
|
162
211
|
),
|
|
163
212
|
});
|
|
164
213
|
|
|
@@ -196,42 +245,46 @@ export type MutationServices<Schema extends DatabaseSchema.AnyWithProps> =
|
|
|
196
245
|
| MutationCtx.MutationCtx<DataModel.ToConvex<DataModel.FromSchema<Schema>>>;
|
|
197
246
|
|
|
198
247
|
const mutationFunction = <
|
|
199
|
-
|
|
248
|
+
DatabaseSchema_ extends DatabaseSchema.AnyWithProps,
|
|
200
249
|
Args,
|
|
201
250
|
ConvexArgs extends DefaultFunctionArgs,
|
|
202
251
|
Returns,
|
|
203
252
|
ConvexReturns,
|
|
204
253
|
E,
|
|
205
|
-
>(
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
254
|
+
>({
|
|
255
|
+
databaseSchema,
|
|
256
|
+
args,
|
|
257
|
+
returns,
|
|
258
|
+
error,
|
|
259
|
+
handler,
|
|
260
|
+
}: {
|
|
261
|
+
databaseSchema: DatabaseSchema_;
|
|
262
|
+
args: Schema.Schema<Args, ConvexArgs>;
|
|
263
|
+
returns: Schema.Schema<Returns, ConvexReturns>;
|
|
264
|
+
error: Schema.Schema<Error, Value> | undefined;
|
|
265
|
+
handler: (
|
|
266
|
+
a: Args,
|
|
267
|
+
) => Effect.Effect<Returns, E, MutationServices<DatabaseSchema_>>;
|
|
268
|
+
}) => ({
|
|
217
269
|
args: SchemaToValidator.compileArgsSchema(args),
|
|
218
270
|
returns: SchemaToValidator.compileReturnsSchema(returns),
|
|
219
271
|
handler: (
|
|
220
|
-
ctx: GenericMutationCtx<
|
|
272
|
+
ctx: GenericMutationCtx<
|
|
273
|
+
DataModel.ToConvex<DataModel.FromSchema<DatabaseSchema_>>
|
|
274
|
+
>,
|
|
221
275
|
actualArgs: ConvexArgs,
|
|
222
276
|
): Promise<ConvexReturns> =>
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
)
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
),
|
|
233
|
-
|
|
234
|
-
),
|
|
277
|
+
Effect.gen(function* () {
|
|
278
|
+
const decodedArgs = yield* pipe(
|
|
279
|
+
actualArgs,
|
|
280
|
+
Schema.decode(args),
|
|
281
|
+
Effect.orDie,
|
|
282
|
+
);
|
|
283
|
+
const decodedReturns = yield* handler(decodedArgs).pipe(
|
|
284
|
+
Effect.provide(mutationLayer(databaseSchema, ctx)),
|
|
285
|
+
);
|
|
286
|
+
return yield* pipe(decodedReturns, Schema.encode(returns), Effect.orDie);
|
|
287
|
+
}).pipe(RegisteredFunction.runHandlerPromise(error)),
|
|
235
288
|
});
|
|
236
289
|
|
|
237
290
|
const convexActionFunction = <
|
|
@@ -246,10 +299,12 @@ const convexActionFunction = <
|
|
|
246
299
|
{
|
|
247
300
|
args,
|
|
248
301
|
returns,
|
|
302
|
+
error,
|
|
249
303
|
handler,
|
|
250
304
|
}: {
|
|
251
305
|
args: Schema.Schema<Args, ConvexArgs>;
|
|
252
306
|
returns: Schema.Schema<Returns, ConvexReturns>;
|
|
307
|
+
error: Schema.Schema.AnyNoContext | undefined;
|
|
253
308
|
handler: (
|
|
254
309
|
a: Args,
|
|
255
310
|
) => Effect.Effect<
|
|
@@ -262,6 +317,7 @@ const convexActionFunction = <
|
|
|
262
317
|
RegisteredFunction.actionFunctionBase({
|
|
263
318
|
args,
|
|
264
319
|
returns,
|
|
320
|
+
error,
|
|
265
321
|
handler,
|
|
266
322
|
createLayer: (ctx) =>
|
|
267
323
|
Layer.mergeAll(
|
|
@@ -8,7 +8,9 @@ import {
|
|
|
8
8
|
type RegisteredMutation,
|
|
9
9
|
type RegisteredQuery,
|
|
10
10
|
} from "convex/server";
|
|
11
|
-
import {
|
|
11
|
+
import type { Value } from "convex/values";
|
|
12
|
+
import { ConvexError } from "convex/values";
|
|
13
|
+
import { Effect, Either, Layer, pipe, Schema } from "effect";
|
|
12
14
|
import * as ActionCtx from "./ActionCtx";
|
|
13
15
|
import * as ActionRunner from "./ActionRunner";
|
|
14
16
|
import * as Auth from "./Auth";
|
|
@@ -18,9 +20,9 @@ import * as MutationRunner from "./MutationRunner";
|
|
|
18
20
|
import * as QueryRunner from "./QueryRunner";
|
|
19
21
|
import * as Scheduler from "./Scheduler";
|
|
20
22
|
import * as SchemaToValidator from "./SchemaToValidator";
|
|
21
|
-
import
|
|
22
|
-
import
|
|
23
|
-
import
|
|
23
|
+
import * as StorageActionWriter from "./StorageActionWriter";
|
|
24
|
+
import * as StorageReader from "./StorageReader";
|
|
25
|
+
import * as StorageWriter from "./StorageWriter";
|
|
24
26
|
import * as VectorSearch from "./VectorSearch";
|
|
25
27
|
|
|
26
28
|
export type Any =
|
|
@@ -111,6 +113,48 @@ export type RegisteredFunction<
|
|
|
111
113
|
? ConfectRegisteredFunction<FunctionSpec_>
|
|
112
114
|
: never;
|
|
113
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Run the `Effect` as a `Promise`. The error schema acts as an allowlist of
|
|
118
|
+
* failures that may be surfaced to the client as a `ConvexError`:
|
|
119
|
+
*
|
|
120
|
+
* - With a schema: typed errors are schema-encoded and wrapped in a
|
|
121
|
+
* `ConvexError`, then thrown so Convex surfaces the data to the client.
|
|
122
|
+
* `Effect.either` escapes the failure channel before `runPromise` so the thrown
|
|
123
|
+
* `ConvexError` retains its `Symbol.for("ConvexError")` identity instead of
|
|
124
|
+
* being wrapped in Effect's `FiberFailure`.
|
|
125
|
+
*
|
|
126
|
+
* - Without a schema: every failure is converted to a defect via
|
|
127
|
+
* `Effect.orDie`, so nothing—not even a `ConvexError` the handler placed in its
|
|
128
|
+
* error channel—reaches the client as a `ConvexError`. The fiber dies and
|
|
129
|
+
* `runPromise` rejects with a generic failure.
|
|
130
|
+
*/
|
|
131
|
+
export const runHandlerPromise =
|
|
132
|
+
(errorSchema: Schema.Schema.AnyNoContext | undefined) =>
|
|
133
|
+
<A, E>(effect: Effect.Effect<A, E>): Promise<A> => {
|
|
134
|
+
if (errorSchema === undefined) {
|
|
135
|
+
return Effect.runPromise(Effect.orDie(effect));
|
|
136
|
+
}
|
|
137
|
+
const withConvexError = effect.pipe(
|
|
138
|
+
Effect.catchAll((typedError) =>
|
|
139
|
+
pipe(
|
|
140
|
+
Schema.encode(errorSchema)(typedError),
|
|
141
|
+
Effect.orDie,
|
|
142
|
+
Effect.andThen((encodedError) =>
|
|
143
|
+
Effect.fail(new ConvexError(encodedError)),
|
|
144
|
+
),
|
|
145
|
+
),
|
|
146
|
+
),
|
|
147
|
+
);
|
|
148
|
+
return Effect.runPromise(Effect.either(withConvexError)).then(
|
|
149
|
+
Either.match({
|
|
150
|
+
onLeft: (error) => {
|
|
151
|
+
throw error;
|
|
152
|
+
},
|
|
153
|
+
onRight: (value) => value,
|
|
154
|
+
}),
|
|
155
|
+
);
|
|
156
|
+
};
|
|
157
|
+
|
|
114
158
|
export const actionFunctionBase = <
|
|
115
159
|
Schema extends DatabaseSchema.AnyWithProps,
|
|
116
160
|
Args,
|
|
@@ -122,11 +166,13 @@ export const actionFunctionBase = <
|
|
|
122
166
|
>({
|
|
123
167
|
args,
|
|
124
168
|
returns,
|
|
169
|
+
error,
|
|
125
170
|
handler,
|
|
126
171
|
createLayer,
|
|
127
172
|
}: {
|
|
128
173
|
args: Schema.Schema<Args, ConvexArgs>;
|
|
129
174
|
returns: Schema.Schema<Returns, ConvexReturns>;
|
|
175
|
+
error: Schema.Schema<Error, Value> | undefined;
|
|
130
176
|
handler: (a: Args) => Effect.Effect<Returns, E, R>;
|
|
131
177
|
createLayer: (
|
|
132
178
|
ctx: GenericActionCtx<DataModel.ToConvex<DataModel.FromSchema<Schema>>>,
|
|
@@ -138,18 +184,17 @@ export const actionFunctionBase = <
|
|
|
138
184
|
ctx: GenericActionCtx<DataModel.ToConvex<DataModel.FromSchema<Schema>>>,
|
|
139
185
|
actualArgs: ConvexArgs,
|
|
140
186
|
): Promise<ConvexReturns> =>
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
),
|
|
151
|
-
|
|
152
|
-
),
|
|
187
|
+
Effect.gen(function* () {
|
|
188
|
+
const decodedArgs = yield* pipe(
|
|
189
|
+
actualArgs,
|
|
190
|
+
Schema.decode(args),
|
|
191
|
+
Effect.orDie,
|
|
192
|
+
);
|
|
193
|
+
const decodedReturns = yield* handler(decodedArgs).pipe(
|
|
194
|
+
Effect.provide(createLayer(ctx)),
|
|
195
|
+
);
|
|
196
|
+
return yield* pipe(decodedReturns, Schema.encode(returns), Effect.orDie);
|
|
197
|
+
}).pipe(runHandlerPromise(error)),
|
|
153
198
|
});
|
|
154
199
|
|
|
155
200
|
export type ActionServices<
|
|
@@ -157,9 +202,9 @@ export type ActionServices<
|
|
|
157
202
|
> =
|
|
158
203
|
| Scheduler.Scheduler
|
|
159
204
|
| Auth.Auth
|
|
160
|
-
| StorageReader
|
|
161
|
-
| StorageWriter
|
|
162
|
-
| StorageActionWriter
|
|
205
|
+
| StorageReader.StorageReader
|
|
206
|
+
| StorageWriter.StorageWriter
|
|
207
|
+
| StorageActionWriter.StorageActionWriter
|
|
163
208
|
| QueryRunner.QueryRunner
|
|
164
209
|
| MutationRunner.MutationRunner
|
|
165
210
|
| ActionRunner.ActionRunner
|
|
@@ -179,9 +224,9 @@ export const actionLayer = <
|
|
|
179
224
|
Layer.mergeAll(
|
|
180
225
|
Scheduler.layer(ctx.scheduler),
|
|
181
226
|
Auth.layer(ctx.auth),
|
|
182
|
-
StorageReader.layer(ctx.storage),
|
|
183
|
-
StorageWriter.layer(ctx.storage),
|
|
184
|
-
StorageActionWriter.layer(ctx.storage),
|
|
227
|
+
StorageReader.StorageReader.layer(ctx.storage),
|
|
228
|
+
StorageWriter.StorageWriter.layer(ctx.storage),
|
|
229
|
+
StorageActionWriter.StorageActionWriter.layer(ctx.storage),
|
|
185
230
|
QueryRunner.layer(ctx.runQuery),
|
|
186
231
|
MutationRunner.layer(ctx.runMutation),
|
|
187
232
|
ActionRunner.layer(ctx.runAction),
|
|
@@ -33,6 +33,7 @@ export const make = <Api_ extends Api.AnyWithPropsWithRuntime<"Node">>(
|
|
|
33
33
|
nodeActionFunction(api.databaseSchema, {
|
|
34
34
|
args: functionProvenance.args,
|
|
35
35
|
returns: functionProvenance.returns,
|
|
36
|
+
error: functionProvenance.error,
|
|
36
37
|
handler: handler as Handler.AnyConfectProvenance,
|
|
37
38
|
}),
|
|
38
39
|
);
|
|
@@ -52,10 +53,12 @@ const nodeActionFunction = <
|
|
|
52
53
|
{
|
|
53
54
|
args,
|
|
54
55
|
returns,
|
|
56
|
+
error,
|
|
55
57
|
handler,
|
|
56
58
|
}: {
|
|
57
59
|
args: Schema.Schema<Args, ConvexArgs>;
|
|
58
60
|
returns: Schema.Schema<Returns, ConvexReturns>;
|
|
61
|
+
error: Schema.Schema.AnyNoContext | undefined;
|
|
59
62
|
handler: (
|
|
60
63
|
a: Args,
|
|
61
64
|
) => Effect.Effect<
|
|
@@ -69,6 +72,7 @@ const nodeActionFunction = <
|
|
|
69
72
|
RegisteredFunction.actionFunctionBase({
|
|
70
73
|
args,
|
|
71
74
|
returns,
|
|
75
|
+
error,
|
|
72
76
|
handler,
|
|
73
77
|
createLayer: (ctx) =>
|
|
74
78
|
Layer.mergeAll(
|
package/src/Scheduler.ts
CHANGED
|
@@ -2,16 +2,11 @@ import { Ref } from "@confect/core";
|
|
|
2
2
|
import type { Scheduler as ConvexScheduler } from "convex/server";
|
|
3
3
|
import { Context, DateTime, Duration, Effect, Layer } from "effect";
|
|
4
4
|
|
|
5
|
-
type OptionalArgs<Ref_ extends Ref.AnyMutation | Ref.AnyAction> =
|
|
6
|
-
keyof Ref.Args<Ref_> extends never
|
|
7
|
-
? [args?: Ref.Args<Ref_>]
|
|
8
|
-
: [args: Ref.Args<Ref_>];
|
|
9
|
-
|
|
10
5
|
const make = (scheduler: ConvexScheduler) => ({
|
|
11
6
|
runAfter: <Ref_ extends Ref.AnyMutation | Ref.AnyAction>(
|
|
12
7
|
delay: Duration.Duration,
|
|
13
8
|
ref: Ref_,
|
|
14
|
-
...args: OptionalArgs<Ref_>
|
|
9
|
+
...args: Ref.OptionalArgs<Ref_>
|
|
15
10
|
) => {
|
|
16
11
|
const delayMs = Duration.toMillis(delay);
|
|
17
12
|
const functionReference = Ref.getFunctionReference(ref);
|
|
@@ -27,7 +22,7 @@ const make = (scheduler: ConvexScheduler) => ({
|
|
|
27
22
|
runAt: <Ref_ extends Ref.AnyMutation | Ref.AnyAction>(
|
|
28
23
|
dateTime: DateTime.DateTime,
|
|
29
24
|
ref: Ref_,
|
|
30
|
-
...args: OptionalArgs<Ref_>
|
|
25
|
+
...args: Ref.OptionalArgs<Ref_>
|
|
31
26
|
) => {
|
|
32
27
|
const timestamp = DateTime.toEpochMillis(dateTime);
|
|
33
28
|
const functionReference = Ref.getFunctionReference(ref);
|