mirror of
https://github.com/34892002/edgeKey.git
synced 2026-06-01 23:09:35 +08:00
update: en
This commit is contained in:
261
README-en.md
261
README-en.md
@@ -7,7 +7,7 @@ EdgeKey is a full-stack card key shop system built with the Vike framework, depl
|
||||
|
||||
## Features
|
||||
|
||||
- 🚀 **Truly Zero Cost** — No server or domain purchase needed. Runs on Cloudflare's global edge network. One-click deploy, instantly live.
|
||||
- 🚀 **Truly Zero Cost** — No server or domain purchase needed. Runs on Cloudflare's global edge network. One-click deploy, instantly live. Spend money on what matters, give yourself back your time.
|
||||
- 🌍 **Zero Ops** — Built on Workers + D1. The free tier is sufficient for daily operations with no surprise bills.
|
||||
- 🛍️ **Product Management** — Supports categories, product listing/unlisting, inventory modes (limited/unlimited), and min/max purchase quantities.
|
||||
- 🔑 **Card Key Management** — Bulk import card keys, automatic delivery after payment, real-time inventory alerts.
|
||||
@@ -20,6 +20,11 @@ EdgeKey is a full-stack card key shop system built with the Vike framework, depl
|
||||
> [!TIP]
|
||||
> **About zero-cost operation:** When combined with a payment channel (USDT, self-hosted, etc.), personal SMTP, and a free image hosting service, this project can achieve **100% zero-cost** operation.
|
||||
|
||||
## Documentation
|
||||
- [Quick Deploy Guide](./docs/fast_deploy/start.md)
|
||||
- Payment: [BEpusdt](./docs/pay/bepusdt/start.md), [Epay](./docs/pay/epay/start.md), [Alipay](./docs/pay/alipay/start.md), [Stripe](./docs/pay/stripe/start.md)
|
||||
- [Changelog](./CHANGELOG.md)
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||
@@ -49,15 +54,58 @@ Three deployment methods are supported, ordered by recommendation:
|
||||
> 4. After deployment, find a log entry like `Deployed edgekey triggers (0.38 sec) https://edgekey.youraccount.workers.dev` — that URL is your site.
|
||||
> 5. `https://edgekey.youraccount.workers.dev/admin` is the admin login page. Default credentials: `admin` / `admin123456`. **Change your password immediately after first login!**
|
||||
|
||||
**One-Click Deploy FAQ**
|
||||
|
||||
If Cloudflare shows an error like "Unable to fetch repository content", it's usually because your GitHub authorization has expired or become invalid. Unbind and re-authorize your Git account to fix this.
|
||||
|
||||
One-click deploy and manual deploy have conflicts in the `wrangler.jsonc` configuration. Commands starting with `wrangler d1` require `database_id` to be configured. Fill in your [Database ID](#how-to-get-database-id), otherwise you'll get errors. Affected commands include `npm run up` and commands starting with `npm run db:`.
|
||||
|
||||
**Updating After One-Click Deploy**
|
||||
|
||||
a. First update:
|
||||
```bash
|
||||
git remote add upstream https://github.com/34892002/edgeKey.git
|
||||
git fetch upstream
|
||||
git merge upstream/main --allow-unrelated-histories
|
||||
git push origin main
|
||||
```
|
||||
|
||||
b. Subsequent updates:
|
||||
```bash
|
||||
git fetch upstream
|
||||
git merge upstream/main
|
||||
git push origin main
|
||||
```
|
||||
|
||||
> Run the above commands in your repository to update to the latest code. After `git push origin main`, Cloudflare will automatically detect the changes and trigger deployment.
|
||||
|
||||
### Git-Connected Cloudflare Auto Deploy
|
||||
|
||||
If you use Cloudflare Workers' Git integration (auto-deploy on GitHub/GitLab push), complete these prerequisites first:
|
||||
|
||||
### Cloudflare Turnstile (Admin Login CAPTCHA)
|
||||
|
||||
The project now supports integrating Cloudflare Turnstile widget on the **admin login page** to block automated brute-force attacks.
|
||||
|
||||
You need to create a site in Cloudflare Dashboard's Turnstile and configure the following environment variables:
|
||||
|
||||
- `TURNSTILE_SITE_KEY`: Frontend widget Site Key
|
||||
- `TURNSTILE_SECRET_KEY`: Server-side verification Secret Key
|
||||
|
||||
Use the following commands to configure Turnstile for the project:
|
||||
```bash
|
||||
wrangler secret put TURNSTILE_SITE_KEY
|
||||
wrangler secret put TURNSTILE_SECRET_KEY
|
||||
```
|
||||
Notes:
|
||||
- When both variables are unconfigured, Turnstile is disabled by default and doesn't affect existing login flow
|
||||
- When both variables are correctly configured, the admin login page will automatically display the Turnstile widget with server-side enforcement
|
||||
- If only one variable is configured, the system treats it as unconfigured to avoid half-configured states
|
||||
|
||||
**0. Prerequisite: Create a D1 Database in Cloudflare Dashboard**
|
||||
|
||||
1. Go to [dash.cloudflare.com](https://dash.cloudflare.com) → **Storage & Databases** → **D1**
|
||||
2. Click **Create**, name it `edgekey-db`
|
||||
3. Note the `database_id` from the database detail page — you'll need it in the deploy command
|
||||
1. [Create database](#how-to-create-database) with name `edgekey-db`
|
||||
2. Record the [database ID](#how-to-get-database-id) `database_id` for use in deploy commands
|
||||
|
||||
Table schema and seed data are initialized automatically by the `deploy` script on first deploy.
|
||||
|
||||
@@ -65,12 +113,10 @@ Table schema and seed data are initialized automatically by the `deploy` script
|
||||
|
||||
Since `wrangler.jsonc` requires your actual D1 `database_id`, set the build command in Cloudflare's "Build Configuration" to:
|
||||
|
||||
```D:\code\edgeKey\README-en.md#L1-1
|
||||
```bash
|
||||
sed -i 's/"database_name": "edgekey-db"/"database_name": "edgekey-db", "database_id": "YOUR_DATABASE_ID"/' wrangler.jsonc && bun run deploy
|
||||
```
|
||||
|
||||
Replace `YOUR_DATABASE_ID` with your actual D1 database ID (found in Cloudflare Dashboard → D1 → database detail page).
|
||||
|
||||
**2. Configure AUTH_SECRET Environment Variable**
|
||||
|
||||
In the Cloudflare Workers Git integration "Advanced Settings":
|
||||
@@ -82,57 +128,54 @@ In the Cloudflare Workers Git integration "Advanced Settings":
|
||||
|
||||
Before deploying to Cloudflare for the first time, create and initialize the D1 database:
|
||||
|
||||
**1. Login and create the database**
|
||||
1. **Login and create the database**
|
||||
```bash
|
||||
bunx wrangler login
|
||||
bunx wrangler d1 create edgekey-db
|
||||
```
|
||||
|
||||
```D:\code\edgeKey\README-en.md#L1-1
|
||||
bunx wrangler login
|
||||
bunx wrangler d1 create edgekey-db
|
||||
```
|
||||
2. **Bind the Database ID**
|
||||
Copy the `database_id` from the terminal output into `wrangler.jsonc`:
|
||||
|
||||
**2. Bind the Database ID**
|
||||
|
||||
Copy the `database_id` from the terminal output into `wrangler.jsonc`:
|
||||
|
||||
```D:\code\edgeKey\README-en.md#L1-1
|
||||
```jsonc
|
||||
"d1_databases": [
|
||||
{
|
||||
"binding": "DB",
|
||||
"database_name": "edgekey-db",
|
||||
"database_id": "YOUR_UUID_HERE", // <-- add this line
|
||||
"migrations_dir": "prisma/migrations"
|
||||
}
|
||||
{
|
||||
"binding": "DB",
|
||||
"database_name": "edgekey-db",
|
||||
"database_id": "YOUR_UUID_HERE", // <-- add this line
|
||||
"migrations_dir": "prisma/migrations"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
**3. Initialize remote table schema**
|
||||
3. **Initialize remote table schema**
|
||||
```bash
|
||||
bun run db:migrations:remote
|
||||
```
|
||||
|
||||
```D:\code\edgeKey\README-en.md#L1-1
|
||||
bun run db:migrations:remote
|
||||
```
|
||||
4. **Seed admin account and initial data**
|
||||
```bash
|
||||
bun run db:seed:remote
|
||||
```
|
||||
|
||||
**4. Seed admin account and initial data**
|
||||
5. **Configure AUTH_SECRET**
|
||||
Run the command and enter your secret string as prompted:
|
||||
```bash
|
||||
bunx wrangler secret put AUTH_SECRET
|
||||
```
|
||||
|
||||
```D:\code\edgeKey\README-en.md#L1-1
|
||||
bun run db:seed:remote
|
||||
```
|
||||
|
||||
**5. Configure AUTH_SECRET**
|
||||
|
||||
```D:\code\edgeKey\README-en.md#L1-1
|
||||
bunx wrangler secret put AUTH_SECRET
|
||||
```
|
||||
|
||||
**6. Generate Prisma Client and deploy**
|
||||
|
||||
```D:\code\edgeKey\README-en.md#L1-1
|
||||
bun run db:generate
|
||||
bun run up
|
||||
```
|
||||
6. **Generate Prisma Client and deploy**
|
||||
```bash
|
||||
bun run db:generate
|
||||
bun run up
|
||||
```
|
||||
|
||||
`bun run up` is equivalent to build + publish:
|
||||
- `vike build`
|
||||
- `wrangler deploy`
|
||||
|
||||
See `wrangler.jsonc` for deployment config (`main` points to Photon's Cloudflare server-entry virtual entry).
|
||||
|
||||
## Security Notes (Important)
|
||||
|
||||
The project uses admin username/password login. Before using in production:
|
||||
@@ -143,11 +186,7 @@ The project uses admin username/password login. Before using in production:
|
||||
|
||||
### Forgot Your Password?
|
||||
|
||||
Reset your password to `admin123456` via the D1 Console in Cloudflare Dashboard:
|
||||
|
||||
1. Go to [dash.cloudflare.com](https://dash.cloudflare.com) → **Storage & Databases** → **D1** → click `edgekey-db`
|
||||
2. Open the **Console** tab
|
||||
3. Run the following SQL:
|
||||
Reset your password to `admin123456` via the D1 Console in Cloudflare Dashboard. [How to execute SQL](#how-to-execute-sql):
|
||||
|
||||
```sql
|
||||
UPDATE Admin SET passwordHash = '$2b$10$viMe8RgcpM30gmmF9OpOcuA/QgleSIUk5VRtqjOulfSIbgK5jQCI6' WHERE username = 'admin';
|
||||
@@ -159,13 +198,13 @@ UPDATE Admin SET passwordHash = '$2b$10$viMe8RgcpM30gmmF9OpOcuA/QgleSIUk5VRtqjOu
|
||||
|
||||
Bun is recommended (npm/pnpm/yarn also work).
|
||||
|
||||
```D:\code\edgeKey\README-en.md#L1-1
|
||||
```bash
|
||||
bun install
|
||||
```
|
||||
|
||||
Since this project uses Cloudflare D1, you must initialize the local D1 simulator schema before starting the dev server for the first time:
|
||||
|
||||
```D:\code\edgeKey\README-en.md#L1-1
|
||||
```bash
|
||||
# 1. Generate Prisma Client (required after first install)
|
||||
bun run db:generate
|
||||
|
||||
@@ -182,49 +221,127 @@ bun run db:seed
|
||||
bun run dev
|
||||
```
|
||||
|
||||
## Cloudflare Platform Operations
|
||||
|
||||
### How to Create Database
|
||||
|
||||
1. Go to [dash.cloudflare.com](https://dash.cloudflare.com) → **Storage & Databases** → **D1**
|
||||
2. Click **Create** on the right side to enter the D1 database creation page
|
||||
3. Fill in the database name in **Name**, and for **Location** generally select "Automatic... nearest available region" if no special requirements
|
||||
|
||||
#### How to Get Database ID
|
||||
|
||||
1. Go to [dash.cloudflare.com](https://dash.cloudflare.com) → **Storage & Databases** → **D1**
|
||||
2. All your created databases will be displayed on the right side
|
||||
3. Find the database you want to operate on, e.g., `edgekey-db`, and click the corresponding `UUID` to copy the ID
|
||||
|
||||
### How to Execute SQL
|
||||
|
||||
1. Go to [dash.cloudflare.com](https://dash.cloudflare.com) → **Storage & Databases** → **D1**
|
||||
2. All your created databases will be displayed on the right side. Click the database name you want to operate on, e.g., `edgekey-db`
|
||||
3. Click the top tab → **Console**
|
||||
|
||||
### Cloudflare D1 + Prisma Local Dev Workflow
|
||||
|
||||
This project follows the official [Prisma + Cloudflare D1 guide](https://www.prisma.io/docs/guides/deployment/cloudflare-d1) best practices.
|
||||
|
||||
### D1 Transaction Limitations & Solutions
|
||||
|
||||
> [!WARNING]
|
||||
> **Cloudflare D1 does not fully support Prisma's interactive transactions** (`prisma.$transaction(async (tx) => {...})`)
|
||||
|
||||
According to [Cloudflare Workers SDK Issue #2733](https://github.com/cloudflare/workers-sdk/issues/2733), D1 has limited transaction support, and the official team has stated no plans to add full interactive transaction support.
|
||||
|
||||
**This project's solution: Compensating Transaction**
|
||||
|
||||
For scenarios requiring data consistency (such as order creation + payment initialization), this project uses the following pattern:
|
||||
|
||||
```typescript
|
||||
// 1. Execute the main operation first
|
||||
const order = await createOrderRecord(prisma, {...});
|
||||
// 2. Attempt the related operation
|
||||
try {
|
||||
const result = await createPaymentForOrder(order.orderNo, prisma);
|
||||
return result;
|
||||
} catch (error) {
|
||||
// 3. If failed, execute compensating operation (delete created records)
|
||||
await prisma.order.delete({ where: { id: order.id } })
|
||||
.catch(e => logger.error("Compensating delete failed:", e));
|
||||
throw error;
|
||||
}
|
||||
```
|
||||
|
||||
**Advantages:**
|
||||
- ✅ Fully compatible with D1 limitations
|
||||
- ✅ No dependency on database transaction features
|
||||
- ✅ Ensures data consistency
|
||||
- ✅ Complete error logs on failure
|
||||
|
||||
**Notes:**
|
||||
- The compensating delete itself may fail (edge cases), so logging is required
|
||||
- Suitable for most business scenarios, but not for high-concurrency race condition sensitive scenarios
|
||||
- For stronger consistency guarantees, consider adding additional state checks at the application layer
|
||||
|
||||
### Current Runtime Mode
|
||||
|
||||
- `bun dev` runs in a Cloudflare-style local environment; Prisma connects to the **local D1 simulator** via `env.DB`.
|
||||
- After `bun run up`, Prisma connects to **remote D1** via the same `env.DB` binding.
|
||||
- `DATABASE_URL` in `.env` is only used by the Prisma CLI, not at runtime.
|
||||
- `DATABASE_URL` in `.env` is only used by the Prisma CLI/config layer, not at runtime.
|
||||
- The current `prisma/schema.prisma` only retains the Cloudflare client generator; runtime uses `generated/prisma/client`.
|
||||
- Therefore, the current database runtime mode is: **local D1 for development, remote D1 for production**.
|
||||
|
||||
### Database Development Workflow
|
||||
### Correct Database Development Workflow
|
||||
|
||||
When modifying the database schema, follow this process strictly:
|
||||
|
||||
**Step 1: Modify schema and generate SQL migration**
|
||||
|
||||
```D:\code\edgeKey\README-en.md#L1-1
|
||||
After modifying `prisma/schema.prisma`, do not use the regular `migrate dev`. Instead, use `migrate diff` to generate the SQL script:
|
||||
|
||||
```bash
|
||||
# Since Cloudflare D1 is completely different from regular MySQL.
|
||||
# Regular Prisma migrate dev relies on a long-running database connection to compare states,
|
||||
# create shadow database, etc., which D1 doesn't support.
|
||||
# For incremental migrations (modifying existing table structure):
|
||||
# New Prisma has deprecated --from-local-d1, recommended to use --from-migrations
|
||||
bunx prisma migrate diff \
|
||||
--from-migrations prisma/migrations \
|
||||
--to-schema prisma/schema.prisma \
|
||||
--script > prisma/migrations/0002_xxx.sql
|
||||
```
|
||||
|
||||
- `0001_init.sql` is for initial setup only — do not overwrite it.
|
||||
- Add incremental files in order: `0002_add_foo.sql`, `0003_add_bar.sql`, etc.
|
||||
### Migration File Restrictions
|
||||
|
||||
**Step 2: Sync to local D1 simulator**
|
||||
- **Existing migration files in `prisma/migrations/` are considered historical records. Do not modify, rename, or delete them.**
|
||||
- **Database changes can only be made by adding new migration files, e.g., `0002_*.sql`, `0003_*.sql`.**
|
||||
- **Only when you explicitly want to rebuild all databases and no longer support any old database upgrades can you redo the migration history.**
|
||||
- **If you need to fix the impact of old migrations, do not modify old files. Instead, add patch migrations or adjust the deployment process.**
|
||||
- **Before committing, ensure `schema.prisma` is consistent with migration file responsibilities, avoiding duplicate field definitions across multiple migrations.**
|
||||
|
||||
```D:\code\edgeKey\README-en.md#L1-1
|
||||
**Step 2: Sync to local D1 simulator (for local dev/testing)**
|
||||
|
||||
```bash
|
||||
bun run db:migrations:local
|
||||
```
|
||||
|
||||
If you skip this step, accessing pages with `bun dev` will show `no such table` errors.
|
||||
|
||||
**Step 3: Sync to Cloudflare remote (before publishing)**
|
||||
|
||||
```D:\code\edgeKey\README-en.md#L1-1
|
||||
```bash
|
||||
bun run db:migrations:remote
|
||||
```
|
||||
|
||||
### Daily Dev Command
|
||||
Both local and remote need to be executed once separately.
|
||||
|
||||
```D:\code\edgeKey\README-en.md#L1-1
|
||||
### Daily Dev Commands
|
||||
|
||||
```bash
|
||||
bun dev
|
||||
```
|
||||
|
||||
The above command starts the local dev server and connects to the **local D1 simulator** using the D1 binding defined in `wrangler.jsonc`.
|
||||
|
||||
### Telefunc Notes
|
||||
|
||||
- Telefunc functions are placed in the corresponding page directory, ending with `.telefunc.ts`.
|
||||
@@ -234,6 +351,20 @@ bun dev
|
||||
1. Do **not** assume `bun dev` uses `prisma/db.sqlite` — it uses the local D1 simulator.
|
||||
2. Do **not** use `prisma migrate dev` — it deviates from the D1 migration workflow.
|
||||
3. Do **not** overwrite `prisma/migrations/0001_init.sql` — keep init and incremental migrations separate.
|
||||
4. Do **not** trust Prisma-generated migration SQL blindly. Always review scripts manually, specifically watch for unexpected **DROP TABLE** or **full rebuild** logic, ensuring migrations are incremental and don't overwrite existing data.
|
||||
|
||||
## Code Standards
|
||||
|
||||
### TypeScript Type Import Standards
|
||||
|
||||
All type imports **must use `import type` at the top of the file**. Inline `import()` usage in variable declarations, function parameters, generics, etc. is prohibited.
|
||||
```typescript
|
||||
// bad: inline import
|
||||
function handle(data: import("./types").SomeType) { ... }
|
||||
// good: top-level import
|
||||
import type { SomeType } from "./types";
|
||||
function handle(data: SomeType) { ... }
|
||||
```
|
||||
|
||||
## Tech Stack
|
||||
|
||||
@@ -245,7 +376,7 @@ bun dev
|
||||
|
||||
## Project Structure
|
||||
|
||||
```D:\code\edgeKey\README-en.md#L1-1
|
||||
```
|
||||
.
|
||||
├─ assets/ # Static assets
|
||||
├─ components/ # Reusable components (non-route pages)
|
||||
@@ -293,6 +424,8 @@ Common `+` files:
|
||||
|
||||
When email or payment callback issues occur, check Workers logs in Cloudflare Dashboard:
|
||||
|
||||
> Real-time production logs: bunx wrangler tail --format pretty
|
||||
|
||||
1. Go to [dash.cloudflare.com](https://dash.cloudflare.com)
|
||||
2. Left menu → **Workers & Pages** → click **edgekey**
|
||||
3. Top tab → **Observability**
|
||||
@@ -315,5 +448,5 @@ Thanks to the following open source projects:
|
||||
|
||||
|
||||
## 🏝️ Get Involved
|
||||
- Join our Group: https://t.me/edgeKeyChannel
|
||||
- Subscribe to Channel: https://t.me/edgeKeyGroup
|
||||
- Telegram Group: https://t.me/edgeKeyChannel
|
||||
- Telegram Channel: https://t.me/edgeKeyGroup
|
||||
|
||||
Reference in New Issue
Block a user