दस्तावेज़फॉर्म और डेटा
क्रियाएँ
एक @Action एक Python फ़ंक्शन को POST समापन बिंदु में बदल देता है। एक मानक एपीआई हैंडलर के विपरीत, इसे एक टाइप किए गए संचार ब्रिज के रूप में डिज़ाइन किया गया है: नेक्सी स्वचालित रूप से TypeScript क्लाइंट उत्पन्न करता है, इनपुट को मान्य करता है, और प्रतिक्रिया को संभालता है।
शुरू करने से पहले: त्वरित शुरुआत द्वारा बनाया गया एक प्रोजेक्ट। क्रियाएँ पृष्ठों के बगल में, src/actions/ में रहती हैं।
Client (UI) ─── 1. Call (Typed Input) ───► [ Nexy Bridge ]
│
▼
2. Validate & Execute (Python)
│
▼
Client (UI) ◄─── 5. Consume (Typed Result) ◄── 4. Serialize ◄── 3. Resultक्रिया चक्र
1. परिभाषित करें
एक क्रिया एक सामान्य Python फ़ंक्शन है जिसे @Action से चिह्नित किया जाता है। एपीआई अनुबंध को परिभाषित करने के लिए नेक्सी अपने हस्ताक्षर का उपयोग करता है।
from pydantic import BaseModelfrom nexy.decorators import Action, revalidate class User(BaseModel): name: str age: int = 0 @Actionasync def create_user(name: str, age: int = 0) -> User: revalidate() return User(name=name, age=age)पैरामीटर इनपुट हैं, जो Pydantic द्वारा मान्य हैं। request या response नाम का एक पैरामीटर इंजेक्ट किया गया है और यह इनपुट का हिस्सा नहीं है।
2. मान्य करें
जब कार्रवाई को कॉल किया जाता है, तो नेक्सी फ़ंक्शन के प्रकार संकेतों के विरुद्ध इनपुट को मान्य करता है। यदि कोई फ़ील्ड गुम है या उसका प्रकार गलत है, तो कार्रवाई निष्पादित नहीं होती है, और एक 422 Unprocessable Entity वापस आ जाता है।
3. निष्पादित करना
तर्क सर्वर पर चलता है. चूँकि यह एक मानक Python फ़ंक्शन है, आप किसी भी लाइब्रेरी का उपयोग कर सकते हैं, डेटाबेस तक पहुंच सकते हैं, या अन्य सेवाओं को कॉल कर सकते हैं। आप revalidate() का उपयोग करके पेज रिफ्रेश को भी ट्रिगर कर सकते हैं।
4. क्रमबद्ध करें
रिटर्न मान स्वचालित रूप से JSON पर क्रमबद्ध होता है। Pydantic मॉडल को मूल रूप से नियंत्रित किया जाता है, और मानक Python प्रकारों को उनके JSON समकक्षों में मैप किया जाता है।
5. उपभोग करें
फ्रंटएंड को पूर्ण प्रकार की सुरक्षा के साथ परिणाम प्राप्त होता है। नेक्सी आपके हस्ताक्षरों से __nexy__/src/actions.ts लिखता है, और @nexy/actions उसका समाधान करता है।
import { useAction } from "@nexy/client";import { create_user } from "@nexy/actions"; export default function NewUser() { const { run, pending, error, data } = useAction(create_user); return ( <button disabled={pending} onClick={() => run({ name: "Ada" })}> {error ? error.message : data ? `Created ${data.name}` : "Create"} </button> );}घटक उस दृश्य का एक द्वीप है जिसे नियंत्रक लौटाता है:
import { useAction } from "@nexy/client";import { create_user } from "@nexy/actions"; export function NewUser() { const { run, pending, error, data } = useAction(create_user); return ( <button disabled={pending} onClick={() => run({ name: "Ada" })}> {error ? error.message : data ? `Created ${data.name}` : "Create"} </button> );}from "@/components/NewUser.tsx" import NewUser<NewUser directive="client:load" />हुक के बिना, एक क्रिया केवल एक async फ़ंक्शन है: const user = await create_user({ name: "Ada" })।
| ढाँचा | क्या useAction लौटता है |
|---|---|
| React, Preact | { pending, data, error, run, reset } |
| Solid | वही, pending(), data() और error() के साथ एक्सेसर्स के रूप में |
| Vue | वही, pending, data और error के साथ संदर्भ के रूप में |
| Svelte | एक दुकान: $save.pending, $save.data, $save.error, प्लस save.run(input) और save.reset() |
useAction(action, { onSuccess, onError }) भी दो कॉलबैक लेता है। run कभी नहीं फेंकता: एक विफलता error में आती है और run undefined के साथ हल हो जाती है।
प्रकार Python से आते हैं: str string है, int और float हैं number, list[T] है T[], एक Pydantic मॉडल या Enum एक नामित प्रकार है, और डिफ़ॉल्ट वाला फ़ील्ड इनपुट में वैकल्पिक है। एक प्रकार Pydantic जिसका वर्णन नहीं किया जा सकता वह unknown बन जाता है।
त्रुटियाँ और असफलताएँ
कोई कार्रवाई विभिन्न चरणों में विफल हो सकती है. आपको अपने यूआई में उनके बीच अंतर करना चाहिए:
- सत्यापन त्रुटियाँ (422): इनपुट Python हस्ताक्षर से मेल नहीं खाता।
error.fieldsप्रत्येक अमान्य फ़ील्ड को उसके संदेश में मैप करता है। - व्यावसायिक त्रुटियाँ (
HTTPException): आपके कोड ने कॉल अस्वीकार कर दी, उदाहरण के लिए403 Forbiddenया409 Conflict। - सर्वर त्रुटियाँ (500): आपके Python कोड में एक हैंडल न किया गया अपवाद उत्पन्न हुआ।
- नेटवर्क त्रुटियाँ: अनुरोध सर्वर तक कभी नहीं पहुंचा, उदाहरण के लिए टाइमआउट या खोया हुआ कनेक्शन।
- प्राधिकरण त्रुटियाँ (401, 403): आपके स्वयं के चेक ने कॉल करने वाले को अस्वीकार कर दिया। नेक्सी आपके लिए यह निर्णय नहीं लेता.
नीचे वर्णित मूल जांच एक सीएसआरएफ सुरक्षा है, प्राधिकरण नहीं: यह बताता है कि कॉल कहां से आई है, यह नहीं बताता कि इसे करने की अनुमति किसे है।
किसी कार्रवाई के बाद पृष्ठ को ताज़ा करें
एक क्रिया बताती है कि उसके परिवर्तन से कौन से पृष्ठ पुराने हो गए हैं, जैसा कि Next.js revalidatePath के साथ होता है:
revalidate() # the page that is openrevalidate("/users") # that page, if it is the one open
उत्तर में पथों को x-nexy-revalidate हेडर में दर्शाया गया है। क्लाइंट फिर राउटर के माध्यम से वर्तमान पृष्ठ को पुनः प्राप्त करता है, या क्लाइंट राउटर न होने पर इसे पुनः लोड करता है।
बिना प्रपत्र JavaScript
एक क्रिया एक मानक HTML फॉर्म भी लेती है, इसलिए पेज किसी भी स्क्रिप्ट के लोड होने से पहले काम करता है:
<form method="post" action="{{ __actions_path['create_user'] }}"> <input name="name"> <button type="submit">Create</button></form>
.nexy टेम्पलेट में __actions_path["name"] पथ है, __actions["name"] फ़ंक्शन है, और फ़ंक्शन भी अपने नाम के तहत दायरे में है।
सफलता पर, विज़िटर को स्थिति 303 के साथ उस पृष्ठ पर वापस भेज दिया जाता है जिस पर फ़ॉर्म था। अलग-अलग उत्तर देने के लिए, एक Response ऑब्जेक्ट लौटाएँ (उदाहरण के लिए, RedirectResponse("/done", status_code=303))।
application/x-www-form-urlencoded के रूप में भेजे गए फॉर्म को, जो ब्राउज़र डिफ़ॉल्ट रूप से करता है, किसी अतिरिक्त पैकेज की आवश्यकता नहीं है। enctype="multipart/form-data" जोड़ें और कॉल की आवश्यकता है python-multipart: इसके बिना कार्रवाई 500 को कमांड नाम देने वाले संदेश के साथ उत्तर देती है, uv add python-multipart।
एक क्रिया फ़ील्ड्स को पढ़ती है, फ़ाइलों को नहीं: एक फ़ाइल इनपुट एक स्ट्रिंग के रूप में उस तक पहुंचता है। अपलोड प्राप्त करने के लिए, src/routes/api/ में File या UploadFile पैरामीटर के साथ एक रूट लिखें।
सुरक्षा
पथ अस्पष्टता प्राधिकरण नहीं है
क्रिया पथ /_nx_ है जिसके बाद फ़ंक्शन के मॉड्यूल का हैश, उसका नाम और प्रोजेक्ट का रहस्य आता है। इसे NEXY_ACTION_SECRET द्वारा सेट किया जाता है, या __nexy__/action.key में रखा जाता है, जो nx build बनाता है ताकि क्लाइंट बंडल और nx start सहमत हों: उस फ़ाइल को बिल्ड के साथ रखें। पथ आकस्मिक खोज से समापन बिंदु को छुपाता है, और उत्पन्न पथ एक प्राधिकरण तंत्र नहीं है।
जो कोई भी रास्ता जानता है वह कार्रवाई को बुला सकता है। आप **** कार्रवाई के अंदर उपयोगकर्ता की पहचान और अनुमतियों को सत्यापित करना होगा:
@Actionasync def delete_user(user_id: str, request: Request): if not request.state.user.is_admin: raise HTTPException(403, "Admin rights required") # ...
मूल सुरक्षा
क्रॉस-साइट अनुरोध जालसाजी (सीएसआरएफ) को रोकने के लिए, नेक्सी उन अनुरोधों को अस्वीकार कर देता है जिनकी Origin कोई अन्य साइट है या ब्राउज़र Sec-Fetch-Site: cross-site को 403 से चिह्नित करता है। NEXY_ALLOWED_ORIGINS में उन साइटों की सूची बनाएं जो आपके कार्यों का कारण बन सकती हैं। Origin (जैसे curl) के बिना कॉल स्वीकार की जाती हैं।
आयात त्रुटियाँ
स्टार्टअप पर नेक्सी क्रियाओं को खोजने के लिए src/ के प्रत्येक मॉड्यूल को आयात करता है। एक मॉड्यूल जो आयात करने में विफल रहता है, उसकी सूचना दी जाती है, और अन्य अभी भी लोड होते हैं:
x src.actions.billing: src/actions/billing.py:3 ModuleNotFoundError: No module named 'stripe'