Files
scriptforge/DESIGN.md
zhilv 10a200b96c
Some checks failed
Release / build-and-release (push) Failing after 1m31s
初始提交: ScriptForge 脚本快速转运行链接服务
- Go 后端 (Gin + GORM + SQLite) 提供 API 和纯文本脚本服务
- Vite + React + TypeScript + Tailwind 前端
- 单二进制部署 (Go embed 前端静态文件)
- Gitea Actions CI/CD: 打标签自动构建多平台 Release
- 支持 bash/zsh/sh/fish/python3/node/ruby/php 8种运行环境

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 23:48:19 +08:00

195 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ScriptForge 设计文档
## 概述
脚本快速转运行链接服务。用户粘贴脚本内容,选择运行环境,生成一个短链。在终端执行 `curl URL | <runtime>` 即可运行脚本。
- 前端Next.js (App Router + Tailwind CSS + TypeScript)
- 后端Go (Gin + GORM + SQLite)
- 部署Go embed 前端静态文件,单二进制部署
- CI/CDGitea Actions
## 核心流程
1. 用户打开首页 `/`
2. 粘贴脚本内容(上限 16KB
3. 选择运行环境bash / zsh / sh / fish / python3 / node / ruby / php
4. 选择过期时间1小时 / 24小时 / 7天 / 30天
5. 提交 → 后端存入 SQLite → 返回短链 ID
6. 页面展示生成的命令:`curl https://example.com/raw/xK8mPq | bash`
7. 用户可以复制命令到终端执行
## API 设计
### POST /api/scripts — 创建脚本
请求体:
```json
{
"content": "#!/bin/bash\necho hello",
"runtime": "bash",
"expires_in": "24h"
}
```
响应:
```json
{
"id": "xK8mPq",
"admin_token": "dGhpcyBpcyBhIHRva2Vu",
"url": "https://example.com/raw/xK8mPq",
"command": "curl https://example.com/raw/xK8mPq | bash",
"runtime": "bash",
"expires_at": "2026-05-29T16:27:00Z"
}
```
### GET /api/scripts/:id — 获取脚本元数据
响应:
```json
{
"id": "xK8mPq",
"runtime": "bash",
"content_length": 25,
"created_at": "2026-05-28T16:27:00Z",
"expires_at": "2026-05-29T16:27:00Z",
"expired": false
}
```
> 注意:此接口不返回脚本原始内容(内容通过 `/raw/:id` 获取),避免前端二次暴露。
### GET /raw/:id — 获取脚本纯文本内容
- 响应头 `Content-Type`: 根据 runtime 设置对应 MIME见运行时配置表
- 响应头 `Content-Disposition`: `attachment; filename="script.<ext>"`(根据 runtime 设置扩展名)
- 响应体:脚本纯文本内容
- 如脚本已过期,返回 404
### DELETE /api/scripts/:id?token=xxx — 删除脚本
- 需要 `admin_token` 参数
- 成功返回 204
## 数据模型
```go
type Script struct {
ID string `gorm:"primaryKey;size:8"`
Content string `gorm:"type:text;not null"`
Runtime string `gorm:"size:16;not null;index"`
AdminToken string `gorm:"size:64;not null"`
ExpiresAt time.Time `gorm:"not null;index"`
CreatedAt time.Time `gorm:"not null"`
}
```
## 运行时配置
| Runtime | 扩展名 | MIME 类型 | 命令模板 |
|---------|--------|-----------|----------|
| bash | `.sh` | `text/x-shellscript` | `curl {url} \| bash` |
| zsh | `.zsh` | `text/x-shellscript` | `curl {url} \| zsh` |
| sh | `.sh` | `text/x-shellscript` | `curl {url} \| sh` |
| fish | `.fish` | `text/x-shellscript` | `curl {url} \| fish` |
| python3 | `.py` | `text/x-python` | `curl {url} \| python3` |
| node | `.js` | `text/javascript` | `curl {url} \| node` |
| ruby | `.rb` | `text/x-ruby` | `curl {url} \| ruby` |
| php | `.php` | `text/x-php` | `curl {url} \| php` |
运行环境列表在 Go 后端定义为常量数组,用于校验请求中的 runtime 字段。
## 过期策略
- 用户保存时选择1小时 / 24小时 / 7天 / 30天
- 后端定时任务(每分钟扫描一次),删除过期记录
- 过期后 `/raw/:id` 返回 404详情页标记为已过期
## 限流策略
- 创建接口10 次/分钟/IP
- 其他接口60 次/分钟/IP
- 请求体上限17KB
## 安全设计
- 完全公开,无需注册/登录
- 创建时返回 `admin_token`(随机 64 位字符串),持有者可删除脚本
- 无内容过滤,靠过期机制和限流控制风险
- 编辑功能:无(`admin_token` 仅用于删除,不能改内容。设计上 script 是一次性的,编辑会带来版本管理等复杂问题)
## 前端路由
| 路由 | 页面 | 说明 |
|------|------|------|
| `/` | 首页 | 粘贴脚本 + 选择运行环境/过期时间 + 提交 + 结果展示 |
| `/s/[id]` | 脚本详情页 | 展示脚本内容语法高亮、元数据、curl 命令卡片 |
| `/s/[id]/delete` | 删除确认页 | 输入 admin_token 确认删除 |
## 项目目录结构
```
scriptforge/
├── frontend/ # Next.js 项目
│ ├── src/
│ │ ├── app/
│ │ │ ├── page.tsx # 首页
│ │ │ ├── layout.tsx # 根布局
│ │ │ └── s/[id]/
│ │ │ ├── page.tsx # 脚本详情页
│ │ │ └── delete/
│ │ │ └── page.tsx # 删除确认页
│ │ ├── components/
│ │ │ ├── ScriptForm.tsx # 脚本提交表单
│ │ │ ├── ResultCard.tsx # 结果展示卡(含复制按钮)
│ │ │ ├── ScriptViewer.tsx # 脚本内容展示(语法高亮)
│ │ │ └── CommandCard.tsx # curl 命令展示卡
│ │ └── lib/
│ │ └── api.ts # API 调用封装
│ ├── package.json
│ └── next.config.js
├── backend/ # Go 项目
│ ├── cmd/
│ │ └── server/
│ │ └── main.go # 入口
│ ├── internal/
│ │ ├── handler/
│ │ │ ├── script.go # 脚本 CRUD handlers
│ │ │ └── raw.go # 原始内容 handler
│ │ ├── model/
│ │ │ └── script.go # GORM model
│ │ ├── service/
│ │ │ └── script.go # 业务逻辑
│ │ ├── middleware/
│ │ │ └── ratelimit.go # 限流中间件
│ │ └── config/
│ │ └── runtime.go # 运行时配置列表
│ ├── go.mod
│ └── go.sum
├── .gitea/
│ └── workflows/
│ └── deploy.yml # Gitea Actions 部署流程
├── Makefile # 统一构建命令
├── DESIGN.md # 本设计文档
└── README.md
```
## CI/CD 部署流程Gitea Actions
1. 触发条件push 到 `main` 分支
2. 构建步骤:
- `cd frontend && npm ci && npm run build` → 输出 `out/`
- `cd backend && cp -r ../frontend/out ./internal/embed && go build -o server ./cmd/server`
3. 部署步骤:
- `scp` 二进制到服务器
- `ssh` 执行 `systemctl restart scriptforge`
## 后续可扩展方向
- 大模型集成:根据脚本内容自动推荐运行环境
- 更多运行时dockerfile、powershell、deno、bun 等
- 脚本版本管理(不基于 admin_token需要真正的用户系统
- 统计数据:脚本执行次数、来源 IP 等(需要跟踪 curl 请求)
- WebSocket 实时执行输出流