diff --git a/docs/BACKEND-INTEGRATION-PROMPT.md b/docs/BACKEND-INTEGRATION-PROMPT.md new file mode 100644 index 0000000..a4acd6c --- /dev/null +++ b/docs/BACKEND-INTEGRATION-PROMPT.md @@ -0,0 +1,54 @@ +# Backend Implementation Prompt — B2B branch + +Copy-paste this to a backend developer or an AI agent. It is self-contained; pair it with [`BACKEND-INTEGRATION.md`](BACKEND-INTEGRATION.md) (contract detail) and [`BACKEND.md`](BACKEND.md) (per-domain models). + +--- + +## Prompt + +You are implementing the backend for the **`B2B` branch** of an Angular marketplace/storefront + admin builder. The frontend is already built and runs offline against mocks. Your job is to expose real HTTP endpoints the frontend already calls. **Do not touch authentication (Telegram QR session) or payments — those contracts are frozen and out of scope.** + +### Context you must honor +- **Single build, multi-tenant.** Base URL is resolved per-tenant at runtime. Serve each tenant at `https://.api.dexarmarket.ru:445` (template) or get it registered in `environment.tenantApiBaseUrls`. Default tenant → `https://api.dexarmarket.ru:445`. +- Every storefront request carries headers: `X-Region` (`Moscow`/`ST. Petersburg`/`Yerevan`), `X-Language` (`RU`/`EN`/`AM`), `Currency` (`RUB`/`USD`/`AMD`), `WebSessionID` (32-char hex). Localize and session-scope responses off these. +- The frontend normalizes both legacy and "backOffice" field variants, but you should match the documented models to avoid surprises. + +### Part A — Keep existing storefront endpoints working (already in `main`, do not change shapes) +- `GET /ping` +- `GET /category` +- `GET /category/:id?count=&skip=` +- `GET /items/:id` +- `GET /searchitems?search=&count=&skip=&categoryIDs=&minPrice=&maxPrice=&tag=&sort=` → `{ items, total }` +- `GET /items/randomitems?count=&category=` +- `POST /websession/:sessionId` (cart lines) +- `POST /items/:id/callback` (review), `POST /items/:id/questiion` (question — keep the typo), `POST /purchase-email` + +### Part B — New: `GET /bootstrap` (blocking dependency for prod) +Return one JSON document of type `BootstrapConfig` per tenant: `tenant, branding, theme, company, featureFlags, apiEndpoints, localization, seo, permissions, navigation, footer, pages, staticPages, widgetRegistry`. +- Schema: `src/app/shared/models/config/bootstrap-config.model.ts` +- Reference payload to match field-for-field: `src/assets/mock/bootstrap/bootstrap.json` +- Must be cacheable; frontend loads it once at startup. + +### Part C — New: Builder (Project Editor persistence) — highest priority +The editor edits the same `BootstrapConfig` the storefront reads. Implement: +- `GET /builder/bootstrap/draft` → current draft +- `PUT /builder/bootstrap/draft` ← save draft (whole document) +- `POST /builder/bootstrap/publish` → promote draft to the live `GET /bootstrap` +- `POST /builder/bootstrap/validate` (optional endpoint) — **but server-side validation on publish is mandatory**; treat the client validator as untrusted. + +### Part D — New: Backoffice (admin) CRUD, per domain +For each domain — categories, products, orders, transactions, users/roles, dashboard metrics, monitoring, media — expose REST endpoints under `/backoffice/` matching the interfaces the frontend mock gateways implement. Model shapes and required operations per domain: `BACKEND.md` §5–§16 and `features/admin//models/*.model.ts` / `*-gateway.interface.ts`. The frontend swaps mock→api by rebinding one DI token per domain; your endpoints must satisfy the same interface (list/get/create/update/soft-delete/restore/draft-publish where the interface declares them). + +### Constraints +- No changes to auth or payment endpoints. +- Preserve existing storefront request/response shapes exactly. +- Populate `apiEndpoints.website / builder / backoffice` in the bootstrap document as you add endpoints, so the frontend can discover them. +- Add server-side authorization: admin/builder sessions must be distinguishable from customer sessions server-side (the frontend cannot enforce this). + +### Deliverables +1. `GET /bootstrap` per tenant. +2. Builder draft/publish/validate with server-side re-validation. +3. Backoffice CRUD per domain against the documented interfaces. +4. OpenAPI/spec for B, C, D. Storefront (A) is already specified by the client normalizers — do not deviate. + +Ask before assuming any field you cannot find in the referenced models or `bootstrap.json`. diff --git a/docs/BACKEND-INTEGRATION.md b/docs/BACKEND-INTEGRATION.md new file mode 100644 index 0000000..9a2a131 --- /dev/null +++ b/docs/BACKEND-INTEGRATION.md @@ -0,0 +1,120 @@ +# Backend Integration — B2B branch + +How the `B2B` frontend **sends** and **gets** data, and how that differs from `main`. +Scope excludes **login/auth** and **payments** — those contracts are frozen and untouched here. + +Source of truth in code: +- `src/app/services/api.service.ts` — storefront reads/writes +- `src/app/core/config/api-config.service.ts` — base-URL resolution +- `src/app/interceptors/api-base-url.interceptor.ts` + `api-headers.interceptor.ts` — request rewriting + headers +- `src/app/core/config/config.service.ts` + `core/bootstrap/providers/*` — bootstrap load +- `src/app/shared/models/config/*` — bootstrap/endpoint models + +--- + +## 1. What changed vs `main` (one screen) + +| Concern | `main` | `B2B` | +|---|---|---| +| API base URL | Hardcoded `environment.apiUrl` (`/api`) | Resolved per-tenant at runtime by `ApiConfigService` | +| Multi-tenant | One build per brand (`environment.lavero.ts`, `index.novo.html`, …) | **Single build**, tenant resolved from host; per-brand env/html files deleted | +| Config source | Compiled into `environment.ts` (brand, theme, logo, phones) | Fetched at runtime via **`GET /bootstrap`** → `BootstrapConfig` | +| Data providers | `ApiService` called directly everywhere | Same endpoints, now behind **repository/provider interfaces + DI tokens** (swap mock↔api without touching UI) | +| Mock strategy | `mockDataInterceptor` intercepts HTTP | Provider/gateway pattern picks mock vs api per domain (`RuntimeProviderStrategyService`) | +| Interceptor chain | `[mockData, apiHeaders, cache]` | `[mockData, **apiBaseUrl**, apiHeaders, adminAuth, cache]` | +| Storefront read/write endpoints | see §3 | **unchanged in shape** | + +**Bottom line for backend:** the storefront read/write contract (categories, items, search, cart, reviews) is the **same as `main`**. What is *new* is (a) a `GET /bootstrap` document the frontend now depends on, and (b) two whole endpoint namespaces (`builder`, `backoffice`) that are declared but **empty** and served by client-side mocks today. + +--- + +## 2. How a request is built (B2B pipeline) + +Every storefront call goes through this chain: + +1. Code calls `this.http.get('/api/category')` (or `${apiConfig.getBaseUrl()}/category`). +2. **`apiBaseUrlInterceptor`** — if the URL starts with `/api`, rewrites it to the resolved tenant base via `ApiConfigService.toApiUrl()`. +3. **`apiHeadersInterceptor`** — on any API request, attaches: + - `X-Region` — `Moscow` / `ST. Petersburg` / `Yerevan` (from region id) + - `X-Language` — `RU` / `EN` / `AM` + - `Currency` — `RUB` (default) / `USD` / `AMD` + - `WebSessionID` — 32-char hex; from auth session if present, else a persisted anonymous id (`localStorage: web_session_id`) +4. Request goes out to the resolved absolute base. + +### Base-URL resolution (`ApiConfigService.getBaseUrl`) +Priority order: +1. localhost → `environment.localhostApiUrl` (`/api`, proxied by dev server) +2. `environment.tenantApiBaseUrls[tenantKey]` (e.g. `default`/`dexarmarket` → `https://api.dexarmarket.ru:445`) +3. `environment.tenantApiTemplate` → `https://{tenant}.api.dexarmarket.ru:445` +4. (opt-in) `bootstrap.apiEndpoints.website.baseUrl` / `bootstrap.tenant.apiBaseUrl` — only if `allowBootstrapApiOverride: true` **and** absolute +5. fallback `environment.apiUrl` + +> Backend impact: for a **new tenant**, either add it to `tenantApiBaseUrls`, or serve it at `https://.api.dexarmarket.ru:445` so the template matches. No frontend rebuild needed if the template host pattern holds. + +--- + +## 3. GET — reads (storefront, real HTTP today) + +Identical shapes to `main`. `ApiService` normalizes legacy **and** backOffice response formats (see `normalizeItem`/`normalizeCategory` — dual field names, `0x`-hex colours, `names[]`→translations, `imgs[]`→photos, Go-typo tolerance like `valuue`). + +| Method | Endpoint | Notes | +|---|---|---| +| `getCategories()` | `GET /category` | retry ×2 backoff | +| `getCategoryItems(id,count,skip)` | `GET /category/:id?count=&skip=` | | +| `getItem(id)` | `GET /items/:id` | rating/reviews/questions derived from item | +| `searchItems(q,count,skip,opts)` | `GET /searchitems?search=&count=&skip=&categoryIDs=&minPrice=&maxPrice=&tag=&sort=` | returns `{items,total}` | +| `getRandomItems(count,category?)` | `GET /items/randomitems?count=&category=` | featured/related | +| `ping()` | `GET /ping` | health | + +`GET /bootstrap` — **new, required in prod.** Returns the full `BootstrapConfig` (tenant, branding, theme, company, featureFlags, `apiEndpoints`, localization, seo, permissions, navigation, footer, pages, staticPages, widgetRegistry). Loaded once, cached (`ConfigService.loadBootstrap`, `shareReplay(1)`). Shape: `src/app/shared/models/config/bootstrap-config.model.ts`; canonical example: `src/assets/mock/bootstrap/bootstrap.json`. + +On **localhost** (or `useMockData:true`) the `MockBootstrapProvider` serves `bootstrap.json` instead of hitting `/bootstrap`, so the app runs fully offline (`npm run dexar`). + +--- + +## 4. POST — writes (storefront, real HTTP today) + +Unchanged from `main` (payment writes omitted per scope): + +| Method | Endpoint | Body | +|---|---|---| +| `addToCart(sessionId, items)` | `POST /websession/:sessionId` | `[{itemID,quantity,colour?,size?,price?}]` | +| `submitReview({...})` | `POST /items/:id/callback` | `{rating,comment,sessionID,timestamp}` | +| `submitQuestion({...})` | `POST /items/:id/questiion` | `{question,sessionID,timestamp}` — **note existing path typo, keep it** | +| `submitPurchaseEmail({...})` | `POST /purchase-email` | `{email,phone?,telegramUserId,items[]}` | + +--- + +## 5. New backend surface the frontend is waiting on + +Declared in the bootstrap model (`apiEndpoints.builder`, `apiEndpoints.backoffice`) but currently `{}` empty and served by **localStorage / in-memory gateways**. UI is done; wiring a real API = implement one gateway/provider against the existing interface and rebind its DI token — no page/component changes. + +### 5a. Builder (Project Editor) — **highest priority** +The editor edits the same `BootstrapConfig` the storefront consumes. Today `ProjectEditorIoService` only `JSON.stringify`s it (export) — **no HTTP, no persistence**. Needed: +- `GET /builder/bootstrap/draft` → current draft `BootstrapConfig` +- `PUT /builder/bootstrap/draft` ← save draft +- `POST /builder/bootstrap/publish` → promote draft to the live `GET /bootstrap` document +- `POST /builder/bootstrap/validate` (optional) → **server-side re-validation is mandatory**; the client validator is not a trust boundary + +### 5b. Backoffice (admin) — mock gateways awaiting real API +Each domain has a `*Gateway`/`*Provider` interface + a `*LocalGateway` mock bound via token. Implement `*ApiGateway` against the same interface, endpoints under `/backoffice/...`, models in `features/admin//models/*.model.ts`: +categories, products, orders, transactions, users/roles, dashboard metrics, monitoring feeds, media. + +Provider selection is centralized in `RuntimeProviderStrategyService` (`getBackofficeProviderMode`, `getProductProviderMode`, `getCategoryProviderMode`): returns `mock` only when `environment.useMockData`, else `api`. + +> Full per-domain punch list and model shapes: [`BACKEND.md`](BACKEND.md) §5–§16. Handoff framing: [`BACKEND-DIFF-VS-MAIN.md`](BACKEND-DIFF-VS-MAIN.md). + +--- + +## 6. Contract rules for the backend + +- **Do not change** existing storefront read/write shapes (categories, items, search, cart, reviews, questions) — frontend `main` and `B2B` both depend on them. +- **Serve `GET /bootstrap`** matching `bootstrap-config.model.ts`. Field-name tolerance exists on the client, but match the model to avoid normalization surprises. +- Respect request headers `X-Region`, `X-Language`, `Currency`, `WebSessionID` for localization/session-scoped responses. +- New namespaces `builder/*` and `backoffice/*` are yours to define; keep them consistent with the declared `apiEndpoints` block so they can be published via bootstrap. +- **Out of scope here:** auth (Telegram QR session) and payments (`/qr`, `/card`, `/cart` payment) — unchanged, see existing docs. + +--- + +## 7. Known reliability issue (not fixable in frontend) +Intermittent `502`/`504` on refresh/back-nav in prod originate from the upstream reverse proxy at `api.dexarmarket.ru:445` / `users.vitanova.network:456` — the frontend calls those absolute URLs directly. Needs DevOps/backend investigation of upstream health/timeouts around bootstrap + session-check.