inngest 4.2.6 → 4.4.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 (175) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/api/schema.d.cts +2 -2
  3. package/api/schema.d.cts.map +1 -1
  4. package/api/schema.d.ts +2 -2
  5. package/api/schema.d.ts.map +1 -1
  6. package/components/DeferredFunction.cjs +66 -0
  7. package/components/DeferredFunction.cjs.map +1 -0
  8. package/components/DeferredFunction.d.cts +99 -0
  9. package/components/DeferredFunction.d.cts.map +1 -0
  10. package/components/DeferredFunction.d.ts +99 -0
  11. package/components/DeferredFunction.d.ts.map +1 -0
  12. package/components/DeferredFunction.js +65 -0
  13. package/components/DeferredFunction.js.map +1 -0
  14. package/components/Inngest.cjs +5 -2
  15. package/components/Inngest.cjs.map +1 -1
  16. package/components/Inngest.d.cts +11 -4
  17. package/components/Inngest.d.cts.map +1 -1
  18. package/components/Inngest.d.ts +11 -4
  19. package/components/Inngest.d.ts.map +1 -1
  20. package/components/Inngest.js +5 -2
  21. package/components/Inngest.js.map +1 -1
  22. package/components/InngestCommHandler.cjs +28 -23
  23. package/components/InngestCommHandler.cjs.map +1 -1
  24. package/components/InngestCommHandler.d.cts +9 -4
  25. package/components/InngestCommHandler.d.cts.map +1 -1
  26. package/components/InngestCommHandler.d.ts +9 -4
  27. package/components/InngestCommHandler.d.ts.map +1 -1
  28. package/components/InngestCommHandler.js +28 -23
  29. package/components/InngestCommHandler.js.map +1 -1
  30. package/components/InngestFunction.cjs +27 -19
  31. package/components/InngestFunction.cjs.map +1 -1
  32. package/components/InngestFunction.d.cts +6 -1
  33. package/components/InngestFunction.d.cts.map +1 -1
  34. package/components/InngestFunction.d.ts +6 -1
  35. package/components/InngestFunction.d.ts.map +1 -1
  36. package/components/InngestFunction.js +27 -19
  37. package/components/InngestFunction.js.map +1 -1
  38. package/components/InngestGroupTools.cjs +1 -1
  39. package/components/InngestGroupTools.cjs.map +1 -1
  40. package/components/InngestGroupTools.js +1 -1
  41. package/components/InngestGroupTools.js.map +1 -1
  42. package/components/InngestStepTools.cjs +3 -7
  43. package/components/InngestStepTools.cjs.map +1 -1
  44. package/components/InngestStepTools.d.cts +10 -7
  45. package/components/InngestStepTools.d.cts.map +1 -1
  46. package/components/InngestStepTools.d.ts +10 -7
  47. package/components/InngestStepTools.d.ts.map +1 -1
  48. package/components/InngestStepTools.js +3 -7
  49. package/components/InngestStepTools.js.map +1 -1
  50. package/components/connect/config.cjs +2 -0
  51. package/components/connect/config.cjs.map +1 -1
  52. package/components/connect/config.js +2 -0
  53. package/components/connect/config.js.map +1 -1
  54. package/components/connect/strategies/core/connection.cjs +91 -11
  55. package/components/connect/strategies/core/connection.cjs.map +1 -1
  56. package/components/connect/strategies/core/connection.js +91 -11
  57. package/components/connect/strategies/core/connection.js.map +1 -1
  58. package/components/connect/strategies/core/heartbeat.cjs +2 -1
  59. package/components/connect/strategies/core/heartbeat.cjs.map +1 -1
  60. package/components/connect/strategies/core/heartbeat.js +2 -1
  61. package/components/connect/strategies/core/heartbeat.js.map +1 -1
  62. package/components/connect/strategies/core/requestProcessor.cjs +27 -4
  63. package/components/connect/strategies/core/requestProcessor.cjs.map +1 -1
  64. package/components/connect/strategies/core/requestProcessor.js +27 -4
  65. package/components/connect/strategies/core/requestProcessor.js.map +1 -1
  66. package/components/connect/strategies/core/types.cjs +21 -0
  67. package/components/connect/strategies/core/types.cjs.map +1 -0
  68. package/components/connect/strategies/core/types.js +20 -0
  69. package/components/connect/strategies/core/types.js.map +1 -0
  70. package/components/connect/types.cjs.map +1 -1
  71. package/components/connect/types.d.cts +18 -0
  72. package/components/connect/types.d.cts.map +1 -1
  73. package/components/connect/types.d.ts +18 -0
  74. package/components/connect/types.d.ts.map +1 -1
  75. package/components/connect/types.js.map +1 -1
  76. package/components/execution/InngestExecution.cjs.map +1 -1
  77. package/components/execution/InngestExecution.d.cts +19 -2
  78. package/components/execution/InngestExecution.d.cts.map +1 -1
  79. package/components/execution/InngestExecution.d.ts +19 -2
  80. package/components/execution/InngestExecution.d.ts.map +1 -1
  81. package/components/execution/InngestExecution.js.map +1 -1
  82. package/components/execution/engine.cjs +233 -28
  83. package/components/execution/engine.cjs.map +1 -1
  84. package/components/execution/engine.d.cts +14 -0
  85. package/components/execution/engine.d.cts.map +1 -1
  86. package/components/execution/engine.d.ts +14 -0
  87. package/components/execution/engine.d.ts.map +1 -1
  88. package/components/execution/engine.js +233 -28
  89. package/components/execution/engine.js.map +1 -1
  90. package/components/execution/lazyOps.cjs +64 -0
  91. package/components/execution/lazyOps.cjs.map +1 -0
  92. package/components/execution/lazyOps.d.cts +42 -0
  93. package/components/execution/lazyOps.d.cts.map +1 -0
  94. package/components/execution/lazyOps.d.ts +42 -0
  95. package/components/execution/lazyOps.d.ts.map +1 -0
  96. package/components/execution/lazyOps.js +63 -0
  97. package/components/execution/lazyOps.js.map +1 -0
  98. package/components/execution/otel/middleware.d.cts +14 -5
  99. package/components/execution/otel/middleware.d.cts.map +1 -1
  100. package/components/execution/otel/middleware.d.ts +14 -5
  101. package/components/execution/otel/middleware.d.ts.map +1 -1
  102. package/components/middleware/manager.cjs +1 -1
  103. package/components/middleware/manager.cjs.map +1 -1
  104. package/components/middleware/manager.js +2 -2
  105. package/components/middleware/manager.js.map +1 -1
  106. package/components/middleware/middleware.cjs.map +1 -1
  107. package/components/middleware/middleware.d.cts +1 -1
  108. package/components/middleware/middleware.d.cts.map +1 -1
  109. package/components/middleware/middleware.d.ts +1 -1
  110. package/components/middleware/middleware.d.ts.map +1 -1
  111. package/components/middleware/middleware.js.map +1 -1
  112. package/components/middleware/utils.cjs +5 -3
  113. package/components/middleware/utils.cjs.map +1 -1
  114. package/components/middleware/utils.js +5 -3
  115. package/components/middleware/utils.js.map +1 -1
  116. package/components/triggers/typeHelpers.cjs.map +1 -1
  117. package/components/triggers/typeHelpers.d.cts +11 -0
  118. package/components/triggers/typeHelpers.d.cts.map +1 -1
  119. package/components/triggers/typeHelpers.d.ts +11 -0
  120. package/components/triggers/typeHelpers.d.ts.map +1 -1
  121. package/components/triggers/typeHelpers.js.map +1 -1
  122. package/experimental.cjs +3 -0
  123. package/experimental.d.cts +2 -1
  124. package/experimental.d.ts +2 -1
  125. package/experimental.js +2 -1
  126. package/helpers/consts.cjs +6 -0
  127. package/helpers/consts.cjs.map +1 -1
  128. package/helpers/consts.d.cts +6 -0
  129. package/helpers/consts.d.cts.map +1 -1
  130. package/helpers/consts.d.ts +6 -0
  131. package/helpers/consts.d.ts.map +1 -1
  132. package/helpers/consts.js +6 -0
  133. package/helpers/consts.js.map +1 -1
  134. package/helpers/functions.cjs +1 -0
  135. package/helpers/functions.cjs.map +1 -1
  136. package/helpers/functions.js +1 -0
  137. package/helpers/functions.js.map +1 -1
  138. package/helpers/marker.cjs +21 -0
  139. package/helpers/marker.cjs.map +1 -0
  140. package/helpers/marker.d.cts +12 -0
  141. package/helpers/marker.d.cts.map +1 -0
  142. package/helpers/marker.d.ts +12 -0
  143. package/helpers/marker.d.ts.map +1 -0
  144. package/helpers/marker.js +19 -0
  145. package/helpers/marker.js.map +1 -0
  146. package/helpers/strings.cjs +10 -4
  147. package/helpers/strings.cjs.map +1 -1
  148. package/helpers/strings.d.cts.map +1 -1
  149. package/helpers/strings.d.ts.map +1 -1
  150. package/helpers/strings.js +10 -4
  151. package/helpers/strings.js.map +1 -1
  152. package/helpers/temporal.cjs +2 -0
  153. package/helpers/temporal.d.ts +3 -0
  154. package/helpers/temporal.d.ts.map +1 -1
  155. package/helpers/temporal.js +1 -1
  156. package/package.json +2 -2
  157. package/proto/src/components/connect/protobuf/connect.cjs +11 -2
  158. package/proto/src/components/connect/protobuf/connect.cjs.map +1 -1
  159. package/proto/src/components/connect/protobuf/connect.js +11 -2
  160. package/proto/src/components/connect/protobuf/connect.js.map +1 -1
  161. package/react.d.cts.map +1 -1
  162. package/types.cjs +2 -0
  163. package/types.cjs.map +1 -1
  164. package/types.d.cts +43 -8
  165. package/types.d.cts.map +1 -1
  166. package/types.d.ts +43 -8
  167. package/types.d.ts.map +1 -1
  168. package/types.js +2 -0
  169. package/types.js.map +1 -1
  170. package/version.cjs +1 -1
  171. package/version.cjs.map +1 -1
  172. package/version.d.cts +1 -1
  173. package/version.d.ts +1 -1
  174. package/version.js +1 -1
  175. package/version.js.map +1 -1
@@ -93,8 +93,16 @@ interface InngestExecutionOptions {
93
93
  internalFnId?: string;
94
94
  reqArgs: unknown[];
95
95
  runId: string;
96
- data: Omit<Context.Any, "step" | "group" | "publish">;
96
+ data: Omit<Context.Any, "step" | "group" | "publish" | "defer">;
97
97
  stepState: Record<string, MemoizedOp>;
98
+ /**
99
+ * A map of hashed defer step IDs to their backend-side metadata
100
+ * (e.g. `{ abortable: true }`). Defer ops are not steps in the
101
+ * memoization sense — they don't produce results — but the backend
102
+ * tracks which ones it has already received so the SDK can avoid
103
+ * re-emitting them on replay.
104
+ */
105
+ priorDefers?: Record<string, unknown>;
98
106
  stepCompletionOrder: string[];
99
107
  stepMode: StepMode;
100
108
  checkpointingConfig?: InternalCheckpointingOptions;
@@ -111,7 +119,16 @@ interface InngestExecutionOptions {
111
119
  headers: Record<string, string>;
112
120
  requestedRunStep?: string;
113
121
  timer?: ServerTiming;
114
- isFailureHandler?: boolean;
122
+ /**
123
+ * Which handler variant is being executed. `"failure"` skips
124
+ * trigger-schema validation and resolves `onFailure` instead of the
125
+ * main handler. `"defer"` marks the fn as a standalone defer function
126
+ * (created via `createDefer`); incoming event data is validated
127
+ * against the defer function's schema.
128
+ *
129
+ * @default "main"
130
+ */
131
+ handlerKind?: "main" | "failure" | "defer";
115
132
  disableImmediateExecution?: boolean;
116
133
  /**
117
134
  * Information about the incoming HTTP request that triggered this execution.
@@ -1 +1 @@
1
- {"version":3,"file":"InngestExecution.d.cts","names":[],"sources":["../../../src/components/execution/InngestExecution.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;UA6BiB,gBAAA;;;;;UAEK;;;;;;;;IAFL,KAAA,EAAA,CAIU,UAJM,EAAA,GAIS,UAJT,EAAA,CAAA;EAAA,CAAA;kBAEX,EAAA;IAEK,IAAA,EAEjB,UAFiB;IAAe,UAAA,EAG1B,cAH0B,EAAA;IAEhC,eAAA,EAAA,MAAA;;;;AAeV;;eACc,EAAA;IAEF,EAAA,EARJ,QAQI;IACD,KAAA,EAAQ,MAAA;;;AAEX,KANI,eAAA,GAMJ,QAAiB,MALX,gBAKW,GALQ,QAKR,CAAA;EALQ,IAAA,EAErB,CAFqB;EAOzB,GAAA,EAJG,OAAA,CAAQ,GAIX;EAAgB,GAAA,EAHb,MAGa,CAAA,MAAA,EAHE,UAGF,CAAA;AAEP,CAAA,GAJT,gBAIuB,CAJN,CAIM,CAAA,CAAA,EAK/B,CAAA,MAPQ,gBAOI,CAAA;AAAsB,UALjB,cAAA,CAKiB;MAAK,MAAA;aAC7B,CAAA,EAAA,MAAA;;AACL,KAFO,sBAEP,CAAA,IAFkC,cAElC,CAAA,GAAA,CAAA,MAAA,EADK,eACL,EAAA,GAAA,YAAA,CAAa,CAAb,CAAA;AAAY,KAEL,uBAFK,CAAA,IAEuB,cAFvB,CAAA,GAAA,QAGT,eADI,IACe,CADQ,CAAA,MAAA,CAAA,GAAA,CAAA,MAAA,EACa,CADb,EAAA,GACmB,YADnB,CACgC,CADhC,CAAA,EAAA;AAAK,UAIvB,UAAA,SAAmB,UAJI,CAAA;;;;;SACc,CAAA,EAAA,OAAA,EAAA;EAAY,SAAA,CAAA,EAAA,OAAA;EAGjD;;;SAAmB,CAAA,EAWxB,OAXwB,CAAA,OAAA,CAAA;EAAU,IAAA,CAAA,EAAA,OAAA;AAsB9C;AAMA;;;;;;;AAea,cArBA,iCAAA,GAqBA,gBAAA,CAAA,EAAA;;;;AAkBH,UAjCO,uBAAA,CAiCP;QAQM,EAxCN,OAAA,CAAQ,GAwCS;MAvCrB,eAAA,CAAgB,GA8Ca;;;;;;;AAwBnC;EAAmC,YAAA,CAAA,EAAA,MAAA;SACxB,EAAA,OAAA,EAAA;OACN,EAAA,MAAA;EAAiB,IAAA,EA5Dd,IA4Dc,CA5DT,OAAA,CAAQ,GA4DC,EAAA,MAAA,GAAA,OAAA,GAAA,SAAA,CAAA;EAET,SAAA,EA7DA,MA6DA,CAAA,MAAgB,EA7DD,UA6DC,CAAA;EAAA,mBAAA,EAAA,MAAA,EAAA;UAGI,EA9DrB,QA8DqB;qBAFX,CAAA,EA3DE,4BA2DF;;;AAOtB;;;;aAEW,CAAA,EAAA,MAAA;;;;SAOC,EA9DD,MA8DC,CAAA,MAAA,EAAA,MAAA,CAAA;EAAM,gBAAA,CAAA,EAAA,MAAA;UA5DR;;;;;;;gBAQM,UAAA,CAAW;;;;;;wBAOH,UAAA,CAAW;;;;;;;;;;;uBAaZ,SAAS,OAAA,CAAQ,SAAS,OAAA,CAAQ;;;;;;;sCAQnB,aAAa;;KAGvC,uBAAA,aACD,4BACN;cAEQ,gBAAA;qBAGoB;sBAFX;uBAEW;;UAKhB,iBAAA;WACN;WACA,QAAQ;oCAIT,qBACC,mBACH,wBACI"}
1
+ {"version":3,"file":"InngestExecution.d.cts","names":[],"sources":["../../../src/components/execution/InngestExecution.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;UA6BiB,gBAAA;;;;;UAEK;;;;;;;;IAFL,KAAA,EAAA,CAIU,UAJM,EAAA,GAIS,UAJT,EAAA,CAAA;EAAA,CAAA;kBAEX,EAAA;IAEK,IAAA,EAEjB,UAFiB;IAAe,UAAA,EAG1B,cAH0B,EAAA;IAEhC,eAAA,EAAA,MAAA;;;;AAeV;;eACc,EAAA;IAEF,EAAA,EARJ,QAQI;IACD,KAAA,EAAQ,MAAA;;;AAEX,KANI,eAAA,GAMJ,QAAiB,MALX,gBAKW,GALQ,QAKR,CAAA;EALQ,IAAA,EAErB,CAFqB;EAOzB,GAAA,EAJG,OAAA,CAAQ,GAIX;EAAgB,GAAA,EAHb,MAGa,CAAA,MAAA,EAHE,UAGF,CAAA;AAEP,CAAA,GAJT,gBAIuB,CAJN,CAIM,CAAA,CAAA,EAK/B,CAAA,MAPQ,gBAOI,CAAA;AAAsB,UALjB,cAAA,CAKiB;MAAK,MAAA;aAC7B,CAAA,EAAA,MAAA;;AACL,KAFO,sBAEP,CAAA,IAFkC,cAElC,CAAA,GAAA,CAAA,MAAA,EADK,eACL,EAAA,GAAA,YAAA,CAAa,CAAb,CAAA;AAAY,KAEL,uBAFK,CAAA,IAEuB,cAFvB,CAAA,GAAA,QAGT,eADI,IACe,CADQ,CAAA,MAAA,CAAA,GAAA,CAAA,MAAA,EACa,CADb,EAAA,GACmB,YADnB,CACgC,CADhC,CAAA,EAAA;AAAK,UAIvB,UAAA,SAAmB,UAJI,CAAA;;;;;SACc,CAAA,EAAA,OAAA,EAAA;EAAY,SAAA,CAAA,EAAA,OAAA;EAGjD;;;SAAmB,CAAA,EAWxB,OAXwB,CAAA,OAAA,CAAA;EAAU,IAAA,CAAA,EAAA,OAAA;AAsB9C;AAMA;;;;;;;AAea,cArBA,iCAAA,GAqBA,gBAAA,CAAA,EAAA;;;;AA0BF,UAzCM,uBAAA,CAyCN;QAED,EA1CA,OAAA,CAAQ,GA0CR;MAzCJ,eAAA,CAAgB,GA2DK;;;;;;;;EA+Bf,YAAA,CAAA,EAAA,MAAA;EAAuB,OAAA,EAAA,OAAA,EAAA;OACxB,EAAA,MAAA;MACN,EAhFG,IAgFH,CAhFQ,OAAA,CAAQ,GAgFhB,EAAA,MAAA,GAAA,OAAA,GAAA,SAAA,GAAA,OAAA,CAAA;EAAiB,SAAA,EA/ET,MA+ES,CAAA,MAAA,EA/EM,UA+EN,CAAA;EAET;;;;;;AAQb;EAAkC,WAAA,CAAA,EAhFlB,MAgFkB,CAAA,MAAA,EAAA,OAAA,CAAA;qBACvB,EAAA,MAAA,EAAA;UACQ,EA/EP,QA+EO;qBAAR,CAAA,EA9Ea,4BA8Eb;;;;;;;;;;;WAjEA;;UAED;;;;;;;;;;;;;;;;gBAkBM,UAAA,CAAW;;;;;;wBAOH,UAAA,CAAW;;;;;;;;;;;uBAaZ,SAAS,OAAA,CAAQ,SAAS,OAAA,CAAQ;;;;;;;sCAQnB,aAAa;;KAGvC,uBAAA,aACD,4BACN;cAEQ,gBAAA;qBAGoB;sBAFX;uBAEW;;UAKhB,iBAAA;WACN;WACA,QAAQ;oCAIT,qBACC,mBACH,wBACI"}
@@ -93,8 +93,16 @@ interface InngestExecutionOptions {
93
93
  internalFnId?: string;
94
94
  reqArgs: unknown[];
95
95
  runId: string;
96
- data: Omit<Context.Any, "step" | "group" | "publish">;
96
+ data: Omit<Context.Any, "step" | "group" | "publish" | "defer">;
97
97
  stepState: Record<string, MemoizedOp>;
98
+ /**
99
+ * A map of hashed defer step IDs to their backend-side metadata
100
+ * (e.g. `{ abortable: true }`). Defer ops are not steps in the
101
+ * memoization sense — they don't produce results — but the backend
102
+ * tracks which ones it has already received so the SDK can avoid
103
+ * re-emitting them on replay.
104
+ */
105
+ priorDefers?: Record<string, unknown>;
98
106
  stepCompletionOrder: string[];
99
107
  stepMode: StepMode;
100
108
  checkpointingConfig?: InternalCheckpointingOptions;
@@ -111,7 +119,16 @@ interface InngestExecutionOptions {
111
119
  headers: Record<string, string>;
112
120
  requestedRunStep?: string;
113
121
  timer?: ServerTiming;
114
- isFailureHandler?: boolean;
122
+ /**
123
+ * Which handler variant is being executed. `"failure"` skips
124
+ * trigger-schema validation and resolves `onFailure` instead of the
125
+ * main handler. `"defer"` marks the fn as a standalone defer function
126
+ * (created via `createDefer`); incoming event data is validated
127
+ * against the defer function's schema.
128
+ *
129
+ * @default "main"
130
+ */
131
+ handlerKind?: "main" | "failure" | "defer";
115
132
  disableImmediateExecution?: boolean;
116
133
  /**
117
134
  * Information about the incoming HTTP request that triggered this execution.
@@ -1 +1 @@
1
- {"version":3,"file":"InngestExecution.d.ts","names":[],"sources":["../../../src/components/execution/InngestExecution.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;UA6BiB,gBAAA;;;;;UAEK;;;;;;;;IAFL,KAAA,EAAA,CAIU,UAJM,EAAA,GAIS,UAJT,EAAA,CAAA;EAAA,CAAA;kBAEX,EAAA;IAEK,IAAA,EAEjB,UAFiB;IAAe,UAAA,EAG1B,cAH0B,EAAA;IAEhC,eAAA,EAAA,MAAA;;;;AAeV;;eACc,EAAA;IAEF,EAAA,EARJ,QAQI;IACD,KAAA,EAAQ,MAAA;;;AAEX,KANI,eAAA,GAMJ,QAAiB,MALX,gBAKW,GALQ,QAKR,CAAA;EALQ,IAAA,EAErB,CAFqB;EAOzB,GAAA,EAJG,OAAA,CAAQ,GAIX;EAAgB,GAAA,EAHb,MAGa,CAAA,MAAA,EAHE,UAGF,CAAA;AAEP,CAAA,GAJT,gBAIuB,CAJN,CAIM,CAAA,CAAA,EAK/B,CAAA,MAPQ,gBAOI,CAAA;AAAsB,UALjB,cAAA,CAKiB;MAAK,MAAA;aAC7B,CAAA,EAAA,MAAA;;AACL,KAFO,sBAEP,CAAA,IAFkC,cAElC,CAAA,GAAA,CAAA,MAAA,EADK,eACL,EAAA,GAAA,YAAA,CAAa,CAAb,CAAA;AAAY,KAEL,uBAFK,CAAA,IAEuB,cAFvB,CAAA,GAAA,QAGT,eADI,IACe,CADQ,CAAA,MAAA,CAAA,GAAA,CAAA,MAAA,EACa,CADb,EAAA,GACmB,YADnB,CACgC,CADhC,CAAA,EAAA;AAAK,UAIvB,UAAA,SAAmB,UAJI,CAAA;;;;;SACc,CAAA,EAAA,OAAA,EAAA;EAAY,SAAA,CAAA,EAAA,OAAA;EAGjD;;;SAAmB,CAAA,EAWxB,OAXwB,CAAA,OAAA,CAAA;EAAU,IAAA,CAAA,EAAA,OAAA;AAsB9C;AAMA;;;;;;;AAea,cArBA,iCAAA,GAqBA,gBAAA,CAAA,EAAA;;;;AAkBH,UAjCO,uBAAA,CAiCP;QAQM,EAxCN,OAAA,CAAQ,GAwCS;MAvCrB,eAAA,CAAgB,GA8Ca;;;;;;;AAwBnC;EAAmC,YAAA,CAAA,EAAA,MAAA;SACxB,EAAA,OAAA,EAAA;OACN,EAAA,MAAA;EAAiB,IAAA,EA5Dd,IA4Dc,CA5DT,OAAA,CAAQ,GA4DC,EAAA,MAAA,GAAA,OAAA,GAAA,SAAA,CAAA;EAET,SAAA,EA7DA,MA6DA,CAAA,MAAgB,EA7DD,UA6DC,CAAA;EAAA,mBAAA,EAAA,MAAA,EAAA;UAGI,EA9DrB,QA8DqB;qBAFX,CAAA,EA3DE,4BA2DF;;;AAOtB;;;;aAEW,CAAA,EAAA,MAAA;;;;SAOC,EA9DD,MA8DC,CAAA,MAAA,EAAA,MAAA,CAAA;EAAM,gBAAA,CAAA,EAAA,MAAA;UA5DR;;;;;;;gBAQM,UAAA,CAAW;;;;;;wBAOH,UAAA,CAAW;;;;;;;;;;;uBAaZ,SAAS,OAAA,CAAQ,SAAS,OAAA,CAAQ;;;;;;;sCAQnB,aAAa;;KAGvC,uBAAA,aACD,4BACN;cAEQ,gBAAA;qBAGoB;sBAFX;uBAEW;;UAKhB,iBAAA;WACN;WACA,QAAQ;oCAIT,qBACC,mBACH,wBACI"}
1
+ {"version":3,"file":"InngestExecution.d.ts","names":[],"sources":["../../../src/components/execution/InngestExecution.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;UA6BiB,gBAAA;;;;;UAEK;;;;;;;;IAFL,KAAA,EAAA,CAIU,UAJM,EAAA,GAIS,UAJT,EAAA,CAAA;EAAA,CAAA;kBAEX,EAAA;IAEK,IAAA,EAEjB,UAFiB;IAAe,UAAA,EAG1B,cAH0B,EAAA;IAEhC,eAAA,EAAA,MAAA;;;;AAeV;;eACc,EAAA;IAEF,EAAA,EARJ,QAQI;IACD,KAAA,EAAQ,MAAA;;;AAEX,KANI,eAAA,GAMJ,QAAiB,MALX,gBAKW,GALQ,QAKR,CAAA;EALQ,IAAA,EAErB,CAFqB;EAOzB,GAAA,EAJG,OAAA,CAAQ,GAIX;EAAgB,GAAA,EAHb,MAGa,CAAA,MAAA,EAHE,UAGF,CAAA;AAEP,CAAA,GAJT,gBAIuB,CAJN,CAIM,CAAA,CAAA,EAK/B,CAAA,MAPQ,gBAOI,CAAA;AAAsB,UALjB,cAAA,CAKiB;MAAK,MAAA;aAC7B,CAAA,EAAA,MAAA;;AACL,KAFO,sBAEP,CAAA,IAFkC,cAElC,CAAA,GAAA,CAAA,MAAA,EADK,eACL,EAAA,GAAA,YAAA,CAAa,CAAb,CAAA;AAAY,KAEL,uBAFK,CAAA,IAEuB,cAFvB,CAAA,GAAA,QAGT,eADI,IACe,CADQ,CAAA,MAAA,CAAA,GAAA,CAAA,MAAA,EACa,CADb,EAAA,GACmB,YADnB,CACgC,CADhC,CAAA,EAAA;AAAK,UAIvB,UAAA,SAAmB,UAJI,CAAA;;;;;SACc,CAAA,EAAA,OAAA,EAAA;EAAY,SAAA,CAAA,EAAA,OAAA;EAGjD;;;SAAmB,CAAA,EAWxB,OAXwB,CAAA,OAAA,CAAA;EAAU,IAAA,CAAA,EAAA,OAAA;AAsB9C;AAMA;;;;;;;AAea,cArBA,iCAAA,GAqBA,gBAAA,CAAA,EAAA;;;;AA0BF,UAzCM,uBAAA,CAyCN;QAED,EA1CA,OAAA,CAAQ,GA0CR;MAzCJ,eAAA,CAAgB,GA2DK;;;;;;;;EA+Bf,YAAA,CAAA,EAAA,MAAA;EAAuB,OAAA,EAAA,OAAA,EAAA;OACxB,EAAA,MAAA;MACN,EAhFG,IAgFH,CAhFQ,OAAA,CAAQ,GAgFhB,EAAA,MAAA,GAAA,OAAA,GAAA,SAAA,GAAA,OAAA,CAAA;EAAiB,SAAA,EA/ET,MA+ES,CAAA,MAAA,EA/EM,UA+EN,CAAA;EAET;;;;;;AAQb;EAAkC,WAAA,CAAA,EAhFlB,MAgFkB,CAAA,MAAA,EAAA,OAAA,CAAA;qBACvB,EAAA,MAAA,EAAA;UACQ,EA/EP,QA+EO;qBAAR,CAAA,EA9Ea,4BA8Eb;;;;;;;;;;;WAjEA;;UAED;;;;;;;;;;;;;;;;gBAkBM,UAAA,CAAW;;;;;;wBAOH,UAAA,CAAW;;;;;;;;;;;uBAaZ,SAAS,OAAA,CAAQ,SAAS,OAAA,CAAQ;;;;;;;sCAQnB,aAAa;;KAGvC,uBAAA,aACD,4BACN;cAEQ,gBAAA;qBAGoB;sBAFX;uBAEW;;UAKhB,iBAAA;WACN;WACA,QAAQ;oCAIT,qBACC,mBACH,wBACI"}
@@ -1 +1 @@
1
- {"version":3,"file":"InngestExecution.js","names":["options: InngestExecutionOptions"],"sources":["../../../src/components/execution/InngestExecution.ts"],"sourcesContent":["import Debug, { type Debugger } from \"debug\";\nimport { debugPrefix, ExecutionVersion } from \"../../helpers/consts.ts\";\nimport type { ServerTiming } from \"../../helpers/ServerTiming.ts\";\nimport type { MaybePromise, Simplify } from \"../../helpers/types.ts\";\nimport type {\n Context,\n IncomingOp,\n InternalCheckpointingOptions,\n OutgoingOp,\n StepMode,\n} from \"../../types.ts\";\nimport type { Inngest } from \"../Inngest.ts\";\nimport type { ActionResponse } from \"../InngestCommHandler.ts\";\nimport type { InngestFunction } from \"../InngestFunction.ts\";\nimport type {\n MetadataKind,\n MetadataOpcode,\n MetadataScope,\n} from \"../InngestMetadata.ts\";\nimport type { Middleware } from \"../middleware/middleware.ts\";\n\n// Re-export ExecutionVersion so it's correctly recognized as an enum and not\n// just a type. This can be lost when bundling if we don't re-export it here.\n// See `pnpm run test:dist`.\nexport { ExecutionVersion };\n\n/**\n * The possible results of an execution.\n */\nexport interface ExecutionResults {\n \"function-resolved\": { data: unknown };\n \"step-ran\": { step: OutgoingOp; retriable?: boolean | string };\n \"function-rejected\": { error: unknown; retriable: boolean | string };\n \"steps-found\": { steps: [OutgoingOp, ...OutgoingOp[]] };\n \"step-not-found\": {\n step: OutgoingOp;\n foundSteps: BasicFoundStep[];\n totalFoundSteps: number;\n };\n\n /**\n * Indicates that we need to relinquish control back to Inngest in order to\n * change step modes.\n */\n \"change-mode\": {\n to: StepMode;\n token: string;\n };\n}\n\nexport type ExecutionResult = {\n [K in keyof ExecutionResults]: Simplify<\n {\n type: K;\n ctx: Context.Any;\n ops: Record<string, MemoizedOp>;\n } & ExecutionResults[K]\n >;\n}[keyof ExecutionResults];\n\nexport interface BasicFoundStep {\n id: string;\n displayName?: string;\n}\n\nexport type ExecutionResultHandler<T = ActionResponse> = (\n result: ExecutionResult,\n) => MaybePromise<T>;\n\nexport type ExecutionResultHandlers<T = ActionResponse> = {\n [E in ExecutionResult as E[\"type\"]]: (result: E) => MaybePromise<T>;\n};\n\nexport interface MemoizedOp extends IncomingOp {\n /**\n * If the step has been hit during this run, these will be the arguments\n * passed to it.\n */\n rawArgs?: unknown[];\n fulfilled?: boolean;\n\n /**\n * The promise that has been returned to userland code.\n */\n promise?: Promise<unknown>;\n seen?: boolean;\n}\n\n/**\n * The preferred execution version that will be used by the SDK when handling\n * brand new runs where the Executor is allowing us to choose.\n *\n * Changing this should not ever be a breaking change, as this will only change\n * new runs, not existing ones.\n */\nexport const PREFERRED_ASYNC_EXECUTION_VERSION =\n ExecutionVersion.V2 satisfies ExecutionVersion;\n\n/**\n * Options for creating a new {@link InngestExecution} instance.\n */\nexport interface InngestExecutionOptions {\n client: Inngest.Any;\n fn: InngestFunction.Any;\n\n /**\n * The UUID that represents this function in Inngest.\n *\n * This is used to reference the function during async checkpointing, when we\n * know the function/run already exists and just wish to reference it\n * directly.\n */\n internalFnId?: string;\n reqArgs: unknown[];\n runId: string;\n data: Omit<Context.Any, \"step\" | \"group\" | \"publish\">;\n stepState: Record<string, MemoizedOp>;\n stepCompletionOrder: string[];\n stepMode: StepMode;\n checkpointingConfig?: InternalCheckpointingOptions;\n\n /**\n * If this execution is being run from a queue job, this will be an identifier\n * used to reference this execution in Inngest. SDKs are expected to parrot\n * this back in some responses to correctly attribute actions to this queue\n * item.\n */\n queueItemId?: string;\n\n /**\n * Headers to be sent with any request to Inngest during this execution.\n */\n headers: Record<string, string>;\n requestedRunStep?: string;\n timer?: ServerTiming;\n isFailureHandler?: boolean;\n disableImmediateExecution?: boolean;\n\n /**\n * Information about the incoming HTTP request that triggered this execution.\n * Used by middleware `wrapRequest` hooks.\n */\n requestInfo?: Middleware.Request;\n\n /**\n * Pre-created middleware instances to use for this execution. When provided,\n * the execution will use these instead of instantiating new ones from the\n * client. This ensures `wrapRequest` and other hooks share state on `this`.\n */\n middlewareInstances?: Middleware.BaseMiddleware[];\n\n /**\n * Whether the client accepts SSE (`Accept: text/event-stream`). When true,\n * the execution engine may deliver the result as an SSE stream even if\n * `stream.push()` was not called.\n */\n acceptsSse?: boolean;\n\n /**\n * Provide the ability to transform the context passed to the function before\n * the execution starts.\n */\n transformCtx?: (ctx: Readonly<Context.Any>) => Context.Any;\n\n /**\n * A hook that is called to create an {@link ActionResponse} from the returned\n * value of an execution.\n *\n * This is required for checkpointing executions.\n */\n createResponse?: (data: unknown) => MaybePromise<ActionResponse>;\n}\n\nexport type InngestExecutionFactory = (\n options: InngestExecutionOptions,\n) => IInngestExecution;\n\nexport class InngestExecution {\n protected devDebug: Debugger;\n\n constructor(protected options: InngestExecutionOptions) {\n this.devDebug = Debug(`${debugPrefix}:${this.options.runId}`);\n }\n}\n\nexport interface IInngestExecution {\n version: ExecutionVersion;\n start(): Promise<ExecutionResult>;\n\n addMetadata(\n stepId: string,\n kind: MetadataKind,\n scope: MetadataScope,\n op: MetadataOpcode,\n values: Record<string, unknown>,\n ): boolean;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA+FA,MAAa,oCACX,iBAAiB;AAiFnB,IAAa,mBAAb,MAA8B;CAC5B,AAAU;CAEV,YAAY,AAAUA,SAAkC;EAAlC;AACpB,OAAK,WAAW,MAAM,GAAG,YAAY,GAAG,KAAK,QAAQ,QAAQ"}
1
+ {"version":3,"file":"InngestExecution.js","names":["options: InngestExecutionOptions"],"sources":["../../../src/components/execution/InngestExecution.ts"],"sourcesContent":["import Debug, { type Debugger } from \"debug\";\nimport { debugPrefix, ExecutionVersion } from \"../../helpers/consts.ts\";\nimport type { ServerTiming } from \"../../helpers/ServerTiming.ts\";\nimport type { MaybePromise, Simplify } from \"../../helpers/types.ts\";\nimport type {\n Context,\n IncomingOp,\n InternalCheckpointingOptions,\n OutgoingOp,\n StepMode,\n} from \"../../types.ts\";\nimport type { Inngest } from \"../Inngest.ts\";\nimport type { ActionResponse } from \"../InngestCommHandler.ts\";\nimport type { InngestFunction } from \"../InngestFunction.ts\";\nimport type {\n MetadataKind,\n MetadataOpcode,\n MetadataScope,\n} from \"../InngestMetadata.ts\";\nimport type { Middleware } from \"../middleware/middleware.ts\";\n\n// Re-export ExecutionVersion so it's correctly recognized as an enum and not\n// just a type. This can be lost when bundling if we don't re-export it here.\n// See `pnpm run test:dist`.\nexport { ExecutionVersion };\n\n/**\n * The possible results of an execution.\n */\nexport interface ExecutionResults {\n \"function-resolved\": { data: unknown };\n \"step-ran\": { step: OutgoingOp; retriable?: boolean | string };\n \"function-rejected\": { error: unknown; retriable: boolean | string };\n \"steps-found\": { steps: [OutgoingOp, ...OutgoingOp[]] };\n \"step-not-found\": {\n step: OutgoingOp;\n foundSteps: BasicFoundStep[];\n totalFoundSteps: number;\n };\n\n /**\n * Indicates that we need to relinquish control back to Inngest in order to\n * change step modes.\n */\n \"change-mode\": {\n to: StepMode;\n token: string;\n };\n}\n\nexport type ExecutionResult = {\n [K in keyof ExecutionResults]: Simplify<\n {\n type: K;\n ctx: Context.Any;\n ops: Record<string, MemoizedOp>;\n } & ExecutionResults[K]\n >;\n}[keyof ExecutionResults];\n\nexport interface BasicFoundStep {\n id: string;\n displayName?: string;\n}\n\nexport type ExecutionResultHandler<T = ActionResponse> = (\n result: ExecutionResult,\n) => MaybePromise<T>;\n\nexport type ExecutionResultHandlers<T = ActionResponse> = {\n [E in ExecutionResult as E[\"type\"]]: (result: E) => MaybePromise<T>;\n};\n\nexport interface MemoizedOp extends IncomingOp {\n /**\n * If the step has been hit during this run, these will be the arguments\n * passed to it.\n */\n rawArgs?: unknown[];\n fulfilled?: boolean;\n\n /**\n * The promise that has been returned to userland code.\n */\n promise?: Promise<unknown>;\n seen?: boolean;\n}\n\n/**\n * The preferred execution version that will be used by the SDK when handling\n * brand new runs where the Executor is allowing us to choose.\n *\n * Changing this should not ever be a breaking change, as this will only change\n * new runs, not existing ones.\n */\nexport const PREFERRED_ASYNC_EXECUTION_VERSION =\n ExecutionVersion.V2 satisfies ExecutionVersion;\n\n/**\n * Options for creating a new {@link InngestExecution} instance.\n */\nexport interface InngestExecutionOptions {\n client: Inngest.Any;\n fn: InngestFunction.Any;\n\n /**\n * The UUID that represents this function in Inngest.\n *\n * This is used to reference the function during async checkpointing, when we\n * know the function/run already exists and just wish to reference it\n * directly.\n */\n internalFnId?: string;\n reqArgs: unknown[];\n runId: string;\n data: Omit<Context.Any, \"step\" | \"group\" | \"publish\" | \"defer\">;\n stepState: Record<string, MemoizedOp>;\n\n /**\n * A map of hashed defer step IDs to their backend-side metadata\n * (e.g. `{ abortable: true }`). Defer ops are not steps in the\n * memoization sense — they don't produce results — but the backend\n * tracks which ones it has already received so the SDK can avoid\n * re-emitting them on replay.\n */\n priorDefers?: Record<string, unknown>;\n\n stepCompletionOrder: string[];\n stepMode: StepMode;\n checkpointingConfig?: InternalCheckpointingOptions;\n\n /**\n * If this execution is being run from a queue job, this will be an identifier\n * used to reference this execution in Inngest. SDKs are expected to parrot\n * this back in some responses to correctly attribute actions to this queue\n * item.\n */\n queueItemId?: string;\n\n /**\n * Headers to be sent with any request to Inngest during this execution.\n */\n headers: Record<string, string>;\n requestedRunStep?: string;\n timer?: ServerTiming;\n /**\n * Which handler variant is being executed. `\"failure\"` skips\n * trigger-schema validation and resolves `onFailure` instead of the\n * main handler. `\"defer\"` marks the fn as a standalone defer function\n * (created via `createDefer`); incoming event data is validated\n * against the defer function's schema.\n *\n * @default \"main\"\n */\n handlerKind?: \"main\" | \"failure\" | \"defer\";\n\n disableImmediateExecution?: boolean;\n\n /**\n * Information about the incoming HTTP request that triggered this execution.\n * Used by middleware `wrapRequest` hooks.\n */\n requestInfo?: Middleware.Request;\n\n /**\n * Pre-created middleware instances to use for this execution. When provided,\n * the execution will use these instead of instantiating new ones from the\n * client. This ensures `wrapRequest` and other hooks share state on `this`.\n */\n middlewareInstances?: Middleware.BaseMiddleware[];\n\n /**\n * Whether the client accepts SSE (`Accept: text/event-stream`). When true,\n * the execution engine may deliver the result as an SSE stream even if\n * `stream.push()` was not called.\n */\n acceptsSse?: boolean;\n\n /**\n * Provide the ability to transform the context passed to the function before\n * the execution starts.\n */\n transformCtx?: (ctx: Readonly<Context.Any>) => Context.Any;\n\n /**\n * A hook that is called to create an {@link ActionResponse} from the returned\n * value of an execution.\n *\n * This is required for checkpointing executions.\n */\n createResponse?: (data: unknown) => MaybePromise<ActionResponse>;\n}\n\nexport type InngestExecutionFactory = (\n options: InngestExecutionOptions,\n) => IInngestExecution;\n\nexport class InngestExecution {\n protected devDebug: Debugger;\n\n constructor(protected options: InngestExecutionOptions) {\n this.devDebug = Debug(`${debugPrefix}:${this.options.runId}`);\n }\n}\n\nexport interface IInngestExecution {\n version: ExecutionVersion;\n start(): Promise<ExecutionResult>;\n\n addMetadata(\n stepId: string,\n kind: MetadataKind,\n scope: MetadataScope,\n op: MetadataOpcode,\n values: Record<string, unknown>,\n ): boolean;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA+FA,MAAa,oCACX,iBAAiB;AAqGnB,IAAa,mBAAb,MAA8B;CAC5B,AAAU;CAEV,YAAY,AAAUA,SAAkC;EAAlC;AACpB,OAAK,WAAW,MAAM,GAAG,YAAY,GAAG,KAAK,QAAQ,QAAQ"}
@@ -7,9 +7,10 @@ const require_types = require('../../types.cjs');
7
7
  const require_InngestExecution = require('./InngestExecution.cjs');
8
8
  const require_types$1 = require('../../helpers/types.cjs');
9
9
  const require_functions = require('../../helpers/functions.cjs');
10
+ const require_marker = require('../../helpers/marker.cjs');
11
+ const require_temporal = require('../../helpers/temporal.cjs');
10
12
  const require_promises = require('../../helpers/promises.cjs');
11
13
  const require_als = require('./als.cjs');
12
- const require_temporal = require('../../helpers/temporal.cjs');
13
14
  const require_InngestStepTools = require('../InngestStepTools.cjs');
14
15
  const require_utils = require('../middleware/utils.cjs');
15
16
  const require_manager = require('../middleware/manager.cjs');
@@ -20,6 +21,7 @@ const require_StepError = require('../StepError.cjs');
20
21
  const require_streaming = require('./streaming.cjs');
21
22
  const require_StreamTools = require('../StreamTools.cjs');
22
23
  const require_utils$1 = require('../triggers/utils.cjs');
24
+ const require_lazyOps = require('./lazyOps.cjs');
23
25
  const require_access = require('./otel/access.cjs');
24
26
  let zod_v3 = require("zod/v3");
25
27
  let hash_js = require("hash.js");
@@ -260,6 +262,8 @@ var InngestExecutionEngine = class extends require_InngestExecution.InngestExecu
260
262
  throw new Error("Core loop finished without returning a value");
261
263
  }
262
264
  async checkpoint(steps) {
265
+ const lazyOps = this.state.lazyOps.drain();
266
+ if (lazyOps.length > 0) steps = [...steps, ...lazyOps];
263
267
  if (this.options.stepMode === require_types.StepMode.Sync) if (!this.state.checkpointedRun) {
264
268
  const res = await require_promises.retryWithBackoff(() => this.options.client["inngestApi"].checkpointNewRun({
265
269
  runId: this.fnArg.runId,
@@ -517,12 +521,13 @@ var InngestExecutionEngine = class extends require_InngestExecution.InngestExecu
517
521
  return transformResult;
518
522
  };
519
523
  const maybeReturnNewSteps = async () => {
520
- const newSteps = await this.filterNewSteps(Array.from(this.state.steps.values()));
521
- if (newSteps) return {
524
+ const allSteps = [...await this.filterNewSteps(Array.from(this.state.steps.values())) ?? [], ...this.state.lazyOps.drain()];
525
+ if (allSteps.length === 0) return;
526
+ return {
522
527
  type: "steps-found",
523
528
  ctx: this.fnArg,
524
529
  ops: this.ops,
525
- steps: newSteps
530
+ steps: allSteps
526
531
  };
527
532
  };
528
533
  const attemptCheckpointAndResume = async (stepResult, resume = true, force = false) => {
@@ -668,23 +673,36 @@ var InngestExecutionEngine = class extends require_InngestExecution.InngestExecu
668
673
  sseResponse = extractSseResponse(data, body);
669
674
  resultData = body;
670
675
  } else sseResponse = defaultSseResponse(resultData);
671
- const newStepsResult = await maybeReturnNewSteps();
672
- if (newStepsResult) return newStepsResult;
676
+ const newSteps = await this.filterNewSteps(Array.from(this.state.steps.values()));
677
+ if (newSteps?.length) return this.attachLazyOps({
678
+ type: "steps-found",
679
+ ctx: this.fnArg,
680
+ ops: this.ops,
681
+ steps: newSteps
682
+ });
673
683
  await this.streamCloseSucceeded(sseResponse);
674
684
  if (!this.streamTools.activated) this.postCheckpointStream();
675
685
  if (this.options.createResponse) data = await this.options.createResponse(jsonResponse(resultData));
676
- return this.transformOutput({ data });
686
+ return this.attachLazyOps(this.transformOutput({ data }));
677
687
  },
678
688
  "function-rejected": async (checkpoint) => {
679
689
  if (!this.retriability(checkpoint.error)) await this.streamCloseFailed(errorMessage(checkpoint.error));
680
690
  else await this.streamEnd();
681
691
  if (!this.streamTools.activated) this.postCheckpointStream();
682
- return this.transformOutput({ error: checkpoint.error });
692
+ return this.attachLazyOps(this.transformOutput({ error: checkpoint.error }));
683
693
  },
684
694
  "steps-found": async ({ steps }) => {
685
695
  const stepResult = await this.tryExecuteStep(steps);
686
- if (stepResult) return stepRanHandler(stepResult);
687
- return maybeReturnNewSteps();
696
+ if (!stepResult) return maybeReturnNewSteps();
697
+ if (this.state.lazyOps.length === 0) return stepRanHandler(stepResult);
698
+ const transformed = await stepRanHandler(stepResult);
699
+ if (transformed.type !== "step-ran") return transformed;
700
+ return this.attachLazyOps({
701
+ type: "steps-found",
702
+ ctx: transformed.ctx,
703
+ ops: transformed.ops,
704
+ steps: [transformed.step]
705
+ });
688
706
  },
689
707
  "step-not-found": ({ step }) => {
690
708
  const { foundSteps, totalFoundSteps } = this.getStepNotFoundDetails();
@@ -707,13 +725,18 @@ var InngestExecutionEngine = class extends require_InngestExecution.InngestExecu
707
725
  const asyncCheckpointingHandlers = {
708
726
  "": commonCheckpointHandler,
709
727
  "function-resolved": async (checkpoint, i) => {
728
+ const lazyOps = this.state.lazyOps.drain();
710
729
  const output = await asyncHandlers["function-resolved"](checkpoint, i);
711
730
  if (output?.type === "function-resolved") {
712
- const steps = this.state.checkpointingStepBuffer.concat({
713
- op: require_types.StepOpCode.RunComplete,
714
- id: hashId(RUN_COMPLETE_STEP_ID),
715
- data: output.data
716
- });
731
+ const steps = [
732
+ ...this.state.checkpointingStepBuffer,
733
+ ...lazyOps,
734
+ {
735
+ op: require_types.StepOpCode.RunComplete,
736
+ id: hashId(RUN_COMPLETE_STEP_ID),
737
+ data: output.data
738
+ }
739
+ ];
717
740
  if (isNonEmpty(steps)) return {
718
741
  type: "steps-found",
719
742
  ctx: output.ctx,
@@ -721,9 +744,14 @@ var InngestExecutionEngine = class extends require_InngestExecution.InngestExecu
721
744
  steps
722
745
  };
723
746
  }
747
+ if (output?.type === "steps-found" && lazyOps.length) return {
748
+ ...output,
749
+ steps: [...output.steps, ...lazyOps]
750
+ };
751
+ return output;
724
752
  },
725
753
  "function-rejected": async (checkpoint) => {
726
- if (this.state.checkpointingStepBuffer.length) {
754
+ if (this.state.checkpointingStepBuffer.length || this.state.lazyOps.length > 0) {
727
755
  const fallback = await attemptCheckpointAndResume(void 0, false, true);
728
756
  if (fallback) return fallback;
729
757
  }
@@ -968,7 +996,11 @@ var InngestExecutionEngine = class extends require_InngestExecution.InngestExecu
968
996
  * Validate event data against schemas defined in function triggers.
969
997
  */
970
998
  async validateEventSchemas() {
971
- if (this.options.isFailureHandler) return;
999
+ if (this.options.handlerKind === "failure") return;
1000
+ if (this.options.handlerKind === "defer") {
1001
+ await this.validateDeferEventSchema();
1002
+ return;
1003
+ }
972
1004
  const triggers = this.options.fn.opts.triggers;
973
1005
  if (!triggers || triggers.length === 0) return;
974
1006
  const fnArgEvents = this.fnArg.events;
@@ -979,6 +1011,17 @@ var InngestExecutionEngine = class extends require_InngestExecution.InngestExecu
979
1011
  })), triggers);
980
1012
  }
981
1013
  /**
1014
+ * Validate the deferred event's data against the defer function's own
1015
+ * schema (set via `createDefer`'s `opts.schema`).
1016
+ */
1017
+ async validateDeferEventSchema() {
1018
+ const fn = this.options.fn;
1019
+ if (!require_marker.isDeferredFunction(fn) || !fn.schema) return;
1020
+ const eventData = this.fnArg.event?.data;
1021
+ const result = await fn.schema["~standard"].validate(eventData);
1022
+ if (result.issues) throw new require_NonRetriableError.NonRetriableError(`defer handler "${fn.id(this.options.client.id)}" schema validation failed: ${JSON.stringify(result.issues)}`);
1023
+ }
1024
+ /**
982
1025
  * Using middleware, transform output before returning.
983
1026
  */
984
1027
  transformOutput(dataOrError) {
@@ -1001,6 +1044,64 @@ var InngestExecutionEngine = class extends require_InngestExecution.InngestExecu
1001
1044
  data: require_functions.undefinedToNull(data)
1002
1045
  };
1003
1046
  }
1047
+ /**
1048
+ * Drain buffered lazy ops (e.g. `DeferAdd` from `defer()`) and merge them
1049
+ * into `result` so they ship in the same outbound message. Lazy ops are
1050
+ * fire-and-forget and have no natural shipping moment, so each terminal code
1051
+ * path must ship them or they're silently dropped.
1052
+ */
1053
+ attachLazyOps(result, extras = []) {
1054
+ const lazyOps = this.state.lazyOps.drain();
1055
+ if (lazyOps.length === 0 && extras.length === 0) return result;
1056
+ switch (result.type) {
1057
+ case "function-resolved": {
1058
+ const steps = [
1059
+ ...extras,
1060
+ ...lazyOps,
1061
+ {
1062
+ op: require_types.StepOpCode.RunComplete,
1063
+ id: hashId(RUN_COMPLETE_STEP_ID),
1064
+ data: require_functions.undefinedToNull(result.data)
1065
+ }
1066
+ ];
1067
+ return {
1068
+ type: "steps-found",
1069
+ ctx: result.ctx,
1070
+ ops: result.ops,
1071
+ steps
1072
+ };
1073
+ }
1074
+ case "function-rejected": {
1075
+ const isFinal = result.retriable === false;
1076
+ const steps = [
1077
+ ...extras,
1078
+ ...lazyOps,
1079
+ {
1080
+ op: isFinal ? require_types.StepOpCode.StepFailed : require_types.StepOpCode.StepError,
1081
+ id: hashId(RUN_COMPLETE_STEP_ID),
1082
+ error: result.error
1083
+ }
1084
+ ];
1085
+ return {
1086
+ type: "steps-found",
1087
+ ctx: result.ctx,
1088
+ ops: result.ops,
1089
+ steps
1090
+ };
1091
+ }
1092
+ case "steps-found": return {
1093
+ ...result,
1094
+ steps: [
1095
+ ...result.steps,
1096
+ ...extras,
1097
+ ...lazyOps
1098
+ ]
1099
+ };
1100
+ default:
1101
+ for (const op of lazyOps) this.state.lazyOps.push(op);
1102
+ return result;
1103
+ }
1104
+ }
1004
1105
  createExecutionState() {
1005
1106
  const d = require_promises.createDeferredPromiseWithStack();
1006
1107
  let checkpointResolve = d.deferred.resolve;
@@ -1023,6 +1124,7 @@ var InngestExecutionEngine = class extends require_InngestExecution.InngestExecu
1023
1124
  const stepsToFulfill = Object.keys(this.options.stepState).length;
1024
1125
  return {
1025
1126
  stepState: this.options.stepState,
1127
+ priorDefers: this.options.priorDefers ?? {},
1026
1128
  stepsToFulfill,
1027
1129
  steps: /* @__PURE__ */ new Map(),
1028
1130
  loop,
@@ -1037,6 +1139,7 @@ var InngestExecutionEngine = class extends require_InngestExecution.InngestExecu
1037
1139
  return this.state.remainingStepsToBeSeen.size === 0;
1038
1140
  },
1039
1141
  checkpointingStepBuffer: [],
1142
+ lazyOps: new require_lazyOps.LazyOps(),
1040
1143
  metadata: /* @__PURE__ */ new Map()
1041
1144
  };
1042
1145
  }
@@ -1044,17 +1147,22 @@ var InngestExecutionEngine = class extends require_InngestExecution.InngestExecu
1044
1147
  return Object.fromEntries(this.state.steps);
1045
1148
  }
1046
1149
  createFnArg() {
1047
- const step = this.createStepTools();
1150
+ const { step, defer } = this.createStepTools();
1048
1151
  const experimentStepRun = step[require_InngestStepTools.experimentStepRunSymbol];
1049
1152
  let fnArg = {
1050
1153
  ...this.options.data,
1051
1154
  step,
1052
- group: require_InngestGroupTools.createGroupTools({ experimentStepRun })
1155
+ group: require_InngestGroupTools.createGroupTools({ experimentStepRun }),
1156
+ defer
1053
1157
  };
1158
+ if (this.options.handlerKind === "defer") {
1159
+ delete fnArg.event.data._inngest;
1160
+ for (const event of fnArg.events) delete event.data._inngest;
1161
+ }
1054
1162
  /**
1055
1163
  * Handle use of the `onFailure` option by deserializing the error.
1056
1164
  */
1057
- if (this.options.isFailureHandler) {
1165
+ if (this.options.handlerKind === "failure") {
1058
1166
  const eventData = zod_v3.z.object({ error: require_types.jsonErrorSchema }).parse(fnArg.event?.data);
1059
1167
  fnArg = {
1060
1168
  ...fnArg,
@@ -1183,6 +1291,30 @@ var InngestExecutionEngine = class extends require_InngestExecution.InngestExecu
1183
1291
  };
1184
1292
  const stepHandler = async ({ args, matchOp, opts }) => {
1185
1293
  const opId = matchOp(require_InngestStepTools.getStepOptions(args[0]), ...args.slice(1));
1294
+ if (require_lazyOps.isLazyOp(opts, opId)) {
1295
+ const hashedId$1 = _internals.hashId(opId.id);
1296
+ if (this.state.lazyOps.hasId(hashedId$1)) {
1297
+ this.options.client[require_Inngest.internalLoggerSymbol].warn({
1298
+ runId: this.fnArg.runId,
1299
+ id: opId.userland?.id ?? opId.id
1300
+ }, "defer skipped: duplicate ID within run");
1301
+ return;
1302
+ }
1303
+ if (this.state.priorDefers[hashedId$1]) {
1304
+ this.state.lazyOps.markSeen(hashedId$1);
1305
+ return;
1306
+ }
1307
+ this.state.lazyOps.push({
1308
+ id: hashedId$1,
1309
+ op: opId.op,
1310
+ name: opId.name,
1311
+ displayName: opId.displayName ?? opId.id,
1312
+ opts: opId.opts,
1313
+ userland: opId.userland,
1314
+ data: null
1315
+ });
1316
+ return;
1317
+ }
1186
1318
  if (this.state.executingStep)
1187
1319
  /**
1188
1320
  * If a step is found after asynchronous actions during another step's
@@ -1304,7 +1436,75 @@ var InngestExecutionEngine = class extends require_InngestExecution.InngestExecu
1304
1436
  } else pushStepToReport(step);
1305
1437
  return promise;
1306
1438
  };
1307
- return require_InngestStepTools.createStepTools(this.options.client, this, stepHandler);
1439
+ return {
1440
+ step: require_InngestStepTools.createStepTools(this.options.client, this, stepHandler),
1441
+ defer: this.buildDefer(stepHandler)
1442
+ };
1443
+ }
1444
+ /**
1445
+ * Build the `defer(idOrOptions, { function, data })` method exposed on
1446
+ * every handler context. Validates `data` against the target function's
1447
+ * schema (if any) and emits a `DeferAdd` opcode that routes to the
1448
+ * target's companion function slug.
1449
+ *
1450
+ * `defer()` is fire-and-forget: a misuse should not derail the user's
1451
+ * handler. Validation failures (wrong function, async schema validator,
1452
+ * schema mismatch) are logged and the call is silently skipped.
1453
+ */
1454
+ buildDefer(stepHandler) {
1455
+ return (idOrOptions, { function: deferFn, data }) => {
1456
+ const log = this.options.client[require_Inngest.internalLoggerSymbol];
1457
+ const runId = this.fnArg.runId;
1458
+ try {
1459
+ if (!require_marker.isDeferredFunction(deferFn)) {
1460
+ log.error({ runId }, "defer skipped: function not created via createDefer");
1461
+ return;
1462
+ }
1463
+ const { schema } = deferFn;
1464
+ const deferFnSlug = deferFn.id(this.options.client.id);
1465
+ let input = data;
1466
+ if (schema) {
1467
+ const result = schema["~standard"].validate(data);
1468
+ if (result instanceof Promise) {
1469
+ log.error({ runId }, "defer() requires a synchronous schema validator. The defer call was skipped.");
1470
+ return;
1471
+ }
1472
+ if (result.issues) {
1473
+ log.error({
1474
+ runId,
1475
+ issues: result.issues
1476
+ }, "defer skipped: schema validation failed");
1477
+ return;
1478
+ }
1479
+ input = result.value ?? data;
1480
+ }
1481
+ stepHandler({
1482
+ args: [idOrOptions, input],
1483
+ matchOp: (stepOptions, inputArg) => ({
1484
+ id: stepOptions.id,
1485
+ mode: require_types.StepMode.Sync,
1486
+ op: require_types.StepOpCode.DeferAdd,
1487
+ name: stepOptions.name ?? stepOptions.id,
1488
+ displayName: stepOptions.name ?? stepOptions.id,
1489
+ opts: {
1490
+ fn_slug: deferFnSlug,
1491
+ input: inputArg
1492
+ },
1493
+ userland: { id: stepOptions.id }
1494
+ })
1495
+ }).catch((err) => {
1496
+ log.error({
1497
+ runId,
1498
+ err
1499
+ }, "defer skipped: unexpected error");
1500
+ });
1501
+ } catch (err) {
1502
+ log.error({
1503
+ runId,
1504
+ err
1505
+ }, "defer skipped: unexpected error");
1506
+ }
1507
+ };
1308
1508
  }
1309
1509
  /**
1310
1510
  * Applies middleware transformations to a step, resolves ID collisions,
@@ -1386,14 +1586,19 @@ var InngestExecutionEngine = class extends require_InngestExecution.InngestExecu
1386
1586
  return userlandStep;
1387
1587
  }
1388
1588
  getUserFnToRun() {
1389
- if (!this.options.isFailureHandler) return this.options.fn["fn"];
1390
- if (!this.options.fn["onFailureFn"])
1589
+ switch (this.options.handlerKind) {
1590
+ case "defer": return this.options.fn["fn"];
1591
+ case "failure":
1592
+ if (!this.options.fn["onFailureFn"])
1391
1593
  /**
1392
- * Somehow, we've ended up detecting that this is a failure handler but
1393
- * doesn't have an `onFailure` function. This should never happen.
1394
- */
1395
- throw new Error("Cannot find function `onFailure` handler");
1396
- return this.options.fn["onFailureFn"];
1594
+ * Somehow, we've ended up detecting that this is a failure handler
1595
+ * but doesn't have an `onFailure` function. This should never
1596
+ * happen.
1597
+ */
1598
+ throw new Error("Cannot find function `onFailure` handler");
1599
+ return this.options.fn["onFailureFn"];
1600
+ default: return this.options.fn["fn"];
1601
+ }
1397
1602
  }
1398
1603
  initializeTimer(state) {
1399
1604
  if (!this.options.requestedRunStep) return;