Files
spaceflow/docs/advanced/plugin-development.md
2026-02-15 22:02:21 +08:00

5.5 KiB
Raw Blame History

插件开发指南

本指南介绍如何开发自定义 Spaceflow Extension。

前置知识

快速开始

使用模板创建

spaceflow create my-extension

这会在当前目录下创建一个标准的 Extension 模板。

手动创建

mkdir spaceflow-plugin-hello
cd spaceflow-plugin-hello
pnpm init
pnpm add @spaceflow/core
pnpm add -D typescript @types/node

目录结构

spaceflow-plugin-hello/
├── src/
│   ├── hello.command.ts       # 命令定义
│   ├── hello.service.ts       # 业务逻辑
│   ├── hello.module.ts        # NestJS 模块
│   ├── locales/               # i18n 资源
│   │   ├── zh-cn/
│   │   │   └── hello.json
│   │   ├── en/
│   │   │   └── hello.json
│   │   └── index.ts
│   └── index.ts               # Extension 入口
├── package.json
├── tsconfig.json
└── README.md

Extension 入口

每个 Extension 必须实现 SpaceflowExtension 接口:

// src/index.ts
import type {
  SpaceflowExtension,
  SpaceflowExtensionMetadata,
} from "@spaceflow/core";
import { HelloModule } from "./hello.module";
import { helloLocales } from "./locales";

export class HelloExtension implements SpaceflowExtension {
  getMetadata(): SpaceflowExtensionMetadata {
    return {
      name: "hello",
      commands: ["hello"],
      configKey: "hello",
      description: "示例 Extension",
      locales: helloLocales,
    };
  }

  getModule() {
    return HelloModule;
  }
}

export default HelloExtension;

命令定义

使用 @Command 装饰器定义 CLI 命令:

// src/hello.command.ts
import { Command, CommandRunner, Option } from "@spaceflow/core";
import { t } from "@spaceflow/core";
import { HelloService } from "./hello.service";

interface HelloOptions {
  readonly name?: string;
}

@Command({
  name: "hello",
  description: t("hello:description"),
})
export class HelloCommand extends CommandRunner {
  constructor(private readonly helloService: HelloService) {
    super();
  }

  async run(_params: string[], options: HelloOptions): Promise<void> {
    const name = options.name ?? "World";
    console.log(this.helloService.greet(name));
  }

  @Option({
    flags: "-n, --name <name>",
    description: t("hello:options.name"),
  })
  parseName(val: string): string {
    return val;
  }
}

业务逻辑

// src/hello.service.ts
import { Injectable } from "@spaceflow/core";

@Injectable()
export class HelloService {
  greet(name: string): string {
    return `Hello, ${name}!`;
  }
}

NestJS 模块

// src/hello.module.ts
import { Module } from "@spaceflow/core";
import { HelloCommand } from "./hello.command";
import { HelloService } from "./hello.service";

@Module({
  providers: [HelloCommand, HelloService],
})
export class HelloModule {}

使用核心能力

Extension 可以导入 @spaceflow/core 提供的共享模块:

import { Module } from "@spaceflow/core";
import { GitSdkModule } from "@spaceflow/core";
import { LlmProxyModule } from "@spaceflow/core";

@Module({
  imports: [
    GitSdkModule,       // Git 命令封装
    LlmProxyModule,     // 多 LLM 代理
  ],
  providers: [MyCommand, MyService],
})
export class MyModule {}

在 Service 中注入使用:

import { Injectable } from "@spaceflow/core";
import { GitSdkService } from "@spaceflow/core";

@Injectable()
export class MyService {
  constructor(private readonly gitSdk: GitSdkService) {}

  async getDiff(): Promise<string> {
    return this.gitSdk.diff("HEAD~1", "HEAD");
  }
}

可用的核心模块

模块 说明
GitProviderModule Git 平台适配器GitHub / Gitea
GitSdkModule Git 命令封装
LlmProxyModule 多 LLM 统一代理
FeishuSdkModule 飞书 API
StorageModule 本地存储
ParallelModule 并行执行工具

package.json 规范

{
  "name": "@spaceflow/plugin-hello",
  "version": "1.0.0",
  "description": "Spaceflow Hello Extension",
  "main": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "type": "module",
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "types": "./dist/index.d.ts"
    }
  },
  "peerDependencies": {
    "@spaceflow/core": "^0.17.0"
  },
  "spaceflow": {
    "commands": ["hello"],
    "configKey": "hello"
  }
}

i18n 支持

locales/ 目录下管理翻译资源:

// src/locales/index.ts
import zhCN from "./zh-cn/hello.json";
import en from "./en/hello.json";
import { addLocaleResources } from "@spaceflow/core";

export const helloLocales: Record<string, Record<string, string>> = {
  "zh-CN": zhCN,
  en,
};

// Side-effect: 立即注册资源
addLocaleResources("hello", helloLocales);
// src/locales/zh-cn/hello.json
{
  "description": "打招呼命令",
  "options.name": "名字"
}
// src/locales/en/hello.json
{
  "description": "Say hello",
  "options.name": "Name"
}

构建与发布

构建

spaceflow build

本地测试

spaceflow.json 中使用 link: 引用本地 Extension

{
  "dependencies": {
    "@spaceflow/plugin-hello": "link:./path/to/plugin-hello"
  }
}

发布到 npm

npm publish

用户安装:

spaceflow install @spaceflow/plugin-hello