inngest-middleware by inngest/inngest-skills
npx skills add https://github.com/inngest/inngest-skills --skill inngest-middleware掌握 Inngest 中间件,以处理横切关注点,如日志记录、错误追踪、依赖注入和数据转换。中间件在函数生命周期的关键点运行,为实现可观测性和共享功能提供强大的模式。
这些技能主要针对 TypeScript。 对于 Python 或 Go,请参考 Inngest 文档 获取特定语言的指导。核心概念适用于所有语言。
注意: 中间件系统在 v4 版本中进行了重大重写。本文档记录的生命周期钩子反映了 v4 API。如果从 v3 迁移,请查阅 迁移指南 了解破坏性变更的详细信息。
中间件允许代码在 Inngest 客户端生命周期的各个点运行——在函数执行、事件发送等过程中。可以将中间件视为 Inngest 执行流水线中的钩子。
何时使用中间件:
中间件可以在 客户端级别(影响所有函数)或 函数级别(影响特定函数)注册。
const inngest = new Inngest({
id: "my-app",
middleware: [
loggingMiddleware, // 第 1 个运行
errorMiddleware // 第 2 个运行
]
});
inngest.createFunction(
{
id: "example",
middleware: [
authMiddleware, // 第 3 个运行
metricsMiddleware // 第 4 个运行
],
triggers: [{ event: "test" }]
},
async () => {
/* function code */
}
);
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
顺序很重要: 客户端中间件首先运行,然后是函数中间件,均按指定顺序执行。
import { InngestMiddleware } from "inngest";
const loggingMiddleware = new InngestMiddleware({
name: "Logging Middleware",
init() {
// 设置阶段 - 在客户端初始化时运行
const logger = setupLogger();
return {
// 函数执行生命周期
// 注意:在中间件泛型中,`fn` 是宽松类型;fn.id 在运行时有效
onFunctionRun({ ctx, fn }) {
return {
beforeExecution() {
logger.info("Function starting", {
functionId: fn.id,
eventName: ctx.event.name,
runId: ctx.runId
});
},
afterExecution() {
logger.info("Function completed", {
functionId: fn.id,
runId: ctx.runId
});
},
transformOutput({ result }) {
// 记录函数输出
logger.debug("Function output", {
functionId: fn.id,
output: result.data
});
// 返回未修改的结果
return { result };
}
};
},
// 事件发送生命周期
onSendEvent() {
return {
transformInput({ payloads }) {
logger.info("Sending events", {
count: payloads.length,
events: payloads.map((p) => p.name)
});
// 使用扩展运算符将只读数组转换为可变数组
return { payloads: [...payloads] };
}
};
}
};
}
});
Python 中间件遵循类似的模式。完整的 Python 示例请参见 依赖注入参考。
## 依赖注入
在所有函数间共享昂贵或有状态的客户端。**详细模式请参见 [依赖注入参考](./references/dependency-injection.md)。**
### 快速示例 - 内置 DI
```typescript
import { dependencyInjectionMiddleware } from "inngest";
const inngest = new Inngest({
id: 'my-app',
middleware: [
dependencyInjectionMiddleware({
openai: new OpenAI(),
db: new PrismaClient(),
}),
],
});
// 函数自动获得注入的依赖项
inngest.createFunction(
{ id: "ai-summary", triggers: [{ event: "document/uploaded" }] },
async ({ event, openai, db }) => {
// 依赖项在函数上下文中可用
const summary = await openai.chat.completions.create({
messages: [{ role: "user", content: event.data.content }],
model: "gpt-4",
});
await db.document.update({
where: { id: event.data.documentId },
data: { summary: summary.choices[0].message.content }
});
}
);
除了 dependencyInjectionMiddleware(内置,如上所示),Inngest 还以 独立包 的形式提供官方中间件。完整详情请参见 中间件参考。
npm install @inngest/middleware-encryption
import { encryptionMiddleware } from "@inngest/middleware-encryption";
const inngest = new Inngest({
id: "my-app",
middleware: [
encryptionMiddleware({
key: process.env.ENCRYPTION_KEY
})
]
});
自动加密所有步骤数据、函数输出和事件的 data.encrypted 字段。支持通过 fallbackDecryptionKeys 进行密钥轮换。
npm install @inngest/middleware-sentry
import * as Sentry from "@sentry/node";
import { sentryMiddleware } from "@inngest/middleware-sentry";
Sentry.init({
/* your Sentry config */
});
const inngest = new Inngest({
id: "my-app",
middleware: [sentryMiddleware()]
});
捕获异常,为每次函数运行添加追踪,并将函数 ID 和事件名称作为上下文包含。要求 @sentry/*@>=8.0.0。
const metricsMiddleware = new InngestMiddleware({
name: "Metrics Tracking",
init() {
return {
onFunctionRun({ ctx, fn }) {
let startTime: number;
return {
beforeExecution() {
startTime = Date.now();
metrics.increment("inngest.step.started", {
function: fn.id,
event: ctx.event.name
});
},
afterExecution() {
const duration = Date.now() - startTime;
metrics.histogram("inngest.step.duration", duration, {
function: fn.id,
event: ctx.event.name
});
},
transformOutput({ result }) {
const status = result.error ? "error" : "success";
metrics.increment("inngest.step.completed", {
function: fn.id,
status: status
});
return { result };
}
};
}
};
}
});
身份验证: 验证令牌并注入用户上下文 条件逻辑: 根据事件类型或函数应用中间件 断路器: 防止外部服务导致的级联故障
为不同环境和用例创建具有配置选项的可重用中间件。完整示例请参见参考文档。
const robustMiddleware = new InngestMiddleware({
name: "Robust Middleware",
init() {
return {
onFunctionRun({ ctx, fn }) {
return {
transformOutput({ result }) {
try {
// 你的中间件逻辑写在这里
return performTransformation(result);
} catch (middlewareError) {
// 记录错误但不要中断函数
console.error("Middleware error:", middlewareError);
// 中间件失败时返回原始结果
return { result };
}
}
};
}
};
}
});
使用 Inngest 的测试工具(createMockContext、createMockFunction)对中间件行为进行单元测试。
完整实现示例和高级模式,请参见:
每周安装量
254
代码仓库
GitHub 星标数
15
首次出现
2026年2月17日
安全审计
安装于
codex243
opencode240
gemini-cli239
github-copilot239
amp238
kimi-cli238
Master Inngest middleware to handle cross-cutting concerns like logging, error tracking, dependency injection, and data transformation. Middleware runs at key points in the function lifecycle, enabling powerful patterns for observability and shared functionality.
These skills are focused on TypeScript. For Python or Go, refer to the Inngest documentation for language-specific guidance. Core concepts apply across all languages.
Note: The middleware system was significantly rewritten in v4. The lifecycle hooks documented here reflect the v4 API. If migrating from v3, consult the migration guide for details on breaking changes.
Middleware allows code to run at various points in an Inngest client's lifecycle - during function execution, event sending, and more. Think of middleware as hooks into the Inngest execution pipeline.
When to use middleware:
Middleware can be registered at client-level (affects all functions) or function-level (affects specific functions).
const inngest = new Inngest({
id: "my-app",
middleware: [
loggingMiddleware, // Runs 1st
errorMiddleware // Runs 2nd
]
});
inngest.createFunction(
{
id: "example",
middleware: [
authMiddleware, // Runs 3rd
metricsMiddleware // Runs 4th
],
triggers: [{ event: "test" }]
},
async () => {
/* function code */
}
);
Order matters: Client middleware runs first, then function middleware, in the order specified.
import { InngestMiddleware } from "inngest";
const loggingMiddleware = new InngestMiddleware({
name: "Logging Middleware",
init() {
// Setup phase - runs when client initializes
const logger = setupLogger();
return {
// Function execution lifecycle
// Note: `fn` is loosely typed in middleware generics; fn.id works at runtime
onFunctionRun({ ctx, fn }) {
return {
beforeExecution() {
logger.info("Function starting", {
functionId: fn.id,
eventName: ctx.event.name,
runId: ctx.runId
});
},
afterExecution() {
logger.info("Function completed", {
functionId: fn.id,
runId: ctx.runId
});
},
transformOutput({ result }) {
// Log function output
logger.debug("Function output", {
functionId: fn.id,
output: result.data
});
// Return unmodified result
return { result };
}
};
},
// Event sending lifecycle
onSendEvent() {
return {
transformInput({ payloads }) {
logger.info("Sending events", {
count: payloads.length,
events: payloads.map((p) => p.name)
});
// Spread to convert readonly array to mutable array
return { payloads: [...payloads] };
}
};
}
};
}
});
Python middleware follows a similar pattern. See Dependency Injection Reference for complete Python examples.
## Dependency Injection
Share expensive or stateful clients across all functions. **See [Dependency Injection Reference](./references/dependency-injection.md) for detailed patterns.**
### Quick Example - Built-in DI
```typescript
import { dependencyInjectionMiddleware } from "inngest";
const inngest = new Inngest({
id: 'my-app',
middleware: [
dependencyInjectionMiddleware({
openai: new OpenAI(),
db: new PrismaClient(),
}),
],
});
// Functions automatically get injected dependencies
inngest.createFunction(
{ id: "ai-summary", triggers: [{ event: "document/uploaded" }] },
async ({ event, openai, db }) => {
// Dependencies available in function context
const summary = await openai.chat.completions.create({
messages: [{ role: "user", content: event.data.content }],
model: "gpt-4",
});
await db.document.update({
where: { id: event.data.documentId },
data: { summary: summary.choices[0].message.content }
});
}
);
Beyond dependencyInjectionMiddleware (built-in, shown above), Inngest provides official middleware as separate packages. SeeMiddleware Reference for complete details.
npm install @inngest/middleware-encryption
import { encryptionMiddleware } from "@inngest/middleware-encryption";
const inngest = new Inngest({
id: "my-app",
middleware: [
encryptionMiddleware({
key: process.env.ENCRYPTION_KEY
})
]
});
Automatically encrypts all step data, function output, and event data.encrypted field. Supports key rotation via fallbackDecryptionKeys.
npm install @inngest/middleware-sentry
import * as Sentry from "@sentry/node";
import { sentryMiddleware } from "@inngest/middleware-sentry";
Sentry.init({
/* your Sentry config */
});
const inngest = new Inngest({
id: "my-app",
middleware: [sentryMiddleware()]
});
Captures exceptions, adds tracing to each function run, and includes function ID and event names as context. Requires @sentry/*@>=8.0.0.
const metricsMiddleware = new InngestMiddleware({
name: "Metrics Tracking",
init() {
return {
onFunctionRun({ ctx, fn }) {
let startTime: number;
return {
beforeExecution() {
startTime = Date.now();
metrics.increment("inngest.step.started", {
function: fn.id,
event: ctx.event.name
});
},
afterExecution() {
const duration = Date.now() - startTime;
metrics.histogram("inngest.step.duration", duration, {
function: fn.id,
event: ctx.event.name
});
},
transformOutput({ result }) {
const status = result.error ? "error" : "success";
metrics.increment("inngest.step.completed", {
function: fn.id,
status: status
});
return { result };
}
};
}
};
}
});
Authentication: Validate tokens and inject user context Conditional logic: Apply middleware based on event type or function Circuit breakers: Prevent cascading failures from external services
Create reusable middleware with configuration options for different environments and use cases. See reference documentation for complete examples.
const robustMiddleware = new InngestMiddleware({
name: "Robust Middleware",
init() {
return {
onFunctionRun({ ctx, fn }) {
return {
transformOutput({ result }) {
try {
// Your middleware logic here
return performTransformation(result);
} catch (middlewareError) {
// Log error but don't break the function
console.error("Middleware error:", middlewareError);
// Return original result on middleware failure
return { result };
}
}
};
}
};
}
});
Use Inngest's testing utilities (createMockContext, createMockFunction) to unit test middleware behavior.
For complete implementation examples and advanced patterns, see:
Weekly Installs
254
Repository
GitHub Stars
15
First Seen
Feb 17, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
codex243
opencode240
gemini-cli239
github-copilot239
amp238
kimi-cli238
Azure Data Explorer (Kusto) 查询技能:KQL数据分析、日志遥测与时间序列处理
102,600 周安装