其他
需要上传文件到 IPFS…
用户提到 pinme,或需要上传文件、存储到 IPFS、创建/发布/部署网站或全栈服务(含前端、后端 API、数据库、邮件)时适用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 35/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 39/100 ×0.15
适用场景
需要上传文件到 IPFS 或部署带后端/特定
解决思路
- 判断需求:如果不需要后端 API 或数据库,走 Path 1 上传文件/静态站点;如果需要后端 API 或数据库,走 Path 2 全栈项目。
- Path 1 前先登录:运行 `pinme login` 或 `pinme set-appkey <AppKey>`。
- 检查安装并更新 pinme 到最新:执行 `LOCAL=$(pinme --version 2>/dev/null || echo "0.0.0")`、`LATEST=$(npm view pinme version)`、`[ "$LOCAL" != "$LATEST" ] && npm install -g pinme@latest || echo "pinme is up to date ($LOCAL)"`。
- 认证:运行 `pinme login`,或 `pinme set-appkey <AppKey>`。
- 确定上传目标,按优先级:`dist/`(Vite / Vue / React)、`build/`(Create React App)、`out/`(Next.js static export)、`public/`(纯静态文件)。
- 上传:运行 `pinme upload <path>`;可选绑定子域名:`pinme upload ./dist --domain my-site`(需要钱包余额)。
- 返回 PinMe 打印的最终 URL;URL 优先级为 DNS domain > PinMe subdomain > short URL > preview URL;若回退到 preview,返回包含所有 hash 字符的完整 URL,不要截断。
- 常见上传示例:`pinme upload ./document.pdf`(单文件)、`pinme upload ./my-folder`(文件夹)、`pinme upload dist`(Vite/Vue 构建产物)、`pinme upload build`(CRA 构建产物)、`pinme upload out`(Next.js 静态导出)、`pinme upload ./dist --domain my-site`(绑定 PinMe 子域名,需要钱包余额)、`pinme import ./my-archive.car`(导入 CAR 文件)。
- 不要上传 `node_modules/`、`.env`、`.git/`、`src/`;只上传构建产物,绝不上传源代码。
- Path 2 全栈项目使用 React+Vite 前端 + Cloudflare Worker 后端 + D1 SQLite 数据库;设计前端时以 Ant Design 为主要设计参考,优先遵循其布局、组件、间距和交互模式约定。
- Path 2 前检查并更新 pinme 到最新版本(同 Path 1 的检查更新命令)。
- Path 2 登录:运行 `pinme login`(只需一次)。
- 创建项目:运行 `pinme create <name>` 或 `pinme create <dirName>`;它会克隆模板并自动填充 API URL,生成可用的 Hello World 模板(包含前端页面 + 后端 API 路由 + 数据库 schema)。
- 修改模板代码以匹配业务逻辑,不要从零编写:修改 `backend/src/worker.ts` 替换 API 路由;修改 `frontend/src/pages/` 替换页面组件;修改 `db/001_init.sql` 替换表定义。
- 首次部署或全量更新:运行 `pinme save`,一次性部署前端+后端+数据库。
- 返回预览 URL:`pinme save` 输出 `https://pinme.eth.limo/#/preview/{CID}`;返回包含所有 hash 字符的完整 URL,不要截断。
- 后端 Worker 部署在 `https://{name}.pinme.pro`;前端 API 请求会自动配置指向该地址,无需手动设置。
- 仅修改后端 `backend/src/worker.ts` 时,运行 `pinme update-worker`(更快)。
- 仅修改前端 `frontend/src/` 时,运行 `pinme update-web`(会生成新 CID)。
- 仅修改数据库 `db/` 时,运行 `pinme update-db`(运行新迁移)。
- 多处修改或不确定时,运行 `pinme save`(安全的全量部署)。
- 注意每次前端部署都会生成新 CID 和预览 URL,旧 URL 仍可访问。
- 核心命令:`pinme login`、`pinme create <dirName>`、`pinme save`、`pinme update-worker`、`pinme update-web`、`pinme update-db`;`pinme save` 同时部署前端+后端+数据库,只有确定只改了一部分时才用 `pinme update-*`。
- 项目结构要点:`pinme.toml` 是根配置(自动生成,不要修改);`package.json` 是 monorepo 根(workspaces: frontend + backend);`backend/wrangler.toml` 自动生成,不要修改;`backend/src/worker.ts` 是后端入口,模板中主要用于 JSON API;`db/001_init.sql` 是 SQL 表定义。
- 项目结构要点:`frontend/vite.config.ts` 开发代理 `/api` → `localhost:8787`;`frontend/.env` 自动生成 `VITE_API_URL`(不要修改);`frontend/src/utils/api.ts` 中 `export const API = import.meta.env.VITE_WORKER_URL || ''`;`frontend/src/utils/config.ts` 自动生成 `public_client_config`(仅当启用认证时);`frontend/src/pages/Home/index.tsx` 是页面示例。
- Worker 代码模式:后端主要用于 JSON API;默认优先使用标准 Web API 和简单手动路由;需要时可添加 Worker 兼容库,但默认模板不依赖额外框架;避免依赖完整 Node.js 运行时、持久本地文件系统、原生二进制或子进程的包。
- 在 `Env` 接口中声明环境绑定:`DB: D1Database`(使用数据库时)、`R2: R2Bucket`(项目对象存储,由 PinMe 注入)、`API_KEY?: string`(使用邮件发送时)、`JWT_SECRET: string`(使用 JWT 认证时)、`ADMIN_PASSWORD: string`(使用密码认证时)。
- 定义 CORS 头:`Access-Control-Allow-Origin: '*'`、`Access-Control-Allow-Methods: 'GET, POST, PUT, DELETE, OPTIONS'`、`Access-Control-Allow-Headers: 'Content-Type, Authorization, X-API-Key'`。
- 定义 `json(data: unknown, status = 200): Response` 辅助函数,返回 `Response.json(data, { status, headers: CORS_HEADERS })`。
- 在 `fetch` 处理器中解析 `new URL(request.url).pathname` 和 `request.method`;对 `OPTIONS` 返回 204 和 CORS 头;用 try/catch 包裹路由;按路径和方法手动路由,未匹配返回 `json({ error: 'Not found' }, 404)`,异常返回 `json({ error: 'Internal server error' }, 500)`。
- Worker 约束:依赖选择优先标准 Web API 和简单手动路由;如需额外依赖,优先 Worker 兼容库。
- Worker 约束:Workers 支持部分 Node.js 兼容,但不是完整 Node.js 运行时;不要假设所有 Node.js 内置模块可用或行为完全一致。
- Worker 约束:不要把 Worker 当作有持久本地磁盘的服务器;即使有部分 `fs` 能力,也不要依赖跨请求持久化。
- Worker 约束:模板主要用 Worker 返回 JSON API;如有明确需要,也可适配返回 HTML 或其他内容。
- Worker 约束:密码绝不存储明文;使用专用密码哈希算法如 bcrypt、scrypt 或 Argon2。
- Worker 约束:不要用字符串拼接构建 SQL;使用参数化查询如 `.bind()`。
- 邮件发送:后端需要发送邮件时,使用 PinMe 平台 API `https://pinme.cloud/api/v4/send_email`。
- 邮件配置:在 `Env` 接口添加 `API_KEY?: string;`(发送邮件必需)。
- 邮件处理器:在 `handleSendEmail` 中获取 `env.API_KEY`,若未配置返回 `json({ error: 'API_KEY not configured' }, 500)`。
- 邮件处理器:解析请求体为 `{ to?, subject?, html? }`;若缺少 `to`、`subject`、`html` 分别返回 400 和对应错误 `Email address is required`、`Subject is required`、`HTML content is required`。
- 邮件处理器:用正则 `/^[^\s@]+@[^\s@]+\.[^\s@]+$/` 验证 `body.to`,无效返回 `json({ error: 'Invalid email address' }, 400)`。
- 邮件处理器:用 `fetch('https://pinme.cloud/api/v4/send_email', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': apiKey }, body: JSON.stringify({ to: body.to, subject: body.subject, html: body.html }) })` 发送请求。
- 邮件处理器:解析响应 JSON 并返回 `json(result)`。
- 前端 API 工具:在 `frontend/src/utils/api.ts` 中导出 `API = import.meta.env.VITE_API_URL || ''`;开发时 Vite 将 `/api` 代理到 `localhost:8787`;生产时 `VITE_API_URL` 由 `pinme create` 自动注入。
- 前端 API 工具:导出 `getApiUrl(path: string): string`,返回 `API ? `${API}${path}` : path`。
- D1 查询多行:`const { results } = await env.DB.prepare('SELECT * FROM t WHERE x = ?').bind(val).all();`。
- D1 查询单行:`const row = await env.DB.prepare('SELECT * FROM t WHERE id = ?').bind(id).first();`(未找到返回 null)。
- D1 插入并返回新行:`const row = await env.DB.prepare('INSERT INTO t (a, b) VALUES (?, ?) RETURNING *').bind(a, b).first();`。
- D1 更新:`await env.DB.prepare('UPDATE t SET a = ? WHERE id = ?').bind(val, id).run();`。
- D1 删除并检查影响行数:`const { meta } = await env.DB.prepare('DELETE FROM t WHERE id = ?').bind(id).run(); if (meta.changes === 0) return json({ error: 'Not found' }, 404);`。
- SQL 迁移文件格式:`db/NNN_description.sql`(例如 `001_init.sql`),按文件名顺序执行。
- SQLite 类型约束:不要用 `BOOLEAN`,用 `INTEGER`(0 = false,1 = true)。
- SQLite 类型约束:不要用 `DATETIME` / `TIMESTAMP`,用 `TEXT` 存 ISO 8601(默认 `datetime('now')`)。
- SQLite 类型约束:不要用 `JSON` 类型,用 `TEXT`,配合 `JSON.stringify()` / `JSON.parse()`。
- SQLite 类型约束:不要用 `VARCHAR(n)`,用 `TEXT`。
- 模板架构建议:文件存储(图片、附件、媒体)使用项目 R2 绑定 `env.R2`;使用 `pinme-r2` 技能处理安全路由和元数据模式。
- 模板架构建议:实时通信默认使用常规 HTTP API;如果无明确实时需求,先用轮询。
- 模板架构建议:多个 Workers 默认合并到一个 Worker,并按前缀分离路由。
- 模板架构建议:多个数据库默认合并到一个 D1 数据库,仅在确实需要隔离时才拆分。
- 重要注意事项:`pinme.toml`、`backend/wrangler.toml`、`frontend/.env` 由 PinMe 生成,默认不要手动编辑;如确实需要额外运行时配置,优先通过 PinMe 支持的机制完成。
- 重要注意事项:前端 API URL 从 `VITE_API_URL` 环境变量获取,不要硬编码。
- 重要注意事项:密码、令牌和 API 密钥必须存储在 secrets 中,绝不要放在配置文件里。
- 常见错误处理:`command not found: pinme` → 运行 `npm install -g pinme`。
- 常见错误处理:`No such file or directory` → 验证路径存在。
- 常见错误处理:`Permission denied` → 检查文件或目录权限。
- 常见错误处理:上传失败 → 检查网络连接并重试。
- 常见错误处理:未登录 → 先运行 `pinme login`。
- 其他命令:`pinme list / pinme ls -l 5` 查看上传历史;`pinme list -c` 清空上传历史;`pinme rm <hash>` 删除已上传内容;`pinme bind <path> --domain <domain>` 绑定域名(需要 VIP + AppKey);`pinme export <CID>` 导出为 CAR 文件;`pinme set-appkey` 设置/查看 AppKey;`pinme my-domains` 列出已绑定域名;`pinme delete <project>` 删除项目(Worker + 域名 + D1);`pinme logout` 退出登录。
- 能力特定技能:Worker 文件上传、下载、图片、附件、媒体或对象存储时,使用 `pinme-r2` 技能;PinMe 将项目 bucket 注入为 `env.R2`;不要用 D1 BLOBs 或 Worker 文件系统状态替代。
- 架构层次:前端 React+Vite (`frontend/`) 部署到 IPFS;后端 Cloudflare Worker (`backend/src/worker.ts`) 部署到 `{name}.pinme.pro`;数据库 D1 SQLite (`db/*.sql`) 部署到 Cloudflare D1;对象存储 R2 (`env.R2`) 部署到 Cloudflare R2。
- 全栈项目首次部署命令序列:`LOCAL=$(pinme --version 2>/dev/null || echo "0.0.0")`;`LATEST=$(npm view pinme version)`;`[ "$LOCAL" != "$LATEST" ] && npm install -g pinme@latest`;`pinme login`;`pinme create my-app`;`cd my-app`。
适用边界 · 注意事项
- 无法使用 PinMe CLI 或 PinMe 平台、无法登录或提供 AppKey 时,不适用。
- 需要完整 Node.js 运行时、持久本地文件系统、原生二进制或子进程的场景,不适用。
- 需要实时通信且无明确实时需求时,可先使用常规 HTTP 轮询;若必须使用多个独立 Worker/数据库且不愿合并,也不适用。