inngest 4.7.0 → 4.9.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 (138) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/components/DeferredFunction.cjs +52 -0
  3. package/components/DeferredFunction.cjs.map +1 -1
  4. package/components/DeferredFunction.d.cts +35 -9
  5. package/components/DeferredFunction.d.cts.map +1 -1
  6. package/components/DeferredFunction.d.ts +35 -9
  7. package/components/DeferredFunction.d.ts.map +1 -1
  8. package/components/DeferredFunction.js +53 -1
  9. package/components/DeferredFunction.js.map +1 -1
  10. package/components/Inngest.cjs +24 -1
  11. package/components/Inngest.cjs.map +1 -1
  12. package/components/Inngest.d.cts +23 -3
  13. package/components/Inngest.d.cts.map +1 -1
  14. package/components/Inngest.d.ts +23 -3
  15. package/components/Inngest.d.ts.map +1 -1
  16. package/components/Inngest.js +24 -1
  17. package/components/Inngest.js.map +1 -1
  18. package/components/InngestCommHandler.d.cts +2 -2
  19. package/components/InngestCommHandler.d.ts +2 -2
  20. package/components/InngestFunction.d.cts +2 -2
  21. package/components/InngestFunction.d.ts +2 -2
  22. package/components/InngestGroupTools.cjs +7 -4
  23. package/components/InngestGroupTools.cjs.map +1 -1
  24. package/components/InngestGroupTools.d.cts +5 -24
  25. package/components/InngestGroupTools.d.cts.map +1 -1
  26. package/components/InngestGroupTools.d.ts +5 -24
  27. package/components/InngestGroupTools.d.ts.map +1 -1
  28. package/components/InngestGroupTools.js +7 -4
  29. package/components/InngestGroupTools.js.map +1 -1
  30. package/components/InngestMetadata.cjs +18 -4
  31. package/components/InngestMetadata.cjs.map +1 -1
  32. package/components/InngestMetadata.d.cts +2 -2
  33. package/components/InngestMetadata.d.cts.map +1 -1
  34. package/components/InngestMetadata.d.ts +2 -2
  35. package/components/InngestMetadata.d.ts.map +1 -1
  36. package/components/InngestMetadata.js +18 -5
  37. package/components/InngestMetadata.js.map +1 -1
  38. package/components/InngestScore.cjs +93 -0
  39. package/components/InngestScore.cjs.map +1 -0
  40. package/components/InngestScore.d.cts +89 -0
  41. package/components/InngestScore.d.cts.map +1 -0
  42. package/components/InngestScore.d.ts +89 -0
  43. package/components/InngestScore.d.ts.map +1 -0
  44. package/components/InngestScore.js +88 -0
  45. package/components/InngestScore.js.map +1 -0
  46. package/components/InngestStepTools.cjs +9 -0
  47. package/components/InngestStepTools.cjs.map +1 -1
  48. package/components/InngestStepTools.d.cts +5 -3
  49. package/components/InngestStepTools.d.cts.map +1 -1
  50. package/components/InngestStepTools.d.ts +5 -3
  51. package/components/InngestStepTools.d.ts.map +1 -1
  52. package/components/InngestStepTools.js +9 -0
  53. package/components/InngestStepTools.js.map +1 -1
  54. package/components/ScoreFunction.cjs +37 -0
  55. package/components/ScoreFunction.cjs.map +1 -0
  56. package/components/ScoreFunction.d.cts +24 -0
  57. package/components/ScoreFunction.d.cts.map +1 -0
  58. package/components/ScoreFunction.d.ts +24 -0
  59. package/components/ScoreFunction.d.ts.map +1 -0
  60. package/components/ScoreFunction.js +37 -0
  61. package/components/ScoreFunction.js.map +1 -0
  62. package/components/execution/InngestExecution.d.cts +2 -2
  63. package/components/execution/InngestExecution.d.ts +2 -2
  64. package/components/execution/als.cjs.map +1 -1
  65. package/components/execution/als.d.cts +1 -0
  66. package/components/execution/als.d.cts.map +1 -1
  67. package/components/execution/als.d.ts +1 -0
  68. package/components/execution/als.d.ts.map +1 -1
  69. package/components/execution/als.js.map +1 -1
  70. package/components/execution/engine.cjs +12 -10
  71. package/components/execution/engine.cjs.map +1 -1
  72. package/components/execution/engine.d.cts +1 -1
  73. package/components/execution/engine.d.cts.map +1 -1
  74. package/components/execution/engine.d.ts +1 -1
  75. package/components/execution/engine.d.ts.map +1 -1
  76. package/components/execution/engine.js +13 -11
  77. package/components/execution/engine.js.map +1 -1
  78. package/components/execution/otel/aiExtractor.cjs +90 -125
  79. package/components/execution/otel/aiExtractor.cjs.map +1 -1
  80. package/components/execution/otel/aiExtractor.d.cts +48 -5
  81. package/components/execution/otel/aiExtractor.d.cts.map +1 -1
  82. package/components/execution/otel/aiExtractor.d.ts +48 -5
  83. package/components/execution/otel/aiExtractor.d.ts.map +1 -1
  84. package/components/execution/otel/aiExtractor.js +90 -125
  85. package/components/execution/otel/aiExtractor.js.map +1 -1
  86. package/components/execution/otel/middleware.cjs +3 -1
  87. package/components/execution/otel/middleware.cjs.map +1 -1
  88. package/components/execution/otel/middleware.d.cts +19 -12
  89. package/components/execution/otel/middleware.d.cts.map +1 -1
  90. package/components/execution/otel/middleware.d.ts +19 -12
  91. package/components/execution/otel/middleware.d.ts.map +1 -1
  92. package/components/execution/otel/middleware.js +4 -2
  93. package/components/execution/otel/middleware.js.map +1 -1
  94. package/components/execution/otel/util.cjs +9 -1
  95. package/components/execution/otel/util.cjs.map +1 -1
  96. package/components/execution/otel/util.js +9 -2
  97. package/components/execution/otel/util.js.map +1 -1
  98. package/components/realtime/types.d.cts +3 -3
  99. package/components/realtime/types.d.cts.map +1 -1
  100. package/components/realtime/types.d.ts +3 -3
  101. package/components/realtime/types.d.ts.map +1 -1
  102. package/experimental.cjs +5 -1
  103. package/experimental.d.cts +4 -1
  104. package/experimental.d.ts +4 -1
  105. package/experimental.js +3 -1
  106. package/helpers/consts.cjs +7 -0
  107. package/helpers/consts.cjs.map +1 -1
  108. package/helpers/consts.d.cts.map +1 -1
  109. package/helpers/consts.d.ts.map +1 -1
  110. package/helpers/consts.js +7 -1
  111. package/helpers/consts.js.map +1 -1
  112. package/helpers/errors.cjs +16 -0
  113. package/helpers/errors.cjs.map +1 -1
  114. package/helpers/errors.d.cts +12 -1
  115. package/helpers/errors.d.cts.map +1 -1
  116. package/helpers/errors.d.ts +12 -1
  117. package/helpers/errors.d.ts.map +1 -1
  118. package/helpers/errors.js +16 -1
  119. package/helpers/errors.js.map +1 -1
  120. package/helpers/types.cjs +4 -0
  121. package/helpers/types.cjs.map +1 -1
  122. package/helpers/types.js +4 -1
  123. package/helpers/types.js.map +1 -1
  124. package/index.d.cts +2 -2
  125. package/index.d.ts +2 -2
  126. package/package.json +1 -1
  127. package/types.cjs.map +1 -1
  128. package/types.d.cts +30 -9
  129. package/types.d.cts.map +1 -1
  130. package/types.d.ts +30 -9
  131. package/types.d.ts.map +1 -1
  132. package/types.js.map +1 -1
  133. package/version.cjs +1 -1
  134. package/version.cjs.map +1 -1
  135. package/version.d.cts +1 -1
  136. package/version.d.ts +1 -1
  137. package/version.js +1 -1
  138. package/version.js.map +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # inngest
2
2
 
3
+ ## 4.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#1594](https://github.com/inngest/inngest-js/pull/1594) [`124e55f8`](https://github.com/inngest/inngest-js/commit/124e55f8d159af9145a073c9756a6281da60185b) Thanks [@scottnuma](https://github.com/scottnuma)! - Expand AI step metadata extraction to more OTel GenAI span attributes. The SDK now records additional model, provider, response id, token, and request parameter fields from OTel GenAI spans while continuing to ignore prompt and response content.
8
+
9
+ This removes the previous metadata extraction for Open Inference, Vercel AI SDK-specific, and Langfuse-specific span attributes.
10
+
11
+ ## 4.8.0
12
+
13
+ ### Minor Changes
14
+
15
+ - [#1595](https://github.com/inngest/inngest-js/pull/1595) [`aa315c7e`](https://github.com/inngest/inngest-js/commit/aa315c7ec9b99a69a7f85720e2805991b3e23841) Thanks [@amh4r](https://github.com/amh4r)! - Add opt-out for AI metadata extraction
16
+
17
+ - [#1521](https://github.com/inngest/inngest-js/pull/1521) [`a69ec0e2`](https://github.com/inngest/inngest-js/commit/a69ec0e25acbf5c3a45b547ccf9d4d6819580a86) Thanks [@jakobevangelista](https://github.com/jakobevangelista)! - Add experimental createScorer function
18
+
19
+ - [#1521](https://github.com/inngest/inngest-js/pull/1521) [`a69ec0e2`](https://github.com/inngest/inngest-js/commit/a69ec0e25acbf5c3a45b547ccf9d4d6819580a86) Thanks [@jakobevangelista](https://github.com/jakobevangelista)! - Add experimental scoring primitives for writing run- and step-scoped `inngest.score` metadata via `inngest.score()` and `scoreMiddleware()`-gated `step.score()`.
20
+
21
+ ### Patch Changes
22
+
23
+ - [#1592](https://github.com/inngest/inngest-js/pull/1592) [`748c6cc4`](https://github.com/inngest/inngest-js/commit/748c6cc4fb167af9223c2b87d6c6543245d1428b) Thanks [@amh4r](https://github.com/amh4r)! - Deprecate Extended Traces provider creation. `behaviour: "createProvider"` and the `"auto"` fallback remain functional, but now direct users to preload `@inngest/otel/node` and extend that provider instead.
24
+
3
25
  ## 4.7.0
4
26
 
5
27
  ### Minor Changes
@@ -1,10 +1,39 @@
1
1
  const require_consts = require('../helpers/consts.cjs');
2
+ const require_errors = require('../helpers/errors.cjs');
3
+ const require_types = require('../helpers/types.cjs');
2
4
  const require_marker = require('../helpers/marker.cjs');
3
5
  const require_InngestFunction = require('./InngestFunction.cjs');
4
6
 
5
7
  //#region src/components/DeferredFunction.ts
6
8
  const idDenyRegex = /['\\\n\r]/;
7
9
  /**
10
+ * Validates the reserved experiment-ref input key into an `ExperimentRef`, or
11
+ * `undefined` when it's absent or malformed.
12
+ */
13
+ function parseExperimentRef(value) {
14
+ if (require_types.isRecord(value) && typeof value.experimentName === "string" && typeof value.variant === "string") return {
15
+ experimentName: value.experimentName,
16
+ variant: value.variant
17
+ };
18
+ }
19
+ /**
20
+ * Strips our `_inngest` metadata off an event's `data` in place and returns the
21
+ * parent routing metadata extracted from it.
22
+ */
23
+ function stripInngestMetadata(event) {
24
+ const { _inngest, [require_consts.deferExperimentKey]: experiment, ...input } = event.data ?? {};
25
+ if (!require_types.isRecord(_inngest)) throw new require_errors.UnreachableError("deferred event is missing _inngest metadata");
26
+ const { parent_fn_slug, parent_run_id } = _inngest;
27
+ if (typeof parent_fn_slug !== "string") throw new require_errors.UnreachableError("deferred event _inngest metadata is missing parent_fn_slug");
28
+ if (typeof parent_run_id !== "string") throw new require_errors.UnreachableError("deferred event _inngest metadata is missing parent_run_id");
29
+ event.data = input;
30
+ return {
31
+ fnSlug: parent_fn_slug,
32
+ runId: parent_run_id,
33
+ experiment: parseExperimentRef(experiment)
34
+ };
35
+ }
36
+ /**
8
37
  * EXPERIMENTAL: This API is not yet stable and may change in the future without
9
38
  * a major version bump.
10
39
  *
@@ -37,6 +66,29 @@ var DeferredFunction = class extends require_InngestFunction.InngestFunction {
37
66
  expression: `event.data._inngest.fn_slug == '${fnId}'`
38
67
  }];
39
68
  }
69
+ /**
70
+ * Installs a `transformCtx` hook that runs before middleware and user code:
71
+ * - Strips our `_inngest` metadata off each event's `data`, ensuring it
72
+ * matches what the user expects.
73
+ * - Collects the parent function's slug and run ID from that metadata into
74
+ * `ctx.parents`, so the handler can correlate each event to its parent.
75
+ */
76
+ createExecution(opts) {
77
+ return super.createExecution({
78
+ ...opts,
79
+ partialOptions: {
80
+ ...opts.partialOptions,
81
+ transformCtx: (ctx) => {
82
+ const parents = ctx.events.map(stripInngestMetadata);
83
+ stripInngestMetadata(ctx.event);
84
+ return {
85
+ ...ctx,
86
+ parents
87
+ };
88
+ }
89
+ }
90
+ });
91
+ }
40
92
  };
41
93
  /**
42
94
  * EXPERIMENTAL: This API is not yet stable and may change in the future without
@@ -1 +1 @@
1
- {"version":3,"file":"DeferredFunction.cjs","names":["InngestFunction","markerKey","internalEvents"],"sources":["../../src/components/DeferredFunction.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { internalEvents } from \"../helpers/consts.ts\";\nimport { type Marker, markerKey } from \"../helpers/marker.ts\";\nimport type {\n ApplyAllMiddlewareCtxExtensions,\n ApplyAllMiddlewareStepExtensions,\n BaseContext,\n FunctionConfig,\n Handler,\n} from \"../types.ts\";\nimport type {\n builtInMiddleware,\n ClientOptionsFromInngest,\n Inngest,\n} from \"./Inngest.ts\";\nimport { InngestFunction } from \"./InngestFunction.ts\";\nimport type { createStepTools } from \"./InngestStepTools.ts\";\nimport type { Middleware } from \"./middleware/index.ts\";\n\nconst idDenyRegex = /['\\\\\\n\\r]/;\n\n/**\n * EXPERIMENTAL: This API is not yet stable and may change in the future without\n * a major version bump.\n *\n * A defer (companion) function created via `createDefer(...)`. Real\n * `InngestFunction` at runtime, but with the trigger pinned to\n * `inngest/deferred.schedule` (see `getConfigTriggers`), `triggers` and\n * `onFailure` disallowed, and the schema carried as a typed instance\n * property so callers of `defer(id, { function, data })` can extract it.\n *\n * Identify a defer function at runtime via `isDeferredFunction(value)` from\n * `helpers/marker.ts`. Prefer that over `instanceof`, which fails across\n * duplicate SDK copies in the same process.\n *\n * @public\n */\nexport class DeferredFunction<\n TSchema extends\n | StandardSchemaV1<Record<string, unknown>>\n | undefined = undefined,\n> extends InngestFunction<\n InngestFunction.Options<[], never>,\n Handler.Any,\n never,\n Inngest.Any,\n []\n> {\n readonly schema: TSchema;\n readonly [markerKey]: Marker = { kind: \"DeferredFunction\" };\n\n constructor(\n client: Inngest.Any,\n opts: DeferredFunction.Options,\n handler: Handler.Any,\n schema: TSchema,\n ) {\n // The id is interpolated into a CEL trigger expression\n // (`event.data._inngest.fn_slug == '${fnId}'`). Reject characters that\n // would break the single-quoted string literal.\n if (idDenyRegex.test(opts.id)) {\n throw new Error(\n `invalid id \"${opts.id}\"; must match ${idDenyRegex.source}`,\n );\n }\n super(\n client,\n { ...opts, triggers: [] } as InngestFunction.Options<[], never>,\n handler,\n );\n this.schema = schema;\n }\n\n protected override getConfigTriggers(\n fnId: string,\n ): FunctionConfig[\"triggers\"] {\n return [\n {\n event: internalEvents.DeferredSchedule,\n expression: `event.data._inngest.fn_slug == '${fnId}'`,\n },\n ];\n }\n}\n\n/**\n * @public\n */\nexport namespace DeferredFunction {\n /**\n * Matches any `DeferredFunction` regardless of its schema. Use as the\n * constraint for the `function` argument of `defer()`.\n */\n // biome-ignore lint/suspicious/noExplicitAny: widest schema constraint for inference\n export type Any = DeferredFunction<StandardSchemaV1<any> | undefined>;\n\n /**\n * The user-facing options accepted by `createDefer(client, opts, handler)`.\n * Mirrors `InngestFunction.Options` minus `triggers` (implicit), `onFailure`\n * (not yet supported), and `batchEvents` (each `defer(...)` is its own run).\n */\n export type Options = Omit<\n InngestFunction.Options<[], never>,\n \"triggers\" | \"onFailure\" | \"batchEvents\"\n >;\n}\n\n/**\n * The `event` shape a defer handler receives. With a schema, `data`\n * narrows to its inferred type; without one, it falls back to\n * `Record<string, any>`.\n */\ntype DeferEvent<TSchema> = {\n name: internalEvents.DeferredSchedule;\n data: TSchema extends StandardSchemaV1<\n infer D extends Record<string, unknown>\n >\n ? D\n : // biome-ignore lint/suspicious/noExplicitAny: no schema = any\n Record<string, any>;\n};\n\n/**\n * Base ctx shape for a defer handler: the standard function context\n * (`runId`, `attempt`, `group`, `step` with middleware step extensions)\n * with `event`/`events` pinned to `inngest/deferred.schedule` and the\n * schema-typed payload.\n */\ntype BaseDeferCtx<\n TClient extends Inngest.Any,\n TFnMiddleware extends Middleware.Class[] | undefined,\n TSchema extends StandardSchemaV1<Record<string, unknown>> | undefined,\n> = Omit<BaseContext<TClient>, \"event\" | \"events\" | \"step\"> & {\n event: DeferEvent<TSchema>;\n events: [DeferEvent<TSchema>];\n step: ReturnType<typeof createStepTools<TClient, TFnMiddleware>> &\n ApplyAllMiddlewareStepExtensions<\n ClientOptionsFromInngest<TClient>[\"middleware\"]\n > &\n ApplyAllMiddlewareStepExtensions<TFnMiddleware>;\n};\n\n/**\n * Input type for `createDefer`. Same shape as `DeferredFunction.Options`\n * plus `schema` (the StandardSchema describing `event.data` that flows\n * to caller `defer(id, { function, data })` call sites) and `middleware`.\n */\nexport type CreateDeferInput<\n TFnMiddleware extends Middleware.Class[] | undefined,\n TSchema extends StandardSchemaV1<Record<string, unknown>> | undefined,\n> = DeferredFunction.Options & {\n schema?: TSchema;\n middleware?: TFnMiddleware;\n};\n\n/**\n * EXPERIMENTAL: This API is not yet stable and may change in the future without\n * a major version bump.\n *\n * Create a typed defer function. One `createDefer` call = one Inngest\n * function. Returns a `DeferredFunction<TSchema>` so callers of `defer(id,\n * { function, data })` get the data type inferred from the schema.\n *\n * Mirrors `inngest.createFunction(opts, handler)`, with three differences:\n * the client is the first positional arg, `triggers` is not accepted (the\n * SDK emits an implicit `inngest/deferred.schedule` trigger), and `schema`\n * describes the payload that callers will send via `defer(id, { function,\n * data })`.\n *\n * Pass the result to `serve()` alongside regular functions so the SDK\n * registers it.\n */\nexport function createDefer<\n TClient extends Inngest.Any,\n TSchema extends\n | StandardSchemaV1<Record<string, unknown>>\n | undefined = undefined,\n const TFnMiddleware extends Middleware.Class[] | undefined = undefined,\n THandler extends Handler.Any = (\n ctx: BaseDeferCtx<TClient, TFnMiddleware, TSchema> &\n ApplyAllMiddlewareCtxExtensions<\n [...ReturnType<typeof builtInMiddleware>]\n > &\n ApplyAllMiddlewareCtxExtensions<\n ClientOptionsFromInngest<TClient>[\"middleware\"]\n > &\n ApplyAllMiddlewareCtxExtensions<TFnMiddleware>,\n ) => unknown,\n>(\n client: TClient,\n options: CreateDeferInput<TFnMiddleware, TSchema>,\n handler: THandler,\n): DeferredFunction<TSchema> {\n const { schema, ...rest } = options;\n return new DeferredFunction<TSchema>(\n client,\n rest,\n handler as Handler.Any,\n schema as TSchema,\n );\n}\n"],"mappings":";;;;;AAmBA,MAAM,cAAc;;;;;;;;;;;;;;;;;AAkBpB,IAAa,mBAAb,cAIUA,wCAMR;CACA,AAAS;CACT,CAAUC,4BAAqB,EAAE,MAAM,oBAAoB;CAE3D,YACE,QACA,MACA,SACA,QACA;AAIA,MAAI,YAAY,KAAK,KAAK,GAAG,CAC3B,OAAM,IAAI,MACR,eAAe,KAAK,GAAG,gBAAgB,YAAY,SACpD;AAEH,QACE,QACA;GAAE,GAAG;GAAM,UAAU,EAAE;GAAE,EACzB,QACD;AACD,OAAK,SAAS;;CAGhB,AAAmB,kBACjB,MAC4B;AAC5B,SAAO,CACL;GACE,OAAOC,8BAAe;GACtB,YAAY,mCAAmC,KAAK;GACrD,CACF;;;;;;;;;;;;;;;;;;;;AA2FL,SAAgB,YAiBd,QACA,SACA,SAC2B;CAC3B,MAAM,EAAE,QAAQ,GAAG,SAAS;AAC5B,QAAO,IAAI,iBACT,QACA,MACA,SACA,OACD"}
1
+ {"version":3,"file":"DeferredFunction.cjs","names":["isRecord","deferExperimentKey","UnreachableError","InngestFunction","markerKey","internalEvents"],"sources":["../../src/components/DeferredFunction.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { deferExperimentKey, internalEvents } from \"../helpers/consts.ts\";\nimport { UnreachableError } from \"../helpers/errors.ts\";\nimport { type Marker, markerKey } from \"../helpers/marker.ts\";\nimport { isRecord } from \"../helpers/types.ts\";\nimport type {\n ApplyAllMiddlewareCtxExtensions,\n ApplyAllMiddlewareStepExtensions,\n BaseContext,\n ExperimentRef,\n FunctionConfig,\n Handler,\n} from \"../types.ts\";\nimport type { IInngestExecution } from \"./execution/InngestExecution.ts\";\nimport type {\n builtInMiddleware,\n ClientOptionsFromInngest,\n Inngest,\n} from \"./Inngest.ts\";\nimport {\n type CreateExecutionOptions,\n InngestFunction,\n} from \"./InngestFunction.ts\";\nimport type { createStepTools } from \"./InngestStepTools.ts\";\nimport type { Middleware } from \"./middleware/index.ts\";\n\nconst idDenyRegex = /['\\\\\\n\\r]/;\n\n/**\n * Validates the reserved experiment-ref input key into an `ExperimentRef`, or\n * `undefined` when it's absent or malformed.\n */\nfunction parseExperimentRef(value: unknown): ExperimentRef | undefined {\n if (\n isRecord(value) &&\n typeof value.experimentName === \"string\" &&\n typeof value.variant === \"string\"\n ) {\n return { experimentName: value.experimentName, variant: value.variant };\n }\n return undefined;\n}\n\n/**\n * Strips our `_inngest` metadata off an event's `data` in place and returns the\n * parent routing metadata extracted from it.\n */\nfunction stripInngestMetadata(event: {\n data?: Record<string, unknown>;\n}): DeferredFunction.Parent {\n const data = event.data ?? {};\n const { _inngest, [deferExperimentKey]: experiment, ...input } = data;\n\n if (!isRecord(_inngest)) {\n throw new UnreachableError(\"deferred event is missing _inngest metadata\");\n }\n const { parent_fn_slug, parent_run_id } = _inngest;\n if (typeof parent_fn_slug !== \"string\") {\n throw new UnreachableError(\n \"deferred event _inngest metadata is missing parent_fn_slug\",\n );\n }\n if (typeof parent_run_id !== \"string\") {\n throw new UnreachableError(\n \"deferred event _inngest metadata is missing parent_run_id\",\n );\n }\n\n // Mutate in place\n event.data = input;\n\n return {\n fnSlug: parent_fn_slug,\n runId: parent_run_id,\n experiment: parseExperimentRef(experiment),\n };\n}\n\n/**\n * EXPERIMENTAL: This API is not yet stable and may change in the future without\n * a major version bump.\n *\n * A defer (companion) function created via `createDefer(...)`. Real\n * `InngestFunction` at runtime, but with the trigger pinned to\n * `inngest/deferred.schedule` (see `getConfigTriggers`), `triggers` and\n * `onFailure` disallowed, and the schema carried as a typed instance\n * property so callers of `defer(id, { function, data })` can extract it.\n *\n * Identify a defer function at runtime via `isDeferredFunction(value)` from\n * `helpers/marker.ts`. Prefer that over `instanceof`, which fails across\n * duplicate SDK copies in the same process.\n *\n * @public\n */\nexport class DeferredFunction<\n TSchema extends\n | StandardSchemaV1<Record<string, unknown>>\n | undefined = undefined,\n> extends InngestFunction<\n InngestFunction.Options<[], never>,\n Handler.Any,\n never,\n Inngest.Any,\n []\n> {\n readonly schema: TSchema;\n readonly [markerKey]: Marker = { kind: \"DeferredFunction\" };\n\n constructor(\n client: Inngest.Any,\n opts: DeferredFunction.Options,\n handler: Handler.Any,\n schema: TSchema,\n ) {\n // The id is interpolated into a CEL trigger expression\n // (`event.data._inngest.fn_slug == '${fnId}'`). Reject characters that\n // would break the single-quoted string literal.\n if (idDenyRegex.test(opts.id)) {\n throw new Error(\n `invalid id \"${opts.id}\"; must match ${idDenyRegex.source}`,\n );\n }\n super(\n client,\n { ...opts, triggers: [] } as InngestFunction.Options<[], never>,\n handler,\n );\n this.schema = schema;\n }\n\n protected override getConfigTriggers(\n fnId: string,\n ): FunctionConfig[\"triggers\"] {\n return [\n {\n event: internalEvents.DeferredSchedule,\n expression: `event.data._inngest.fn_slug == '${fnId}'`,\n },\n ];\n }\n\n /**\n * Installs a `transformCtx` hook that runs before middleware and user code:\n * - Strips our `_inngest` metadata off each event's `data`, ensuring it\n * matches what the user expects.\n * - Collects the parent function's slug and run ID from that metadata into\n * `ctx.parents`, so the handler can correlate each event to its parent.\n */\n protected override createExecution(\n opts: CreateExecutionOptions,\n ): IInngestExecution {\n return super.createExecution({\n ...opts,\n partialOptions: {\n ...opts.partialOptions,\n transformCtx: (ctx) => {\n // Get the parent info from each event. Also removes our internal\n // metadata from each event (mutates in place).\n const parents = ctx.events.map(stripInngestMetadata);\n\n // Removes our internal metadata from the event (mutates in place).\n stripInngestMetadata(ctx.event);\n\n return {\n ...ctx,\n parents,\n };\n },\n },\n });\n }\n}\n\n/**\n * @public\n */\nexport namespace DeferredFunction {\n /**\n * Matches any `DeferredFunction` regardless of its schema. Use as the\n * constraint for the `function` argument of `defer()`.\n */\n // biome-ignore lint/suspicious/noExplicitAny: widest schema constraint for inference\n export type Any = DeferredFunction<StandardSchemaV1<any> | undefined>;\n\n /**\n * The user-facing options accepted by `createDefer(client, opts, handler)`.\n * Mirrors `InngestFunction.Options` minus `triggers` (implicit), `onFailure`\n * (not yet supported), and `batchEvents` (each `defer(...)` is its own run).\n */\n export type Options = Omit<\n InngestFunction.Options<[], never>,\n \"triggers\" | \"onFailure\" | \"batchEvents\"\n >;\n\n /**\n * Metadata describing the parent run that triggered the deferred run. Derived\n * from `event.data._inngest` and surfaced on the handler ctx as `parents[i]`,\n * aligned with `events[i]`.\n */\n export type Parent = {\n fnSlug: string;\n runId: string;\n experiment?: ExperimentRef;\n };\n}\n\n/**\n * The `event` shape a defer handler receives. `data` carries the user payload\n * directly, narrowed by the schema if one is set (otherwise\n * `Record<string, any>`). Parent metadata is exposed separately on\n * `ctx.parents` so events and parents can be matched by index.\n */\ntype DeferEvent<TSchema> = {\n name: internalEvents.DeferredSchedule;\n data: TSchema extends StandardSchemaV1<\n infer D extends Record<string, unknown>\n >\n ? D\n : // biome-ignore lint/suspicious/noExplicitAny: no schema = any\n Record<string, any>;\n};\n\n/**\n * Base ctx shape for a defer handler: the standard function context\n * (`runId`, `attempt`, `group`, `step` with middleware step extensions)\n * with `event`/`events` pinned to `inngest/deferred.schedule` and the\n * schema-typed payload, plus `parents` aligned with `events` by index.\n */\ntype BaseDeferCtx<\n TClient extends Inngest.Any,\n TFnMiddleware extends Middleware.Class[] | undefined,\n TSchema extends StandardSchemaV1<Record<string, unknown>> | undefined,\n> = Omit<BaseContext<TClient>, \"event\" | \"events\" | \"step\"> & {\n event: DeferEvent<TSchema>;\n events: [DeferEvent<TSchema>];\n parents: [DeferredFunction.Parent];\n step: ReturnType<typeof createStepTools<TClient, TFnMiddleware>> &\n ApplyAllMiddlewareStepExtensions<\n ClientOptionsFromInngest<TClient>[\"middleware\"]\n > &\n ApplyAllMiddlewareStepExtensions<TFnMiddleware>;\n};\n\n/**\n * Input type for `createDefer`. Same shape as `DeferredFunction.Options`\n * plus `schema` (the StandardSchema describing `event.data` that flows\n * to caller `defer(id, { function, data })` call sites) and `middleware`.\n */\nexport type CreateDeferInput<\n TFnMiddleware extends Middleware.Class[] | undefined,\n TSchema extends StandardSchemaV1<Record<string, unknown>> | undefined,\n> = DeferredFunction.Options & {\n schema?: TSchema;\n middleware?: TFnMiddleware;\n};\n\n/**\n * Full handler context for a defer function: `BaseDeferCtx` plus every\n * middleware ctx extension that applies (built-in, client, function-level).\n */\nexport type DeferContext<\n TClient extends Inngest.Any,\n TFnMiddleware extends Middleware.Class[] | undefined,\n TSchema extends StandardSchemaV1<Record<string, unknown>> | undefined,\n> = BaseDeferCtx<TClient, TFnMiddleware, TSchema> &\n ApplyAllMiddlewareCtxExtensions<[...ReturnType<typeof builtInMiddleware>]> &\n ApplyAllMiddlewareCtxExtensions<\n ClientOptionsFromInngest<TClient>[\"middleware\"]\n > &\n ApplyAllMiddlewareCtxExtensions<TFnMiddleware>;\n\n/**\n * EXPERIMENTAL: This API is not yet stable and may change in the future without\n * a major version bump.\n *\n * Create a typed defer function. One `createDefer` call = one Inngest\n * function. Returns a `DeferredFunction<TSchema>` so callers of `defer(id,\n * { function, data })` get the data type inferred from the schema.\n *\n * Mirrors `inngest.createFunction(opts, handler)`, with three differences:\n * the client is the first positional arg, `triggers` is not accepted (the\n * SDK emits an implicit `inngest/deferred.schedule` trigger), and `schema`\n * describes the payload that callers will send via `defer(id, { function,\n * data })`.\n *\n * Pass the result to `serve()` alongside regular functions so the SDK\n * registers it.\n */\nexport function createDefer<\n TClient extends Inngest.Any,\n TSchema extends\n | StandardSchemaV1<Record<string, unknown>>\n | undefined = undefined,\n const TFnMiddleware extends Middleware.Class[] | undefined = undefined,\n THandler extends Handler.Any = (\n ctx: DeferContext<TClient, TFnMiddleware, TSchema>,\n ) => unknown,\n>(\n client: TClient,\n options: CreateDeferInput<TFnMiddleware, TSchema>,\n handler: THandler,\n): DeferredFunction<TSchema> {\n const { schema, ...rest } = options;\n return new DeferredFunction<TSchema>(\n client,\n rest,\n handler as Handler.Any,\n schema as TSchema,\n );\n}\n"],"mappings":";;;;;;;AA0BA,MAAM,cAAc;;;;;AAMpB,SAAS,mBAAmB,OAA2C;AACrE,KACEA,uBAAS,MAAM,IACf,OAAO,MAAM,mBAAmB,YAChC,OAAO,MAAM,YAAY,SAEzB,QAAO;EAAE,gBAAgB,MAAM;EAAgB,SAAS,MAAM;EAAS;;;;;;AAS3E,SAAS,qBAAqB,OAEF;CAE1B,MAAM,EAAE,WAAWC,oCAAqB,YAAY,GAAG,UAD1C,MAAM,QAAQ,EAAE;AAG7B,KAAI,CAACD,uBAAS,SAAS,CACrB,OAAM,IAAIE,gCAAiB,8CAA8C;CAE3E,MAAM,EAAE,gBAAgB,kBAAkB;AAC1C,KAAI,OAAO,mBAAmB,SAC5B,OAAM,IAAIA,gCACR,6DACD;AAEH,KAAI,OAAO,kBAAkB,SAC3B,OAAM,IAAIA,gCACR,4DACD;AAIH,OAAM,OAAO;AAEb,QAAO;EACL,QAAQ;EACR,OAAO;EACP,YAAY,mBAAmB,WAAW;EAC3C;;;;;;;;;;;;;;;;;;AAmBH,IAAa,mBAAb,cAIUC,wCAMR;CACA,AAAS;CACT,CAAUC,4BAAqB,EAAE,MAAM,oBAAoB;CAE3D,YACE,QACA,MACA,SACA,QACA;AAIA,MAAI,YAAY,KAAK,KAAK,GAAG,CAC3B,OAAM,IAAI,MACR,eAAe,KAAK,GAAG,gBAAgB,YAAY,SACpD;AAEH,QACE,QACA;GAAE,GAAG;GAAM,UAAU,EAAE;GAAE,EACzB,QACD;AACD,OAAK,SAAS;;CAGhB,AAAmB,kBACjB,MAC4B;AAC5B,SAAO,CACL;GACE,OAAOC,8BAAe;GACtB,YAAY,mCAAmC,KAAK;GACrD,CACF;;;;;;;;;CAUH,AAAmB,gBACjB,MACmB;AACnB,SAAO,MAAM,gBAAgB;GAC3B,GAAG;GACH,gBAAgB;IACd,GAAG,KAAK;IACR,eAAe,QAAQ;KAGrB,MAAM,UAAU,IAAI,OAAO,IAAI,qBAAqB;AAGpD,0BAAqB,IAAI,MAAM;AAE/B,YAAO;MACL,GAAG;MACH;MACD;;IAEJ;GACF,CAAC;;;;;;;;;;;;;;;;;;;;AAuHN,SAAgB,YAUd,QACA,SACA,SAC2B;CAC3B,MAAM,EAAE,QAAQ,GAAG,SAAS;AAC5B,QAAO,IAAI,iBACT,QACA,MACA,SACA,OACD"}
@@ -1,9 +1,10 @@
1
1
  import { internalEvents } from "../helpers/consts.cjs";
2
2
  import { Marker, markerKey } from "../helpers/marker.cjs";
3
- import { Middleware } from "./middleware/middleware.cjs";
4
3
  import { createStepTools } from "./InngestStepTools.cjs";
5
- import { InngestFunction } from "./InngestFunction.cjs";
6
- import { ApplyAllMiddlewareCtxExtensions, ApplyAllMiddlewareStepExtensions, BaseContext, FunctionConfig, Handler } from "../types.cjs";
4
+ import { Middleware } from "./middleware/middleware.cjs";
5
+ import { CreateExecutionOptions, InngestFunction } from "./InngestFunction.cjs";
6
+ import { IInngestExecution } from "./execution/InngestExecution.cjs";
7
+ import { ApplyAllMiddlewareCtxExtensions, ApplyAllMiddlewareStepExtensions, BaseContext, ExperimentRef, FunctionConfig, Handler } from "../types.cjs";
7
8
  import { ClientOptionsFromInngest, Inngest, builtInMiddleware } from "./Inngest.cjs";
8
9
  import { StandardSchemaV1 } from "@standard-schema/spec";
9
10
 
@@ -30,6 +31,14 @@ declare class DeferredFunction<TSchema extends StandardSchemaV1<Record<string, u
30
31
  readonly [markerKey]: Marker;
31
32
  constructor(client: Inngest.Any, opts: DeferredFunction.Options, handler: Handler.Any, schema: TSchema);
32
33
  protected getConfigTriggers(fnId: string): FunctionConfig["triggers"];
34
+ /**
35
+ * Installs a `transformCtx` hook that runs before middleware and user code:
36
+ * - Strips our `_inngest` metadata off each event's `data`, ensuring it
37
+ * matches what the user expects.
38
+ * - Collects the parent function's slug and run ID from that metadata into
39
+ * `ctx.parents`, so the handler can correlate each event to its parent.
40
+ */
41
+ protected createExecution(opts: CreateExecutionOptions): IInngestExecution;
33
42
  }
34
43
  /**
35
44
  * @public
@@ -46,11 +55,22 @@ declare namespace DeferredFunction {
46
55
  * (not yet supported), and `batchEvents` (each `defer(...)` is its own run).
47
56
  */
48
57
  type Options = Omit<InngestFunction.Options<[], never>, "triggers" | "onFailure" | "batchEvents">;
58
+ /**
59
+ * Metadata describing the parent run that triggered the deferred run. Derived
60
+ * from `event.data._inngest` and surfaced on the handler ctx as `parents[i]`,
61
+ * aligned with `events[i]`.
62
+ */
63
+ type Parent = {
64
+ fnSlug: string;
65
+ runId: string;
66
+ experiment?: ExperimentRef;
67
+ };
49
68
  }
50
69
  /**
51
- * The `event` shape a defer handler receives. With a schema, `data`
52
- * narrows to its inferred type; without one, it falls back to
53
- * `Record<string, any>`.
70
+ * The `event` shape a defer handler receives. `data` carries the user payload
71
+ * directly, narrowed by the schema if one is set (otherwise
72
+ * `Record<string, any>`). Parent metadata is exposed separately on
73
+ * `ctx.parents` so events and parents can be matched by index.
54
74
  */
55
75
  type DeferEvent<TSchema> = {
56
76
  name: internalEvents.DeferredSchedule;
@@ -60,11 +80,12 @@ type DeferEvent<TSchema> = {
60
80
  * Base ctx shape for a defer handler: the standard function context
61
81
  * (`runId`, `attempt`, `group`, `step` with middleware step extensions)
62
82
  * with `event`/`events` pinned to `inngest/deferred.schedule` and the
63
- * schema-typed payload.
83
+ * schema-typed payload, plus `parents` aligned with `events` by index.
64
84
  */
65
85
  type BaseDeferCtx<TClient extends Inngest.Any, TFnMiddleware extends Middleware.Class[] | undefined, TSchema extends StandardSchemaV1<Record<string, unknown>> | undefined> = Omit<BaseContext<TClient>, "event" | "events" | "step"> & {
66
86
  event: DeferEvent<TSchema>;
67
87
  events: [DeferEvent<TSchema>];
88
+ parents: [DeferredFunction.Parent];
68
89
  step: ReturnType<typeof createStepTools<TClient, TFnMiddleware>> & ApplyAllMiddlewareStepExtensions<ClientOptionsFromInngest<TClient>["middleware"]> & ApplyAllMiddlewareStepExtensions<TFnMiddleware>;
69
90
  };
70
91
  /**
@@ -76,6 +97,11 @@ type CreateDeferInput<TFnMiddleware extends Middleware.Class[] | undefined, TSch
76
97
  schema?: TSchema;
77
98
  middleware?: TFnMiddleware;
78
99
  };
100
+ /**
101
+ * Full handler context for a defer function: `BaseDeferCtx` plus every
102
+ * middleware ctx extension that applies (built-in, client, function-level).
103
+ */
104
+ type DeferContext<TClient extends Inngest.Any, TFnMiddleware extends Middleware.Class[] | undefined, TSchema extends StandardSchemaV1<Record<string, unknown>> | undefined> = BaseDeferCtx<TClient, TFnMiddleware, TSchema> & ApplyAllMiddlewareCtxExtensions<[...ReturnType<typeof builtInMiddleware>]> & ApplyAllMiddlewareCtxExtensions<ClientOptionsFromInngest<TClient>["middleware"]> & ApplyAllMiddlewareCtxExtensions<TFnMiddleware>;
79
105
  /**
80
106
  * EXPERIMENTAL: This API is not yet stable and may change in the future without
81
107
  * a major version bump.
@@ -93,7 +119,7 @@ type CreateDeferInput<TFnMiddleware extends Middleware.Class[] | undefined, TSch
93
119
  * Pass the result to `serve()` alongside regular functions so the SDK
94
120
  * registers it.
95
121
  */
96
- declare function createDefer<TClient extends Inngest.Any, TSchema extends StandardSchemaV1<Record<string, unknown>> | undefined = undefined, const TFnMiddleware extends Middleware.Class[] | undefined = undefined, THandler extends Handler.Any = (ctx: BaseDeferCtx<TClient, TFnMiddleware, TSchema> & ApplyAllMiddlewareCtxExtensions<[...ReturnType<typeof builtInMiddleware>]> & ApplyAllMiddlewareCtxExtensions<ClientOptionsFromInngest<TClient>["middleware"]> & ApplyAllMiddlewareCtxExtensions<TFnMiddleware>) => unknown>(client: TClient, options: CreateDeferInput<TFnMiddleware, TSchema>, handler: THandler): DeferredFunction<TSchema>;
122
+ declare function createDefer<TClient extends Inngest.Any, TSchema extends StandardSchemaV1<Record<string, unknown>> | undefined = undefined, const TFnMiddleware extends Middleware.Class[] | undefined = undefined, THandler extends Handler.Any = (ctx: DeferContext<TClient, TFnMiddleware, TSchema>) => unknown>(client: TClient, options: CreateDeferInput<TFnMiddleware, TSchema>, handler: THandler): DeferredFunction<TSchema>;
97
123
  //#endregion
98
- export { DeferredFunction, createDefer };
124
+ export { CreateDeferInput, DeferContext, DeferredFunction, createDefer };
99
125
  //# sourceMappingURL=DeferredFunction.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DeferredFunction.d.cts","names":[],"sources":["../../src/components/DeferredFunction.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;AAqCA;;;;;;;;;;;;;;AAsCK,cAtCQ,gBAsCR,CAAA,gBApCC,gBAoCD,CApCkB,MAoClB,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,GAAA,SAAA,GAAA,SAAA,CAAA,SAlCK,eAkCL,CAjCH,eAAA,CAAgB,OAiCb,CAAA,EAAA,EAAA,KAAA,CAAA,EAhCH,OAAA,CAAQ,GAgCL,EAAA,KAAA,EA9BH,OAAA,CAAQ,GA8BL,EAAA;EAlCoB,SAAA,MAAA,EAON,OAPM;EA+CR,UAvCL,SAAA,CAuCqB,EAvCT,MAuCS;EAAA,WAAA,CAAA,MAAA,EApCrB,OAAA,CAAQ,GAoCa,EAAA,IAAA,EAnCvB,gBAAA,CAAiB,OAmCM,EAAA,OAAA,EAlCpB,OAAA,CAAQ,GAkCY,EAAA,MAAA,EAjCrB,OAiCqB;YAMI,iBAAA,CAAA,IAAA,EAAA,MAAA,CAAA,EAnBhC,cAmBgC,CAAA,UAAA,CAAA;;;;;AAkBhC,kBAxBY,gBAAA,CAwBF;EAAA;;;;OAES,GAAA,GApBJ,gBAoBI,CApBa,gBAoBb,CAAA,GAAA,CAAA,GAAA,SAAA,CAAA;;;;AAKZ;;OAUM,OAAQ,GA5BF,IA4BE,CA3BtB,eAAA,CAAgB,OA2BM,CAAA,EAAA,EAAA,KAAA,CAAA,EAAA,UAAA,GAAA,WAAA,GAAA,aAAA,CAAA;;;;;;;KAjBrB,UAqBe,CAAA,OAAA,CAAA,GAAA;MAAX,EApBD,cAAA,CAAe,gBAoBd;MACa,EApBd,OAoBc,SApBE,gBAoBF,CAAA,KAAA,WAnBF,MAmBE,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,GAjBhB,CAiBgB,GAfhB,MAegB,CAAA,MAAA,EAAA,GAAA,CAAA;;;;;;;;KANjB,YAQD,CAAA,gBAPc,OAAA,CAAQ,GAOtB,EAAA,sBANoB,UAAA,CAAW,KAM/B,EAAA,GAAA,SAAA,EAAA,gBALc,gBAKd,CAL+B,MAK/B,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,GAAA,SAAA,CAAA,GAJA,IAIA,CAJK,WAIL,CAJiB,OAIjB,CAAA,EAAA,OAAA,GAAA,QAAA,GAAA,MAAA,CAAA,GAAA;OAGiC,EAN5B,UAM4B,CANjB,OAMiB,CAAA;QAAjC,EAAA,CALO,UAKP,CALkB,OAKlB,CAAA,CAAA;EAAgC,IAAA,EAJ5B,UAI4B,CAAA,OAJV,eAIU,CAJM,OAIN,EAJe,aAIf,CAAA,CAAA,GAHhC,gCAGgC,CAF9B,wBAE8B,CAFL,OAEK,CAAA,CAAA,YAAA,CAAA,CAAA,GAAhC,gCAAgC,CAAC,aAAD,CAAA;AAQpC,CAAA;;;;;;AAIW,KAJC,gBAID,CAAA,sBAHa,UAAA,CAAW,KAGxB,EAAA,GAAA,SAAA,EAAA,gBAFO,gBAEP,CAFwB,MAExB,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,GAAA,SAAA,CAAA,GADP,gBAAA,CAAiB,OACV,GAAA;QACI,CAAA,EADJ,OACI;EAAa,UAAA,CAAA,EAAb,aAAa;AAoB5B,CAAA;;;;;;;;;;;;;;;;;;AAcM,iBAdU,WAcV,CAAA,gBAbY,OAAA,CAAQ,GAapB,EAAA,gBAXA,gBAWA,CAXiB,MAWjB,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,GAAA,SAAA,GAAA,SAAA,EAAA,4BATwB,UAAA,CAAW,KASnC,EAAA,GAAA,SAAA,GAAA,SAAA,EAAA,iBARa,OAAA,CAAQ,GAQrB,GAAA,CAAA,GAAA,EAPG,YAOH,CAPgB,OAOhB,EAPyB,aAOzB,EAPwC,OAOxC,CAAA,GANA,+BAMA,CAAA,IALM,UAQF,CAAA,OARoB,iBAQpB,CAAA,KANJ,+BAOsB,CANpB,wBAMoB,CANK,OAML,CAAA,CAAA,YAAA,CAAA,CAAA,GAJtB,+BAIsB,CAJU,aAIV,CAAA,EAAA,GAAA,OAAA,CAAA,CAAA,MAAA,EADlB,OACkB,EAAA,OAAA,EAAjB,gBAAiB,CAAA,aAAA,EAAe,OAAf,CAAA,EAAA,OAAA,EACjB,QADiB,CAAA,EAEzB,gBAFyB,CAER,OAFQ,CAAA"}
1
+ {"version":3,"file":"DeferredFunction.d.cts","names":[],"sources":["../../src/components/DeferredFunction.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1,9 +1,10 @@
1
1
  import { internalEvents } from "../helpers/consts.js";
2
2
  import { Marker, markerKey } from "../helpers/marker.js";
3
- import { Middleware } from "./middleware/middleware.js";
4
3
  import { createStepTools } from "./InngestStepTools.js";
5
- import { InngestFunction } from "./InngestFunction.js";
6
- import { ApplyAllMiddlewareCtxExtensions, ApplyAllMiddlewareStepExtensions, BaseContext, FunctionConfig, Handler } from "../types.js";
4
+ import { Middleware } from "./middleware/middleware.js";
5
+ import { CreateExecutionOptions, InngestFunction } from "./InngestFunction.js";
6
+ import { IInngestExecution } from "./execution/InngestExecution.js";
7
+ import { ApplyAllMiddlewareCtxExtensions, ApplyAllMiddlewareStepExtensions, BaseContext, ExperimentRef, FunctionConfig, Handler } from "../types.js";
7
8
  import { ClientOptionsFromInngest, Inngest, builtInMiddleware } from "./Inngest.js";
8
9
  import { StandardSchemaV1 } from "@standard-schema/spec";
9
10
 
@@ -30,6 +31,14 @@ declare class DeferredFunction<TSchema extends StandardSchemaV1<Record<string, u
30
31
  readonly [markerKey]: Marker;
31
32
  constructor(client: Inngest.Any, opts: DeferredFunction.Options, handler: Handler.Any, schema: TSchema);
32
33
  protected getConfigTriggers(fnId: string): FunctionConfig["triggers"];
34
+ /**
35
+ * Installs a `transformCtx` hook that runs before middleware and user code:
36
+ * - Strips our `_inngest` metadata off each event's `data`, ensuring it
37
+ * matches what the user expects.
38
+ * - Collects the parent function's slug and run ID from that metadata into
39
+ * `ctx.parents`, so the handler can correlate each event to its parent.
40
+ */
41
+ protected createExecution(opts: CreateExecutionOptions): IInngestExecution;
33
42
  }
34
43
  /**
35
44
  * @public
@@ -46,11 +55,22 @@ declare namespace DeferredFunction {
46
55
  * (not yet supported), and `batchEvents` (each `defer(...)` is its own run).
47
56
  */
48
57
  type Options = Omit<InngestFunction.Options<[], never>, "triggers" | "onFailure" | "batchEvents">;
58
+ /**
59
+ * Metadata describing the parent run that triggered the deferred run. Derived
60
+ * from `event.data._inngest` and surfaced on the handler ctx as `parents[i]`,
61
+ * aligned with `events[i]`.
62
+ */
63
+ type Parent = {
64
+ fnSlug: string;
65
+ runId: string;
66
+ experiment?: ExperimentRef;
67
+ };
49
68
  }
50
69
  /**
51
- * The `event` shape a defer handler receives. With a schema, `data`
52
- * narrows to its inferred type; without one, it falls back to
53
- * `Record<string, any>`.
70
+ * The `event` shape a defer handler receives. `data` carries the user payload
71
+ * directly, narrowed by the schema if one is set (otherwise
72
+ * `Record<string, any>`). Parent metadata is exposed separately on
73
+ * `ctx.parents` so events and parents can be matched by index.
54
74
  */
55
75
  type DeferEvent<TSchema> = {
56
76
  name: internalEvents.DeferredSchedule;
@@ -60,11 +80,12 @@ type DeferEvent<TSchema> = {
60
80
  * Base ctx shape for a defer handler: the standard function context
61
81
  * (`runId`, `attempt`, `group`, `step` with middleware step extensions)
62
82
  * with `event`/`events` pinned to `inngest/deferred.schedule` and the
63
- * schema-typed payload.
83
+ * schema-typed payload, plus `parents` aligned with `events` by index.
64
84
  */
65
85
  type BaseDeferCtx<TClient extends Inngest.Any, TFnMiddleware extends Middleware.Class[] | undefined, TSchema extends StandardSchemaV1<Record<string, unknown>> | undefined> = Omit<BaseContext<TClient>, "event" | "events" | "step"> & {
66
86
  event: DeferEvent<TSchema>;
67
87
  events: [DeferEvent<TSchema>];
88
+ parents: [DeferredFunction.Parent];
68
89
  step: ReturnType<typeof createStepTools<TClient, TFnMiddleware>> & ApplyAllMiddlewareStepExtensions<ClientOptionsFromInngest<TClient>["middleware"]> & ApplyAllMiddlewareStepExtensions<TFnMiddleware>;
69
90
  };
70
91
  /**
@@ -76,6 +97,11 @@ type CreateDeferInput<TFnMiddleware extends Middleware.Class[] | undefined, TSch
76
97
  schema?: TSchema;
77
98
  middleware?: TFnMiddleware;
78
99
  };
100
+ /**
101
+ * Full handler context for a defer function: `BaseDeferCtx` plus every
102
+ * middleware ctx extension that applies (built-in, client, function-level).
103
+ */
104
+ type DeferContext<TClient extends Inngest.Any, TFnMiddleware extends Middleware.Class[] | undefined, TSchema extends StandardSchemaV1<Record<string, unknown>> | undefined> = BaseDeferCtx<TClient, TFnMiddleware, TSchema> & ApplyAllMiddlewareCtxExtensions<[...ReturnType<typeof builtInMiddleware>]> & ApplyAllMiddlewareCtxExtensions<ClientOptionsFromInngest<TClient>["middleware"]> & ApplyAllMiddlewareCtxExtensions<TFnMiddleware>;
79
105
  /**
80
106
  * EXPERIMENTAL: This API is not yet stable and may change in the future without
81
107
  * a major version bump.
@@ -93,7 +119,7 @@ type CreateDeferInput<TFnMiddleware extends Middleware.Class[] | undefined, TSch
93
119
  * Pass the result to `serve()` alongside regular functions so the SDK
94
120
  * registers it.
95
121
  */
96
- declare function createDefer<TClient extends Inngest.Any, TSchema extends StandardSchemaV1<Record<string, unknown>> | undefined = undefined, const TFnMiddleware extends Middleware.Class[] | undefined = undefined, THandler extends Handler.Any = (ctx: BaseDeferCtx<TClient, TFnMiddleware, TSchema> & ApplyAllMiddlewareCtxExtensions<[...ReturnType<typeof builtInMiddleware>]> & ApplyAllMiddlewareCtxExtensions<ClientOptionsFromInngest<TClient>["middleware"]> & ApplyAllMiddlewareCtxExtensions<TFnMiddleware>) => unknown>(client: TClient, options: CreateDeferInput<TFnMiddleware, TSchema>, handler: THandler): DeferredFunction<TSchema>;
122
+ declare function createDefer<TClient extends Inngest.Any, TSchema extends StandardSchemaV1<Record<string, unknown>> | undefined = undefined, const TFnMiddleware extends Middleware.Class[] | undefined = undefined, THandler extends Handler.Any = (ctx: DeferContext<TClient, TFnMiddleware, TSchema>) => unknown>(client: TClient, options: CreateDeferInput<TFnMiddleware, TSchema>, handler: THandler): DeferredFunction<TSchema>;
97
123
  //#endregion
98
- export { DeferredFunction, createDefer };
124
+ export { CreateDeferInput, DeferContext, DeferredFunction, createDefer };
99
125
  //# sourceMappingURL=DeferredFunction.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DeferredFunction.d.ts","names":[],"sources":["../../src/components/DeferredFunction.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"DeferredFunction.d.ts","names":[],"sources":["../../src/components/DeferredFunction.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1,10 +1,39 @@
1
- import { internalEvents } from "../helpers/consts.js";
1
+ import { deferExperimentKey, internalEvents } from "../helpers/consts.js";
2
+ import { UnreachableError } from "../helpers/errors.js";
3
+ import { isRecord } from "../helpers/types.js";
2
4
  import { markerKey } from "../helpers/marker.js";
3
5
  import { InngestFunction } from "./InngestFunction.js";
4
6
 
5
7
  //#region src/components/DeferredFunction.ts
6
8
  const idDenyRegex = /['\\\n\r]/;
7
9
  /**
10
+ * Validates the reserved experiment-ref input key into an `ExperimentRef`, or
11
+ * `undefined` when it's absent or malformed.
12
+ */
13
+ function parseExperimentRef(value) {
14
+ if (isRecord(value) && typeof value.experimentName === "string" && typeof value.variant === "string") return {
15
+ experimentName: value.experimentName,
16
+ variant: value.variant
17
+ };
18
+ }
19
+ /**
20
+ * Strips our `_inngest` metadata off an event's `data` in place and returns the
21
+ * parent routing metadata extracted from it.
22
+ */
23
+ function stripInngestMetadata(event) {
24
+ const { _inngest, [deferExperimentKey]: experiment, ...input } = event.data ?? {};
25
+ if (!isRecord(_inngest)) throw new UnreachableError("deferred event is missing _inngest metadata");
26
+ const { parent_fn_slug, parent_run_id } = _inngest;
27
+ if (typeof parent_fn_slug !== "string") throw new UnreachableError("deferred event _inngest metadata is missing parent_fn_slug");
28
+ if (typeof parent_run_id !== "string") throw new UnreachableError("deferred event _inngest metadata is missing parent_run_id");
29
+ event.data = input;
30
+ return {
31
+ fnSlug: parent_fn_slug,
32
+ runId: parent_run_id,
33
+ experiment: parseExperimentRef(experiment)
34
+ };
35
+ }
36
+ /**
8
37
  * EXPERIMENTAL: This API is not yet stable and may change in the future without
9
38
  * a major version bump.
10
39
  *
@@ -37,6 +66,29 @@ var DeferredFunction = class extends InngestFunction {
37
66
  expression: `event.data._inngest.fn_slug == '${fnId}'`
38
67
  }];
39
68
  }
69
+ /**
70
+ * Installs a `transformCtx` hook that runs before middleware and user code:
71
+ * - Strips our `_inngest` metadata off each event's `data`, ensuring it
72
+ * matches what the user expects.
73
+ * - Collects the parent function's slug and run ID from that metadata into
74
+ * `ctx.parents`, so the handler can correlate each event to its parent.
75
+ */
76
+ createExecution(opts) {
77
+ return super.createExecution({
78
+ ...opts,
79
+ partialOptions: {
80
+ ...opts.partialOptions,
81
+ transformCtx: (ctx) => {
82
+ const parents = ctx.events.map(stripInngestMetadata);
83
+ stripInngestMetadata(ctx.event);
84
+ return {
85
+ ...ctx,
86
+ parents
87
+ };
88
+ }
89
+ }
90
+ });
91
+ }
40
92
  };
41
93
  /**
42
94
  * EXPERIMENTAL: This API is not yet stable and may change in the future without
@@ -1 +1 @@
1
- {"version":3,"file":"DeferredFunction.js","names":[],"sources":["../../src/components/DeferredFunction.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { internalEvents } from \"../helpers/consts.ts\";\nimport { type Marker, markerKey } from \"../helpers/marker.ts\";\nimport type {\n ApplyAllMiddlewareCtxExtensions,\n ApplyAllMiddlewareStepExtensions,\n BaseContext,\n FunctionConfig,\n Handler,\n} from \"../types.ts\";\nimport type {\n builtInMiddleware,\n ClientOptionsFromInngest,\n Inngest,\n} from \"./Inngest.ts\";\nimport { InngestFunction } from \"./InngestFunction.ts\";\nimport type { createStepTools } from \"./InngestStepTools.ts\";\nimport type { Middleware } from \"./middleware/index.ts\";\n\nconst idDenyRegex = /['\\\\\\n\\r]/;\n\n/**\n * EXPERIMENTAL: This API is not yet stable and may change in the future without\n * a major version bump.\n *\n * A defer (companion) function created via `createDefer(...)`. Real\n * `InngestFunction` at runtime, but with the trigger pinned to\n * `inngest/deferred.schedule` (see `getConfigTriggers`), `triggers` and\n * `onFailure` disallowed, and the schema carried as a typed instance\n * property so callers of `defer(id, { function, data })` can extract it.\n *\n * Identify a defer function at runtime via `isDeferredFunction(value)` from\n * `helpers/marker.ts`. Prefer that over `instanceof`, which fails across\n * duplicate SDK copies in the same process.\n *\n * @public\n */\nexport class DeferredFunction<\n TSchema extends\n | StandardSchemaV1<Record<string, unknown>>\n | undefined = undefined,\n> extends InngestFunction<\n InngestFunction.Options<[], never>,\n Handler.Any,\n never,\n Inngest.Any,\n []\n> {\n readonly schema: TSchema;\n readonly [markerKey]: Marker = { kind: \"DeferredFunction\" };\n\n constructor(\n client: Inngest.Any,\n opts: DeferredFunction.Options,\n handler: Handler.Any,\n schema: TSchema,\n ) {\n // The id is interpolated into a CEL trigger expression\n // (`event.data._inngest.fn_slug == '${fnId}'`). Reject characters that\n // would break the single-quoted string literal.\n if (idDenyRegex.test(opts.id)) {\n throw new Error(\n `invalid id \"${opts.id}\"; must match ${idDenyRegex.source}`,\n );\n }\n super(\n client,\n { ...opts, triggers: [] } as InngestFunction.Options<[], never>,\n handler,\n );\n this.schema = schema;\n }\n\n protected override getConfigTriggers(\n fnId: string,\n ): FunctionConfig[\"triggers\"] {\n return [\n {\n event: internalEvents.DeferredSchedule,\n expression: `event.data._inngest.fn_slug == '${fnId}'`,\n },\n ];\n }\n}\n\n/**\n * @public\n */\nexport namespace DeferredFunction {\n /**\n * Matches any `DeferredFunction` regardless of its schema. Use as the\n * constraint for the `function` argument of `defer()`.\n */\n // biome-ignore lint/suspicious/noExplicitAny: widest schema constraint for inference\n export type Any = DeferredFunction<StandardSchemaV1<any> | undefined>;\n\n /**\n * The user-facing options accepted by `createDefer(client, opts, handler)`.\n * Mirrors `InngestFunction.Options` minus `triggers` (implicit), `onFailure`\n * (not yet supported), and `batchEvents` (each `defer(...)` is its own run).\n */\n export type Options = Omit<\n InngestFunction.Options<[], never>,\n \"triggers\" | \"onFailure\" | \"batchEvents\"\n >;\n}\n\n/**\n * The `event` shape a defer handler receives. With a schema, `data`\n * narrows to its inferred type; without one, it falls back to\n * `Record<string, any>`.\n */\ntype DeferEvent<TSchema> = {\n name: internalEvents.DeferredSchedule;\n data: TSchema extends StandardSchemaV1<\n infer D extends Record<string, unknown>\n >\n ? D\n : // biome-ignore lint/suspicious/noExplicitAny: no schema = any\n Record<string, any>;\n};\n\n/**\n * Base ctx shape for a defer handler: the standard function context\n * (`runId`, `attempt`, `group`, `step` with middleware step extensions)\n * with `event`/`events` pinned to `inngest/deferred.schedule` and the\n * schema-typed payload.\n */\ntype BaseDeferCtx<\n TClient extends Inngest.Any,\n TFnMiddleware extends Middleware.Class[] | undefined,\n TSchema extends StandardSchemaV1<Record<string, unknown>> | undefined,\n> = Omit<BaseContext<TClient>, \"event\" | \"events\" | \"step\"> & {\n event: DeferEvent<TSchema>;\n events: [DeferEvent<TSchema>];\n step: ReturnType<typeof createStepTools<TClient, TFnMiddleware>> &\n ApplyAllMiddlewareStepExtensions<\n ClientOptionsFromInngest<TClient>[\"middleware\"]\n > &\n ApplyAllMiddlewareStepExtensions<TFnMiddleware>;\n};\n\n/**\n * Input type for `createDefer`. Same shape as `DeferredFunction.Options`\n * plus `schema` (the StandardSchema describing `event.data` that flows\n * to caller `defer(id, { function, data })` call sites) and `middleware`.\n */\nexport type CreateDeferInput<\n TFnMiddleware extends Middleware.Class[] | undefined,\n TSchema extends StandardSchemaV1<Record<string, unknown>> | undefined,\n> = DeferredFunction.Options & {\n schema?: TSchema;\n middleware?: TFnMiddleware;\n};\n\n/**\n * EXPERIMENTAL: This API is not yet stable and may change in the future without\n * a major version bump.\n *\n * Create a typed defer function. One `createDefer` call = one Inngest\n * function. Returns a `DeferredFunction<TSchema>` so callers of `defer(id,\n * { function, data })` get the data type inferred from the schema.\n *\n * Mirrors `inngest.createFunction(opts, handler)`, with three differences:\n * the client is the first positional arg, `triggers` is not accepted (the\n * SDK emits an implicit `inngest/deferred.schedule` trigger), and `schema`\n * describes the payload that callers will send via `defer(id, { function,\n * data })`.\n *\n * Pass the result to `serve()` alongside regular functions so the SDK\n * registers it.\n */\nexport function createDefer<\n TClient extends Inngest.Any,\n TSchema extends\n | StandardSchemaV1<Record<string, unknown>>\n | undefined = undefined,\n const TFnMiddleware extends Middleware.Class[] | undefined = undefined,\n THandler extends Handler.Any = (\n ctx: BaseDeferCtx<TClient, TFnMiddleware, TSchema> &\n ApplyAllMiddlewareCtxExtensions<\n [...ReturnType<typeof builtInMiddleware>]\n > &\n ApplyAllMiddlewareCtxExtensions<\n ClientOptionsFromInngest<TClient>[\"middleware\"]\n > &\n ApplyAllMiddlewareCtxExtensions<TFnMiddleware>,\n ) => unknown,\n>(\n client: TClient,\n options: CreateDeferInput<TFnMiddleware, TSchema>,\n handler: THandler,\n): DeferredFunction<TSchema> {\n const { schema, ...rest } = options;\n return new DeferredFunction<TSchema>(\n client,\n rest,\n handler as Handler.Any,\n schema as TSchema,\n );\n}\n"],"mappings":";;;;;AAmBA,MAAM,cAAc;;;;;;;;;;;;;;;;;AAkBpB,IAAa,mBAAb,cAIU,gBAMR;CACA,AAAS;CACT,CAAU,aAAqB,EAAE,MAAM,oBAAoB;CAE3D,YACE,QACA,MACA,SACA,QACA;AAIA,MAAI,YAAY,KAAK,KAAK,GAAG,CAC3B,OAAM,IAAI,MACR,eAAe,KAAK,GAAG,gBAAgB,YAAY,SACpD;AAEH,QACE,QACA;GAAE,GAAG;GAAM,UAAU,EAAE;GAAE,EACzB,QACD;AACD,OAAK,SAAS;;CAGhB,AAAmB,kBACjB,MAC4B;AAC5B,SAAO,CACL;GACE,OAAO,eAAe;GACtB,YAAY,mCAAmC,KAAK;GACrD,CACF;;;;;;;;;;;;;;;;;;;;AA2FL,SAAgB,YAiBd,QACA,SACA,SAC2B;CAC3B,MAAM,EAAE,QAAQ,GAAG,SAAS;AAC5B,QAAO,IAAI,iBACT,QACA,MACA,SACA,OACD"}
1
+ {"version":3,"file":"DeferredFunction.js","names":[],"sources":["../../src/components/DeferredFunction.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { deferExperimentKey, internalEvents } from \"../helpers/consts.ts\";\nimport { UnreachableError } from \"../helpers/errors.ts\";\nimport { type Marker, markerKey } from \"../helpers/marker.ts\";\nimport { isRecord } from \"../helpers/types.ts\";\nimport type {\n ApplyAllMiddlewareCtxExtensions,\n ApplyAllMiddlewareStepExtensions,\n BaseContext,\n ExperimentRef,\n FunctionConfig,\n Handler,\n} from \"../types.ts\";\nimport type { IInngestExecution } from \"./execution/InngestExecution.ts\";\nimport type {\n builtInMiddleware,\n ClientOptionsFromInngest,\n Inngest,\n} from \"./Inngest.ts\";\nimport {\n type CreateExecutionOptions,\n InngestFunction,\n} from \"./InngestFunction.ts\";\nimport type { createStepTools } from \"./InngestStepTools.ts\";\nimport type { Middleware } from \"./middleware/index.ts\";\n\nconst idDenyRegex = /['\\\\\\n\\r]/;\n\n/**\n * Validates the reserved experiment-ref input key into an `ExperimentRef`, or\n * `undefined` when it's absent or malformed.\n */\nfunction parseExperimentRef(value: unknown): ExperimentRef | undefined {\n if (\n isRecord(value) &&\n typeof value.experimentName === \"string\" &&\n typeof value.variant === \"string\"\n ) {\n return { experimentName: value.experimentName, variant: value.variant };\n }\n return undefined;\n}\n\n/**\n * Strips our `_inngest` metadata off an event's `data` in place and returns the\n * parent routing metadata extracted from it.\n */\nfunction stripInngestMetadata(event: {\n data?: Record<string, unknown>;\n}): DeferredFunction.Parent {\n const data = event.data ?? {};\n const { _inngest, [deferExperimentKey]: experiment, ...input } = data;\n\n if (!isRecord(_inngest)) {\n throw new UnreachableError(\"deferred event is missing _inngest metadata\");\n }\n const { parent_fn_slug, parent_run_id } = _inngest;\n if (typeof parent_fn_slug !== \"string\") {\n throw new UnreachableError(\n \"deferred event _inngest metadata is missing parent_fn_slug\",\n );\n }\n if (typeof parent_run_id !== \"string\") {\n throw new UnreachableError(\n \"deferred event _inngest metadata is missing parent_run_id\",\n );\n }\n\n // Mutate in place\n event.data = input;\n\n return {\n fnSlug: parent_fn_slug,\n runId: parent_run_id,\n experiment: parseExperimentRef(experiment),\n };\n}\n\n/**\n * EXPERIMENTAL: This API is not yet stable and may change in the future without\n * a major version bump.\n *\n * A defer (companion) function created via `createDefer(...)`. Real\n * `InngestFunction` at runtime, but with the trigger pinned to\n * `inngest/deferred.schedule` (see `getConfigTriggers`), `triggers` and\n * `onFailure` disallowed, and the schema carried as a typed instance\n * property so callers of `defer(id, { function, data })` can extract it.\n *\n * Identify a defer function at runtime via `isDeferredFunction(value)` from\n * `helpers/marker.ts`. Prefer that over `instanceof`, which fails across\n * duplicate SDK copies in the same process.\n *\n * @public\n */\nexport class DeferredFunction<\n TSchema extends\n | StandardSchemaV1<Record<string, unknown>>\n | undefined = undefined,\n> extends InngestFunction<\n InngestFunction.Options<[], never>,\n Handler.Any,\n never,\n Inngest.Any,\n []\n> {\n readonly schema: TSchema;\n readonly [markerKey]: Marker = { kind: \"DeferredFunction\" };\n\n constructor(\n client: Inngest.Any,\n opts: DeferredFunction.Options,\n handler: Handler.Any,\n schema: TSchema,\n ) {\n // The id is interpolated into a CEL trigger expression\n // (`event.data._inngest.fn_slug == '${fnId}'`). Reject characters that\n // would break the single-quoted string literal.\n if (idDenyRegex.test(opts.id)) {\n throw new Error(\n `invalid id \"${opts.id}\"; must match ${idDenyRegex.source}`,\n );\n }\n super(\n client,\n { ...opts, triggers: [] } as InngestFunction.Options<[], never>,\n handler,\n );\n this.schema = schema;\n }\n\n protected override getConfigTriggers(\n fnId: string,\n ): FunctionConfig[\"triggers\"] {\n return [\n {\n event: internalEvents.DeferredSchedule,\n expression: `event.data._inngest.fn_slug == '${fnId}'`,\n },\n ];\n }\n\n /**\n * Installs a `transformCtx` hook that runs before middleware and user code:\n * - Strips our `_inngest` metadata off each event's `data`, ensuring it\n * matches what the user expects.\n * - Collects the parent function's slug and run ID from that metadata into\n * `ctx.parents`, so the handler can correlate each event to its parent.\n */\n protected override createExecution(\n opts: CreateExecutionOptions,\n ): IInngestExecution {\n return super.createExecution({\n ...opts,\n partialOptions: {\n ...opts.partialOptions,\n transformCtx: (ctx) => {\n // Get the parent info from each event. Also removes our internal\n // metadata from each event (mutates in place).\n const parents = ctx.events.map(stripInngestMetadata);\n\n // Removes our internal metadata from the event (mutates in place).\n stripInngestMetadata(ctx.event);\n\n return {\n ...ctx,\n parents,\n };\n },\n },\n });\n }\n}\n\n/**\n * @public\n */\nexport namespace DeferredFunction {\n /**\n * Matches any `DeferredFunction` regardless of its schema. Use as the\n * constraint for the `function` argument of `defer()`.\n */\n // biome-ignore lint/suspicious/noExplicitAny: widest schema constraint for inference\n export type Any = DeferredFunction<StandardSchemaV1<any> | undefined>;\n\n /**\n * The user-facing options accepted by `createDefer(client, opts, handler)`.\n * Mirrors `InngestFunction.Options` minus `triggers` (implicit), `onFailure`\n * (not yet supported), and `batchEvents` (each `defer(...)` is its own run).\n */\n export type Options = Omit<\n InngestFunction.Options<[], never>,\n \"triggers\" | \"onFailure\" | \"batchEvents\"\n >;\n\n /**\n * Metadata describing the parent run that triggered the deferred run. Derived\n * from `event.data._inngest` and surfaced on the handler ctx as `parents[i]`,\n * aligned with `events[i]`.\n */\n export type Parent = {\n fnSlug: string;\n runId: string;\n experiment?: ExperimentRef;\n };\n}\n\n/**\n * The `event` shape a defer handler receives. `data` carries the user payload\n * directly, narrowed by the schema if one is set (otherwise\n * `Record<string, any>`). Parent metadata is exposed separately on\n * `ctx.parents` so events and parents can be matched by index.\n */\ntype DeferEvent<TSchema> = {\n name: internalEvents.DeferredSchedule;\n data: TSchema extends StandardSchemaV1<\n infer D extends Record<string, unknown>\n >\n ? D\n : // biome-ignore lint/suspicious/noExplicitAny: no schema = any\n Record<string, any>;\n};\n\n/**\n * Base ctx shape for a defer handler: the standard function context\n * (`runId`, `attempt`, `group`, `step` with middleware step extensions)\n * with `event`/`events` pinned to `inngest/deferred.schedule` and the\n * schema-typed payload, plus `parents` aligned with `events` by index.\n */\ntype BaseDeferCtx<\n TClient extends Inngest.Any,\n TFnMiddleware extends Middleware.Class[] | undefined,\n TSchema extends StandardSchemaV1<Record<string, unknown>> | undefined,\n> = Omit<BaseContext<TClient>, \"event\" | \"events\" | \"step\"> & {\n event: DeferEvent<TSchema>;\n events: [DeferEvent<TSchema>];\n parents: [DeferredFunction.Parent];\n step: ReturnType<typeof createStepTools<TClient, TFnMiddleware>> &\n ApplyAllMiddlewareStepExtensions<\n ClientOptionsFromInngest<TClient>[\"middleware\"]\n > &\n ApplyAllMiddlewareStepExtensions<TFnMiddleware>;\n};\n\n/**\n * Input type for `createDefer`. Same shape as `DeferredFunction.Options`\n * plus `schema` (the StandardSchema describing `event.data` that flows\n * to caller `defer(id, { function, data })` call sites) and `middleware`.\n */\nexport type CreateDeferInput<\n TFnMiddleware extends Middleware.Class[] | undefined,\n TSchema extends StandardSchemaV1<Record<string, unknown>> | undefined,\n> = DeferredFunction.Options & {\n schema?: TSchema;\n middleware?: TFnMiddleware;\n};\n\n/**\n * Full handler context for a defer function: `BaseDeferCtx` plus every\n * middleware ctx extension that applies (built-in, client, function-level).\n */\nexport type DeferContext<\n TClient extends Inngest.Any,\n TFnMiddleware extends Middleware.Class[] | undefined,\n TSchema extends StandardSchemaV1<Record<string, unknown>> | undefined,\n> = BaseDeferCtx<TClient, TFnMiddleware, TSchema> &\n ApplyAllMiddlewareCtxExtensions<[...ReturnType<typeof builtInMiddleware>]> &\n ApplyAllMiddlewareCtxExtensions<\n ClientOptionsFromInngest<TClient>[\"middleware\"]\n > &\n ApplyAllMiddlewareCtxExtensions<TFnMiddleware>;\n\n/**\n * EXPERIMENTAL: This API is not yet stable and may change in the future without\n * a major version bump.\n *\n * Create a typed defer function. One `createDefer` call = one Inngest\n * function. Returns a `DeferredFunction<TSchema>` so callers of `defer(id,\n * { function, data })` get the data type inferred from the schema.\n *\n * Mirrors `inngest.createFunction(opts, handler)`, with three differences:\n * the client is the first positional arg, `triggers` is not accepted (the\n * SDK emits an implicit `inngest/deferred.schedule` trigger), and `schema`\n * describes the payload that callers will send via `defer(id, { function,\n * data })`.\n *\n * Pass the result to `serve()` alongside regular functions so the SDK\n * registers it.\n */\nexport function createDefer<\n TClient extends Inngest.Any,\n TSchema extends\n | StandardSchemaV1<Record<string, unknown>>\n | undefined = undefined,\n const TFnMiddleware extends Middleware.Class[] | undefined = undefined,\n THandler extends Handler.Any = (\n ctx: DeferContext<TClient, TFnMiddleware, TSchema>,\n ) => unknown,\n>(\n client: TClient,\n options: CreateDeferInput<TFnMiddleware, TSchema>,\n handler: THandler,\n): DeferredFunction<TSchema> {\n const { schema, ...rest } = options;\n return new DeferredFunction<TSchema>(\n client,\n rest,\n handler as Handler.Any,\n schema as TSchema,\n );\n}\n"],"mappings":";;;;;;;AA0BA,MAAM,cAAc;;;;;AAMpB,SAAS,mBAAmB,OAA2C;AACrE,KACE,SAAS,MAAM,IACf,OAAO,MAAM,mBAAmB,YAChC,OAAO,MAAM,YAAY,SAEzB,QAAO;EAAE,gBAAgB,MAAM;EAAgB,SAAS,MAAM;EAAS;;;;;;AAS3E,SAAS,qBAAqB,OAEF;CAE1B,MAAM,EAAE,WAAW,qBAAqB,YAAY,GAAG,UAD1C,MAAM,QAAQ,EAAE;AAG7B,KAAI,CAAC,SAAS,SAAS,CACrB,OAAM,IAAI,iBAAiB,8CAA8C;CAE3E,MAAM,EAAE,gBAAgB,kBAAkB;AAC1C,KAAI,OAAO,mBAAmB,SAC5B,OAAM,IAAI,iBACR,6DACD;AAEH,KAAI,OAAO,kBAAkB,SAC3B,OAAM,IAAI,iBACR,4DACD;AAIH,OAAM,OAAO;AAEb,QAAO;EACL,QAAQ;EACR,OAAO;EACP,YAAY,mBAAmB,WAAW;EAC3C;;;;;;;;;;;;;;;;;;AAmBH,IAAa,mBAAb,cAIU,gBAMR;CACA,AAAS;CACT,CAAU,aAAqB,EAAE,MAAM,oBAAoB;CAE3D,YACE,QACA,MACA,SACA,QACA;AAIA,MAAI,YAAY,KAAK,KAAK,GAAG,CAC3B,OAAM,IAAI,MACR,eAAe,KAAK,GAAG,gBAAgB,YAAY,SACpD;AAEH,QACE,QACA;GAAE,GAAG;GAAM,UAAU,EAAE;GAAE,EACzB,QACD;AACD,OAAK,SAAS;;CAGhB,AAAmB,kBACjB,MAC4B;AAC5B,SAAO,CACL;GACE,OAAO,eAAe;GACtB,YAAY,mCAAmC,KAAK;GACrD,CACF;;;;;;;;;CAUH,AAAmB,gBACjB,MACmB;AACnB,SAAO,MAAM,gBAAgB;GAC3B,GAAG;GACH,gBAAgB;IACd,GAAG,KAAK;IACR,eAAe,QAAQ;KAGrB,MAAM,UAAU,IAAI,OAAO,IAAI,qBAAqB;AAGpD,0BAAqB,IAAI,MAAM;AAE/B,YAAO;MACL,GAAG;MACH;MACD;;IAEJ;GACF,CAAC;;;;;;;;;;;;;;;;;;;;AAuHN,SAAgB,YAUd,QACA,SACA,SAC2B;CAC3B,MAAM,EAAE,QAAQ,GAAG,SAAS;AAC5B,QAAO,IAAI,iBACT,QACA,MACA,SACA,OACD"}
@@ -14,6 +14,7 @@ const require_metadataProcessor = require('./execution/otel/metadataProcessor.cj
14
14
  const require_InngestFunction = require('./InngestFunction.cjs');
15
15
  const require_middleware = require('./middleware/middleware.cjs');
16
16
  const require_InngestMetadata = require('./InngestMetadata.cjs');
17
+ const require_InngestScore = require('./InngestScore.cjs');
17
18
  const require_InngestStepTools = require('./InngestStepTools.cjs');
18
19
  const require_utils = require('./middleware/utils.cjs');
19
20
  const require_index = require('./realtime/subscribe/index.cjs');
@@ -58,6 +59,12 @@ var Inngest = class Inngest {
58
59
  _cachedFetch;
59
60
  _logger;
60
61
  /**
62
+ * Whether this client should collect AI metadata from OpenTelemetry spans.
63
+ *
64
+ * @internal
65
+ */
66
+ aiMetadataEnabled;
67
+ /**
61
68
  * Logger for SDK internal messages. Falls back to the user's `logger` if
62
69
  * `internalLogger` is not provided in client options.
63
70
  *
@@ -77,6 +84,11 @@ var Inngest = class Inngest {
77
84
  */
78
85
  experimentalMetadataEnabled = false;
79
86
  /**
87
+ * @internal
88
+ * Flag set by scoreMiddleware to enable step.score().
89
+ */
90
+ experimentalScoreEnabled = false;
91
+ /**
80
92
  * A dummy Inngest function used in Durable Endpoints. This is necessary
81
93
  * because the vast majority of middleware hooks require the Inngest function.
82
94
  * But for Durable Endpoints, there is no Inngest function. So we need some
@@ -173,6 +185,16 @@ var Inngest = class Inngest {
173
185
  return new require_InngestMetadata.UnscopedMetadataBuilder(this);
174
186
  }
175
187
  /**
188
+ * Write scores. Call directly to write a live score for a run or step; use
189
+ * `inngest.score.experiment(...)` to attach a score to a `group.experiment()`
190
+ * variant.
191
+ *
192
+ * For standalone durable score writes, prefer `step.score()`.
193
+ */
194
+ get score() {
195
+ return Object.assign((options) => require_InngestScore.sendScore(this, options), { experiment: (options) => require_InngestScore.sendScoreExperiment(this, options) });
196
+ }
197
+ /**
176
198
  * A client used to interact with the Inngest API by sending or reacting to
177
199
  * events.
178
200
  *
@@ -185,6 +207,7 @@ var Inngest = class Inngest {
185
207
  const { id, logger, middleware, appVersion } = this.options;
186
208
  if (!id) throw new Error("An `id` must be passed to create an Inngest instance.");
187
209
  this.id = id;
210
+ this.aiMetadataEnabled = this.options.aiMetadata !== false;
188
211
  this._env = require_env.protectEnv({ ...require_env.getProcessEnv() });
189
212
  this._userProvidedFetch = options.fetch;
190
213
  this.inngestApi = new require_api.InngestApi({
@@ -201,7 +224,7 @@ var Inngest = class Inngest {
201
224
  client: this,
202
225
  fn: null
203
226
  });
204
- require_metadataProcessor.metadataSpanProcessor.attach();
227
+ if (this.aiMetadataEnabled) require_metadataProcessor.metadataSpanProcessor.attach();
205
228
  this._appVersion = appVersion;
206
229
  }
207
230
  /**