@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.
Files changed (47) hide show
  1. package/CHANGELOG.md +145 -1
  2. package/dist/ActionRunner.d.ts +3 -5
  3. package/dist/ActionRunner.d.ts.map +1 -1
  4. package/dist/ActionRunner.js +1 -1
  5. package/dist/ActionRunner.js.map +1 -1
  6. package/dist/CronJob.d.ts +1 -2
  7. package/dist/CronJob.d.ts.map +1 -1
  8. package/dist/CronJob.js.map +1 -1
  9. package/dist/DatabaseReader.d.ts +5 -5
  10. package/dist/DatabaseWriter.d.ts +4 -4
  11. package/dist/DatabaseWriter.d.ts.map +1 -1
  12. package/dist/Handler.d.ts +1 -1
  13. package/dist/Handler.d.ts.map +1 -1
  14. package/dist/Handler.js.map +1 -1
  15. package/dist/MutationRunner.d.ts +5 -16
  16. package/dist/MutationRunner.d.ts.map +1 -1
  17. package/dist/MutationRunner.js +3 -13
  18. package/dist/MutationRunner.js.map +1 -1
  19. package/dist/QueryInitializer.d.ts +1 -1
  20. package/dist/QueryInitializer.d.ts.map +1 -1
  21. package/dist/QueryRunner.d.ts +3 -5
  22. package/dist/QueryRunner.d.ts.map +1 -1
  23. package/dist/QueryRunner.js +1 -1
  24. package/dist/QueryRunner.js.map +1 -1
  25. package/dist/RegisteredConvexFunction.d.ts +8 -8
  26. package/dist/RegisteredConvexFunction.d.ts.map +1 -1
  27. package/dist/RegisteredConvexFunction.js +41 -9
  28. package/dist/RegisteredConvexFunction.js.map +1 -1
  29. package/dist/RegisteredFunction.d.ts +26 -7
  30. package/dist/RegisteredFunction.d.ts.map +1 -1
  31. package/dist/RegisteredFunction.js +34 -5
  32. package/dist/RegisteredFunction.js.map +1 -1
  33. package/dist/RegisteredNodeFunction.js +3 -1
  34. package/dist/RegisteredNodeFunction.js.map +1 -1
  35. package/dist/Scheduler.d.ts +6 -7
  36. package/dist/Scheduler.d.ts.map +1 -1
  37. package/dist/Scheduler.js.map +1 -1
  38. package/package.json +5 -5
  39. package/src/ActionRunner.ts +13 -3
  40. package/src/CronJob.ts +1 -4
  41. package/src/Handler.ts +5 -1
  42. package/src/MutationRunner.ts +12 -19
  43. package/src/QueryRunner.ts +13 -3
  44. package/src/RegisteredConvexFunction.ts +121 -65
  45. package/src/RegisteredFunction.ts +67 -22
  46. package/src/RegisteredNodeFunction.ts +4 -0
  47. package/src/Scheduler.ts +2 -7
@@ -1,15 +1,22 @@
1
1
  import * as Ref from "@confect/core/Ref";
2
2
  import { type GenericMutationCtx } from "convex/server";
3
- import { Context, Layer, Schema } from "effect";
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.Args<Mutation>,
10
- ) =>
11
- Ref.runWithCodec(mutation, args, (functionReference, encodedArgs) =>
12
- runMutation(functionReference, encodedArgs),
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
- }
@@ -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>(query: Query, args: Ref.Args<Query>) =>
8
- Ref.runWithCodec(query, args, (functionReference, encodedArgs) =>
9
- runQuery(functionReference, encodedArgs),
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 { Effect, Layer, Match, pipe, Schema } from "effect";
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(api.databaseSchema, {
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(api.databaseSchema, {
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: DatabaseSchema_,
104
- {
105
- args,
106
- returns,
107
- handler,
108
- }: {
109
- args: Schema.Schema<Args, ConvexArgs>;
110
- returns: Schema.Schema<Returns, ConvexReturns>;
111
- handler: (
112
- a: Args,
113
- ) => Effect.Effect<
114
- Returns,
115
- E,
116
- | DatabaseReader.DatabaseReader<DatabaseSchema_>
117
- | Auth.Auth
118
- | StorageReader
119
- | QueryRunner.QueryRunner
120
- | QueryCtx.QueryCtx<
121
- DataModel.ToConvex<DataModel.FromSchema<DatabaseSchema_>>
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
- pipe(
135
- actualArgs,
136
- Schema.decode(args),
137
- Effect.orDie,
138
- Effect.andThen((decodedArgs) =>
139
- pipe(
140
- handler(decodedArgs),
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
- Effect.andThen((convexReturns) =>
159
- Schema.encodeUnknown(returns)(convexReturns),
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
- Schema extends DatabaseSchema.AnyWithProps,
248
+ DatabaseSchema_ extends DatabaseSchema.AnyWithProps,
200
249
  Args,
201
250
  ConvexArgs extends DefaultFunctionArgs,
202
251
  Returns,
203
252
  ConvexReturns,
204
253
  E,
205
- >(
206
- schema: Schema,
207
- {
208
- args,
209
- returns,
210
- handler,
211
- }: {
212
- args: Schema.Schema<Args, ConvexArgs>;
213
- returns: Schema.Schema<Returns, ConvexReturns>;
214
- handler: (a: Args) => Effect.Effect<Returns, E, MutationServices<Schema>>;
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<DataModel.ToConvex<DataModel.FromSchema<Schema>>>,
272
+ ctx: GenericMutationCtx<
273
+ DataModel.ToConvex<DataModel.FromSchema<DatabaseSchema_>>
274
+ >,
221
275
  actualArgs: ConvexArgs,
222
276
  ): Promise<ConvexReturns> =>
223
- pipe(
224
- actualArgs,
225
- Schema.decode(args),
226
- Effect.orDie,
227
- Effect.andThen((decodedArgs) =>
228
- handler(decodedArgs).pipe(Effect.provide(mutationLayer(schema, ctx))),
229
- ),
230
- Effect.andThen((convexReturns) =>
231
- Schema.encodeUnknown(returns)(convexReturns),
232
- ),
233
- Effect.runPromise,
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 { Effect, Layer, pipe, Schema } from "effect";
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 { StorageActionWriter } from "./StorageActionWriter";
22
- import { StorageReader } from "./StorageReader";
23
- import { StorageWriter } from "./StorageWriter";
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
- pipe(
142
- actualArgs,
143
- Schema.decode(args),
144
- Effect.orDie,
145
- Effect.andThen((decodedArgs) =>
146
- handler(decodedArgs).pipe(Effect.provide(createLayer(ctx))),
147
- ),
148
- Effect.andThen((convexReturns) =>
149
- Schema.encodeUnknown(returns)(convexReturns),
150
- ),
151
- Effect.runPromise,
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);