inngest 4.7.0 → 4.8.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.
- package/CHANGELOG.md +14 -0
- package/components/DeferredFunction.cjs +52 -0
- package/components/DeferredFunction.cjs.map +1 -1
- package/components/DeferredFunction.d.cts +35 -9
- package/components/DeferredFunction.d.cts.map +1 -1
- package/components/DeferredFunction.d.ts +35 -9
- package/components/DeferredFunction.d.ts.map +1 -1
- package/components/DeferredFunction.js +53 -1
- package/components/DeferredFunction.js.map +1 -1
- package/components/Inngest.cjs +24 -1
- package/components/Inngest.cjs.map +1 -1
- package/components/Inngest.d.cts +23 -3
- package/components/Inngest.d.cts.map +1 -1
- package/components/Inngest.d.ts +23 -3
- package/components/Inngest.d.ts.map +1 -1
- package/components/Inngest.js +24 -1
- package/components/Inngest.js.map +1 -1
- package/components/InngestCommHandler.d.cts +2 -2
- package/components/InngestCommHandler.d.ts +2 -2
- package/components/InngestFunction.d.cts +2 -2
- package/components/InngestFunction.d.ts +2 -2
- package/components/InngestGroupTools.cjs +7 -4
- package/components/InngestGroupTools.cjs.map +1 -1
- package/components/InngestGroupTools.d.cts +5 -24
- package/components/InngestGroupTools.d.cts.map +1 -1
- package/components/InngestGroupTools.d.ts +5 -24
- package/components/InngestGroupTools.d.ts.map +1 -1
- package/components/InngestGroupTools.js +7 -4
- package/components/InngestGroupTools.js.map +1 -1
- package/components/InngestMetadata.cjs +18 -4
- package/components/InngestMetadata.cjs.map +1 -1
- package/components/InngestMetadata.d.cts +2 -2
- package/components/InngestMetadata.d.cts.map +1 -1
- package/components/InngestMetadata.d.ts +2 -2
- package/components/InngestMetadata.d.ts.map +1 -1
- package/components/InngestMetadata.js +18 -5
- package/components/InngestMetadata.js.map +1 -1
- package/components/InngestScore.cjs +93 -0
- package/components/InngestScore.cjs.map +1 -0
- package/components/InngestScore.d.cts +89 -0
- package/components/InngestScore.d.cts.map +1 -0
- package/components/InngestScore.d.ts +89 -0
- package/components/InngestScore.d.ts.map +1 -0
- package/components/InngestScore.js +88 -0
- package/components/InngestScore.js.map +1 -0
- package/components/InngestStepTools.cjs +9 -0
- package/components/InngestStepTools.cjs.map +1 -1
- package/components/InngestStepTools.d.cts +5 -3
- package/components/InngestStepTools.d.cts.map +1 -1
- package/components/InngestStepTools.d.ts +5 -3
- package/components/InngestStepTools.d.ts.map +1 -1
- package/components/InngestStepTools.js +9 -0
- package/components/InngestStepTools.js.map +1 -1
- package/components/ScoreFunction.cjs +37 -0
- package/components/ScoreFunction.cjs.map +1 -0
- package/components/ScoreFunction.d.cts +24 -0
- package/components/ScoreFunction.d.cts.map +1 -0
- package/components/ScoreFunction.d.ts +24 -0
- package/components/ScoreFunction.d.ts.map +1 -0
- package/components/ScoreFunction.js +37 -0
- package/components/ScoreFunction.js.map +1 -0
- package/components/execution/InngestExecution.d.cts +2 -2
- package/components/execution/InngestExecution.d.ts +2 -2
- package/components/execution/als.cjs.map +1 -1
- package/components/execution/als.d.cts +1 -0
- package/components/execution/als.d.cts.map +1 -1
- package/components/execution/als.d.ts +1 -0
- package/components/execution/als.d.ts.map +1 -1
- package/components/execution/als.js.map +1 -1
- package/components/execution/engine.cjs +12 -10
- package/components/execution/engine.cjs.map +1 -1
- package/components/execution/engine.d.cts +1 -1
- package/components/execution/engine.d.cts.map +1 -1
- package/components/execution/engine.d.ts +1 -1
- package/components/execution/engine.d.ts.map +1 -1
- package/components/execution/engine.js +13 -11
- package/components/execution/engine.js.map +1 -1
- package/components/execution/otel/middleware.cjs +3 -1
- package/components/execution/otel/middleware.cjs.map +1 -1
- package/components/execution/otel/middleware.d.cts +14 -7
- package/components/execution/otel/middleware.d.cts.map +1 -1
- package/components/execution/otel/middleware.d.ts +14 -7
- package/components/execution/otel/middleware.d.ts.map +1 -1
- package/components/execution/otel/middleware.js +4 -2
- package/components/execution/otel/middleware.js.map +1 -1
- package/components/execution/otel/util.cjs +9 -1
- package/components/execution/otel/util.cjs.map +1 -1
- package/components/execution/otel/util.js +9 -2
- package/components/execution/otel/util.js.map +1 -1
- package/components/realtime/types.d.cts +4 -4
- package/components/realtime/types.d.cts.map +1 -1
- package/components/realtime/types.d.ts +4 -4
- package/components/realtime/types.d.ts.map +1 -1
- package/experimental.cjs +5 -1
- package/experimental.d.cts +4 -1
- package/experimental.d.ts +4 -1
- package/experimental.js +3 -1
- package/helpers/consts.cjs +7 -0
- package/helpers/consts.cjs.map +1 -1
- package/helpers/consts.d.cts.map +1 -1
- package/helpers/consts.d.ts.map +1 -1
- package/helpers/consts.js +7 -1
- package/helpers/consts.js.map +1 -1
- package/helpers/errors.cjs +16 -0
- package/helpers/errors.cjs.map +1 -1
- package/helpers/errors.d.cts +12 -1
- package/helpers/errors.d.cts.map +1 -1
- package/helpers/errors.d.ts +12 -1
- package/helpers/errors.d.ts.map +1 -1
- package/helpers/errors.js +16 -1
- package/helpers/errors.js.map +1 -1
- package/helpers/types.cjs +4 -0
- package/helpers/types.cjs.map +1 -1
- package/helpers/types.js +4 -1
- package/helpers/types.js.map +1 -1
- package/index.d.cts +2 -2
- package/index.d.ts +2 -2
- package/package.json +1 -1
- package/types.cjs.map +1 -1
- package/types.d.cts +26 -5
- package/types.d.cts.map +1 -1
- package/types.d.ts +26 -5
- package/types.d.ts.map +1 -1
- package/types.js.map +1 -1
- package/version.cjs +1 -1
- package/version.cjs.map +1 -1
- package/version.d.cts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.js.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# inngest
|
|
2
2
|
|
|
3
|
+
## 4.8.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#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
|
|
8
|
+
|
|
9
|
+
- [#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
|
|
10
|
+
|
|
11
|
+
- [#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()`.
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [#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.
|
|
16
|
+
|
|
3
17
|
## 4.7.0
|
|
4
18
|
|
|
5
19
|
### 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 {
|
|
6
|
-
import {
|
|
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.
|
|
52
|
-
*
|
|
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:
|
|
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":"
|
|
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 {
|
|
6
|
-
import {
|
|
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.
|
|
52
|
-
*
|
|
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:
|
|
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":"
|
|
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"}
|
package/components/Inngest.cjs
CHANGED
|
@@ -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
|
/**
|