From e052d29782c710c0ce2175b8fda2b1fdec3770e0 Mon Sep 17 00:00:00 2001 From: ggyy <34892002@qq.com> Date: Thu, 21 May 2026 18:14:36 +0800 Subject: [PATCH] update: en --- README-en.md | 261 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 197 insertions(+), 64 deletions(-) diff --git a/README-en.md b/README-en.md index 540d6bc..c633ee3 100644 --- a/README-en.md +++ b/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 ![1](https://img.91starry.com/uploads/20260427/6286ff36cc987c47a1a27516db0d94c8.jpg) @@ -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