EN

快速开始

使用默认 TypeScript 模板创建、开发和打包 func CLI 项目。

更新于 2周前
  1. 创建项目

    请先安装 Node.js 24.0 或更高版本

    命令会将 ship 作为项目名传给创建器。创建器会建立同名目录,并把 TypeScript 模板复制进去。它不会覆盖已有目录。如果你使用 Agent 自动创建,请参考 Agent 创建指引

    终端
    npm init func@latest ship
  2. 安装并检查生成的 CLI

    进入新目录、安装依赖,然后运行模板自带的帮助处理器。

    终端
    cd ship
    npm install
    npm run dev -- --help

认识生成的项目

在默认模板中,src 文件夹用于存放所有业务代码,tests 用于存放测试用例,如果你后续运行 build 命令则还会出现 dist 文件夹。通常在最后发布时,只有 dist 文件夹的内容会被发布。

项目结构
.
|-- src
|   |-- app.module.ts          根模块
|   |-- config.ts              包信息与运行时设置
|   |-- commands
|   |   |-- error.command.ts   全局输入错误输出
|   |   |-- greet.command.ts   具名命令示例
|   |   |-- major.command.ts   空输入、帮助与版本
|   |   |-- missing.command.ts 未知命令响应
|   |   +-- index.ts           命令列表
|   |-- services
|   |   +-- project.service.ts 可注入服务示例
|   +-- index.ts               可执行入口
|-- tests                      可执行行为测试
|-- package.json
|-- tsconfig.json
+-- README.md

可执行入口会调用 run(AppModule)。根模块收集允许 func 使用的命令类和 服务类:

src/app.module.ts
import { FuncModule } from 'func'
import { commands } from './commands'
import { services } from './services'

@FuncModule({
  commands,
  services,
})
export class AppModule {}

命令描述用户可以如何调用 CLI;可复用且与参数解析、输出无关的逻辑放在服务中。 测试直接启动生成的可执行文件,因此能够同时验证命令分发、输入解析和输出。

开发时运行命令

模板通过普通 npm scripts 暴露 funcgo:

package.json
{
  "scripts": {
    "dev": "funcgo dev --",
    "build": "funcgo build"
  }
}

npm 标签中的 npm run dev -- <参数> 使用的是 npm 参数透传规范。第一个 -- 告诉 npm 停止解析自己的选项,把后续内容追加到 script;script 末尾 的 -- 用于区分 funcgo dev 和你的 CLI 参数。位于它后面的 token 不属于 funcgo。应用代码不需要自行解析或移除这两个分隔符。

终端
npm run dev -- greet
npm run dev -- greet --name Ada
npm run dev -- greet shout --name Ada

每次调用只执行一次 TypeScript 入口,无需生成生产 bundle,适合在编辑命令时快速验证。 其他包管理器的等价写法可以通过终端右上角切换。

添加第一个命令

创建一个带有固定命令名和默认处理器的类。类名只在 TypeScript 代码中使用;用户实际输入的是 @Command 中的 name

src/commands/status.command.ts
import { Command, Handler } from 'func'

@Command({
  name: 'status',
  description: 'Print service status',
})
export class StatusCommand {
  @Handler()
  run() {
    console.log('All systems operational')
  }
}

将它加入命令列表,由 AppModule 注册后运行 npm run dev -- status

src/commands/index.ts
import { ErrorHandler } from './error.command'
import { Major } from './major.command'
import { Missing } from './missing.command'
import { StatusCommand } from './status.command'

export const commands = [Major, StatusCommand, Missing, ErrorHandler]
点击终端以聚焦

如果要添加别名或多个动作,请阅读命令 ;如果要接收标志和值,请阅读 字段选项

可选:把命令映射到全局

这一步不是使用 funcgo 的必要条件。只有希望在开发期间直接输入最终命令名进行调试(例如 ship)时才需要创建全局链接;否则继续使用 npm run dev -- <命令> 即可。

开发期间,包管理器可以把当前包映射到全局命令目录。由于 package.json#bin 指向 生成的 dist/bin.js ,请在项目根目录构建并创建链接:

终端
npm run build
npm link

# 使用 package.json#bin 中的键名

ship --help
点击终端以聚焦

这里的命令名是 ship,因此可以运行上面的 ship --help 。映射使用当前项目的构建产物;源码变化后请重新生成 bundle,必要时重新执行映射命令。

取消映射时,使用当前包管理器对应的解除映射命令:

终端
npm uninstall --global ship

监听文件并持续构建

funcgo build --watch 启动时会执行一次构建,之后默认监听 src/**/*.ts ,匹配文件变化后自动重新构建。可以在一个终端保持监听,在另一 个终端调用已经全局链接的命令。按 Ctrl+C 停止监听。

终端
npm run build -- --watch

# 监听额外文件或自定义 glob
npm run build -- --watch --watch-path 'src/**/*.ts' --watch-path config.json

每个 --watch-path 都可以是文件、目录或正向 glob。配置文件位于 src 之外时,可以用它补充监听范围。生成目录、node_modules.git 会被忽略。

首次运行的常见问题

终端找不到全局命令

确认构建已经生成 dist/bin.js,在包根目录执行 npm link ,并使用 package.json#bin 中的键名,而不是包名调用命令。

func 提示未知命令

请从已注册的命令列表导出命令类。仅创建文件和添加 @Command() 并不会自动注册该类。

npm 吞掉了本应传给 CLI 的选项

保留参数透传分隔符:使用 npm run dev -- status --json。只有 -- 后面的 token 才属于你的 CLI。

打包并准备发布

build script 会把配置的 TypeScript 入口打包到 func.outDir(模板默认 为 dist),并创建可执行的 bin.js。包内的 bin 字段决定用户安装后可以调用的命令名。

终端
npm run build
npm pack --dry-run

终端中的 dry-run pack 命令只展示即将发布的文件,不会真正发布。请确认列表中包含 bundle、 包信息、README 和 license;确认无误后,运行 npm publish 才会真正发布到 npm。自定义入口、输出、 外部依赖和监听范围见工具链