
Security News
PodRocket Podcast: Inside the Recent npm Supply Chain Attacks
Socket CEO Feross Aboukhadijeh discusses the recent npm supply chain attacks on PodRocket, covering novel attack vectors and how developers can protect themselves.
@choiceform/automation-plugin-sdk
Advanced tools
专业的工作流插件开发框架 - 业内领先的插件开发体验
# 使用 npm
npm install -g @choiceform/automation-plugin-sdk
# 使用 pnpm (推荐)
pnpm add -g @choiceform/automation-plugin-sdk
# 交互式创建
automation-plugin init my-awesome-plugin
# 进入项目目录
cd my-awesome-plugin
# 安装依赖
pnpm install
# 启动开发模式
automation-plugin dev
automation-plugin init
创建新的插件项目,支持 5 种插件类型:
automation-plugin init [project-name] [options]
Options:
--dir <directory> 指定创建目录
--no-git 不初始化 Git 仓库
--template <name> 使用指定模板
--no-typescript 禁用 TypeScript
automation-plugin dev
启动开发调试模式,支持热重载:
automation-plugin dev [options]
Options:
--port <port> 指定端口 (默认: 3000)
--host <host> 指定主机 (默认: localhost)
--no-open 不自动打开浏览器
--no-watch 禁用文件监听
automation-plugin build
构建插件项目:
automation-plugin build [options]
Options:
--output <dir> 输出目录 (默认: dist)
--minify 压缩代码
--sourcemap 生成 source map
--watch 监听模式
automation-plugin validate
验证插件配置和代码质量:
automation-plugin validate [plugin-path] [options]
Options:
--fix 自动修复可修复的问题
--strict 严格模式检查
automation-plugin debug
连接到远程实例进行调试:
automation-plugin debug [options]
Options:
--url <url> 远程实例地址
--token <token> 认证令牌
import { Action, ExecutionContext, ExecutionResult, PluginValue } from '@choiceform/automation-plugin-sdk';
export class MyAction extends Action {
async execute(
inputs: Record<string, PluginValue>,
context: ExecutionContext
): Promise<ExecutionResult> {
try {
// 获取输入参数
const message = inputs.message as string;
// 执行业务逻辑
const result = await this.processMessage(message);
// 返回成功结果
return this.createSuccessResult({
output: result,
timestamp: Date.now()
});
} catch (error) {
// 返回错误结果
return this.createErrorResult(
error instanceof Error ? error.message : '处理失败'
);
}
}
private async processMessage(message: string): Promise<string> {
// 业务逻辑实现
return `处理结果: ${message}`;
}
}
import { Trigger, ExecutionContext, PluginValue } from '@choiceform/automation-plugin-sdk';
export class WebhookTrigger extends Trigger {
private server?: HttpServer;
async start(): Promise<void> {
// 启动 HTTP 服务器监听 webhook
this.server = createHttpServer((req, res) => {
const eventData = this.parseWebhookData(req);
this.triggerEvent(eventData);
res.end('OK');
});
await this.server.listen(3001);
this.log('info', 'Webhook 服务器已启动在端口 3001');
}
async stop(): Promise<void> {
if (this.server) {
await this.server.close();
this.log('info', 'Webhook 服务器已停止');
}
}
async execute(inputs: Record<string, PluginValue>): Promise<ExecutionResult> {
// 触发器的执行逻辑
return this.createSuccessResult({
triggered: true,
timestamp: Date.now()
});
}
private parseWebhookData(req: any): Record<string, PluginValue> {
// 解析 webhook 数据
return {
method: req.method,
headers: req.headers,
body: req.body
};
}
}
import { Transform, PluginValue } from '@choiceform/automation-plugin-sdk';
export class DataTransform extends Transform {
async transform(input: PluginValue): Promise<PluginValue> {
if (typeof input !== 'object' || input === null) {
throw new Error('输入必须是对象类型');
}
const data = input as Record<string, PluginValue>;
// 数据转换逻辑
return {
...data,
processed: true,
processedAt: new Date().toISOString(),
version: '1.0.0'
};
}
}
{
"name": "my-awesome-plugin",
"version": "1.0.0",
"description": "一个强大的工作流插件",
"author": "Your Name",
"type": "action",
"features": [
"persistence",
"http",
"credentials"
],
"advanced": true,
"sdk": {
"version": "^1.0.0",
"compatibility": "node-based-workflow",
"features": [
"hot-reload",
"type-safety",
"validation",
"nodes-config-compatible",
"workflow-integration"
]
},
"permissions": [
"credentials"
],
"metadata": {
"createdAt": "2024-01-01T00:00:00.000Z",
"framework": "automation-plugin-sdk",
"compatibility": "workflow-automation-system",
"architecture": "node-based"
}
}
插件完全兼容 nodes-config 标准:
export interface NodeDefinition {
// 身份信息
identity: {
name: string;
category: string;
label?: Record<string, string>;
};
// 描述信息
description: {
ai: string;
human?: Record<string, string>;
};
// 端口配置 (严格按照 nodes-config)
inputs?: NodePort[];
outputs?: NodePort[];
// 样式配置
portStyles?: Record<string, PortStyleConfig>;
// 布局配置
layout: LayoutConfig;
// 工具栏配置
toolbar: ToolbarConfig;
// 注册信息
registry: NodeRegistryItem;
}
开发模式下支持文件热重载:
automation-plugin dev --watch
修改源码时自动重新加载,支持:
支持 WebSocket 实时通信:
// 连接到开发服务器
const ws = new WebSocket('ws://localhost:3000');
ws.on('message', (data) => {
const message = JSON.parse(data);
console.log('调试消息:', message);
});
自动检查代码质量:
# 完整验证
automation-plugin validate --strict
# 自动修复
automation-plugin validate --fix
检查项目包括:
Plugin
所有插件的基类:
abstract class Plugin {
abstract execute(inputs: Record<string, PluginValue>): Promise<ExecutionResult>;
validateInputs(inputs: Record<string, PluginValue>): ValidationResult;
healthCheck(): Promise<HealthCheckResult>;
protected log(level: 'info' | 'warn' | 'error', message: string): void;
protected getCredential(name: string): Promise<string | undefined>;
protected storeData(key: string, value: PluginValue): Promise<void>;
protected retrieveData(key: string): Promise<PluginValue | null>;
}
Trigger
触发器插件基类:
abstract class Trigger extends Plugin {
abstract start(): Promise<void>;
abstract stop(): Promise<void>;
protected triggerEvent(eventData: Record<string, PluginValue>): Promise<void>;
}
Action
动作插件基类:
abstract class Action extends Plugin {
abstract execute(inputs: Record<string, PluginValue>): Promise<ExecutionResult>;
}
Transform
转换器插件基类:
abstract class Transform extends Plugin {
abstract transform(input: PluginValue): Promise<PluginValue>;
}
// 插件值类型
type PluginValue =
| string
| number
| boolean
| null
| undefined
| PluginValue[]
| { [key: string]: PluginValue };
// 执行结果
interface ExecutionResult {
success: boolean;
data?: Record<string, PluginValue>;
error?: {
message: string;
code?: string;
details?: PluginValue;
};
metadata?: {
executionTime?: number;
memoryUsage?: number;
warnings?: string[];
};
}
// 执行上下文
interface ExecutionContext {
nodeId: string;
workflowId: string;
userId: string;
executionId: string;
log: (level: 'info' | 'warn' | 'error', message: string) => void;
getCredential: (name: string) => Promise<string | undefined>;
storeData: (key: string, value: PluginValue) => Promise<void>;
retrieveData: (key: string) => Promise<PluginValue | null>;
getEnvironment: (key: string) => string | undefined;
}
export class RobustAction extends Action {
async execute(inputs: Record<string, PluginValue>): Promise<ExecutionResult> {
try {
// 验证输入
const validation = this.validateInputs(inputs);
if (!validation.isValid) {
return this.createErrorResult(
`输入验证失败: ${validation.errors.map(e => e.message).join(', ')}`
);
}
// 执行业务逻辑
const result = await this.doWork(inputs);
return this.createSuccessResult(result);
} catch (error) {
this.log('error', `执行失败: ${error}`);
return this.createErrorResult(
error instanceof Error ? error.message : '未知错误'
);
}
}
}
protected validateInputs(inputs: Record<string, PluginValue>): ValidationResult {
const errors: ValidationResult['errors'] = [];
// 必需参数检查
if (!inputs.apiKey) {
errors.push({
field: 'apiKey',
message: 'API 密钥是必需的',
code: 'REQUIRED_PARAMETER_MISSING'
});
}
// 类型检查
if (inputs.timeout && typeof inputs.timeout !== 'number') {
errors.push({
field: 'timeout',
message: '超时时间必须是数字类型',
code: 'TYPE_MISMATCH'
});
}
return {
isValid: errors.length === 0,
errors
};
}
async execute(inputs: Record<string, PluginValue>, context: ExecutionContext): Promise<ExecutionResult> {
// 安全获取凭据
const apiKey = await context.getCredential('apiKey');
if (!apiKey) {
return this.createErrorResult('缺少 API 密钥凭据');
}
// 使用凭据进行 API 调用
const response = await fetch('https://api.example.com/data', {
headers: {
'Authorization': `Bearer ${apiKey}`
}
});
// ...
}
async execute(inputs: Record<string, PluginValue>, context: ExecutionContext): Promise<ExecutionResult> {
context.log('info', '开始执行插件');
try {
const startTime = Date.now();
// 业务逻辑
const result = await this.processData(inputs);
const executionTime = Date.now() - startTime;
context.log('info', `执行完成,耗时 ${executionTime}ms`);
return this.createSuccessResult(result, {
executionTime
});
} catch (error) {
context.log('error', `执行失败: ${error}`);
throw error;
}
}
欢迎贡献代码!请阅读 贡献指南 了解详情。
MIT License - 详见 LICENSE 文件。
@choiceform/automation-plugin-sdk - 让插件开发变得简单而专业 🚀
FAQs
Automation Plugin SDK - 业内领先的插件开发框架
We found that @choiceform/automation-plugin-sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 10 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Socket CEO Feross Aboukhadijeh discusses the recent npm supply chain attacks on PodRocket, covering novel attack vectors and how developers can protect themselves.
Security News
Maintainers back GitHub’s npm security overhaul but raise concerns about CI/CD workflows, enterprise support, and token management.
Product
Socket Firewall is a free tool that blocks malicious packages at install time, giving developers proactive protection against rising supply chain attacks.