mirror of
https://github.com/kamask-dev/pchelpmaster.git
synced 2026-11-11 05:49:38 +00:00
feat(dev): proxy /pb to PocketBase in ng serve
Add proxy.conf.mjs mirroring `location /pb/` from nginx: the prefix is stripped, target comes from PB_URL (empty value falls back to the default, same as the SSR provider). Cover the config with tests in tests/lint and update docs. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
2852610488
commit
bf72af9ef4
@@ -1,4 +1,5 @@
|
||||
# Copy to .env and fill in. .env is not committed.
|
||||
# PocketBase address for the SSR server and the ng serve /pb/ proxy (ng serve reads it from the environment, not .env).
|
||||
PB_URL=http://127.0.0.1:8090
|
||||
PB_DIR=pocketbase/pb_data
|
||||
PB_SUPERUSER_EMAIL=
|
||||
|
||||
@@ -47,20 +47,20 @@ pnpm start # приложение на http://localhost:4200/
|
||||
|
||||
## Команды
|
||||
|
||||
| Команда | Что делает |
|
||||
| ----------------------- | ----------------------------------------------------------------------- |
|
||||
| `pnpm start` | dev-сервер приложения |
|
||||
| `pnpm build` | production-сборка в `dist/` |
|
||||
| `pnpm lint` | ESLint |
|
||||
| `pnpm test` | unit-тесты |
|
||||
| `pnpm test:api` | API-тесты PocketBase: схема, правила доступа, изоляция пользователей |
|
||||
| `pnpm test:integration` | репозитории приложения против тестового PocketBase |
|
||||
| `pnpm test:lint` | тесты конфига ESLint; первый шаг `test`, `test:api`, `test:integration` |
|
||||
| `pnpm e2e` | сценарии в браузере и проверка доступности (axe) |
|
||||
| `pnpm e2e:prod` | сценарии на production-сборке |
|
||||
| `pnpm pb:serve` | PocketBase для разработки |
|
||||
| `pnpm pb:migrate` | применить миграции |
|
||||
| `pnpm pb:superuser` | создать суперпользователя или сбросить его пароль |
|
||||
| Команда | Что делает |
|
||||
| ----------------------- | ------------------------------------------------------------------------------------- |
|
||||
| `pnpm start` | dev-сервер приложения |
|
||||
| `pnpm build` | production-сборка в `dist/` |
|
||||
| `pnpm lint` | ESLint |
|
||||
| `pnpm test` | unit-тесты |
|
||||
| `pnpm test:api` | API-тесты PocketBase: схема, правила доступа, изоляция пользователей |
|
||||
| `pnpm test:integration` | репозитории приложения против тестового PocketBase |
|
||||
| `pnpm test:lint` | тесты конфигов ESLint и dev-прокси; первый шаг `test`, `test:api`, `test:integration` |
|
||||
| `pnpm e2e` | сценарии в браузере и проверка доступности (axe) |
|
||||
| `pnpm e2e:prod` | сценарии на production-сборке |
|
||||
| `pnpm pb:serve` | PocketBase для разработки |
|
||||
| `pnpm pb:migrate` | применить миграции |
|
||||
| `pnpm pb:superuser` | создать суперпользователя или сбросить его пароль |
|
||||
|
||||
Тесты, которым нужен PocketBase, сами поднимают временный экземпляр и не трогают `pocketbase/pb_data`. Перед первым запуском e2e установите браузер: `pnpm exec playwright install chromium`.
|
||||
|
||||
|
||||
@@ -59,6 +59,9 @@
|
||||
"defaultConfiguration": "production"
|
||||
},
|
||||
"serve": {
|
||||
"options": {
|
||||
"proxyConfig": "proxy.conf.mjs"
|
||||
},
|
||||
"builder": "@angular/build:dev-server",
|
||||
"configurations": {
|
||||
"production": {
|
||||
|
||||
@@ -174,7 +174,7 @@ PocketBase SDK использует `fetch`, а не `HttpClient`, поэтом
|
||||
- **Сервер:** `PB_URL` — переменная окружения Node-сервера, внутренний адрес PocketBase для серверного рендера (по умолчанию `http://127.0.0.1:8090`). В браузер не передаётся.
|
||||
- **Браузер:** `<window.location.origin>/pb`. Префикс `/pb` — константа `PB_PUBLIC_PATH` в `shared/pocketbase/`; если путь в nginx поменяется, меняется только она.
|
||||
- Всё это задаётся в одном месте: `shared/pocketbase/`. Клиент `POCKETBASE` создаётся одной и той же фабрикой и в браузере, и на сервере (`providePocketBase()` в `app.config.ts`); различается только токен `PB_URL`: `providePocketBase()` даёт браузерное значение по умолчанию, а `providePbUrlForServer()` в `app.config.server.ts` подменяет его серверным.
|
||||
- **Разработка:** `ng serve` проксирует `/pb/*` → `PB_URL` со срезанием префикса (`proxy.conf.mjs`). E2E-тесты production-сборки используют маленький тестовый фронт-прокси, повторяющий правила nginx.
|
||||
- **Разработка:** `ng serve` проксирует `/pb/*` → `PB_URL` со срезанием префикса (`proxy.conf.mjs`; ключ `/pb/` как у `location /pb/` в nginx, формат — Vite `server.proxy`: `target`, `changeOrigin`, `rewrite`). E2E-тесты production-сборки используют маленький тестовый фронт-прокси, повторяющий правила nginx.
|
||||
|
||||
### Ожидаемая конфигурация nginx (пример, деплой — вне MVP)
|
||||
|
||||
|
||||
+4
-3
@@ -18,7 +18,7 @@
|
||||
|
||||
`pnpm test:api` = `tsc -p tsconfig.tests.json && vitest run --config vitest.api.config.mts`: чистый Vitest в Node, без Angular.
|
||||
|
||||
- Сначала проверяются типы тестового кода (`tsconfig.tests.json`: `tests/**` и `vitest.*.config.mts`): сам Vitest типы не проверяет.
|
||||
- Сначала проверяются типы тестового кода (`tsconfig.tests.json`: `tests/**`, `vitest.*.config.mts` и `proxy.conf.mjs`; `allowJs` нужен, чтобы `tests/lint/` импортировали `.mjs`-конфиг): сам Vitest типы не проверяет.
|
||||
- `vitest.api.config.mts`: `include: tests/api/**/*.api.spec.ts`, `globalSetup: tests/support/global-setup.ts`, таймауты 20 с (запас на старт PocketBase внутри теста).
|
||||
- `global-setup.ts` поднимает один PocketBase на прогон и передаёт тестам `pbUrl`, `pbDataDir`, `pbSuperuser` через `project.provide`; в тестах — `inject('pbUrl')` и т. д. из `vitest`. Типы этих значений — `tests/support/provided-context.d.ts`.
|
||||
- Тесты самого стенда — `tests/api/harness.api.spec.ts`. Проверка уборки по `SIGINT`/`SIGTERM` запускает фикстуру `tests/support/fixtures/hold-pocketbase.ts` отдельным процессом `node`: она поднимает PocketBase, печатает `{ url, dataDir }` и ждёт сигнала.
|
||||
@@ -37,12 +37,13 @@
|
||||
|
||||
`tests/support/clients.ts` компилируется в двух программах — `tsconfig.tests.json` и `tsconfig.spec.json`. Типы Node подключены в обеих (спеки выполняются Vitest в Node, а код в `src/` вроде серверного провайдера `PB_URL` читает `process.env`), а `tests/support/provided-context.d.ts` с типами `inject('pbUrl')` перечислен в `include` обоих tsconfig: `references` в `tsconfig.json` программы не объединяют.
|
||||
|
||||
## Тесты конфига ESLint
|
||||
## Тесты конфигов (ESLint, dev-прокси)
|
||||
|
||||
`pnpm test:lint` = `tsc -p tsconfig.tests.json && vitest run --config vitest.lint.config.mts`: чистый Vitest в Node, файлы `tests/lint/**/*.spec.ts`.
|
||||
|
||||
- Проверяют, что ESLint держит границы, от которых зависит изоляция данных при SSR: `new PocketBase(` и импорт класса `PocketBase` (в том числе под другим именем и через `pocketbase/*`) только в фабрике `shared/pocketbase/pocketbase-client.ts` (и в тестовых хелперах `tests/`), импорт `pocketbase` и `pocketbase/*` запрещён в `domain/` и `ui/`.
|
||||
- Способ: `ESLint#lintText(code, { filePath })` на коротких фрагментах кода, проверяется `ruleId` сообщений. Конфиг ESLint ломается молча (опечатка в glob, слишком широкое исключение), и `pnpm lint` при этом остаётся зелёным; тест это ловит.
|
||||
- `tests/lint/pb-dev-proxy.spec.ts` проверяет `proxy.conf.mjs` (dev-прокси `ng serve`): правило `/pb/`, `target` из `PB_URL` с тем же значением по умолчанию, что у серверного провайдера (в том числе при пустой переменной), и срезание префикса `/pb`.
|
||||
- Способ ESLint-тестов: `ESLint#lintText(code, { filePath })` на коротких фрагментах кода, проверяется `ruleId` сообщений. Конфиг ESLint ломается молча (опечатка в glob, слишком широкое исключение), и `pnpm lint` при этом остаётся зелёным; тест это ловит.
|
||||
- Запускаются первым шагом в `pnpm test`, `pnpm test:api` и `pnpm test:integration`, чтобы поломка правила обнаружилась при любом прогоне. ESLint — Node-библиотека, в бандл builder'а Angular её не подключить, поэтому это отдельный набор.
|
||||
|
||||
## Контрактные тесты репозиториев
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// @ts-check
|
||||
// Повторяет `location /pb/` из docs/architecture.md (раздел 7): только пути с префиксом `/pb/`, префикс срезается.
|
||||
// Формат — `server.proxy` dev-сервера Vite (@angular/build).
|
||||
/** @type {Record<string, { target: string; changeOrigin?: boolean; rewrite?: (path: string) => string }>} */
|
||||
export default {
|
||||
'/pb/': {
|
||||
target: process.env['PB_URL'] || 'http://127.0.0.1:8090',
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/pb/, ''),
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
// Проверяет правило `/pb/` в proxy.conf.mjs: оно должно повторять `location /pb/` из nginx и серверный `PB_URL`.
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
type Rules = typeof import('../../proxy.conf.mjs').default;
|
||||
|
||||
async function loadRules(pbUrl: string | undefined): Promise<Rules> {
|
||||
vi.stubEnv('PB_URL', pbUrl);
|
||||
vi.resetModules();
|
||||
return (await import('../../proxy.conf.mjs')).default;
|
||||
}
|
||||
|
||||
describe('прокси /pb для ng serve', () => {
|
||||
afterEach(() => vi.unstubAllEnvs());
|
||||
|
||||
it('содержит правило /pb/ с target из PB_URL', async () => {
|
||||
const rules = await loadRules('http://pb.test:1234');
|
||||
|
||||
expect(rules['/pb/']?.target).toBe('http://pb.test:1234');
|
||||
expect(rules['/pb/']?.changeOrigin).toBe(true);
|
||||
});
|
||||
|
||||
it.each([undefined, ''])('при PB_URL=%j target — http://127.0.0.1:8090', async (pbUrl) => {
|
||||
const rules = await loadRules(pbUrl);
|
||||
|
||||
expect(rules['/pb/']?.target).toBe('http://127.0.0.1:8090');
|
||||
});
|
||||
|
||||
it('rewrite срезает префикс /pb', async () => {
|
||||
const rewrite = (await loadRules(undefined))['/pb/']?.rewrite;
|
||||
|
||||
expect(rewrite?.('/pb/api/health')).toBe('/api/health');
|
||||
expect(rewrite?.('/pb/api/collections/x/records?a=1')).toBe(
|
||||
'/api/collections/x/records?a=1',
|
||||
);
|
||||
});
|
||||
});
|
||||
+3
-1
@@ -5,6 +5,7 @@
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"allowImportingTsExtensions": true,
|
||||
"allowJs": true,
|
||||
"types": ["node"]
|
||||
},
|
||||
"files": [],
|
||||
@@ -12,6 +13,7 @@
|
||||
"tests/**/*.ts",
|
||||
"vitest.api.config.mts",
|
||||
"vitest.integration.config.mts",
|
||||
"vitest.lint.config.mts"
|
||||
"vitest.lint.config.mts",
|
||||
"proxy.conf.mjs"
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user