docs: architecture, guidelines, domain designs, progressive code index
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
# VMall Architecture
|
||||
|
||||
VMall is a B2B2C marketplace MVP: one Rust API serving three Nuxt 3 frontends,
|
||||
with all HTTP contracts centralized in a shared TypeScript package.
|
||||
|
||||
## Workspace layout
|
||||
|
||||
```
|
||||
apps/
|
||||
api/ Rust (crate vmall-api), port 8080 — the only backend
|
||||
mall/ Nuxt 3 shopper storefront (PC), port 3000
|
||||
shop-admin/ Nuxt 3 merchant console, port 3001
|
||||
admin/ Nuxt 3 platform console, port 3002
|
||||
packages/
|
||||
shared/ @vmall/shared — the ONLY API contract (types.ts + api.ts),
|
||||
en/zh locale packs, Tailwind v4 theme tokens
|
||||
ui/ @vmall/ui — shared Vue components (VBtn, VCard, VField,
|
||||
VInput, VTable, VPage, VPanel, VBadge, VAccentSwatch)
|
||||
openspec/ Spec-driven change management (specs/ = archived truth)
|
||||
docs/ Architecture, guidelines, code index
|
||||
```
|
||||
|
||||
## Request path
|
||||
|
||||
```
|
||||
Browser ──► Nuxt (SSR + hydration) ──► $api plugin ──► vmall-api ──► Postgres
|
||||
│ │
|
||||
│ └─► Redis (cache/sessions)
|
||||
└─ mock adapter fallback (mall only)
|
||||
```
|
||||
|
||||
- Frontends never call `fetch` directly; they call the `ApiClient` from
|
||||
`@vmall/shared`, provided as `$api` by each app's `plugins/api.ts`.
|
||||
- The mall additionally composes a mock adapter (`apps/mall/mock/api.ts`) with
|
||||
per-domain live picks (`LIVE_PICKS` in `apps/mall/plugins/api.ts`), so any
|
||||
domain can roll back to deterministic fixtures via `NUXT_PUBLIC_LIVE_DOMAINS`.
|
||||
The consoles are always live.
|
||||
|
||||
## Roles and tenancy
|
||||
|
||||
`platform_admin` (apps/admin), `shop_owner`/`shop_staff` (apps/shop-admin,
|
||||
scoped to their shop via `auth.own_shop()`), `customer` (apps/mall). Every
|
||||
protected route declares its roles; cross-shop access returns 404.
|
||||
|
||||
## Data rules that shape everything
|
||||
|
||||
- **Money**: `i64` minor units + ISO currency code everywhere. No floats. The
|
||||
currency table carries the exponent (JPY=0); display goes through
|
||||
`formatMoney(minor, code, exponent, locale)`.
|
||||
- **User-facing content**: `{en, zh}` JSONB.
|
||||
- **State machines**: guarded `UPDATE … WHERE status = …`; zero rows → 409.
|
||||
- **Concurrent counters**: guarded `SET col = col - $q … AND col >= $q`;
|
||||
replenish with `col + n`, never read-then-write.
|
||||
- **Migrations**: `apps/api/migrations/`, append-only, run on boot.
|
||||
|
||||
## Where to look next
|
||||
|
||||
- Backend conventions → `docs/backend-guidelines.md`
|
||||
- Frontend conventions → `docs/frontend-guidelines.md`
|
||||
- Run/develop/test → `docs/development.md`
|
||||
- Domain deep dives → `docs/domains/`
|
||||
- Find the file for a feature → `docs/code_index/index.md`
|
||||
- Normative behavior → `openspec/specs/`
|
||||
Reference in New Issue
Block a user