feat(pwa): вход для сотрудника, просмотр от лица водителя и вкладка «Отладка»
Приложение обкатывается на боевом контуре, поэтому интерфейс надо проверять на живых данных — а живые данные лежат у настоящих водителей. * «Вход для сотрудника» (/dev) — логин учётки CRM, поддержан второй шаг 2FA; дальше поиск водителя по ФИО/телефону/id и просмотр его экранов. * Плашка «Смотрю как …» над всеми экранами: интерфейс в этом режиме неотличим от водительского, и чужой баланс легко принять за свой. * Вкладка «Отладка» (/debug, водителю недоступна): смена водителя, driver_id, режим, срок токена, адрес API, коммит и время сборки, журнал последних 40 ответивших запросов, сброс кэша сервис-воркера. * Пополнение под просмотром идёт в учебный контур: экран /mock-pay/:orderId выбирает, что «ответит» банк, а настоящий экран оплаты разбирает эти статусы своим боевым кодом. Ни рубля, ни чека 54-ФЗ. Заодно доезжает незакоммиченная работа прошлой сессии: дев-прокси в vite.config.ts, его тест и разобранный .env.example. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,13 +1,73 @@
|
||||
import { defineConfig } from "vite";
|
||||
import { execSync } from "child_process";
|
||||
import { defineConfig, loadEnv } from "vite";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import { VitePWA } from "vite-plugin-pwa";
|
||||
import path from "path";
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
react(),
|
||||
VitePWA({ registerType: "autoUpdate", manifest: false, includeAssets: ["icons/*.png"] }),
|
||||
],
|
||||
resolve: { alias: { "@": path.resolve(__dirname, "src") } },
|
||||
server: { port: 5174 },
|
||||
/**
|
||||
* Что именно сейчас открыто — видно на вкладке «Отладка».
|
||||
*
|
||||
* Без этого «правка не приехала» и «приехала, но кэш старый» выглядят
|
||||
* одинаково, а проверяются по-разному. Коммит берём из git; вне репозитория
|
||||
* (сборка из архива, CI без .git) — честный «unknown», а не падение сборки.
|
||||
*/
|
||||
function buildCommit(): string {
|
||||
try {
|
||||
return execSync("git rev-parse --short HEAD", { stdio: ["ignore", "pipe", "ignore"] })
|
||||
.toString().trim() || "unknown";
|
||||
} catch {
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Локальная разработка ходит в бэкенд ЧЕРЕЗ ПРОКСИ dev-сервера, а не напрямую.
|
||||
*
|
||||
* Почему не «разрешить localhost в CORS бэкенда»: через прокси запрос уходит с
|
||||
* того же origin, что и страница (http://localhost:5174/api/...), поэтому CORS
|
||||
* в разработке не участвует вообще — ни preflight, ни credentials. Боевой
|
||||
* список origin'ов на бэкенде остаётся закрытым, и CORS_ALLOW_LOCALHOST ради
|
||||
* этого фронта включать не нужно.
|
||||
*
|
||||
* Дефолтная цель прокси — ЛОКАЛЬНЫЙ бэкенд, а не crm.pptaxi.ru. Контур боевой:
|
||||
* «по умолчанию проксировать в прод» означало бы, что первый же тычок в
|
||||
* «Пополнить» на машине разработчика создаёт платёж на живом терминале и живой
|
||||
* чек 54-ФЗ. Другой адрес задаётся VITE_API_TARGET — тем же именем, что в CRM
|
||||
* (crm2/frontend/vite.config.ts), чтобы рецепт был один на оба фронта.
|
||||
*/
|
||||
export default defineConfig(({ command, mode }) => {
|
||||
// База для ky (src/api/client.ts): в dev — свой же origin, дальше прокси.
|
||||
// Ставим ТОЛЬКО если разработчик не задал базу сам (.env.local, .env,
|
||||
// VITE_API_BASE=... перед командой): loadEnv отдаёт и файлы, и process.env,
|
||||
// причём process.env приоритетнее файлов — без этой проверки собственная
|
||||
// настройка молча перебивалась бы нашим дефолтом.
|
||||
// В сборку (command === "build") не лезем никогда: там база остаётся боевой —
|
||||
// из .env, либо из дефолта в client.ts.
|
||||
if (command === "serve" && !loadEnv(mode, __dirname, "VITE_").VITE_API_BASE) {
|
||||
process.env.VITE_API_BASE = "/api";
|
||||
}
|
||||
|
||||
return {
|
||||
define: {
|
||||
__BUILD_COMMIT__: JSON.stringify(buildCommit()),
|
||||
__BUILD_TIME__: JSON.stringify(new Date().toISOString().slice(0, 16).replace("T", " ")),
|
||||
},
|
||||
plugins: [
|
||||
react(),
|
||||
VitePWA({ registerType: "autoUpdate", manifest: false, includeAssets: ["icons/*.png"] }),
|
||||
],
|
||||
resolve: { alias: { "@": path.resolve(__dirname, "src") } },
|
||||
server: {
|
||||
port: 5174,
|
||||
proxy: {
|
||||
"/api": {
|
||||
// secure: false нужен только для VITE_API_TARGET на https-цель с
|
||||
// самоподписанным сертификатом; на дефолтную http-цель не влияет.
|
||||
target: process.env.VITE_API_TARGET || "http://127.0.0.1:8000",
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user