64 lines
2.7 KiB
Markdown
64 lines
2.7 KiB
Markdown
# 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/`
|