初始提交: ScriptForge 脚本快速转运行链接服务
Some checks failed
Release / build-and-release (push) Failing after 1m31s

- 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>
This commit is contained in:
2026-05-28 23:48:19 +08:00
commit 10a200b96c
37 changed files with 4400 additions and 0 deletions

194
DESIGN.md Normal file
View File

@@ -0,0 +1,194 @@
# 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 实时执行输出流