effect-inngest 0.1.2 → 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 +83 -32
  47. package/dist/_virtual/rolldown_runtime.js +0 -18
@@ -1,11 +1,12 @@
1
1
  import * as Duration from "effect/Duration";
2
-
2
+ import * as DateTime from "effect/DateTime";
3
3
  //#region src/internal/helpers.ts
4
4
  /**
5
5
  * Internal helper utilities.
6
6
  * @internal
7
7
  */
8
- const second = 1 * 1e3;
8
+ const millisecond = 1;
9
+ const second = millisecond * 1e3;
9
10
  const minute = second * 60;
10
11
  const hour = minute * 60;
11
12
  const day = hour * 24;
@@ -14,7 +15,8 @@ const periods = [
14
15
  ["d", day],
15
16
  ["h", hour],
16
17
  ["m", minute],
17
- ["s", second]
18
+ ["s", second],
19
+ ["ms", millisecond]
18
20
  ];
19
21
  /**
20
22
  * Convert a Duration to an Inngest-compatible time string (e.g. `"1d"` or `"2h30m"`).
@@ -23,7 +25,7 @@ const periods = [
23
25
  * to their equivalent in weeks/days.
24
26
  */
25
27
  const timeStr = (input) => {
26
- let ms = Duration.toMillis(Duration.decode(input));
28
+ let ms = Duration.toMillis(Duration.fromInputUnsafe(input));
27
29
  const [, result] = periods.reduce(([num, str], [suffix, period]) => {
28
30
  const numPeriods = Math.floor(num / period);
29
31
  if (numPeriods > 0) return [num % period, `${str}${numPeriods}${suffix}`];
@@ -33,12 +35,13 @@ const timeStr = (input) => {
33
35
  };
34
36
  /**
35
37
  * Format a timestamp as an ISO string for Inngest's sleepUntil.
38
+ *
39
+ * String inputs are passed through unchanged (assumed ISO-formatted), matching
40
+ * the prior contract. Date/number inputs are normalized via DateTime.
36
41
  */
37
42
  const formatTimestamp = (timestamp) => {
38
- if (timestamp instanceof Date) return timestamp.toISOString();
39
- if (typeof timestamp === "number") return new Date(timestamp).toISOString();
40
- return timestamp;
43
+ if (typeof timestamp === "string") return timestamp;
44
+ return DateTime.formatIso(DateTime.makeUnsafe(timestamp));
41
45
  };
42
-
43
46
  //#endregion
44
- export { formatTimestamp, timeStr };
47
+ export { formatTimestamp, timeStr };
@@ -1,2 +1 @@
1
- import "./protocol.js";
2
- import "effect/Schema";
1
+ export { };
@@ -1,7 +1,6 @@
1
1
  import { GeneratorOpcode, UserError, invokeFunction, sleep, stepError, stepPlanned, stepRun, waitForEvent } from "./protocol.js";
2
2
  import * as Schema from "effect/Schema";
3
3
  import * as Predicate from "effect/Predicate";
4
-
5
4
  //#region src/internal/interrupts.ts
6
5
  /**
7
6
  * StepInterrupt schema and factory functions.
@@ -40,6 +39,5 @@ const errorInterrupt = (opts) => StepInterrupt.make({
40
39
  opcode: stepError(opts.info, toUserError(opts.error), opts.noRetry),
41
40
  retryAfterMs: opts.retryAfterMs
42
41
  });
43
-
44
42
  //#endregion
45
- export { StepInterrupt, errorInterrupt, invokeInterrupt, plannedInterrupt, runInterrupt, sleepInterrupt, waitForEventInterrupt };
43
+ export { StepInterrupt, errorInterrupt, invokeInterrupt, plannedInterrupt, runInterrupt, sleepInterrupt, waitForEventInterrupt };
@@ -1,56 +1,58 @@
1
+ import * as Option from "effect/Option";
1
2
  import * as Schema from "effect/Schema";
2
3
  import * as Predicate from "effect/Predicate";
3
-
4
+ import * as SchemaTransformation from "effect/SchemaTransformation";
4
5
  //#region src/internal/memo.ts
5
6
  /**
6
7
  * Step memoization schemas for decoding cached step results.
7
8
  * @internal
8
9
  */
9
- const hasKey = (key) => (u) => Predicate.isRecord(u) && Predicate.hasProperty(u, key);
10
+ const hasKey = (key) => (u) => Predicate.isObject(u) && Predicate.hasProperty(u, key);
10
11
  const MemoDataSchema = Schema.TaggedStruct("MemoData", { data: Schema.Unknown });
11
12
  const MemoErrorSchema = Schema.TaggedStruct("MemoError", { error: Schema.Unknown });
12
13
  const MemoInputSchema = Schema.TaggedStruct("MemoInput", { input: Schema.Unknown });
13
14
  const MemoTimeoutSchema = Schema.TaggedStruct("MemoTimeout", {});
14
15
  const MemoNoneSchema = Schema.TaggedStruct("MemoNone", {});
15
- const DataWire = Schema.Unknown.pipe(Schema.filter(hasKey("data")), Schema.transform(MemoDataSchema, {
16
+ const DataWire = Schema.Unknown.pipe(Schema.check(Schema.makeFilter(hasKey("data"))), Schema.decodeTo(MemoDataSchema, SchemaTransformation.transform({
16
17
  decode: (v) => ({
17
18
  _tag: "MemoData",
18
19
  data: v.data
19
20
  }),
20
21
  encode: ({ data }) => ({ data })
21
- }));
22
- const ErrorWire = Schema.Unknown.pipe(Schema.filter(hasKey("error")), Schema.transform(MemoErrorSchema, {
22
+ })));
23
+ const ErrorWire = Schema.Unknown.pipe(Schema.check(Schema.makeFilter(hasKey("error"))), Schema.decodeTo(MemoErrorSchema, SchemaTransformation.transform({
23
24
  decode: (v) => ({
24
25
  _tag: "MemoError",
25
26
  error: v.error
26
27
  }),
27
28
  encode: ({ error }) => ({ error })
28
- }));
29
- const InputWire = Schema.Unknown.pipe(Schema.filter(hasKey("input")), Schema.transform(MemoInputSchema, {
29
+ })));
30
+ const InputWire = Schema.Unknown.pipe(Schema.check(Schema.makeFilter(hasKey("input"))), Schema.decodeTo(MemoInputSchema, SchemaTransformation.transform({
30
31
  decode: (v) => ({
31
32
  _tag: "MemoInput",
32
33
  input: v.input
33
34
  }),
34
35
  encode: ({ input }) => ({ input })
35
- }));
36
- const TimeoutWire = Schema.transform(Schema.Null, MemoTimeoutSchema, {
36
+ })));
37
+ const TimeoutWire = Schema.Null.pipe(Schema.decodeTo(MemoTimeoutSchema, SchemaTransformation.transform({
37
38
  decode: () => ({ _tag: "MemoTimeout" }),
38
39
  encode: () => null
39
- });
40
- const NoneWire = Schema.transform(Schema.Undefined, MemoNoneSchema, {
40
+ })));
41
+ const NoneWire = Schema.Undefined.pipe(Schema.decodeTo(MemoNoneSchema, SchemaTransformation.transform({
41
42
  decode: () => ({ _tag: "MemoNone" }),
42
43
  encode: () => void 0
43
- });
44
- const MemoSchema = Schema.Union(ErrorWire, InputWire, DataWire, TimeoutWire, NoneWire);
44
+ })));
45
+ const MemoSchema = Schema.Union([
46
+ ErrorWire,
47
+ InputWire,
48
+ DataWire,
49
+ TimeoutWire,
50
+ NoneWire
51
+ ]);
45
52
  /**
46
53
  * Decode a step result into a Memo type.
47
54
  * Order matters: error > input > data (more specific properties first).
48
55
  */
49
- const decodeMemo = (value) => {
50
- const result = Schema.decodeUnknownOption(MemoSchema)(value);
51
- if (result._tag === "Some") return result.value;
52
- return MemoNoneSchema.make();
53
- };
54
-
56
+ const decodeMemo = (value) => Option.getOrElse(Schema.decodeUnknownOption(MemoSchema)(value), () => MemoNoneSchema.make({}));
55
57
  //#endregion
56
- export { decodeMemo };
58
+ export { decodeMemo };
@@ -1 +1,28 @@
1
- import "effect/Schema";
1
+ import * as Schema from "effect/Schema";
2
+
3
+ //#region src/internal/protocol.d.ts
4
+ declare const UserError_base: Schema.Class<UserError, Schema.Struct<{
5
+ readonly name: Schema.String;
6
+ readonly message: Schema.String;
7
+ readonly stack: Schema.optional<Schema.String>;
8
+ readonly data: Schema.optional<Schema.Unknown>;
9
+ readonly noRetry: Schema.optional<Schema.Boolean>;
10
+ readonly cause: Schema.optional<Schema.Unknown>;
11
+ }>, {}>;
12
+ declare class UserError extends UserError_base {}
13
+ declare const GeneratorOpcode_base: Schema.Class<GeneratorOpcode, Schema.Struct<{
14
+ readonly op: Schema.Literals<readonly ["None", "Step", "StepRun", "StepError", "StepPlanned", "Sleep", "WaitForEvent", "InvokeFunction", "AIGateway", "Gateway", "WaitForSignal", "RunComplete", "StepFailed", "SyncRunComplete", "DiscoveryRequest"]>;
15
+ readonly id: Schema.String;
16
+ readonly name: Schema.String;
17
+ readonly mode: Schema.optional<Schema.Literals<readonly ["sync", "async"]>>;
18
+ readonly opts: Schema.optional<Schema.decodeTo<Schema.Unknown, Schema.Unknown, never, never>>;
19
+ readonly data: Schema.optional<Schema.decodeTo<Schema.Unknown, Schema.Unknown, never, never>>;
20
+ readonly error: Schema.optional<typeof UserError>;
21
+ readonly displayName: Schema.optional<Schema.String>;
22
+ readonly userland: Schema.optional<Schema.Struct<{
23
+ readonly id: Schema.String;
24
+ }>>;
25
+ }>, {}>;
26
+ declare class GeneratorOpcode extends GeneratorOpcode_base {}
27
+ //#endregion
28
+ export { GeneratorOpcode };
@@ -1,20 +1,18 @@
1
- import { Predicate, Struct } from "effect";
1
+ import { Effect, Predicate, SchemaTransformation, Struct } from "effect";
2
2
  import * as Schema$1 from "effect/Schema";
3
-
4
3
  //#region src/internal/protocol.ts
5
4
  /**
6
5
  * Wire protocol schemas and opcode factories for Inngest communication.
7
6
  * @internal
8
7
  */
9
8
  const stripTopLevelTag = (value) => {
10
- if (Predicate.isRecord(value)) return Struct.omit(value, "_tag");
9
+ if (Predicate.isObject(value)) return Struct.omit(value, ["_tag"]);
11
10
  return value;
12
11
  };
13
- const WireUnknown = Schema$1.transform(Schema$1.Unknown, Schema$1.Unknown, {
14
- strict: true,
12
+ const WireUnknown = Schema$1.Unknown.pipe(Schema$1.decodeTo(Schema$1.Unknown, SchemaTransformation.transform({
15
13
  decode: (value) => value,
16
14
  encode: (value) => stripTopLevelTag(value)
17
- });
15
+ })));
18
16
  const Opcode = {
19
17
  None: "None",
20
18
  Step: "Step",
@@ -40,10 +38,7 @@ var UserError = class extends Schema$1.Class("UserError")({
40
38
  noRetry: Schema$1.optional(Schema$1.Boolean),
41
39
  cause: Schema$1.optional(Schema$1.Unknown)
42
40
  }) {};
43
- const StepResult = Schema$1.NullOr(Schema$1.Record({
44
- key: Schema$1.String,
45
- value: Schema$1.Unknown
46
- }).pipe(Schema$1.annotations({ identifier: "StepResultObject" })));
41
+ const StepResult = Schema$1.NullOr(Schema$1.Record(Schema$1.String, Schema$1.Unknown).pipe(Schema$1.annotate({ identifier: "StepResultObject" })));
47
42
  var FunctionStack = class extends Schema$1.Class("FunctionStack")({
48
43
  stack: Schema$1.Array(Schema$1.String),
49
44
  current: Schema$1.Number
@@ -51,45 +46,33 @@ var FunctionStack = class extends Schema$1.Class("FunctionStack")({
51
46
  var InngestEvent = class extends Schema$1.Class("InngestEvent")({
52
47
  id: Schema$1.optional(Schema$1.String),
53
48
  name: Schema$1.String,
54
- data: Schema$1.optionalWith(Schema$1.Record({
55
- key: Schema$1.String,
56
- value: Schema$1.Unknown
57
- }), {
58
- default: () => ({}),
59
- nullable: true
60
- }),
49
+ data: Schema$1.NullOr(Schema$1.Record(Schema$1.String, Schema$1.Unknown)).pipe(Schema$1.withDecodingDefaultType(Effect.succeed({}))),
61
50
  ts: Schema$1.optional(Schema$1.Number),
62
- user: Schema$1.optional(Schema$1.Record({
63
- key: Schema$1.String,
64
- value: Schema$1.Unknown
65
- })),
51
+ user: Schema$1.optional(Schema$1.Record(Schema$1.String, Schema$1.Unknown)),
66
52
  v: Schema$1.optional(Schema$1.String)
67
53
  }) {};
68
54
  var SDKRequestContext = class extends Schema$1.Class("SDKRequestContext")({
69
55
  fn_id: Schema$1.String,
70
56
  run_id: Schema$1.String,
71
- env: Schema$1.optionalWith(Schema$1.String, { default: () => "dev" }),
72
- step_id: Schema$1.optionalWith(Schema$1.String, { default: () => "step" }),
73
- attempt: Schema$1.optionalWith(Schema$1.Number, { default: () => 0 }),
74
- max_attempts: Schema$1.optionalWith(Schema$1.Number, { default: () => 4 }),
75
- stack: Schema$1.optionalWith(FunctionStack, { default: () => FunctionStack.make({
57
+ env: Schema$1.String.pipe(Schema$1.withDecodingDefault(Effect.succeed("dev"))),
58
+ step_id: Schema$1.String.pipe(Schema$1.withDecodingDefault(Effect.succeed("step"))),
59
+ attempt: Schema$1.Number.pipe(Schema$1.withDecodingDefault(Effect.succeed(0))),
60
+ max_attempts: Schema$1.Number.pipe(Schema$1.withDecodingDefault(Effect.succeed(4))),
61
+ stack: FunctionStack.pipe(Schema$1.withDecodingDefaultType(Effect.succeed(FunctionStack.make({
76
62
  stack: [],
77
63
  current: 0
78
- }) }),
79
- qi_id: Schema$1.optionalWith(Schema$1.String, { default: () => "" }),
80
- disable_immediate_execution: Schema$1.optionalWith(Schema$1.Boolean, { default: () => false }),
81
- use_api: Schema$1.optionalWith(Schema$1.Boolean, { default: () => false })
64
+ })))),
65
+ qi_id: Schema$1.String.pipe(Schema$1.withDecodingDefault(Effect.succeed(""))),
66
+ disable_immediate_execution: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(false))),
67
+ use_api: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(false)))
82
68
  }) {};
83
69
  var SDKRequestBody = class extends Schema$1.Class("SDKRequestBody")({
84
70
  event: InngestEvent,
85
71
  events: Schema$1.Array(InngestEvent),
86
- steps: Schema$1.optionalWith(Schema$1.Record({
87
- key: Schema$1.String,
88
- value: StepResult
89
- }), { default: () => ({}) }),
72
+ steps: Schema$1.Record(Schema$1.String, StepResult).pipe(Schema$1.withDecodingDefault(Effect.succeed({}))),
90
73
  ctx: SDKRequestContext,
91
- version: Schema$1.optionalWith(Schema$1.Number, { default: () => 1 }),
92
- use_api: Schema$1.optionalWith(Schema$1.Boolean, { default: () => false })
74
+ version: Schema$1.Number.pipe(Schema$1.withDecodingDefault(Effect.succeed(1))),
75
+ use_api: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(false)))
93
76
  }) {};
94
77
  const Headers = {
95
78
  SDK: "X-Inngest-SDK",
@@ -105,10 +88,26 @@ const Headers = {
105
88
  Env: "X-Inngest-Env"
106
89
  };
107
90
  var GeneratorOpcode = class extends Schema$1.Class("GeneratorOpcode")({
108
- op: Schema$1.Literal(Opcode.None, Opcode.Step, Opcode.StepRun, Opcode.StepError, Opcode.StepPlanned, Opcode.Sleep, Opcode.WaitForEvent, Opcode.InvokeFunction, Opcode.AIGateway, Opcode.Gateway, Opcode.WaitForSignal, Opcode.RunComplete, Opcode.StepFailed, Opcode.SyncRunComplete, Opcode.DiscoveryRequest),
91
+ op: Schema$1.Literals([
92
+ Opcode.None,
93
+ Opcode.Step,
94
+ Opcode.StepRun,
95
+ Opcode.StepError,
96
+ Opcode.StepPlanned,
97
+ Opcode.Sleep,
98
+ Opcode.WaitForEvent,
99
+ Opcode.InvokeFunction,
100
+ Opcode.AIGateway,
101
+ Opcode.Gateway,
102
+ Opcode.WaitForSignal,
103
+ Opcode.RunComplete,
104
+ Opcode.StepFailed,
105
+ Opcode.SyncRunComplete,
106
+ Opcode.DiscoveryRequest
107
+ ]),
109
108
  id: Schema$1.String,
110
109
  name: Schema$1.String,
111
- mode: Schema$1.optional(Schema$1.Literal("sync", "async")),
110
+ mode: Schema$1.optional(Schema$1.Literals(["sync", "async"])),
112
111
  opts: Schema$1.optional(WireUnknown),
113
112
  data: Schema$1.optional(WireUnknown),
114
113
  error: Schema$1.optional(UserError),
@@ -138,7 +137,8 @@ const sleep = (info, duration) => GeneratorOpcode.make({
138
137
  id: info.hash,
139
138
  name: duration,
140
139
  displayName: info.name,
141
- mode: "async"
140
+ mode: "async",
141
+ opts: { duration }
142
142
  });
143
143
  const waitForEvent = (info, opts) => mkOpcode(info, Opcode.WaitForEvent, {
144
144
  mode: "async",
@@ -149,23 +149,41 @@ const invokeFunction = (info, opts) => mkOpcode(info, Opcode.InvokeFunction, {
149
149
  opts,
150
150
  userland: { id: info.id }
151
151
  });
152
+ /**
153
+ * Terminal opcode emitted by the SDK in checkpoint mode when the function
154
+ * completes successfully. The executor uses this to correlate run completion
155
+ * (spec §10.4.1).
156
+ */
157
+ const runComplete = (data) => GeneratorOpcode.make({
158
+ op: Opcode.RunComplete,
159
+ id: "step",
160
+ name: "step",
161
+ data
162
+ });
163
+ /**
164
+ * Yield opcode emitted by the SDK in checkpoint mode when `maxRuntime` is
165
+ * exceeded. Tells the executor to schedule a new Call Request to continue
166
+ * execution (spec §10.4.1).
167
+ */
168
+ const discoveryRequest = () => GeneratorOpcode.make({
169
+ op: Opcode.DiscoveryRequest,
170
+ id: "step",
171
+ name: "step"
172
+ });
152
173
  const IntrospectionBase = Schema$1.Struct({
153
174
  function_count: Schema$1.Number,
154
175
  has_event_key: Schema$1.Boolean,
155
176
  has_signing_key: Schema$1.Boolean,
156
177
  has_signing_key_fallback: Schema$1.Boolean,
157
- mode: Schema$1.Literal("cloud", "dev"),
178
+ mode: Schema$1.Literals(["cloud", "dev"]),
158
179
  schema_version: Schema$1.Literal("2024-05-24"),
159
- extra: Schema$1.optional(Schema$1.Record({
160
- key: Schema$1.String,
161
- value: Schema$1.Unknown
162
- }))
180
+ extra: Schema$1.optional(Schema$1.Record(Schema$1.String, Schema$1.Unknown))
163
181
  });
164
- const IntrospectionUnauthenticated = Schema$1.extend(IntrospectionBase, Schema$1.Struct({
165
- authentication_succeeded: Schema$1.Union(Schema$1.Literal(false), Schema$1.Null),
166
- functions: Schema$1.optionalWith(Schema$1.Array(Schema$1.Unknown), { exact: true })
182
+ const IntrospectionUnauthenticated = IntrospectionBase.pipe(Schema$1.fieldsAssign({
183
+ authentication_succeeded: Schema$1.Union([Schema$1.Literal(false), Schema$1.Null]),
184
+ functions: Schema$1.optionalKey(Schema$1.Array(Schema$1.Unknown))
167
185
  }));
168
- const IntrospectionAuthenticated = Schema$1.extend(IntrospectionBase, Schema$1.Struct({
186
+ const IntrospectionAuthenticated = IntrospectionBase.pipe(Schema$1.fieldsAssign({
169
187
  authentication_succeeded: Schema$1.Literal(true),
170
188
  api_origin: Schema$1.String,
171
189
  app_id: Schema$1.String,
@@ -180,8 +198,22 @@ const IntrospectionAuthenticated = Schema$1.extend(IntrospectionBase, Schema$1.S
180
198
  signing_key_fallback_hash: Schema$1.NullOr(Schema$1.String),
181
199
  signing_key_hash: Schema$1.NullOr(Schema$1.String)
182
200
  }));
183
- const IntrospectionResponse = Schema$1.Union(IntrospectionAuthenticated, IntrospectionUnauthenticated);
184
- const RegisterResponse = Schema$1.Struct({ message: Schema$1.optional(Schema$1.String) });
185
-
201
+ const IntrospectionResponse = Schema$1.Union([IntrospectionAuthenticated, IntrospectionUnauthenticated]);
202
+ /**
203
+ * SDK → executor response shape for PUT sync requests per spec §4.3.1.
204
+ */
205
+ const RegisterResponse = Schema$1.Struct({
206
+ message: Schema$1.String,
207
+ modified: Schema$1.Boolean
208
+ });
209
+ /**
210
+ * Executor → SDK response shape from `POST /fn/register` per spec §4.3.4.
211
+ * On success the body has `{ ok: true, modified?: boolean }`; on failure
212
+ * the body may carry an `error` string.
213
+ */
214
+ const RegisterServerResponse = Schema$1.Union([Schema$1.Struct({
215
+ ok: Schema$1.Literal(true),
216
+ modified: Schema$1.optional(Schema$1.Boolean)
217
+ }), Schema$1.Struct({ error: Schema$1.optional(Schema$1.String) })]);
186
218
  //#endregion
187
- export { GeneratorOpcode, Headers, IntrospectionResponse, Opcode, RegisterResponse, SDKRequestBody, SDKRequestContext, UserError, invokeFunction, sleep, stepError, stepPlanned, stepRun, waitForEvent };
219
+ export { GeneratorOpcode, Headers, IntrospectionResponse, Opcode, RegisterResponse, RegisterServerResponse, SDKRequestBody, SDKRequestContext, UserError, discoveryRequest, invokeFunction, runComplete, sleep, stepError, stepPlanned, stepRun, waitForEvent };
@@ -1,15 +1,11 @@
1
- import "effect/Context";
2
- import "effect/Effect";
3
- import "effect/Layer";
4
1
  import * as Schema from "effect/Schema";
2
+ import * as _$effect_Cause0 from "effect/Cause";
5
3
 
6
4
  //#region src/internal/signature.d.ts
7
- declare const SignatureError_base: Schema.TaggedErrorClass<SignatureError, "SignatureError", {
8
- readonly _tag: Schema.tag<"SignatureError">;
9
- } & {
10
- reason: Schema.Literal<["missing_header", "invalid_format", "expired", "invalid_signature", "missing_signing_key"]>;
11
- message: typeof Schema.String;
12
- }>;
5
+ declare const SignatureError_base: Schema.Class<SignatureError, Schema.TaggedStruct<"SignatureError", {
6
+ readonly reason: Schema.Literals<readonly ["missing_header", "invalid_format", "expired", "invalid_signature", "missing_signing_key"]>;
7
+ readonly message: Schema.String;
8
+ }>, _$effect_Cause0.YieldableError>;
13
9
  /**
14
10
  * @internal
15
11
  */
@@ -1,11 +1,11 @@
1
1
  import { Headers } from "./protocol.js";
2
- import * as Context from "effect/Context";
3
2
  import * as Effect from "effect/Effect";
4
- import * as Layer from "effect/Layer";
5
3
  import * as Schema from "effect/Schema";
6
- import * as Crypto from "node:crypto";
7
4
  import * as DateTime from "effect/DateTime";
8
-
5
+ import * as Context from "effect/Context";
6
+ import * as Layer from "effect/Layer";
7
+ import * as Crypto from "node:crypto";
8
+ import * as SchemaTransformation from "effect/SchemaTransformation";
9
9
  //#region src/internal/signature.ts
10
10
  /**
11
11
  * Signature verification service for Inngest requests.
@@ -14,19 +14,25 @@ import * as DateTime from "effect/DateTime";
14
14
  /**
15
15
  * @internal
16
16
  */
17
- var SignatureError = class extends Schema.TaggedError()("SignatureError", {
18
- reason: Schema.Literal("missing_header", "invalid_format", "expired", "invalid_signature", "missing_signing_key"),
17
+ var SignatureError = class extends Schema.TaggedErrorClass()("SignatureError", {
18
+ reason: Schema.Literals([
19
+ "missing_header",
20
+ "invalid_format",
21
+ "expired",
22
+ "invalid_signature",
23
+ "missing_signing_key"
24
+ ]),
19
25
  message: Schema.String
20
26
  }) {};
21
27
  /**
22
28
  * @internal
23
29
  */
24
- var Signature = class extends Context.Tag("effect-inngest/Signature")() {};
25
- const TimestampSeconds = Schema.NumberFromString.pipe(Schema.int(), Schema.positive());
26
- const SignatureHex = Schema.String.pipe(Schema.pattern(/^[a-fA-F0-9]{64}$/), Schema.transform(Schema.String, {
30
+ var Signature = class extends Context.Service()("effect-inngest/Signature") {};
31
+ const TimestampSeconds = Schema.NumberFromString.pipe(Schema.check(Schema.isInt(), Schema.isGreaterThan(0)));
32
+ const SignatureHex = Schema.String.pipe(Schema.check(Schema.isPattern(/^[a-fA-F0-9]{64}$/)), Schema.decodeTo(Schema.String, SchemaTransformation.transform({
27
33
  decode: (s) => s.toLowerCase(),
28
34
  encode: (s) => s
29
- }));
35
+ })));
30
36
  const SignatureParams = Schema.Struct({
31
37
  t: TimestampSeconds,
32
38
  s: SignatureHex
@@ -38,7 +44,7 @@ const parseSignatureHeader = (header) => {
38
44
  t: params.get("t") ?? "",
39
45
  s: params.get("s") ?? ""
40
46
  };
41
- return Schema.decodeUnknown(SignatureParams)(raw).pipe(Effect.mapError(() => new SignatureError({
47
+ return Schema.decodeUnknownEffect(SignatureParams)(raw).pipe(Effect.mapError(() => new SignatureError({
42
48
  reason: "invalid_format",
43
49
  message: `Invalid signature format: expected t=<int>&s=<64-hex>, got: ${header}`
44
50
  })));
@@ -47,6 +53,17 @@ const extractKeyBytes = (signingKey) => {
47
53
  const keyWithoutPrefix = signingKey.replace(/^signkey-\w+-/, "");
48
54
  return Buffer.from(keyWithoutPrefix, "hex");
49
55
  };
56
+ /**
57
+ * SHA-256 hex of the signing key with the `signkey-{prefix}-` prefix stripped.
58
+ * Used as the Bearer token for outbound requests to the Inngest API per spec
59
+ * §4.1.1.
60
+ *
61
+ * @internal
62
+ */
63
+ const hashSigningKey = (signingKey) => {
64
+ const keyWithoutPrefix = signingKey.replace(/^signkey-\w+-/, "");
65
+ return Crypto.createHash("sha256").update(keyWithoutPrefix).digest("hex");
66
+ };
50
67
  const computeSignature = (keyBytes, body, timestamp) => Crypto.createHmac("sha256", keyBytes).update(body).update(timestamp).digest("hex");
51
68
  const timingSafeEqual = (a, b) => {
52
69
  if (a.length !== b.length) return false;
@@ -62,8 +79,8 @@ const checkSignature = (signature, body, timestamp, signingKey) => {
62
79
  /**
63
80
  * @internal
64
81
  */
65
- const SignatureLive = Layer.effect(Signature, Effect.succeed({
66
- verify: ({ body, signatureHeader, signingKey, signingKeyFallback, isDev }) => Effect.gen(function* () {
82
+ const SignatureLive = Layer.succeed(Signature, {
83
+ verify: Effect.fn("Signature.verify")(function* ({ body, signatureHeader, signingKey, signingKeyFallback, isDev }) {
67
84
  if (isDev) return true;
68
85
  if (!signingKey) return yield* new SignatureError({
69
86
  reason: "missing_signing_key",
@@ -76,7 +93,7 @@ const SignatureLive = Layer.effect(Signature, Effect.succeed({
76
93
  const { t: timestampSeconds, s: signature } = yield* parseSignatureHeader(signatureHeader);
77
94
  const timestampMs = timestampSeconds * 1e3;
78
95
  const now = yield* DateTime.now;
79
- if (Math.abs(now.epochMillis - timestampMs) > SIGNATURE_VALIDITY_WINDOW_MS) return yield* new SignatureError({
96
+ if (Math.abs(now.epochMilliseconds - timestampMs) > SIGNATURE_VALIDITY_WINDOW_MS) return yield* new SignatureError({
80
97
  reason: "expired",
81
98
  message: `Signature expired: timestamp ${timestampSeconds} is outside the validity window`
82
99
  });
@@ -88,10 +105,9 @@ const SignatureLive = Layer.effect(Signature, Effect.succeed({
88
105
  });
89
106
  }),
90
107
  sign: (body, signingKey) => DateTime.now.pipe(Effect.map((now) => {
91
- const ts = Math.floor(now.epochMillis / 1e3);
108
+ const ts = Math.floor(now.epochMilliseconds / 1e3);
92
109
  return `t=${ts}&s=${computeSignature(extractKeyBytes(signingKey), body, String(ts))}`;
93
110
  }))
94
- }));
95
-
111
+ });
96
112
  //#endregion
97
- export { Signature, SignatureError, SignatureLive };
113
+ export { Signature, SignatureError, SignatureLive, hashSigningKey };
@@ -1,15 +1,9 @@
1
1
  import { InngestFunction } from "../Function.js";
2
- import "./protocol.js";
3
2
  import { SendEventError, StepError } from "./errors.js";
4
- import "./interrupts.js";
5
3
  import * as Duration from "effect/Duration";
6
- import "effect/Context";
7
4
  import * as Effect from "effect/Effect";
8
5
  import * as Option from "effect/Option";
9
6
  import * as Schema from "effect/Schema";
10
- import "effect/HashMap";
11
- import "effect/Ref";
12
-
13
7
  //#region src/internal/step.d.ts
14
8
  interface StepOptions {
15
9
  readonly id: string;
@@ -17,27 +11,27 @@ interface StepOptions {
17
11
  }
18
12
  type StepOptionsOrId = string | StepOptions;
19
13
  interface WaitForEventOptions {
20
- readonly timeout: Duration.DurationInput;
14
+ readonly timeout: Duration.Input;
21
15
  readonly if?: string;
22
16
  }
23
17
  interface InvokeOptionsBase<F extends InngestFunction.Any> {
24
18
  readonly function: F;
25
19
  readonly user?: Record<string, unknown>;
26
20
  readonly v?: string;
27
- readonly timeout?: Duration.DurationInput;
21
+ readonly timeout?: Duration.Input;
28
22
  }
29
23
  type InvokeOptions<F extends InngestFunction.Any> = [InngestFunction.EventType<F>] extends [never] ? InvokeOptionsBase<F> : InvokeOptionsBase<F> & {
30
24
  readonly data: InngestFunction.EventType<F>;
31
25
  };
32
- type EventSchema = Schema.Schema.Any & {
33
- readonly _tag: string;
26
+ type EventSchema = Schema.Top & {
27
+ readonly identifier: string;
34
28
  };
35
29
  type TaggedEvent = {
36
30
  readonly _tag: string;
37
31
  };
38
32
  interface StepTools {
39
33
  readonly run: <A, Err, R>(id: StepOptionsOrId, effect: Effect.Effect<A, Err, R>) => Effect.Effect<A, StepError | Err, R>;
40
- readonly sleep: (id: StepOptionsOrId, duration: Duration.DurationInput) => Effect.Effect<void>;
34
+ readonly sleep: (id: StepOptionsOrId, duration: Duration.Input) => Effect.Effect<void>;
41
35
  readonly sleepUntil: (id: StepOptionsOrId, timestamp: Date | number | string) => Effect.Effect<void>;
42
36
  readonly waitForEvent: <E extends EventSchema>(id: StepOptionsOrId, event: E, options: WaitForEventOptions) => Effect.Effect<Option.Option<Schema.Schema.Type<E>>>;
43
37
  readonly invoke: <F extends InngestFunction.Any>(id: StepOptionsOrId, options: InvokeOptions<F>) => Effect.Effect<InngestFunction.Success<F>, StepError>;