effect-inngest 0.1.3 → 0.2.0-beta.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/dist/Client.d.ts +55 -24
  2. package/dist/Client.js +84 -25
  3. package/dist/Events.d.ts +36 -61
  4. package/dist/Events.js +5 -13
  5. package/dist/Function.d.ts +35 -15
  6. package/dist/Function.js +14 -8
  7. package/dist/Group.d.ts +5 -4
  8. package/dist/Group.js +26 -24
  9. package/dist/HttpApi.d.ts +49 -54
  10. package/dist/HttpApi.js +32 -17
  11. package/dist/_virtual/_rolldown/runtime.js +13 -0
  12. package/dist/index.js +1 -2
  13. package/dist/internal/checkpoint.d.ts +32 -0
  14. package/dist/internal/checkpoint.js +112 -0
  15. package/dist/internal/constants.js +1 -2
  16. package/dist/internal/driver.d.ts +1 -5
  17. package/dist/internal/driver.js +164 -52
  18. package/dist/internal/errors.d.ts +20 -27
  19. package/dist/internal/errors.js +29 -15
  20. package/dist/internal/handler.d.ts +4 -13
  21. package/dist/internal/handler.js +70 -43
  22. package/dist/internal/helpers.js +12 -9
  23. package/dist/internal/interrupts.d.ts +1 -2
  24. package/dist/internal/interrupts.js +1 -3
  25. package/dist/internal/memo.js +22 -20
  26. package/dist/internal/protocol.d.ts +28 -1
  27. package/dist/internal/protocol.js +84 -52
  28. package/dist/internal/signature.d.ts +5 -9
  29. package/dist/internal/signature.js +34 -18
  30. package/dist/internal/step.d.ts +5 -11
  31. package/dist/internal/step.js +48 -32
  32. package/package.json +26 -21
  33. package/src/Client.ts +244 -68
  34. package/src/Events.ts +3 -3
  35. package/src/Function.ts +52 -15
  36. package/src/Group.ts +39 -26
  37. package/src/HttpApi.ts +38 -27
  38. package/src/internal/checkpoint.ts +218 -0
  39. package/src/internal/driver.ts +241 -93
  40. package/src/internal/errors.ts +21 -14
  41. package/src/internal/handler.ts +185 -142
  42. package/src/internal/helpers.ts +9 -9
  43. package/src/internal/memo.ts +48 -33
  44. package/src/internal/protocol.ts +89 -45
  45. package/src/internal/signature.ts +76 -58
  46. package/src/internal/step.ts +84 -31
  47. package/dist/_virtual/rolldown_runtime.js +0 -18
@@ -1,12 +1,24 @@
1
- import { GeneratorOpcode, Headers as Headers$1, Opcode, UserError } from "./protocol.js";
1
+ import { make } from "./checkpoint.js";
2
+ import { GeneratorOpcode, Headers as Headers$1, Opcode, UserError, discoveryRequest, runComplete } from "./protocol.js";
3
+ import { InngestClient } from "../Client.js";
2
4
  import { isNonRetriableError, isRetryAfterError, isStepError } from "./errors.js";
3
5
  import { StepInterrupt } from "./interrupts.js";
4
6
  import { OtelAttributes } from "./constants.js";
5
- import { Step, buildHandlerContext, createStepTools } from "./step.js";
6
- import { Array as Array$1, Chunk, Duration, Effect, HashMap, Option, Predicate, Ref, Schema, pipe } from "effect";
7
- import * as Headers from "@effect/platform/Headers";
8
- import * as HttpTraceContext from "@effect/platform/HttpTraceContext";
9
-
7
+ import { buildHandlerContext, createStepTools } from "./step.js";
8
+ import * as Duration from "effect/Duration";
9
+ import * as Effect from "effect/Effect";
10
+ import * as Option from "effect/Option";
11
+ import * as Ref from "effect/Ref";
12
+ import * as Schema from "effect/Schema";
13
+ import * as Context from "effect/Context";
14
+ import "effect/Layer";
15
+ import * as Predicate from "effect/Predicate";
16
+ import * as Headers from "effect/unstable/http/Headers";
17
+ import * as Cause from "effect/Cause";
18
+ import * as HttpTraceContext from "effect/unstable/http/HttpTraceContext";
19
+ import * as Chunk from "effect/Chunk";
20
+ import * as HashMap from "effect/HashMap";
21
+ import { pipe } from "effect/Function";
10
22
  //#region src/internal/driver.ts
11
23
  /**
12
24
  * Driver execution logic.
@@ -14,20 +26,21 @@ import * as HttpTraceContext from "@effect/platform/HttpTraceContext";
14
26
  */
15
27
  const SDK_VERSION = "2.0.0";
16
28
  var ExecutionResult = class extends Schema.Class("ExecutionResult")({
17
- status: Schema.Literal(200, 206, 500),
29
+ status: Schema.Literals([
30
+ 200,
31
+ 206,
32
+ 400,
33
+ 500
34
+ ]),
18
35
  body: Schema.Unknown,
19
- headers: Schema.Record({
20
- key: Schema.String,
21
- value: Schema.String
22
- })
36
+ headers: Schema.Record(Schema.String, Schema.String)
23
37
  }) {};
24
38
  const isStepInterrupt = Schema.is(StepInterrupt);
25
- const isSomeWithValue = (v) => Predicate.isRecord(v) && Predicate.hasProperty(v, "_tag") && v._tag === "Some" && Predicate.hasProperty(v, "value");
26
- const extractStepInterrupt = (value) => pipe(Option.liftPredicate(isStepInterrupt)(value), Option.orElse(() => pipe(Option.liftPredicate(isSomeWithValue)(value), Option.flatMap((v) => Option.liftPredicate(isStepInterrupt)(v.value)))));
27
- const collectStepInterruptsFromError = (error) => pipe(extractStepInterrupt(error), Option.match({
28
- onSome: Chunk.of,
29
- onNone: () => Array.isArray(error) ? Chunk.fromIterable(Array$1.filterMap(error, extractStepInterrupt)) : Chunk.empty()
30
- }));
39
+ const collectStepInterruptsFromCause = (cause) => {
40
+ const interrupts = [];
41
+ for (const reason of cause.reasons) if (Cause.isFailReason(reason) && isStepInterrupt(reason.error)) interrupts.push(reason.error);
42
+ return Chunk.fromIterable(interrupts);
43
+ };
31
44
  const toUserError = (error) => UserError.make({
32
45
  name: Predicate.hasProperty(error, "name") ? String(error.name) : "Error",
33
46
  message: Predicate.hasProperty(error, "message") ? String(error.message) : String(error),
@@ -36,65 +49,164 @@ const toUserError = (error) => UserError.make({
36
49
  const baseHeaders = () => ({
37
50
  "Content-Type": "application/json",
38
51
  [Headers$1.SDK]: `effect-inngest:v${SDK_VERSION}`,
39
- [Headers$1.RequestVersion]: "1"
52
+ [Headers$1.RequestVersion]: "2"
40
53
  });
41
- const execute = (fn, handler, request, appName, traceHeaders = {}) => Effect.gen(function* () {
42
- const step = createStepTools(request, appName, yield* Ref.make(HashMap.empty()));
43
- const context = buildHandlerContext(fn, step, request);
54
+ const encodeOpcodes = (opcodes) => Schema.encodeSync(Schema.Array(GeneratorOpcode))(opcodes);
55
+ const execute = (fn, handler, request, appName, traceHeaders = {}, checkpointConfig = Option.none()) => Effect.gen(function* () {
56
+ const stepIdCounts = yield* Ref.make(HashMap.empty());
44
57
  const headers = baseHeaders();
45
- return yield* handler(context).pipe(Effect.provideService(Step, step), Effect.map((value) => ExecutionResult.make({
46
- status: 200,
47
- body: value,
48
- headers
49
- })), Effect.catchAll((error) => {
50
- const interrupts = collectStepInterruptsFromError(error);
58
+ const checkpointState = yield* Option.match(checkpointConfig, {
59
+ onNone: () => Effect.succeed(Option.none()),
60
+ onSome: (config) => Effect.gen(function* () {
61
+ const client = yield* InngestClient;
62
+ const state = yield* make({
63
+ config,
64
+ runId: request.ctx.run_id,
65
+ fnId: request.ctx.fn_id,
66
+ qiId: request.ctx.qi_id,
67
+ checkpointAsync: (steps) => client.checkpointAsync({
68
+ runId: request.ctx.run_id,
69
+ fnId: request.ctx.fn_id,
70
+ qiId: request.ctx.qi_id,
71
+ steps
72
+ })
73
+ });
74
+ return Option.some(state);
75
+ })
76
+ });
77
+ const context = buildHandlerContext(fn, createStepTools(request, appName, stepIdCounts, checkpointState), request);
78
+ /**
79
+ * Drain any unflushed buffered opcodes (no-op outside checkpoint mode).
80
+ * Used at every terminal branch so step results are never lost.
81
+ */
82
+ const drainBuffer = Option.match(checkpointState, {
83
+ onNone: () => Effect.succeed([]),
84
+ onSome: (state) => state.drain
85
+ });
86
+ const handlerWithRace = Option.match(checkpointState, {
87
+ onNone: () => Effect.map(handler(context), Option.some),
88
+ onSome: (state) => Effect.raceFirst(Effect.map(handler(context), Option.some), Effect.sleep(state.config.maxRuntime).pipe(Effect.tap(() => state.markRuntimeExceeded), Effect.as(Option.none())))
89
+ });
90
+ return yield* Effect.scoped(handlerWithRace).pipe(Effect.flatMap((raced) => Effect.gen(function* () {
91
+ const drained = yield* drainBuffer;
92
+ if (Option.isSome(checkpointState)) {
93
+ const terminal = (yield* checkpointState.value.isRuntimeExceeded) || Option.isNone(raced) ? discoveryRequest() : runComplete(raced.value);
94
+ const opcodes = [...drained, terminal];
95
+ return ExecutionResult.make({
96
+ status: 206,
97
+ body: encodeOpcodes(opcodes),
98
+ headers
99
+ });
100
+ }
101
+ return ExecutionResult.make({
102
+ status: 200,
103
+ body: Option.getOrThrow(raced),
104
+ headers
105
+ });
106
+ })), Effect.catchCause((cause) => Effect.gen(function* () {
107
+ const drained = yield* drainBuffer;
108
+ const interrupts = collectStepInterruptsFromCause(cause);
51
109
  if (!Chunk.isEmpty(interrupts)) {
52
110
  const interruptArray = Chunk.toReadonlyArray(interrupts);
53
- const opcodes = interruptArray.map((interrupt) => interrupt.opcode);
54
- const hasNonRetriableError = opcodes.some((op) => op.op === Opcode.StepError && Predicate.isRecord(op.error) && Predicate.hasProperty(op.error, "noRetry") && op.error.noRetry === true);
111
+ const opcodes = [...drained, ...interruptArray.map((interrupt) => interrupt.opcode)];
112
+ const hasNonRetriableError = opcodes.some((op) => op.op === Opcode.StepError && Predicate.isObject(op.error) && Predicate.hasProperty(op.error, "noRetry") && op.error.noRetry === true);
55
113
  const retryAfterMs = interruptArray.find((i) => i.retryAfterMs !== void 0)?.retryAfterMs;
56
114
  const responseHeaders = hasNonRetriableError ? {
57
115
  ...headers,
58
116
  [Headers$1.NoRetry]: "true"
59
117
  } : headers;
60
- if (retryAfterMs !== void 0) responseHeaders[Headers$1.RetryAfter] = String(Math.ceil(retryAfterMs / 1e3));
61
- const encodedOpcodes = Schema.encodeSync(Schema.Array(GeneratorOpcode))(opcodes);
62
- return Effect.succeed(ExecutionResult.make({
118
+ if (retryAfterMs !== void 0) {
119
+ responseHeaders[Headers$1.RetryAfter] = String(Math.ceil(retryAfterMs / 1e3));
120
+ responseHeaders[Headers$1.NoRetry] = "false";
121
+ }
122
+ return ExecutionResult.make({
63
123
  status: 206,
64
- body: encodedOpcodes,
124
+ body: encodeOpcodes(opcodes),
65
125
  headers: responseHeaders
66
- }));
126
+ });
67
127
  }
128
+ const errorOpt = Option.orElse(Cause.findErrorOption(cause), () => {
129
+ const dieReason = cause.reasons.find(Cause.isDieReason);
130
+ return dieReason ? Option.some(dieReason.defect) : Option.none();
131
+ });
132
+ if (Option.isNone(errorOpt)) {
133
+ if (drained.length > 0) return ExecutionResult.make({
134
+ status: 206,
135
+ body: encodeOpcodes(drained),
136
+ headers
137
+ });
138
+ return ExecutionResult.make({
139
+ status: 500,
140
+ body: {
141
+ name: "Error",
142
+ message: "Unknown error"
143
+ },
144
+ headers: {
145
+ ...headers,
146
+ [Headers$1.NoRetry]: "false"
147
+ }
148
+ });
149
+ }
150
+ const error = errorOpt.value;
68
151
  if (isRetryAfterError(error)) {
69
152
  const retryAfterMs = Duration.toMillis(error.retryAfter);
70
153
  const retryAfterSeconds = Math.ceil(retryAfterMs / 1e3);
71
- return Effect.succeed(ExecutionResult.make({
154
+ if (drained.length > 0) return ExecutionResult.make({
155
+ status: 206,
156
+ body: encodeOpcodes(drained),
157
+ headers: {
158
+ ...headers,
159
+ [Headers$1.NoRetry]: "false",
160
+ [Headers$1.RetryAfter]: String(retryAfterSeconds)
161
+ }
162
+ });
163
+ return ExecutionResult.make({
72
164
  status: 500,
73
- body: { error: toUserError(error) },
165
+ body: toUserError(error),
74
166
  headers: {
75
167
  ...headers,
76
168
  [Headers$1.NoRetry]: "false",
77
169
  [Headers$1.RetryAfter]: String(retryAfterSeconds)
78
170
  }
79
- }));
171
+ });
80
172
  }
81
- const noRetry = isNonRetriableError(error) || isStepError(error) && error.noRetry === true ? "true" : "false";
82
- return Effect.succeed(ExecutionResult.make({
83
- status: 500,
84
- body: { error: toUserError(error) },
173
+ const noRetryValue = isNonRetriableError(error) || isStepError(error) && error.noRetry === true;
174
+ const noRetry = noRetryValue ? "true" : "false";
175
+ if (drained.length > 0) return ExecutionResult.make({
176
+ status: 206,
177
+ body: encodeOpcodes(drained),
85
178
  headers: {
86
179
  ...headers,
87
180
  [Headers$1.NoRetry]: noRetry
88
181
  }
89
- }));
90
- }), Effect.catchAllDefect((defect) => Effect.succeed(ExecutionResult.make({
91
- status: 500,
92
- body: { error: toUserError(defect) },
93
- headers: {
94
- ...headers,
95
- [Headers$1.NoRetry]: "false"
96
- }
97
- }))));
182
+ });
183
+ return ExecutionResult.make({
184
+ status: noRetryValue ? 400 : 500,
185
+ body: toUserError(error),
186
+ headers: {
187
+ ...headers,
188
+ [Headers$1.NoRetry]: noRetry
189
+ }
190
+ });
191
+ })), Effect.catchDefect((defect) => Effect.gen(function* () {
192
+ const drained = yield* drainBuffer;
193
+ if (drained.length > 0) return ExecutionResult.make({
194
+ status: 206,
195
+ body: encodeOpcodes(drained),
196
+ headers: {
197
+ ...headers,
198
+ [Headers$1.NoRetry]: "false"
199
+ }
200
+ });
201
+ return ExecutionResult.make({
202
+ status: 500,
203
+ body: toUserError(defect),
204
+ headers: {
205
+ ...headers,
206
+ [Headers$1.NoRetry]: "false"
207
+ }
208
+ });
209
+ })));
98
210
  }).pipe((base) => {
99
211
  const headers = {};
100
212
  if (traceHeaders.traceparent) headers["traceparent"] = traceHeaders.traceparent;
@@ -112,6 +224,6 @@ const execute = (fn, handler, request, appName, traceHeaders = {}) => Effect.gen
112
224
  [OtelAttributes.Attempt]: request.ctx.attempt
113
225
  }
114
226
  }));
115
-
227
+ Context.Service()("effect-inngest/Driver");
116
228
  //#endregion
117
- export { execute };
229
+ export { execute };
@@ -1,34 +1,29 @@
1
1
  import * as Schema from "effect/Schema";
2
+ import * as _$effect_Cause0 from "effect/Cause";
2
3
 
3
4
  //#region src/internal/errors.d.ts
4
- declare const SendEventError_base: Schema.TaggedErrorClass<SendEventError, "SendEventError", {
5
- readonly _tag: Schema.tag<"SendEventError">;
6
- } & {
7
- message: typeof Schema.String;
8
- events: Schema.Array$<typeof Schema.String>;
9
- }>;
5
+ declare const SendEventError_base: Schema.Class<SendEventError, Schema.TaggedStruct<"SendEventError", {
6
+ readonly message: Schema.String;
7
+ readonly events: Schema.$Array<Schema.String>;
8
+ }>, _$effect_Cause0.YieldableError>;
10
9
  /**
11
10
  * @internal
12
11
  */
13
12
  declare class SendEventError extends SendEventError_base {}
14
- declare const StepError_base: Schema.TaggedErrorClass<StepError, "StepError", {
15
- readonly _tag: Schema.tag<"StepError">;
16
- } & {
17
- message: typeof Schema.String;
18
- stepId: typeof Schema.String;
19
- cause: Schema.optional<typeof Schema.Unknown>;
20
- noRetry: Schema.optional<typeof Schema.Boolean>;
21
- }>;
13
+ declare const StepError_base: Schema.Class<StepError, Schema.TaggedStruct<"StepError", {
14
+ readonly message: Schema.String;
15
+ readonly stepId: Schema.String;
16
+ readonly cause: Schema.optional<Schema.Unknown>;
17
+ readonly noRetry: Schema.optional<Schema.Boolean>;
18
+ }>, _$effect_Cause0.YieldableError>;
22
19
  /**
23
20
  * @internal
24
21
  */
25
22
  declare class StepError extends StepError_base {}
26
- declare const NonRetriableError_base: Schema.TaggedErrorClass<NonRetriableError, "NonRetriableError", {
27
- readonly _tag: Schema.tag<"NonRetriableError">;
28
- } & {
29
- message: typeof Schema.String;
30
- cause: Schema.optional<typeof Schema.Unknown>;
31
- }>;
23
+ declare const NonRetriableError_base: Schema.Class<NonRetriableError, Schema.TaggedStruct<"NonRetriableError", {
24
+ readonly message: Schema.String;
25
+ readonly cause: Schema.optional<Schema.Unknown>;
26
+ }>, _$effect_Cause0.YieldableError>;
32
27
  /**
33
28
  * Thrown to indicate that the error should not be retried.
34
29
  * Use this when you know retrying won't help (e.g., validation errors, auth failures).
@@ -37,13 +32,11 @@ declare const NonRetriableError_base: Schema.TaggedErrorClass<NonRetriableError,
37
32
  * @category errors
38
33
  */
39
34
  declare class NonRetriableError extends NonRetriableError_base {}
40
- declare const RetryAfterError_base: Schema.TaggedErrorClass<RetryAfterError, "RetryAfterError", {
41
- readonly _tag: Schema.tag<"RetryAfterError">;
42
- } & {
43
- message: typeof Schema.String;
44
- retryAfter: typeof Schema.DurationFromMillis;
45
- cause: Schema.optional<typeof Schema.Unknown>;
46
- }>;
35
+ declare const RetryAfterError_base: Schema.Class<RetryAfterError, Schema.TaggedStruct<"RetryAfterError", {
36
+ readonly message: Schema.String;
37
+ readonly retryAfter: Schema.DurationFromMillis;
38
+ readonly cause: Schema.optional<Schema.Unknown>;
39
+ }>, _$effect_Cause0.YieldableError>;
47
40
  /**
48
41
  * Thrown to indicate that the operation should be retried after a specific delay.
49
42
  * Use this for rate limiting or when you know when a resource will become available.
@@ -1,21 +1,31 @@
1
1
  import * as Schema from "effect/Schema";
2
-
3
- //#region src/internal/errors.ts
4
- /**
5
- * Internal error types for the Effect Inngest SDK.
6
- * @internal
7
- */
2
+ import * as Predicate from "effect/Predicate";
3
+ Schema.TaggedErrorClass()("SignatureError", { message: Schema.String });
4
+ Schema.TaggedErrorClass()("RegistrationError", {
5
+ message: Schema.String,
6
+ functions: Schema.Array(Schema.String)
7
+ });
8
+ Schema.TaggedErrorClass()("FunctionNotFoundError", {
9
+ message: Schema.String,
10
+ functionId: Schema.String
11
+ });
8
12
  /**
9
13
  * @internal
10
14
  */
11
- var SendEventError = class extends Schema.TaggedError()("SendEventError", {
15
+ var SendEventError = class extends Schema.TaggedErrorClass()("SendEventError", {
12
16
  message: Schema.String,
13
17
  events: Schema.Array(Schema.String)
14
18
  }) {};
19
+ Schema.TaggedErrorClass()("UseApiFetchError", {
20
+ message: Schema.String,
21
+ endpoint: Schema.Literals(["batch", "actions"]),
22
+ runId: Schema.String,
23
+ statusCode: Schema.optional(Schema.Number)
24
+ });
15
25
  /**
16
26
  * @internal
17
27
  */
18
- var StepError = class extends Schema.TaggedError()("StepError", {
28
+ var StepError = class extends Schema.TaggedErrorClass()("StepError", {
19
29
  message: Schema.String,
20
30
  stepId: Schema.String,
21
31
  cause: Schema.optional(Schema.Unknown),
@@ -24,7 +34,12 @@ var StepError = class extends Schema.TaggedError()("StepError", {
24
34
  /**
25
35
  * @internal
26
36
  */
27
- const isStepError = Schema.is(StepError);
37
+ const isStepError = Predicate.isTagged("StepError");
38
+ Schema.TaggedErrorClass()("TimeoutError", {
39
+ message: Schema.String,
40
+ stepId: Schema.optional(Schema.String),
41
+ timeout: Schema.DurationFromMillis
42
+ });
28
43
  /**
29
44
  * Thrown to indicate that the error should not be retried.
30
45
  * Use this when you know retrying won't help (e.g., validation errors, auth failures).
@@ -32,14 +47,14 @@ const isStepError = Schema.is(StepError);
32
47
  * @since 0.1.0
33
48
  * @category errors
34
49
  */
35
- var NonRetriableError = class extends Schema.TaggedError()("NonRetriableError", {
50
+ var NonRetriableError = class extends Schema.TaggedErrorClass()("NonRetriableError", {
36
51
  message: Schema.String,
37
52
  cause: Schema.optional(Schema.Unknown)
38
53
  }) {};
39
54
  /**
40
55
  * @internal
41
56
  */
42
- const isNonRetriableError = Schema.is(NonRetriableError);
57
+ const isNonRetriableError = Predicate.isTagged("NonRetriableError");
43
58
  /**
44
59
  * Thrown to indicate that the operation should be retried after a specific delay.
45
60
  * Use this for rate limiting or when you know when a resource will become available.
@@ -47,7 +62,7 @@ const isNonRetriableError = Schema.is(NonRetriableError);
47
62
  * @since 0.1.0
48
63
  * @category errors
49
64
  */
50
- var RetryAfterError = class extends Schema.TaggedError()("RetryAfterError", {
65
+ var RetryAfterError = class extends Schema.TaggedErrorClass()("RetryAfterError", {
51
66
  message: Schema.String,
52
67
  retryAfter: Schema.DurationFromMillis,
53
68
  cause: Schema.optional(Schema.Unknown)
@@ -55,7 +70,6 @@ var RetryAfterError = class extends Schema.TaggedError()("RetryAfterError", {
55
70
  /**
56
71
  * @internal
57
72
  */
58
- const isRetryAfterError = Schema.is(RetryAfterError);
59
-
73
+ const isRetryAfterError = Predicate.isTagged("RetryAfterError");
60
74
  //#endregion
61
- export { NonRetriableError, RetryAfterError, SendEventError, StepError, isNonRetriableError, isRetryAfterError, isStepError };
75
+ export { NonRetriableError, RetryAfterError, SendEventError, StepError, isNonRetriableError, isRetryAfterError, isStepError };
@@ -1,20 +1,11 @@
1
- import "../Client.js";
2
- import "./protocol.js";
3
- import "../Group.js";
4
1
  import { SignatureError } from "./signature.js";
5
- import "./driver.js";
6
- import "@effect/platform/HttpClient";
7
- import "@effect/platform/HttpServerRequest";
8
- import "effect/Context";
9
- import "effect/Effect";
10
2
  import * as Schema from "effect/Schema";
3
+ import * as Cause from "effect/Cause";
11
4
 
12
5
  //#region src/internal/handler.d.ts
13
- declare const InvalidRequestError_base: Schema.TaggedErrorClass<InvalidRequestError, "InvalidRequestError", {
14
- readonly _tag: Schema.tag<"InvalidRequestError">;
15
- } & {
16
- message: typeof Schema.String;
17
- }>;
6
+ declare const InvalidRequestError_base: Schema.Class<InvalidRequestError, Schema.TaggedStruct<"InvalidRequestError", {
7
+ readonly message: Schema.String;
8
+ }>, Cause.YieldableError>;
18
9
  declare class InvalidRequestError extends InvalidRequestError_base {}
19
10
  //#endregion
20
11
  export { InvalidRequestError };
@@ -1,27 +1,30 @@
1
- import { Headers, RegisterResponse, SDKRequestBody, SDKRequestContext, UserError } from "./protocol.js";
1
+ import { resolveConfig } from "./checkpoint.js";
2
+ import { Headers as Headers$1, RegisterServerResponse, SDKRequestBody, SDKRequestContext, UserError } from "./protocol.js";
3
+ import { Signature } from "./signature.js";
2
4
  import { InngestClient } from "../Client.js";
3
- import { Signature, SignatureError } from "./signature.js";
4
5
  import { execute } from "./driver.js";
5
- import * as HttpClient from "@effect/platform/HttpClient";
6
- import "@effect/platform/HttpServerRequest";
7
- import "effect/Context";
8
6
  import * as Effect from "effect/Effect";
7
+ import * as Option from "effect/Option";
9
8
  import * as Schema from "effect/Schema";
10
- import * as HttpClientRequest from "@effect/platform/HttpClientRequest";
11
- import * as HttpClientResponse from "@effect/platform/HttpClientResponse";
9
+ import * as HttpClient from "effect/unstable/http/HttpClient";
10
+ import "effect/unstable/http/HttpServerRequest";
11
+ import "effect/Context";
12
+ import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest";
13
+ import * as HttpClientResponse from "effect/unstable/http/HttpClientResponse";
12
14
  import * as Predicate from "effect/Predicate";
13
-
15
+ import * as Headers from "effect/unstable/http/Headers";
16
+ import * as Cause from "effect/Cause";
14
17
  //#region src/internal/handler.ts
15
18
  /**
16
19
  * Internal handler implementation.
17
20
  * @internal
18
21
  */
19
- var InvalidRequestError = class extends Schema.TaggedError()("InvalidRequestError", { message: Schema.String }) {};
22
+ var InvalidRequestError = class extends Schema.TaggedErrorClass()("InvalidRequestError", { message: Schema.String }) {};
20
23
  const SDK_VERSION = "2.0.0";
21
24
  const baseHeaders = () => ({
22
25
  "Content-Type": "application/json",
23
- [Headers.SDK]: `effect-inngest:v${SDK_VERSION}`,
24
- [Headers.RequestVersion]: "1"
26
+ [Headers$1.SDK]: `effect-inngest:v${SDK_VERSION}`,
27
+ [Headers$1.RequestVersion]: "2"
25
28
  });
26
29
  const buildServeUrl = (requestUrl, serveHost, servePath) => {
27
30
  const url = new URL(requestUrl);
@@ -29,22 +32,24 @@ const buildServeUrl = (requestUrl, serveHost, servePath) => {
29
32
  if (serveHost) return new URL(url.pathname + url.search, serveHost);
30
33
  return url;
31
34
  };
32
- const verifyAndParseRequestBody = (request) => Effect.gen(function* () {
35
+ const verifyAndParseRequestBody = Effect.fn("effect-inngest/handler/verifyAndParseRequestBody")(function* (request) {
33
36
  const client = yield* InngestClient;
34
37
  const sig = yield* Signature;
35
38
  const config = client.config;
36
39
  const isDev = client.mode === "dev";
37
- const bodyText = yield* request.text.pipe(Effect.mapError((error) => new InvalidRequestError({ message: `Failed to read request body: ${String(error)}` })));
40
+ const bodyText = yield* request.text.pipe(Effect.mapError((error) => {
41
+ return new InvalidRequestError({ message: `Failed to read request body: ${Predicate.hasProperty(error, "message") && typeof error.message === "string" ? error.message : "unknown"}` });
42
+ }));
38
43
  yield* sig.verify({
39
44
  body: new TextEncoder().encode(bodyText),
40
- signatureHeader: request.headers[Headers.Signature.toLowerCase()],
45
+ signatureHeader: Option.getOrUndefined(Headers.get(request.headers, Headers$1.Signature)),
41
46
  signingKey: config.signingKey,
42
47
  signingKeyFallback: config.signingKeyFallback,
43
48
  isDev
44
49
  });
45
- return yield* Schema.decodeUnknown(Schema.parseJson(SDKRequestBody))(bodyText).pipe(Effect.mapError((error) => new InvalidRequestError({ message: `Invalid request body: ${String(error)}` })));
50
+ return yield* Schema.decodeUnknownEffect(Schema.fromJsonString(SDKRequestBody))(bodyText).pipe(Effect.mapError((error) => new InvalidRequestError({ message: `Invalid request body: ${String(error)}` })));
46
51
  });
47
- const handleIntrospection = (group, _requestUrl) => Effect.gen(function* () {
52
+ const handleIntrospection = Effect.fn("effect-inngest/handler/handleIntrospection")(function* (group, _requestUrl) {
48
53
  const client = yield* InngestClient;
49
54
  const config = client.config;
50
55
  const body = {
@@ -62,16 +67,7 @@ const handleIntrospection = (group, _requestUrl) => Effect.gen(function* () {
62
67
  body
63
68
  };
64
69
  });
65
- const RegisterRequest = Schema.Struct({
66
- url: Schema.String,
67
- v: Schema.String,
68
- deployType: Schema.Literal("ping"),
69
- sdk: Schema.String,
70
- appName: Schema.String,
71
- framework: Schema.String,
72
- functions: Schema.Array(Schema.Unknown)
73
- });
74
- const handleRegistration = (group, requestUrl) => Effect.gen(function* () {
70
+ const handleRegistration = Effect.fn("effect-inngest/handler/handleRegistration")(function* (group, requestUrl) {
75
71
  const client = yield* InngestClient;
76
72
  const httpClient = yield* HttpClient.HttpClient;
77
73
  const config = client.config;
@@ -81,10 +77,10 @@ const handleRegistration = (group, requestUrl) => Effect.gen(function* () {
81
77
  url: url.href
82
78
  }));
83
79
  const registerUrl = new URL("fn/register", client.apiBaseUrl).toString();
84
- const response = yield* HttpClientRequest.post(registerUrl).pipe(HttpClientRequest.setHeaders({
80
+ const request = HttpClientRequest.post(registerUrl).pipe(HttpClientRequest.setHeaders({
85
81
  ...baseHeaders(),
86
82
  Authorization: `Bearer ${config.signingKey ?? ""}`
87
- }), HttpClientRequest.schemaBodyJson(RegisterRequest)({
83
+ }), HttpClientRequest.bodyJsonUnsafe({
88
84
  url: url.href,
89
85
  v: "0.1",
90
86
  deployType: "ping",
@@ -92,31 +88,58 @@ const handleRegistration = (group, requestUrl) => Effect.gen(function* () {
92
88
  appName: config.id,
93
89
  framework: "effect",
94
90
  functions
95
- })).pipe(Effect.flatMap(httpClient.execute), Effect.flatMap(HttpClientResponse.schemaBodyJson(RegisterResponse)), Effect.scoped, Effect.catchAll((error) => Effect.succeed({ message: `Registration failed: ${Predicate.hasProperty(error, "message") ? error.message : "Unknown error"}` })));
96
- return {
97
- status: 200,
98
- headers: baseHeaders(),
99
- body: response
100
- };
91
+ }));
92
+ return yield* Effect.gen(function* () {
93
+ const response = yield* httpClient.execute(request).pipe(Effect.scoped);
94
+ const responseBody = yield* HttpClientResponse.schemaBodyJson(RegisterServerResponse)(response).pipe(Effect.catch(() => Effect.succeed({ error: "Unknown registration response" })));
95
+ if (response.status !== 200 || !Predicate.hasProperty(responseBody, "ok")) return {
96
+ status: 500,
97
+ headers: baseHeaders(),
98
+ body: {
99
+ message: Predicate.hasProperty(responseBody, "error") && responseBody.error ? responseBody.error : `Registration failed with status ${response.status}`,
100
+ modified: false
101
+ }
102
+ };
103
+ return {
104
+ status: 200,
105
+ headers: baseHeaders(),
106
+ body: {
107
+ message: "Successfully synced.",
108
+ modified: responseBody.modified ?? false
109
+ }
110
+ };
111
+ }).pipe(Effect.catchCause((cause) => {
112
+ const errorOpt = Cause.findErrorOption(cause);
113
+ const dieReason = cause.reasons.find(Cause.isDieReason);
114
+ const message = Option.isSome(errorOpt) ? Predicate.hasProperty(errorOpt.value, "message") && typeof errorOpt.value.message === "string" ? errorOpt.value.message : "Registration failed" : dieReason ? Predicate.hasProperty(dieReason.defect, "message") && typeof dieReason.defect.message === "string" ? dieReason.defect.message : "Registration failed" : "Registration failed";
115
+ return Effect.succeed({
116
+ status: 500,
117
+ headers: baseHeaders(),
118
+ body: {
119
+ message,
120
+ modified: false
121
+ }
122
+ });
123
+ }));
101
124
  });
102
- const handleExecution = (group, fnId, urlStepId, body, traceHeaders = {}) => Effect.gen(function* () {
125
+ const handleExecution = Effect.fn("effect-inngest/handler/handleExecution")(function* (group, fnId, urlStepId, body, traceHeaders = {}) {
103
126
  const client = yield* InngestClient;
104
127
  const context = yield* Effect.context();
105
128
  const appId = client.config.id;
106
129
  const prefix = `${appId}-`;
107
130
  const fnTag = fnId.startsWith(prefix) ? fnId.slice(prefix.length) : fnId;
108
131
  const fn = group.functions.get(fnTag);
109
- const entry = fn ? context.unsafeMap.get(fn.key) : void 0;
132
+ const entry = fn ? context.mapUnsafe.get(fn.key) : void 0;
110
133
  if (!fn || !entry) return {
111
- status: 404,
134
+ status: 500,
112
135
  headers: {
113
136
  ...baseHeaders(),
114
- [Headers.NoRetry]: "true"
137
+ [Headers$1.NoRetry]: "false"
115
138
  },
116
- body: { error: UserError.make({
139
+ body: UserError.make({
117
140
  name: "FunctionNotFoundError",
118
141
  message: `Unknown function: ${fnId}`
119
- }) }
142
+ })
120
143
  };
121
144
  const effectiveBody = urlStepId && urlStepId !== body.ctx.step_id ? SDKRequestBody.make({
122
145
  event: body.event,
@@ -125,21 +148,25 @@ const handleExecution = (group, fnId, urlStepId, body, traceHeaders = {}) => Eff
125
148
  ctx: SDKRequestContext.make({
126
149
  fn_id: body.ctx.fn_id,
127
150
  run_id: body.ctx.run_id,
151
+ env: body.ctx.env,
128
152
  step_id: urlStepId,
129
153
  attempt: body.ctx.attempt,
154
+ max_attempts: body.ctx.max_attempts,
155
+ qi_id: body.ctx.qi_id,
130
156
  disable_immediate_execution: body.ctx.disable_immediate_execution,
131
157
  use_api: body.ctx.use_api,
132
158
  stack: body.ctx.stack
133
159
  }),
160
+ version: body.version,
134
161
  use_api: body.use_api
135
162
  }) : body;
136
- const result = yield* Effect.provide(execute(fn, entry.handler, effectiveBody, appId, traceHeaders), entry.context);
163
+ const checkpointConfig = !urlStepId && effectiveBody.ctx.fn_id !== "" && !effectiveBody.ctx.disable_immediate_execution ? Option.fromNullishOr(resolveConfig(fn.options.checkpointing, client.config.checkpointing)) : Option.none();
164
+ const result = yield* Effect.provide(execute(fn, entry.handler, effectiveBody, appId, traceHeaders, checkpointConfig), entry.context);
137
165
  return {
138
166
  status: result.status,
139
167
  headers: result.headers,
140
168
  body: result.body
141
169
  };
142
170
  });
143
-
144
171
  //#endregion
145
- export { InvalidRequestError, handleExecution, handleIntrospection, handleRegistration, verifyAndParseRequestBody };
172
+ export { InvalidRequestError, handleExecution, handleIntrospection, handleRegistration, verifyAndParseRequestBody };