mirror of
https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools.git
synced 2026-06-17 23:09:35 +00:00
chore(dealix): launch checklist, E2E port helper, OpenAPI path scan
- Document verify-launch, py/py-3, E2E, and port 3000 troubleshooting - Add scripts/kill-port-3000.ps1 for Playwright webServer conflicts - Increase Playwright webServer timeout to 180s - Extend verify_frontend_openapi_paths for template literals; empty allowlist - Commit Next routes.d.ts reference in next-env.d.ts after build Made-with: Cursor
This commit is contained in:
parent
fcdbc1f004
commit
67fcc35877
@ -2,19 +2,22 @@
|
||||
|
||||
## 1. الكود والاختبارات
|
||||
|
||||
- [ ] `cd backend && py -m pytest tests -q` — يجب أن تمر كل الاختبارات.
|
||||
- [ ] `cd frontend && npm run lint && npm run build`.
|
||||
- [ ] **اختبارات الباكند:** من `backend/` شغّل `python -m pytest tests -q` (مثل CI على Linux) أو على ويندوز إذا الأمر `python` غير موجود: `py -3 -m pytest tests -q`.
|
||||
- [ ] **بوابة موحّدة (موصى به):** من جذر `salesflow-saas`: `.\verify-launch.ps1` — يشغّل pytest + مزامنة التسويق + lint + build.
|
||||
- [ ] `cd frontend && npm run lint && npm run build` (أو تُغطّى بواسطة `verify-launch.ps1`).
|
||||
- [ ] من جذر `salesflow-saas`: `node scripts/sync-marketing-to-public.cjs` (يُشغَّل أيضاً تلقائياً قبل `npm run build`).
|
||||
- [ ] (اختياري) من جذر `salesflow-saas`: `py scripts/verify_frontend_openapi_paths.py` — يطابق مسارات `/api/v1` الظاهرة حرفيًا في الفرونت مع OpenAPI.
|
||||
- [ ] **E2E (Playwright):** بعد `npm run build`، حرّر المنفذ **3000** ثم من `frontend/`: `CI=true npm run test:e2e`. إن ظهر «port already in use» أو timeout على `webServer`: من جذر `salesflow-saas` شغّل `.\scripts\kill-port-3000.ps1` ثم أعد المحاولة.
|
||||
- [ ] (اختياري) من جذر `salesflow-saas`: `py -3 scripts/verify_frontend_openapi_paths.py` (أو `python3 scripts/...`) — يطابق مسارات `/api/v1` في الفرونت مع OpenAPI (حرفيًا وفي قوالب مثل `` `${base}/api/v1/...` ``).
|
||||
|
||||
## 2. الخادم (API)
|
||||
|
||||
- [ ] تشغيل من **أحدث** كود في المستودع:
|
||||
`cd backend && py -m uvicorn app.main:app --host 0.0.0.0 --port 8000`
|
||||
`cd backend && python -m uvicorn app.main:app --host 0.0.0.0 --port 8000`
|
||||
(ويندوز: `py -3 -m uvicorn app.main:app --host 0.0.0.0 --port 8000`)
|
||||
- [ ] إذا ظهر **404** على `/api/v1/marketing/hub` أو `/api/v1/strategy/summary` فالعملية غالباً **قديمة** — أعد تشغيل `uvicorn` بعد `git pull`.
|
||||
- [ ] اختبار HTTP:
|
||||
`py scripts/full_stack_launch_test.py --http-only --soft-ready`
|
||||
أو:
|
||||
- [ ] اختبار HTTP (من مجلد `backend/`):
|
||||
`py -3 scripts/full_stack_launch_test.py --http-only --soft-ready`
|
||||
أو من جذر `salesflow-saas`:
|
||||
`.\scripts\grand_launch_verify.ps1 -HttpCheck -SoftReady`
|
||||
مع `DEALIX_BASE_URL` إذا لم يكن الـ API على `http://127.0.0.1:8000`.
|
||||
|
||||
|
||||
1
salesflow-saas/frontend/next-env.d.ts
vendored
1
salesflow-saas/frontend/next-env.d.ts
vendored
@ -1,5 +1,6 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
/// <reference path="./.next/types/routes.d.ts" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||
|
||||
@ -16,7 +16,7 @@ export default defineConfig({
|
||||
webServer: {
|
||||
command: "node .next/standalone/server.js",
|
||||
url: "http://127.0.0.1:3000",
|
||||
timeout: 120_000,
|
||||
timeout: 180_000,
|
||||
reuseExistingServer: !process.env.CI,
|
||||
},
|
||||
});
|
||||
|
||||
7
salesflow-saas/scripts/kill-port-3000.ps1
Normal file
7
salesflow-saas/scripts/kill-port-3000.ps1
Normal file
@ -0,0 +1,7 @@
|
||||
# Stops processes listening on TCP port 3000 (fixes Playwright webServer "port already in use").
|
||||
# Run from salesflow-saas: .\scripts\kill-port-3000.ps1
|
||||
$ErrorActionPreference = "SilentlyContinue"
|
||||
Get-NetTCPConnection -LocalPort 3000 -ErrorAction SilentlyContinue | ForEach-Object {
|
||||
Stop-Process -Id $_.OwningProcess -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
Write-Host "Port 3000 cleared (if anything was listening)." -ForegroundColor DarkGray
|
||||
@ -1,10 +1,14 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Scan frontend/src for literal /api/v1/... path strings and verify exact matches
|
||||
Scan frontend/src for /api/v1/... path strings and verify exact matches
|
||||
against the FastAPI OpenAPI schema.
|
||||
|
||||
Detects:
|
||||
- Quoted literals: '/api/v1/foo', "/api/v1/foo", `/api/v1/foo`
|
||||
- Template tails after ${...}: `${base}/api/v1/foo` (query string stripped)
|
||||
|
||||
Run from anywhere:
|
||||
py salesflow-saas/scripts/verify_frontend_openapi_paths.py
|
||||
py -3 salesflow-saas/scripts/verify_frontend_openapi_paths.py
|
||||
|
||||
Requires backend deps on PYTHONPATH (run after: cd salesflow-saas/backend && py -m pip install -r requirements.txt).
|
||||
"""
|
||||
@ -15,6 +19,10 @@ import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Paths that appear in the frontend but use OpenAPI path parameters ({id}, etc.)
|
||||
# or are intentionally not registered as separate operations — extend only with a comment.
|
||||
OPENAPI_PATH_ALLOWLIST: frozenset[str] = frozenset()
|
||||
|
||||
|
||||
def main() -> int:
|
||||
saas = Path(__file__).resolve().parent.parent
|
||||
@ -31,30 +39,37 @@ def main() -> int:
|
||||
schema = app.openapi()
|
||||
open_paths = {p.rstrip("/") or "/" for p in schema.get("paths", {}).keys()}
|
||||
|
||||
# Literal path segments in quotes or template strings (no ${...} inside path)
|
||||
pat = re.compile(r"""['"`]((/api/v1/[a-zA-Z0-9_\-./]+))['"`]""")
|
||||
quoted = re.compile(r"""['"`]((/api/v1/[a-zA-Z0-9_\-./]+))['"`]""")
|
||||
after_subst = re.compile(r"\$\{[^}]+\}(/api/v1/[a-zA-Z0-9_\-./]+)")
|
||||
|
||||
found: set[str] = set()
|
||||
for p in fe_src.rglob("*"):
|
||||
if p.suffix not in (".ts", ".tsx"):
|
||||
continue
|
||||
text = p.read_text(encoding="utf-8", errors="ignore")
|
||||
for m in pat.finditer(text):
|
||||
raw = m.group(1).rstrip("/")
|
||||
if "${" in raw or "{" in raw:
|
||||
continue
|
||||
for pat in (quoted,):
|
||||
for m in pat.finditer(text):
|
||||
raw = m.group(1).split("?")[0].rstrip("/")
|
||||
if "${" in raw or "{" in raw:
|
||||
continue
|
||||
if raw.endswith("/api/v1"):
|
||||
continue
|
||||
found.add(raw)
|
||||
for m in after_subst.finditer(text):
|
||||
raw = m.group(1).split("?")[0].rstrip("/")
|
||||
if raw.endswith("/api/v1"):
|
||||
continue
|
||||
found.add(raw)
|
||||
|
||||
missing = sorted(p for p in found if p not in open_paths)
|
||||
missing = sorted(p for p in found if p not in open_paths and p not in OPENAPI_PATH_ALLOWLIST)
|
||||
if missing:
|
||||
print("Frontend literal paths not found as exact OpenAPI paths (may use path params or be dynamic):")
|
||||
print("Frontend paths not found as exact OpenAPI paths (may use path params or be dynamic):")
|
||||
for m in missing:
|
||||
print(f" - {m}")
|
||||
print("\nTip: paths with {{id}} in OpenAPI need manual review.")
|
||||
print("\nTip: paths with {id} in OpenAPI need allowlisting or a manual mapping.")
|
||||
return 1
|
||||
|
||||
print(f"OK: {len(found)} literal /api/v1 paths match OpenAPI.")
|
||||
print(f"OK: {len(found)} /api/v1 paths in frontend match OpenAPI.")
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user