npm package: @kaiyan/init
Description: Kaiyan 全自动初始化 CLI（拉取模板、创建云资源、生成 env、push 触发流水线）
Latest version: 0.8.1

# @kaiyan/init

Kaiyan 全自动初始化 CLI，实现从零到生产环境的一键部署。

**当前版本：** 0.7.3

## 目录

- [概述](#概述)
- [技术架构](#技术架构)
- [完整工作流程](#完整工作流程)
- [先决条件](#先决条件)
- [安装](#安装)
- [使用方法](#使用方法)
- [参数详解](#参数详解)
- [自动生成的配置](#自动生成的配置)
- [GitHub Secrets](#github-secrets)
- [注意事项](#注意事项)
- [故障排除](#故障排除)
- [模板仓库要求](#模板仓库要求)
- [开发者迭代指南](#开发者迭代指南)

---

## 概述

`@kaiyan/init` 是一个自动化 CLI 工具，用于快速初始化基于 ky-framework 模板的全栈项目。它会自动完成以下工作：
- 克隆模板仓库并初始化 git
- 安装依赖并配置 pnpm
- 创建阿里云 OSS Bucket（生产环境）
- 构建并部署后端到阿里云函数计算 (FC3)
- 生成前后端环境变量文件
- 创建 GitHub 仓库并同步 Secrets
- 推送代码触发 CI/CD 流水线

**简化架构**：只部署生产环境（FC + OSS），本地开发使用 `pnpm dev:frontend/backend` 连接 dev RDS。详见 [架构简化方案](https://github.com/kaiyan-tech/ky-framework/blob/main/docs/SIMPLIFY-ARCHITECTURE.md)。

## 技术架构

### FC3 自定义运行时

项目使用阿里云 FC3 的自定义运行时（`custom.debian12`），而非内置的 `nodejs20` 运行时：

| 特性 | 说明 |
|------|------|
| **运行时** | `custom.debian12` |
| **Node.js** | `/var/fc/lang/nodejs22/bin/node` |
| **启动方式** | NestJS 直接监听端口，FC 作为反向代理 |
| **端口** | 9000（通过 `FC_SERVER_PORT` 环境变量） |

**优势**：
- 代码简洁：无需 FC Handler 适配代码
- 本地与线上一致：同一份代码在本地和 FC 上运行行为相同
- 无需适配库：FC 只做流量转发，不涉及 request/response 对象转换
- 更好的可移植性：代码不依赖 FC 特定 API

### 技术栈

| 组件 | 技术 | 版本要求 |
|------|------|----------|
| **运行时** | Node.js | >= 22.0.0 |
| **包管理** | pnpm | >= 10.0.0 |
| **后端框架** | NestJS | 最新 |
| **数据库 ORM** | Prisma | 最新 |
| **前端框架** | React + Vite | 最新 |
| **部署工具** | Serverless Devs 3.x | FC3 组件 |

## 完整工作流程

脚本执行的详细步骤如下：

### 1. 环境检查

```
ensureNodeAndPnpm()    → 检查 Node.js >= 22, pnpm >= 10
ensureGit()            → 检查 git 可用
ensureServerlessDevs() → 检查/安装 Serverless Devs CLI (s)
ensureAliyunCli()      → 检查 aliyun CLI（macOS 尝试 brew 安装）
ensureGhAuth()         → 检查 GitHub CLI (gh) 已登录
```

### 2. 收集配置信息

交互式或通过命令行参数收集：
- Region（默认 `cn-shenzhen`）
- 阿里云 AccessKey ID/Secret（必填）
- 数据库连接串：生产库（用于 GitHub Secrets）、开发库（用于本地 .env）
- VPC/VSwitch/SecurityGroup ID（必填，FC 必须与 RDS 同 VPC）
- GitHub 组织（必填）

以下字段自动从项目名派生，无需输入：
- FC 服务名：默认使用项目名
- OSS Bucket 名：默认使用项目名
- GitHub 仓库名：默认使用项目名

### 3. 克隆模板

```javascript
cloneTemplate(targetDir)
├── git clone --depth 1 https://github.com/kaiyan-tech/ky-framework.git
├── 删除模板的 .git 目录
└── git init -b main  // 立即初始化新仓库，避免 husky 报错
```

### 4. 修复模板配置

```javascript
fixSharedTypesExport(targetDir)
└── 调整 packages/shared/package.json 的 types 导出，避免 tsup 警告
```

### 5. 安装依赖

```javascript
installDeps(targetDir)
├── 写入 .npmrc 批准构建脚本包（prisma, esbuild 等）
└── pnpm install
```

**批准的包列表：**
- `@prisma/client`
- `@prisma/engines`
- `prisma`
- `esbuild`
- `@nestjs/core`

### 6. 生成 Prisma Client

```javascript
generatePrismaClient(targetDir)
└── pnpm --filter backend prisma:generate
```

### 7. 更新基础设施配置

```javascript
updateInfraRegion(targetDir, region)
└── 更新 s.yaml 和 s.prod.yaml 的 region 配置
    // functionName 使用环境变量 ${env('FC_SERVICE_NAME')}-api，无需替换
```

### 8. 创建 OSS Bucket

```javascript
ensureOssBucket(targetDir, bucket, region, env)
├── 创建临时 aliyun CLI profile
├── aliyun oss mb oss://{bucket}  // 创建 Bucket
├── aliyun oss set-acl ... public-read  // 设置公开读
├── aliyun oss website ...  // 应用 website.xml 配置
└── aliyun oss cors ...  // 应用 cors.xml 配置
```

**Endpoint 格式：** `oss-{region}.aliyuncs.com`
**额外操作：** 阿里云的OSS设置成静态页面后，依然无法直接访问，必须到OSS的控制面板中进行手动绑定域名。

### 9. 构建后端

```javascript
buildForFc(targetDir)
├── pnpm --filter @kaiyan/shared build
└── pnpm --filter backend build
```

### 10. 部署到函数计算（生产环境）

```javascript
deployFc(targetDir, env, { configFile: 's.prod.yaml', envName: 'prod' })
├── 清空 fc-deploy 目录
├── pnpm deploy 创建独立部署包
├── s deploy -y --use-local -t infra/s.prod.yaml
└── 获取生产 FC URL
```

**FC 函数命名（自动从项目名派生）：**
| FC_SERVICE_NAME | 函数名 | 示例（项目名=my-app） |
|-----------------|--------|----------------------|
| `${projectName}` | `${FC_SERVICE_NAME}-api` | `my-app-api` |

**FC 部署环境变量：**
| 变量 | 值 |
|------|----------|
| `NODE_ENV` | `production` |
| `DATABASE_URL` | 生产数据库 |
| `JWT_SECRET` | 自动生成 |
| `JWT_EXPIRES_IN` | `7d` |
| `APP_VERSION` | `init-{timestamp}` |
| `MIGRATION_TOKEN` | 自动生成 |
| `FC_SERVICE_NAME` | `${projectName}` |

### 11. 写入环境变量文件

```javascript
writeEnvFiles(targetDir, answers, fcDomain)
├── apps/backend/.env
└── apps/frontend/.env
```

### 12. 创建 GitHub 仓库

```javascript
createGithubRepo(org, name, visibility)
└── gh repo create {org}/{name} --public --confirm
```

### 13. 同步 GitHub Secrets

```javascript
syncSecrets(targetDir, answers, fcDomainProd, repoSlug)
└── 遍历所有 secrets，使用 gh secret set 写入
```

### 14. 推送代码

```javascript
gitInitAndPush(targetDir, remote)
├── git add .
├── git commit --no-verify -m "feat: 项目初始化 by kaiyan-init"
├── git remote add origin {remote}
└── git push -u origin main
```

**注意：** 使用 `--no-verify` 跳过 pre-commit hooks，避免 lint-staged 在初始化时失败。

## 先决条件

### 必需工具

| 工具 | 最低版本 | 安装方式 | 说明 |
|------|----------|----------|------|
| **Node.js** | 22.0.0 | [nodejs.org](https://nodejs.org/) | 运行时环境 |
| **pnpm** | 10.0.0 | `npm install -g pnpm` | 包管理器 |
| **git** | - | 系统自带或 brew/apt | 版本控制 |
| **Serverless Devs** | 3.x | `npm install -g @serverless-devs/s` | FC 部署工具（脚本可自动安装） |
| **aliyun CLI** | - | `brew install aliyun-cli` | 阿里云资源管理 |
| **GitHub CLI** | - | `brew install gh` | GitHub 操作 |

### 阿里云准备

1. AccessKey：需具备以下权限
   - OSS：创建 Bucket、设置 ACL、配置 website/CORS
   - FC：创建/更新函数、触发器
   - VPC：读取 VPC/VSwitch/SecurityGroup

2. RDS 数据库：
   - 准备两个数据库：生产环境和开发环境
   - 连接串格式：`postgresql://user:pass@host:5432/dbname?schema=public`
   - 生产库用于 FC 部署，开发库用于本地开发
   - 确保 FC 所在 VPC 可访问生产数据库

3. VPC 配置：
   - 提供 VPC ID、VSwitch ID、Security Group ID
   - RDS 必须在同一个 VPC 内
   - FC 必须部署到同一 VPC 以访问数据库

### GitHub 准备

1. 安装并登录 GitHub CLI：
   ```bash
   gh auth login
   ```

2. 确保有权限在目标组织下创建仓库

## 安装

### 全局安装（推荐）

```bash
npm install -g @kaiyan/init
```

### 使用 npx（无需安装）

```bash
npx @kaiyan/init my-project
```

### 本地开发

```bash
cd packages/init
pnpm link --global
# 或
npm link
```

## 使用方法

### 交互式（推荐新手）

```bash
kaiyan-init my-project
```
按提示依次输入所需信息。

### 命令行参数（适合自动化）

```bash
kaiyan-init my-project \
  --ak-id AKID \
  --ak-secret AKSECRET \
  --db-url "postgresql://user:pass@host:5432/prod?schema=public" \
  --db-url-dev "postgresql://user:pass@host:5432/dev?schema=public" \
  --vpc-id vpc-xxx \
  --vsw-id vsw-xxx \
  --sg-id sg-xxx \
  --github-org my-org
```

以上命令会自动派生：
- FC 服务名：`my-project`
- OSS Bucket：`my-project`
- GitHub 仓库名：`my-project`

### 使用已有仓库

```bash
kaiyan-init my-project --no-auto-create-repo
# 然后输入已有仓库地址
```

## 参数详解

### 必填参数

| 参数 | 说明 | 示例 |
|------|------|------|
| `<project-name>` 或 `--project` | 项目名称，也是目标目录名 | `my-project` |
| `--ak-id` | 阿里云 AccessKey ID | `LTAI5t...` |
| `--ak-secret` | 阿里云 AccessKey Secret | `xxxxxxxx` |
| `--db-url` | 生产环境数据库连接串（用于 GitHub Secrets） | `postgresql://...` |
| `--db-url-dev` | 开发环境数据库连接串（用于本地 .env） | `postgresql://...` |
| `--vpc-id` | VPC ID（FC 必须与 RDS 同 VPC） | `vpc-xxx` |
| `--vsw-id` | VSwitch ID | `vsw-xxx` |
| `--sg-id` | Security Group ID | `sg-xxx` |
| `--github-org` | GitHub 组织/用户名 | `my-org` |

### 可选参数（有智能默认值）

| 参数 | 默认值 | 说明 |
|------|--------|------|
| `--region` | `cn-shenzhen` | 阿里云 Region |
| `--fc-service-name` | 项目名 | FC 服务名 |
| `--oss-bucket` | 项目名 | OSS Bucket 名 |
| `--repo` | 项目名 | GitHub 仓库名 |
| `--auto-create-repo` | `true` | 是否自动创建 GitHub 仓库 |
| `--no-auto-create-repo` | - | 使用已有仓库 |
| `--help` / `-h` | - | 显示帮助信息 |

## 自动生成的配置

### JWT Secret

- **生成方式：** `crypto.randomBytes(32).toString('hex')`
- **长度：** 64 字符十六进制
- **存储位置：** `apps/backend/.env`、GitHub Secrets

### Migration Token

- **生成方式：** `crypto.randomBytes(24).toString('hex')`
- **长度：** 48 字符十六进制
- **用途：** 保护数据库迁移 API 端点
- **存储位置：** `apps/backend/.env`、GitHub Secrets（`MIGRATION_TOKEN_PROD`）

### 环境变量文件

**apps/backend/.env：**（本地开发使用 dev 数据库）
```env
NODE_ENV=development
PORT=3000
DATABASE_URL=postgresql://...dev...
JWT_SECRET=<自动生成>
MIGRATION_TOKEN=<自动生成>
JWT_EXPIRES_IN=7d
CORS_ORIGIN=http://localhost:5173
OSS_BUCKET=xxx
VPC_ID=
VSWITCH_ID=
SECURITY_GROUP_ID=
```

**apps/frontend/.env：**
```env
VITE_API_BASE_URL=https://xxx.cn-shenzhen.fcapp.run
VITE_SENTRY_DSN=
```

## GitHub Secrets

脚本会自动同步以下 Secrets 到 GitHub 仓库：

| Secret | 说明 | 来源 |
|--------|------|------|
| `ALIYUN_ACCESS_KEY_ID` | 阿里云 AK ID | 用户输入 |
| `ALIYUN_ACCESS_KEY_SECRET` | 阿里云 AK Secret | 用户输入 |
| `OSS_BUCKET_PROD` | OSS Bucket | 自动派生 |
| `FC_SERVICE_NAME` | FC 函数名 | 自动派生 |
| `DATABASE_URL` | 生产数据库连接串 | 用户输入 |
| `DATABASE_URL_DEV` | 开发数据库连接串 | 用户输入 |
| `JWT_SECRET` | JWT 密钥 | 自动生成 |
| `VPC_ID` | VPC ID | 用户输入 |
| `VSWITCH_ID` | VSwitch ID | 用户输入 |
| `SECURITY_GROUP_ID` | 安全组 ID | 用户输入 |
| `VITE_API_BASE_URL` | 后端 API 地址 | FC 部署后获取 |
| `VITE_SENTRY_DSN` | Sentry DSN | 空（需手动配置） |
| `MIGRATION_TOKEN_PROD` | 生产迁移令牌 | 自动生成 |
| `MIGRATION_ENDPOINT_PROD` | 生产迁移 API 端点 | 生产 FC URL + `/api/internal/db-migrate` |

## 注意事项

### OSS Bucket 命名

- Bucket 名称**全局唯一**，如果被占用会导致初始化失败
- 默认使用项目名作为 Bucket 名
- 命名规则：3-63 字符，小写字母、数字、短横线

### CORS 配置

默认 `infra/oss/cors.xml` 允许的域名：
- `https://app.kaiyan.net`

如需自定义域名，请在初始化后修改该文件并重新应用：
```bash
aliyun oss cors --method put oss://your-bucket infra/oss/cors.xml -e oss-cn-shenzhen.aliyuncs.com
```

### VPC 部署（必填）

RDS 在 VPC 内，FC 必须与 RDS 在同一 VPC 才能互联：
1. VPC ID、VSwitch ID、Security Group ID 为**必填参数**
2. 确保 Security Group 允许 FC 访问 RDS 端口（通常 5432）
3. VSwitch 需要与 RDS 在同一可用区

### 数据库迁移

数据库迁移通过 FC 内部 API 端点触发，CI/CD 流水线会在部署后自动调用：

```bash
POST /api/internal/db-migrate
Headers:
  x-migration-token: {MIGRATION_TOKEN_PROD}
Body:
  {"env": "prod", "gitSha": "xxx"}
```

**FC 环境特殊处理**：由于 custom.debian12 运行时中 `node`、`npx` 不在默认 PATH，迁移脚本会直接使用 `/var/fc/lang/nodejs22/bin/node` 运行 Prisma CLI。

### 敏感信息安全

- 脚本运行时会在终端显示敏感信息（AK、数据库连接串等）
- **请勿在不安全的环境中运行**
- `.env` 文件已被 `.gitignore` 忽略，不会提交到仓库

## 后续开发注意事项（初始化后）

`kaiyan-init` 完成后，后续开发可以完全通过正常的 `git push` 触发 CI/CD。但存在以下需要注意的脱节点：

### 1. OSS 配置文件（website.xml/cors.xml）不会自动更新

**问题**：`kaiyan-init` 在初始化时会将 `infra/oss/website.xml` 和 `infra/oss/cors.xml` 应用到 OSS Bucket。但后续的 GitHub Actions 前端部署**只上传静态文件**，不会重新应用这些配置。

**影响**：如果你修改了 `cors.xml`（如添加新域名）或 `website.xml`（如修改默认首页），需要手动重新应用。

**解决方法**：
```bash
# 手动应用 website 配置
aliyun oss website --method put oss://your-bucket infra/oss/website.xml -e oss-cn-shenzhen.aliyuncs.com

# 手动应用 CORS 配置
aliyun oss cors --method put oss://your-bucket infra/oss/cors.xml -e oss-cn-shenzhen.aliyuncs.com
```

**可选优化**：在 GitHub Actions 的前端部署流程中添加自动应用配置的步骤：
```yaml
- name: 更新 OSS 配置
  run: |
    aliyun oss website --method put oss://${{ secrets.OSS_BUCKET_PROD }} infra/oss/website.xml
    aliyun oss cors --method put oss://${{ secrets.OSS_BUCKET_PROD }} infra/oss/cors.xml
```

### 2. VPC 配置修改需要手动更新 GitHub Secrets

**问题**：初始化时指定的 VPC/VSwitch/SecurityGroup ID 被写入 GitHub Secrets。后续 CI/CD 部署会读取这些 Secrets。

**影响**：如果需要修改 VPC 配置（如切换可用区、更换安全组），需要手动更新 GitHub Secrets。

**解决方法**：
1. 进入 GitHub 仓库 → Settings → Secrets and variables → Actions
2. 更新 `VPC_ID`、`VSWITCH_ID`、`SECURITY_GROUP_ID`
3. 下次 `git push` 时新配置会自动生效

或使用命令行：
```bash
gh secret set VPC_ID --body "vpc-new-xxx" --repo your-org/your-repo
gh secret set VSWITCH_ID --body "vsw-new-xxx" --repo your-org/your-repo
gh secret set SECURITY_GROUP_ID --body "sg-new-xxx" --repo your-org/your-repo
```

### 3. FC 和 OSS 资源支持无限次更新

**无需担心**：阿里云 FC 和 OSS 都支持幂等部署：
- **FC 函数**：`s deploy` 会自动判断是创建还是更新，不存在"只能创建"的问题
- **OSS 文件**：上传会覆盖已存在的同名文件
- **数据库迁移**：Prisma 通过 `_prisma_migrations` 表记录已执行的迁移，重复调用是安全的

### 4. .prisma 目录检查（v0.7.3+ 强制错误）

从 v0.7.3 版本开始，如果在 FC 部署包创建过程中未找到 `.prisma` 目录，脚本会**立即报错并中止**，而非仅输出警告。

**如果遇到此错误**：
```bash
# 确保已安装依赖
pnpm install

# 手动生成 Prisma Client
pnpm --filter backend exec prisma generate

# 检查 .prisma 目录是否存在
ls node_modules/.pnpm/@prisma+client*/node_modules/.prisma
```

## 故障排除

### 常见错误

#### 1. `Bucket 名 xxx 已被占用`

OSS Bucket 名称全局唯一，并且删除后也不可用，请更换一个独特的名称。

#### 2. `gh 未登录`

```bash
gh auth login
# 选择 GitHub.com，使用浏览器登录
```

#### 3. `s deploy 失败`

可能原因：
- AccessKey 权限不足
- Region 不正确
- 网络问题
调试：
```bash
cd your-project
s deploy -y --use-local -t infra/s.yaml --debug
```

#### 4. `git push 失败`

可能原因：
- SSH 密钥未配置
- 仓库权限不足
检查：
```bash
ssh -T git@github.com
gh auth status
```

#### 5. FC 域名获取失败

如果出现 `未能获取 FC 域名` 警告：
```bash
cd your-project
s info -t infra/s.yaml
```
手动获取 `system_url` 并更新 `apps/frontend/.env` 和 GitHub Secrets。

#### 6. TypeScript 构建错误（CI/CD）

如果 GitHub Actions 报告 TypeScript 错误，这通常是模板仓库 ky-framework 的问题，而非 kaiyan-init 的问题。常见问题：
- `tsconfig.node.json` 缺少 `noEmit` 配置
- `tsconfig.json` 的 `exclude` 未包含 `test` 目录
请在模板仓库中修复这些问题。

#### 7. DB Migration 失败：`spawn npx ENOENT`

**原因**：FC3 custom.debian12 运行时中 `npx` 不在默认 PATH
**解决**：此问题已在模板仓库 ky-framework 中修复。如果使用旧版本模板创建的项目遇到此问题，需要更新 `apps/backend/src/migration/prisma-migration.runner.ts`，直接使用 `/var/fc/lang/nodejs22/bin/node` 运行 Prisma CLI。

#### 8. alias publish 失败：`Version ID not specified`

**原因**：FC3 组件不返回版本号，导致 alias publish 步骤失败
**解决**：此问题已在模板仓库中修复，workflow 会在没有版本号时自动跳过 alias publish 步骤。FC3 的 HTTP 触发器默认就指向最新部署，跳过此步骤不影响正常访问。

#### 9. `ERR_PNPM_DEPLOY_DIR_NOT_EMPTY`

**原因**：连续部署时 `fc-deploy` 目录已存在
**解决**：此问题已在模板仓库和 CLI 中修复，每次部署前会自动清空 `fc-deploy` 目录。

### 日志前缀说明

| 前缀 | 含义 |
|------|------|
| `[kaiyan]` | 正常信息 |
| `[kaiyan][warn]` | 警告（可继续但需注意） |

## 模板仓库要求

kaiyan-init 依赖模板仓库 `ky-framework` 的特定结构：
```
ky-framework/
├── apps/
│   ├── backend/           # NestJS 后端
│   │   ├── prisma/
│   │   ├── src/
│   │   │   └── migration/ # DB Migration 模块
│   │   ├── package.json
│   │   └── tsconfig.json
│   └── frontend/          # React + Vite 前端
│       ├── src/
│       ├── package.json
│       └── tsconfig.json
├── packages/
│   └── shared/            # 共享类型/工具
├── infra/
│   ├── s.yaml             # Serverless Devs 配置（生产）
│   ├── s.prod.yaml        # 生产环境完整配置
│   └── oss/
│       ├── website.xml    # OSS 静态网站配置
│       └── cors.xml       # OSS CORS 配置
├── .github/
│   └── workflows/         # CI/CD 流水线
├── docs/
│   └── FC-DEPLOY-PATCHES.md  # FC 部署补丁记录
├── package.json           # pnpm workspace 根配置
└── pnpm-workspace.yaml
```

### FC3 Custom Runtime 配置

模板使用 `custom.debian12` 运行时，s.yaml 配置示例：
```yaml
resources:
  api-server:
    component: fc3
    props:
      runtime: custom.debian12
      customRuntimeConfig:
        command:
          - /var/fc/lang/nodejs22/bin/node
        args:
          - dist/main.js
        port: 9000
      memorySize: 512
      timeout: 180
      instanceConcurrency: 10
```
重要：`command` 和 `args` 需要分开配置，不能都放在 `command` 数组中。

### 模板修改注意事项

如果修改模板仓库，请确保：

1. **s.yaml 兼容性：**
   - 使用 `custom.debian12` 运行时
   - 使用完整 Node.js 路径 `/var/fc/lang/nodejs22/bin/node`
   - 使用 `resources:` 而非旧版 `services:`
   - 使用 `code:` 而非旧版 `codeUri:`

2. **DB Migration 兼容性：**
   - `prisma-migration.runner.ts` 需要检测 FC 环境并使用完整路径
   - 设置 PATH 环境变量供 Prisma 内部调用

3. **TypeScript 配置：**
   - `tsconfig.node.json` 需要 `noEmit: true`（如使用 `allowImportingTsExtensions`）
   - `tsconfig.json` 需要正确的 `exclude` 配置

4. **pnpm 10 兼容性：**
   - 需要批准的构建脚本包应在 `.npmrc` 中配置
   - 或在 `package.json` 的 `pnpm.onlyBuiltDependencies` 中配置

5. **Prisma binaryTargets：**
   ```prisma
   generator client {
     provider      = "prisma-client-js"
     // native: 本地开发，debian-openssl-3.0.x: 阿里云 FC custom.debian12 运行时
     binaryTargets = ["native", "debian-openssl-3.0.x"]
   }
   ```

## 开发者迭代指南

### 项目结构

```
packages/init/
├── bin/
│   └── kaiyan.js  # CLI 主程序（单文件，无需构建）
├── package.json
└── README.md
```

### 本地测试

```bash
# 链接到全局
cd packages/init
pnpm link --global

# 测试运行
kaiyan-init test-project --help
```

### 发布流程

1. **更新版本号：**
   ```bash
   npm version patch  # 或 minor / major
   ```

2. **检查打包内容：**
   ```bash
   npm pack --dry-run
   # 或实际打包检查
   npm pack
   tar -tf kaiyan-init-*.tgz
   rm kaiyan-init-*.tgz
   ```

3. **发布：**
   ```bash
   npm publish --access public
   ```

### 添加新功能

1. **新增参数：**
   - 在 `printHelp()` 中添加帮助文档
   - 在 `main()` 的 `answers` 对象中添加处理逻辑
   - 更新 README 的参数表格

2. **新增步骤：**
   - 创建对应的 async 函数
   - 在 `main()` 的 try 块中按顺序调用
   - 添加适当的日志输出

3. **修改模板处理：**
   - 如需修改模板文件，在对应的处理函数中添加逻辑
   - 注意处理文件不存在的情况

### 调试技巧

1. **查看命令输出：**
   ```javascript
   const res = await runCmd('cmd', ['args'], { capture: true });
   console.log('stdout:', res.stdout);
   console.log('stderr:', res.stderr);
   ```

2. **跳过某些步骤：**
   临时注释掉 `main()` 中的函数调用

3. **保留中间状态：**
   脚本失败时，目标目录会保留，可以进入目录手动调试

### 版本兼容性

- **Node.js：** 要求 >= 22（使用 ES Modules）
- **pnpm：** 要求 >= 10（使用 `onlyBuiltDependencies`）
- **Serverless Devs：** 3.x + FC3 组件
- **aliyun CLI：** 使用 profile 模式，避免修改默认配置

### 与模板仓库的关系

`@kaiyan/init` 是一个脚手架工具，每次运行时从 GitHub 动态克隆 `ky-framework` 模板：
```javascript
const templateRepo = 'https://github.com/kaiyan-tech/ky-framework.git';
await runCmd('git', ['clone', '--depth', '1', templateRepo, targetDir]);
```
**这意味着**：
- 模板的更新不需要发布新版本的 `@kaiyan/init`
- 用户运行 `kaiyan-init` 时会自动获取最新模板
- 只有 CLI 工具本身的逻辑变更才需要发布新版本

## 相关文档

- [FC 部署补丁日志](https://github.com/kaiyan-tech/ky-framework/blob/main/docs/FC-DEPLOY-PATCHES.md) - 记录所有 FC 部署相关的问题和解决方案
- [开沿核心技术宪章](https://github.com/kaiyan-tech/ky-framework/blob/main/docs/开沿核心技术宪章.md) - 技术架构和规范
- [开沿工程指导手册](https://github.com/kaiyan-tech/ky-framework/blob/main/docs/开沿工程指导手册.md) - 开发和部署指南