pinme 2.0.0-beta.2 → 2.0.0-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1544 -962
- package/package.json +32 -32
- package/template/README.md +0 -177
- package/template/backend/package.json +0 -12
- package/template/backend/schema/001_init.sql +0 -35
- package/template/backend/src/worker.ts +0 -108
- package/template/backend/wrangler.toml +0 -11
- package/template/frontend/.env.example +0 -4
- package/template/frontend/index.html +0 -12
- package/template/frontend/package.json +0 -25
- package/template/frontend/pnpm-lock.yaml +0 -1119
- package/template/frontend/src/App.css +0 -389
- package/template/frontend/src/App.tsx +0 -38
- package/template/frontend/src/components/Header.tsx +0 -29
- package/template/frontend/src/main.tsx +0 -21
- package/template/frontend/src/pages/About/index.tsx +0 -39
- package/template/frontend/src/pages/Demo/index.tsx +0 -87
- package/template/frontend/src/pages/Home/index.tsx +0 -94
- package/template/frontend/src/utils/api.ts +0 -6
- package/template/frontend/src/vite-env.d.ts +0 -1
- package/template/frontend/tsconfig.json +0 -22
- package/template/frontend/tsconfig.node.json +0 -11
- package/template/frontend/vite.config.ts +0 -27
- package/template/package.json +0 -16
- package/template/pinme.toml +0 -18
- package/template/pnpm-workspace.yaml +0 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pinme",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.21",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
"pinme": "./dist/index.js"
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
|
-
"dist"
|
|
19
|
-
"template"
|
|
18
|
+
"dist"
|
|
20
19
|
],
|
|
20
|
+
|
|
21
21
|
"keywords": [
|
|
22
22
|
"ipfs",
|
|
23
23
|
"cli",
|
|
@@ -27,38 +27,38 @@
|
|
|
27
27
|
"author": "Glitter Protocol",
|
|
28
28
|
"license": "MIT",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"archiver": "
|
|
31
|
-
"axios": "
|
|
32
|
-
"base-x": "
|
|
33
|
-
"bip39": "
|
|
34
|
-
"chalk": "
|
|
35
|
-
"commander": "
|
|
36
|
-
"crypto-js": "
|
|
37
|
-
"dayjs": "
|
|
30
|
+
"archiver": "7.0.1",
|
|
31
|
+
"axios": "1.3.2",
|
|
32
|
+
"base-x": "5.0.1",
|
|
33
|
+
"bip39": "3.1.0",
|
|
34
|
+
"chalk": "2.4.2",
|
|
35
|
+
"commander": "11.1.0",
|
|
36
|
+
"crypto-js": "4.2.0",
|
|
37
|
+
"dayjs": "1.11.7",
|
|
38
38
|
"ethers": "5.7.2",
|
|
39
|
-
"figlet": "
|
|
40
|
-
"form-data": "
|
|
41
|
-
"formdata-node": "
|
|
42
|
-
"fs-extra": "
|
|
43
|
-
"inquirer": "
|
|
44
|
-
"ora": "
|
|
45
|
-
"uuid": "
|
|
39
|
+
"figlet": "1.7.0",
|
|
40
|
+
"form-data": "4.0.0",
|
|
41
|
+
"formdata-node": "6.0.3",
|
|
42
|
+
"fs-extra": "11.2.0",
|
|
43
|
+
"inquirer": "8.2.6",
|
|
44
|
+
"ora": "3.4.0",
|
|
45
|
+
"uuid": "9.0.1"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@rollup/plugin-commonjs": "
|
|
49
|
-
"@rollup/plugin-json": "
|
|
50
|
-
"@rollup/plugin-node-resolve": "
|
|
51
|
-
"dotenv": "
|
|
52
|
-
"esbuild": "
|
|
53
|
-
"eslint": "
|
|
54
|
-
"eslint-config-airbnb-base": "
|
|
55
|
-
"eslint-config-prettier": "
|
|
56
|
-
"eslint-plugin-import": "
|
|
57
|
-
"eslint-plugin-prettier": "
|
|
58
|
-
"prettier": "
|
|
59
|
-
"rollup": "
|
|
60
|
-
"rollup-plugin-copy": "
|
|
61
|
-
"rollup-plugin-terser": "
|
|
48
|
+
"@rollup/plugin-commonjs": "22.0.2",
|
|
49
|
+
"@rollup/plugin-json": "4.1.0",
|
|
50
|
+
"@rollup/plugin-node-resolve": "14.1.0",
|
|
51
|
+
"dotenv": "16.5.0",
|
|
52
|
+
"esbuild": "0.25.2",
|
|
53
|
+
"eslint": "8.33.0",
|
|
54
|
+
"eslint-config-airbnb-base": "15.0.0",
|
|
55
|
+
"eslint-config-prettier": "8.6.0",
|
|
56
|
+
"eslint-plugin-import": "2.27.5",
|
|
57
|
+
"eslint-plugin-prettier": "4.2.1",
|
|
58
|
+
"prettier": "2.8.3",
|
|
59
|
+
"rollup": "2.79.2",
|
|
60
|
+
"rollup-plugin-copy": "3.5.0",
|
|
61
|
+
"rollup-plugin-terser": "7.0.2"
|
|
62
62
|
},
|
|
63
63
|
"engines": {
|
|
64
64
|
"node": ">= 16.13.0"
|
package/template/README.md
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
# Pinme Template
|
|
2
|
-
|
|
3
|
-
Pinme 官方模板 - 前后端分离架构,使用 Vite + React 前端和 Cloudflare Workers 后端。
|
|
4
|
-
|
|
5
|
-
## 项目结构(Monorepo)
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
.
|
|
9
|
-
├── pinme.toml # Pinme 配置
|
|
10
|
-
├── package.json # 根配置
|
|
11
|
-
├── frontend/ # 前端应用(React + Vite)
|
|
12
|
-
│ ├── src/
|
|
13
|
-
│ └── package.json
|
|
14
|
-
├── backend/ # 后端 Worker
|
|
15
|
-
│ ├── src/
|
|
16
|
-
│ │ └── worker.ts # ← 用户编辑这个文件
|
|
17
|
-
│ ├── wrangler.toml # Wrangler 配置
|
|
18
|
-
│ └── metadata.json # Worker 元数据(API 返回)
|
|
19
|
-
├── save-worker.ts # 构建并保存 Worker 脚本
|
|
20
|
-
└── README.md
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## 快速开始
|
|
24
|
-
|
|
25
|
-
### 1. 创建项目
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
pinme create <project-name>
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### 2. 安装依赖
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
cd <project-name>
|
|
35
|
-
npm install
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
### 3. 开发
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
# 前端开发
|
|
42
|
-
npm run dev:frontend
|
|
43
|
-
|
|
44
|
-
# 后端开发
|
|
45
|
-
# 直接编辑 backend/src/worker.ts
|
|
46
|
-
npm run dev # 本地预览
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### 4. 保存到平台
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
npm run save
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## 使用说明
|
|
58
|
-
|
|
59
|
-
### 创建项目
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
pinme create my-app
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
会调用 `create_worker` API,返回:
|
|
66
|
-
- `backend/metadata.json` - Worker 元数据
|
|
67
|
-
- `backend/src/worker.ts` - Worker 源代码
|
|
68
|
-
|
|
69
|
-
### 开发后端
|
|
70
|
-
|
|
71
|
-
编辑 `backend/src/worker.ts`:
|
|
72
|
-
|
|
73
|
-
```typescript
|
|
74
|
-
export default {
|
|
75
|
-
async fetch(request: Request, env: any) {
|
|
76
|
-
const url = new URL(request.url);
|
|
77
|
-
|
|
78
|
-
if (url.pathname === '/api/hello') {
|
|
79
|
-
return new Response('Hello World!');
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return new Response('Not Found', { status: 404 });
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
本地预览:
|
|
88
|
-
```bash
|
|
89
|
-
npm run dev
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### 保存部署
|
|
93
|
-
|
|
94
|
-
```bash
|
|
95
|
-
npm run save
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
流程:
|
|
99
|
-
1. `wrangler deploy --dry-run --outdir` - 构建 `backend/src/worker.ts` → `dist-worker/`
|
|
100
|
-
2. 上传 `dist-worker/*.js` + `backend/metadata.json` 到平台 API
|
|
101
|
-
|
|
102
|
-
### 前端开发
|
|
103
|
-
|
|
104
|
-
```bash
|
|
105
|
-
npm run dev:frontend
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
访问 `http://localhost:5173`
|
|
109
|
-
|
|
110
|
-
---
|
|
111
|
-
|
|
112
|
-
## 命令
|
|
113
|
-
|
|
114
|
-
| 命令 | 说明 |
|
|
115
|
-
|------|------|
|
|
116
|
-
| `npm run dev` | 本地预览后端 Worker |
|
|
117
|
-
| `npm run dev:frontend` | 启动前端开发服务器 |
|
|
118
|
-
| `npm run build` | 构建前端 + 后端 |
|
|
119
|
-
| `npm run build:worker` | 构建后端 Worker |
|
|
120
|
-
| `npm run build:frontend` | 构建前端 |
|
|
121
|
-
| `npm run save` | **一键部署**(构建 + 部署前端到 IPFS + 保存 Worker 到平台) |
|
|
122
|
-
|
|
123
|
-
---
|
|
124
|
-
|
|
125
|
-
## 配置
|
|
126
|
-
|
|
127
|
-
编辑 `pinme.toml`:
|
|
128
|
-
|
|
129
|
-
```toml
|
|
130
|
-
project_name = "my-app"
|
|
131
|
-
|
|
132
|
-
[vars]
|
|
133
|
-
VITE_WORKER_URL = ""
|
|
134
|
-
|
|
135
|
-
[d1]
|
|
136
|
-
migrations_dir = "backend/schema"
|
|
137
|
-
# database_id = "xxx"
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
编辑 `backend/wrangler.toml` 配置 D1 等:
|
|
141
|
-
|
|
142
|
-
```toml
|
|
143
|
-
name = "my-app"
|
|
144
|
-
compatibility_date = "2026-03-01"
|
|
145
|
-
main = "src/worker.ts"
|
|
146
|
-
|
|
147
|
-
[[d1_databases]]
|
|
148
|
-
binding = "DB"
|
|
149
|
-
database_name = "my-app-db"
|
|
150
|
-
database_id = "xxx"
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
---
|
|
154
|
-
|
|
155
|
-
## 文件说明
|
|
156
|
-
|
|
157
|
-
| 文件 | 说明 |
|
|
158
|
-
|------|------|
|
|
159
|
-
| `backend/src/worker.ts` | 用户编辑的 Worker 源代码 |
|
|
160
|
-
| `backend/metadata.json` | Worker 元数据(包含 bindings 等) |
|
|
161
|
-
| `backend/wrangler.toml` | Wrangler 配置 |
|
|
162
|
-
| `pinme.toml` | 项目配置 |
|
|
163
|
-
|
|
164
|
-
---
|
|
165
|
-
|
|
166
|
-
## 技术栈
|
|
167
|
-
|
|
168
|
-
- **前端**: Vite + React + TypeScript + React Router
|
|
169
|
-
- **后端**: Cloudflare Workers (TypeScript)
|
|
170
|
-
- **数据库**: Cloudflare D1 (SQLite)
|
|
171
|
-
- **部署**: Pinme 平台 API
|
|
172
|
-
|
|
173
|
-
---
|
|
174
|
-
|
|
175
|
-
## License
|
|
176
|
-
|
|
177
|
-
MIT
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
CREATE TABLE IF NOT EXISTS messages (
|
|
2
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
3
|
-
content TEXT NOT NULL,
|
|
4
|
-
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
5
|
-
);
|
|
6
|
-
|
|
7
|
-
CREATE INDEX IF NOT EXISTS idx_messages_created_at ON messages(created_at);
|
|
8
|
-
|
|
9
|
-
-- 项目表(D1 数据库关联)
|
|
10
|
-
CREATE TABLE IF NOT EXISTS projects (
|
|
11
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
12
|
-
project_name TEXT NOT NULL UNIQUE,
|
|
13
|
-
db_uuid TEXT NOT NULL,
|
|
14
|
-
db_name TEXT NOT NULL,
|
|
15
|
-
created_at TEXT NOT NULL,
|
|
16
|
-
region TEXT,
|
|
17
|
-
created_by TEXT,
|
|
18
|
-
created_at_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
CREATE INDEX IF NOT EXISTS idx_projects_name ON projects(project_name);
|
|
22
|
-
|
|
23
|
-
-- Worker 部署记录表
|
|
24
|
-
CREATE TABLE IF NOT EXISTS workers (
|
|
25
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
26
|
-
user_id TEXT NOT NULL,
|
|
27
|
-
project_name TEXT NOT NULL,
|
|
28
|
-
worker_name TEXT NOT NULL,
|
|
29
|
-
url TEXT NOT NULL,
|
|
30
|
-
deployed_at TEXT NOT NULL,
|
|
31
|
-
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
32
|
-
UNIQUE(user_id, project_name)
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
CREATE INDEX IF NOT EXISTS idx_workers_user_project ON workers(user_id, project_name);
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
// ============ 类型定义 ============
|
|
2
|
-
|
|
3
|
-
export interface Env {
|
|
4
|
-
DB: any;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
// ============ 工具函数 ============
|
|
8
|
-
|
|
9
|
-
const CORS_HEADERS = {
|
|
10
|
-
'Access-Control-Allow-Origin': '*',
|
|
11
|
-
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
|
12
|
-
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
function json(data: unknown, status = 200): Response {
|
|
16
|
-
return Response.json(data, { status, headers: CORS_HEADERS });
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function handleOptions(): Response {
|
|
20
|
-
return new Response(null, { status: 204, headers: CORS_HEADERS });
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// 内存存储(开发阶段使用,上线后换 D1)
|
|
24
|
-
const messages: { id: number; content: string; created_at: string }[] = [];
|
|
25
|
-
let messageId = 0;
|
|
26
|
-
|
|
27
|
-
// ============ 路由处理器 ============
|
|
28
|
-
|
|
29
|
-
async function handleHello(env: Env): Promise<Response> {
|
|
30
|
-
// 如果有 D1 数据库,使用数据库
|
|
31
|
-
if (env.DB) {
|
|
32
|
-
const { results } = await env.DB
|
|
33
|
-
.prepare('SELECT * FROM messages ORDER BY created_at DESC LIMIT 10')
|
|
34
|
-
.all();
|
|
35
|
-
return json({ message: 'Hello from Worker!', data: results, source: 'd1' });
|
|
36
|
-
}
|
|
37
|
-
// 否则使用内存存储
|
|
38
|
-
return json({
|
|
39
|
-
message: 'Hello from Worker!',
|
|
40
|
-
data: messages.slice(-10).reverse(),
|
|
41
|
-
source: 'memory'
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async function handleAddMessage(request: Request, env: Env): Promise<Response> {
|
|
46
|
-
const body = await request.json() as { message?: string };
|
|
47
|
-
const message = (body.message ?? '').trim().slice(0, 500);
|
|
48
|
-
if (!message) return json({ error: 'message is required' }, 400);
|
|
49
|
-
|
|
50
|
-
// 如果有 D1 数据库,使用数据库
|
|
51
|
-
if (env.DB) {
|
|
52
|
-
const result = await env.DB
|
|
53
|
-
.prepare('INSERT INTO messages (content) VALUES (?) RETURNING *')
|
|
54
|
-
.bind(message)
|
|
55
|
-
.first();
|
|
56
|
-
return json(result, 201);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// 否则使用内存存储
|
|
60
|
-
const newMessage = {
|
|
61
|
-
id: ++messageId,
|
|
62
|
-
content: message,
|
|
63
|
-
created_at: new Date().toISOString(),
|
|
64
|
-
};
|
|
65
|
-
messages.push(newMessage);
|
|
66
|
-
return json(newMessage, 201);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// ============ 示例 Demo API ============
|
|
70
|
-
|
|
71
|
-
async function handleGetRootDomain(): Promise<Response> {
|
|
72
|
-
try {
|
|
73
|
-
const response = await fetch('https://pinme.dev/api/v4/root_domain', {
|
|
74
|
-
method: 'GET',
|
|
75
|
-
headers: {
|
|
76
|
-
'Content-Type': 'application/json',
|
|
77
|
-
},
|
|
78
|
-
});
|
|
79
|
-
const data = await response.json();
|
|
80
|
-
return json(data);
|
|
81
|
-
} catch (error) {
|
|
82
|
-
return json({ error: 'Failed to fetch root domain' }, 500);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// ============ 主入口 ============
|
|
87
|
-
|
|
88
|
-
export default {
|
|
89
|
-
async fetch(request: Request, env: Env): Promise<Response> {
|
|
90
|
-
const { pathname } = new URL(request.url);
|
|
91
|
-
const method = request.method;
|
|
92
|
-
|
|
93
|
-
// 处理 CORS 预检请求
|
|
94
|
-
if (method === 'OPTIONS') {
|
|
95
|
-
return handleOptions();
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
try {
|
|
99
|
-
if (pathname === '/api/hello' && method === 'GET') return handleHello(env);
|
|
100
|
-
if (pathname === '/api/messages' && method === 'POST') return handleAddMessage(request, env);
|
|
101
|
-
if (pathname === '/api/root-domain' && method === 'GET') return handleGetRootDomain();
|
|
102
|
-
|
|
103
|
-
return json({ error: 'Not found' }, 404);
|
|
104
|
-
} catch {
|
|
105
|
-
return json({ error: 'Internal server error' }, 500);
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
name = "pinme-template"
|
|
2
|
-
compatibility_date = "2026-03-01"
|
|
3
|
-
main = "src/worker.ts"
|
|
4
|
-
|
|
5
|
-
[[d1_databases]]
|
|
6
|
-
binding = "pinme_template_db"
|
|
7
|
-
database_name = "pinme-template-db"
|
|
8
|
-
database_id = "e75f6af9-73a1-490c-80b1-4cd77895b2b9"
|
|
9
|
-
|
|
10
|
-
[vars]
|
|
11
|
-
VITE_WORKER_URL = "https://vite-react-ts-{hash}.pinme.pro"
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="zh">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>Pinme App</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<div id="root"></div>
|
|
10
|
-
<script type="module" src="/src/main.tsx"></script>
|
|
11
|
-
</body>
|
|
12
|
-
</html>
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "pinme-template-frontend",
|
|
3
|
-
"private": true,
|
|
4
|
-
"version": "0.0.0",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"dev": "vite",
|
|
8
|
-
"build": "tsc && vite build",
|
|
9
|
-
"preview": "vite preview",
|
|
10
|
-
"deploy": "tsc && vite build && pinme upload ./dist"
|
|
11
|
-
},
|
|
12
|
-
"dependencies": {
|
|
13
|
-
"react": "^18.3.1",
|
|
14
|
-
"react-dom": "^18.3.1",
|
|
15
|
-
"react-router-dom": "^6.22.0"
|
|
16
|
-
},
|
|
17
|
-
"devDependencies": {
|
|
18
|
-
"@types/node": "^22.10.5",
|
|
19
|
-
"@types/react": "^18.3.1",
|
|
20
|
-
"@types/react-dom": "^18.3.1",
|
|
21
|
-
"@vitejs/plugin-react": "^4.3.1",
|
|
22
|
-
"typescript": "^5.5.3",
|
|
23
|
-
"vite": "^5.4.1"
|
|
24
|
-
}
|
|
25
|
-
}
|