الوثائقJavaScript الواجهات الخلفية
من إليسيا إلى Nexy
في Nexy، يتحول مسار Elysia إلى ملف Python ضمن src/routes/: تصبح مخططات t.Object نماذج Pydantic، ويصبح .group مجلدًا، و beforeHandle إلى dependencies.py، ويصبح عميل Eden المكتوب إجراءات مكتوبة.
يعرض كل قسم أدناه عادة إليسيا، ثم نفس الشيء في Nexy.
طريق
import { Elysia } from "elysia"; new Elysia().get("/api/hello", () => ({ message: "Hello" })).listen(3000);مسار الملف هو عنوان URL، واسم الوظيفة هو الطريقة:
async def GET(): return {"message": "Hello"}المعلمات والاستعلام مع t
import { Elysia, t } from "elysia"; new Elysia().get("/api/users/:id", ({ params, query }) => ({ id: params.id, fields: query.fields }), { params: t.Object({ id: t.Numeric() }), query: t.Object({ fields: t.Optional(t.String()) }),});تنتقل الأنواع إلى المعلمات، و :id هو مقطع [id]:
async def GET(id: int, fields: str | None = None): return {"id": id, "fields": fields}جسم به t.Object
app.post("/api/items", ({ body, set }) => { set.status = 201; return body;}, { body: t.Object({ name: t.String(), price: t.Number({ exclusiveMinimum: 0 }) }),});from pydantic import BaseModel, Field from nexy.http import JSONResponse class NewItem(BaseModel): name: str price: float = Field(gt=0) async def POST(item: NewItem): return JSONResponse(item.model_dump(), status_code=201)response المخططات
app.get("/api/me", () => ({ name: "Ada" }), { response: t.Object({ name: t.String() }),});نوع الإرجاع هو مخطط الاستجابة: يتم ترك الحقول غير المعلنة خارج الإجابة.
from pydantic import BaseModel class PublicUser(BaseModel): name: str async def GET() -> PublicUser: return {"name": "Ada", "password_hash": "x"}.group
app.group("/admin", (admin) => admin.get("/stats", () => ({ users: 3 })));المجلد هو المجموعة:
async def GET(): return {"users": 3}beforeHandle و guard
app.group("/admin", (admin) => admin .guard({ beforeHandle({ headers, error }) { if (headers["x-role"] !== "admin") return error(403, "Admins only"); }, }) .get("/stats", () => ({ users: 3 })),);A dependencies.py يحرس كل مسار لمجلده:
from nexy.http import Header, HTTPException def require_admin(x_role: str = Header("")) -> None: if x_role != "admin": raise HTTPException(status_code=403, detail="Admins only") dependencies = [require_admin]derive، decorate و state
app .derive(({ headers }) => ({ token: headers.authorization?.replace("Bearer ", "") })) .get("/api/whoami", ({ token }) => ({ token }));ما يضيفه derive إلى السياق هو التبعية التي يطلبها المعالج:
from nexy.http import Depends, Header def token(authorization: str = Header("")) -> str: return authorization.removeprefix("Bearer ") async def GET(token: str = Depends(token)): return {"token": token}decorate و state عبارة عن كائنات عادية على مستوى الوحدة النمطية، يتم استيرادها عند الحاجة إليها.
onAfterHandle و mapResponse
app.onAfterHandle(({ set }) => { set.headers["x-app"] = "demo";});from nexy.http import Request async def middleware(request: Request, call_next): response = await call_next(request) response.headers["x-app"] = "demo" return responseerror() و onError
app.get("/api/orders/:id", ({ params, error }) => { if (Number(params.id) > 100) return error(404, "No such order"); return { id: params.id };});from nexy.http import HTTPException async def GET(id: int): if id > 100: raise HTTPException(status_code=404, detail="No such order") return {"id": id}A notfound.nexy في المسارات يجيب الجذر على المتصفحات الموجودة على عنوان URL غير معروف.
ملفات تعريف الارتباط
app.get("/api/theme", ({ cookie: { theme } }) => ({ theme: theme.value ?? "light" }));from nexy.http import Cookie async def GET(theme: str = Cookie("light")): return {"theme": theme}معاهدة عدن
const app = new Elysia().post("/todos", ({ body }) => ({ title: body.title, done: false }), { body: t.Object({ title: t.String() }),}); export type App = typeof app;import { treaty } from "@elysiajs/eden";import type { App } from "./src/index"; const api = treaty<App>("localhost:3000");const { data } = await api.todos.post({ title: "Write the docs" });الإجراء هو الدالة Python وعميلها المكتوب في وقت واحد. يقوم Nexy بإنشاء أنواع TypeScript من التوقيع Python:
from pydantic import BaseModel from nexy.decorators import Action class Todo(BaseModel): title: str done: bool = False @Actionasync def add_todo(title: str) -> Todo: return Todo(title=title)
import { useAction } from "@nexy/client";import { add_todo } from "@nexy/actions"; export function AddTodo() { const { run, pending, data } = useAction(add_todo); return ( <button disabled={pending} onClick={() => run({ title: "Write the docs" })}> {data ? `Added ${data.title}` : "Add"} </button> );}انظر الإجراءات.
الإضافات: cors، swagger، static
import { cors } from "@elysiajs/cors";import { staticPlugin } from "@elysiajs/static";import { swagger } from "@elysiajs/swagger"; app.use(cors({ origin: "https://example.com" })).use(swagger()).use(staticPlugin());| إليسيا البرنامج المساعد | نكسي |
|---|---|
@elysiajs/cors |
useCORS = {"allow_origins": [...]} في nexyconfig.py |
@elysiajs/swagger |
لا شيء: /docs قيد التشغيل افتراضيًا |
@elysiajs/static |
لا شيء: public/ يتم تقديمه في / |
from nexy.core.models import NexyConfigModel class NexyConfig(NexyConfigModel): useCORS = {"allow_origins": ["https://example.com"]}WebSockets
app.ws("/ws/echo", { message(ws, message) { ws.send(message); },});from fastapi import WebSocket async def SOCKET(websocket: WebSocket): await websocket.accept() await websocket.send_text(await websocket.receive_text())الاختبارات مع app.handle
import { describe, expect, it } from "bun:test"; it("says hello", async () => { const response = await app.handle(new Request("http://localhost/api/hello")); expect(await response.json()).toEqual({ message: "Hello" });});from fastapi.testclient import TestClient from nexy.app import app def test_hello(): assert TestClient(app).get("/api/hello").json() == {"message": "Hello"}الجري
| إليسيا | نكسي |
|---|---|
bun create elysia app |
nx new |
bun dev |
nx dev |
bun build --compile |
nx build، ثم nx start |
bun test |
nx test |
يعمل نيكسي على Python. تكون العقدة مطلوبة فقط عندما يحتوي المشروع على مكونات العميل: Vite يبنيها، ويعمل nx start بدونها.