Statement कैटलॉग
statements array का हर element एक statement है। यह दस्तावेज़ सभी 25 statement प्रकारों के field, व्यवहार और परिणाम को सूचीबद्ध करता है। हर मान वाली जगह मान अभिव्यक्ति के नियमों (reference, literal, JsonLogic, locale map) का पालन करती है (अपवाद दो हैं: Regex का pattern और Cache की key। Regex और Cache देखें)।
Statement सारांश
| श्रेणी | type | एक-पंक्ति सारांश |
|---|---|---|
| संसाधन लेखन | ResourceCreate | Content/Media बनाना (वैकल्पिक रूप से publish) |
ResourceUpdate | Content/Media के field का पूर्ण प्रतिस्थापन (न दिए गए field/locale हट जाते हैं) | |
ResourcePatch | Content/Media के field का आंशिक मर्ज (केवल निर्दिष्ट field/locale; literal null हटाता है) | |
ResourceDelete | हटाना (केवल Draft/Archived; Published हो तो पहले unpublish) | |
ResourcePublish / ResourceUnpublish | publish / unpublish | |
ResourceArchive / ResourceUnarchive | archive / unarchive | |
| संसाधन पठन | ResourceRead | id से एकल आइटम पठन |
ResourceFind | filter से पहला मेल खाता एकल आइटम (न हो तो null) | |
ResourceForEach | filter से मेल खाते संसाधनों को आंतरिक रूप से पुनरावृत्त करते हुए हर आइटम पर onEach चलाना | |
ResourceCount | filter से मेल खाती केवल गिनती करना (आइटम नहीं पढ़े जाते) | |
| बाहरी | Http | बाहरी HTTP कॉल ({ status, body }) |
EmailSend | पंजीकृत EmailAccount से 1 मेल भेजना | |
| वेरिएबल | SetVar | script-scoped वेरिएबल घोषित/अपडेट करना |
| कैश | Cache | उसी Script के अपने, थोड़ी देर जीने वाले कैश को पढ़ना/लिखना/हटाना |
| मान पार्सिंग | ParseJson | JSON टेक्स्ट को मान (ऑब्जेक्ट·array·स्केलर) में पार्स करके बाइंड करना |
| हस्ताक्षर और टेक्स्ट | Signature | प्राप्त हस्ताक्षर कोड गुप्त key से बने कोड के समान है या नहीं, इसका सत्यापन (Boolean) |
Hash | बिना key वाले डाइजेस्ट की गणना (string) | |
Regex | regex लागू करना। मिलान हुआ या नहीं (Boolean), या capture group (array) | |
| नियंत्रण प्रवाह | If | शर्तीय शाखा |
Loop | पुनरावृत्ति (foreach / while / counted) | |
Parallel | शाखाओं को समवर्ती रूप से चलाना | |
Return | परिणाम लौटाना और जल्दी समाप्त होना | |
Try | अपवाद प्रबंधन (catch/finally) |
जो Content statement अपना लक्ष्य id से निर्दिष्ट नहीं करते, वे जिस Content Type को संभालते हैं उसे लिखना अनिवार्य है।
ResourceFind·ResourceForEach·ResourceCountमेंresource"Content"हो, तोcontentTypeअनिवार्य है। पूरे Space में आर-पार जाने वाली Content क्वेरी नहीं होती।ResourceCreateभी जिस Content Type को बनाना है उसे लिखता है। Media पूरे Space के लिए एक ही समुच्चय है, इसलिए वह कोई दायरा नहीं लेता, और जो statement अपना लक्ष्य id से निर्दिष्ट करते हैं (ResourceRead·ResourceUpdate·ResourcePatch·ResourceDeleteतथा publish एवं archive statements) उनमेंtargetहोता है, इसलिए उन्हें दायरे की आवश्यकता नहीं होती।
चक्रीय कॉल अधिकतम 3 बार। ऊपर दिए गए संसाधन-राइट statement (
ResourceCreate,ResourceUpdate,ResourcePublishआदि) मेंpropagateEventsचालू करने पर (डिफ़ॉल्ट मान बंद है) वे परिवर्तन इवेंट उत्पन्न करते हैं, और वे इवेंट Webhook के माध्यम से फिर से किसी Script को चला सकते हैं। ऐसी श्रृंखला (Script → इवेंट → Webhook → Script → …) अधिकतम 3 बार तक ही चलती है, उसके बाद प्लेटफ़ॉर्म इसे अपने-आप रोक देता है ताकि अनंत लूप न बनें।
साझा field
{ "type": "<StatementType>", "name": "<वैकल्पिक, script में अद्वितीय>", /* ...type-विशिष्ट field... */ }type: विभेदक (discriminator)। ऊपर दी गई तालिका के मानों में से एक (अनिवार्य)।name: वैकल्पिक। सेट करने पर परिणाम/<name>पर context में bind हो जाता है, जिससे बाद के statements उसे{ /<name>/... }के रूप में संदर्भित कर सकते हैं। यदि परिणाम का उपयोग नहीं करना है तो इसे छोड़ दें।- बाइंडिंग नाम नियम:
namecontext रूट पर सीधे रखी जाने वाली key है, इसलिए इसे सहेजते समय सत्यापित किया जाता है। इसमें केवल अंग्रेज़ी अक्षर, अंक,_और-ही आ सकते हैं (इसे JSON Pointer key के रूप में उपयोग किया जाना है, इसलिए इसके अलावा कोई भी वर्ण या खाली नाम अस्वीकृत होता है), यह किसी reserved रूट (payload·rawPayload·headers·vars·error·now) के समान नहीं हो सकती, और एक Script के भीतर अद्वितीय होनी चाहिए। प्रारूप का उल्लंघन, reserved शब्द का उपयोग, या डुप्लिकेट होने पर सहेजना अस्वीकृत हो जाता है।
एंटिटी reference आकार
contentType और target जैसे एंटिटी reference एक ही आकार { "sys": { "id": <मान अभिव्यक्ति> } } में एकीकृत होते हैं। केवल sys.id चाहिए, और लक्ष्य type resource से अनुमानित होता है (sys.type और sys.targetType छोड़ दिए जाते हैं)।
contentType.sys.idआमतौर पर एक literal होता है (उदाहरण:"ct_post")।target.sys.idआमतौर पर एक{ /ptr }मान अभिव्यक्ति होता है (runtime पर resolve; उदाहरण:{ /payload/sys/id })।
resource
संसाधन-परिवार के statements लक्ष्य प्रकार को resource: "Content" | "ContentType" | "Media" | "ServiceUser" से निर्दिष्ट करते हैं।
Content Type को केवल ResourceCount स्वीकार करता है। इसे किसी अन्य statement में लिखने पर सहेजना अस्वीकृत हो जाता है। ढाँचे को स्वयं बनाने या बदलने का काम Script का नहीं, बल्कि CMA का है।
ServiceUser (उत्पाद में साइन अप किया हुआ सदस्य) केवल पठनीय है। पठन के तीन statements (ResourceRead·ResourceFind·ResourceForEach) ही यह मान लेते हैं, और किसी write statement में इसे लिखने पर सहेजना अस्वीकृत हो जाता है (त्रुटियाँ देखें)। नियम सदस्य डायरेक्टरी का पठन में दिए गए हैं।
संसाधन लेखन
हर write statement में propagateEvents (डिफ़ॉल्ट false) होता है। इसे true करने पर वह write एक परिवर्तन इवेंट उत्पन्न करता है, जिससे Webhook जैसी बाद की क्रियाएँ चलती हैं। डिफ़ॉल्ट रूप से यह उत्पन्न नहीं करता (एक शांत system write)।
ResourceCreate
Content या Media बनाता है। Content और Media fields मॉडल साझा करते हैं, और मान locale map होते हैं।
| field | दायरा | विवरण |
|---|---|---|
resource | साझा | "Content" या "Media" (अनिवार्य) |
contentType | Content | बनाया जाने वाला Content Type ({ sys: { id } })। Content होने पर अनिवार्य |
fields | साझा | field map { "<field>": { "<locale>": मान } }। हर populate किए गए field के लिए डिफ़ॉल्ट locale bucket अनिवार्य। Content की keys Content Type की परिभाषा का पालन करती हैं, और Media की keys तय हैं (title·description·file) |
locale | साझा | (सुविधा) देने पर fields के हर मान को { <locale>: मान } के रूप में स्वतः wrap कर देता है |
publish | साझा | write के बाद publish (CDA/ACDA पर दिखता है)। डिफ़ॉल्ट true |
Mediafile:fields.file.{locale}का मान एक ingest निर्देश{ "source": <मान अभिव्यक्ति>, "encoding": "url"|"base64" }होता है (दोनों अनिवार्य)। फ़ाइल शामिल करने वाले write में ingest engine करता है (urlहो तो डाउनलोड, औरbase64हो तो डिकोड करने के बाद अपलोड और प्रोसेस)। यह ingest कोई समय घोषित नहीं करता, इसलिए यह 30 सेकंड के मूल बजट से जाता है (समय बजट), और बाहरी कॉल की सीमा में नहीं गिना जाता। फ़ाइल-रहित (fileless) Media भी बनाया जा सकता है। यदिpublish:trueहै पर फ़ाइल नहीं है या processing अधूरी है, तो publish चरण में error आता है; औरpublish:falseहो तो यहDraftही रहता है।- परिणाम (
namebinding): बनाया गया संसाधन।{ /<name>/sys/id },{ /<name>/fields/<field>/<locale> }।
// Content
{ "type": "ResourceCreate", "resource": "Content", "contentType": { "sys": { "id": "ct_post" } },
"fields": { "title": { "en-US": "{ /payload/fields/title }" } }, "publish": true, "name": "post" }
// Media. file एक ingest निर्देश है
{ "type": "ResourceCreate", "resource": "Media",
"fields": {
"title": { "en-US": "{ /payload/fields/prompt }" },
"file": { "en-US": { "source": "{ /gen/body/data/0/url }", "encoding": "url" } }
}, "name": "img" }ResourceUpdate
लक्ष्य Content या Media के field को पूरी तरह प्रतिस्थापित करता है (PUT)। fields में जो दिया जाता है वही नया field-सेट बन जाता है, और यहाँ मौजूद न होने वाला हर field और locale हटा दिया जाता है। केवल कुछ हिस्सा बदलने के लिए ResourcePatch का उपयोग करें।
| field | विवरण |
|---|---|
resource | "Content" या "Media" |
target | लक्ष्य ({ sys: { id } }, अनिवार्य)। id आमतौर पर { /ptr } होता है |
fields | लिखे जाने वाले सभी field। मान locale map होते हैं। चूँकि यह पूर्ण प्रतिस्थापन है, यहाँ मौजूद न होने वाला हर field और locale हटा दिया जाता है। Media के लिए file एक ingest निर्देश है (ऊपर ResourceCreate देखें)। सूचीबद्ध फ़ाइलें हमेशा पुनः ingest होती हैं, और जिन locales की फ़ाइल नहीं दी गई उन्हें हटा दिया जाता है |
locale | (सुविधा) fields को स्वतः wrap करता है |
version | (वैकल्पिक) मान अभिव्यक्ति (Int)। optimistic locking। देने पर, यह update केवल तभी चलता है जब यह लक्ष्य के वर्तमान sys.version से मेल खाता हो; मेल न खाने पर यह version-conflict error के साथ abort कर देता है (Try से catch किया जा सकता है)। छोड़ने पर कोई जाँच नहीं होती (last-write-wins) |
publish | update के बाद republish। डिफ़ॉल्ट true |
Media का केवल metadata बदलने के लिए Update का उपयोग करने पर file छूट जाता है और फ़ाइल पूरी तरह हट जाती है (क्योंकि यह पूर्ण प्रतिस्थापन है)। आंशिक बदलाव के लिए हमेशा ResourcePatch का उपयोग करें।
{ "type": "ResourceUpdate", "resource": "Content", "target": { "sys": { "id": "{ /payload/sys/id }" } },
"fields": { "title": { "en-US": "Hello", "ko-KR": "안녕" }, "status": { "en-US": "published" } } }ResourcePatch
लक्ष्य Content या Media के field को आंशिक रूप से मर्ज करता है (PATCH)। यह fields में दिए गए केवल उन्हीं field (और उनके भीतर के locale) को अधिलेखित करता है, और जिन field और locale का उल्लेख नहीं किया गया उन्हें ज्यों-का-त्यों रखता है। मान का आकार, locale, version और publish ResourceUpdate जैसे ही हैं।
| field | विवरण |
|---|---|
resource | "Content" या "Media" |
target | लक्ष्य ({ sys: { id } }, अनिवार्य)। id आमतौर पर { /ptr } होता है |
fields | अधिलेखित किए जाने वाले field। मान locale map होते हैं। केवल निर्दिष्ट field और locale bucket अपडेट होते हैं (बाकी बने रहते हैं)। यदि कोई मान literal null है, तो वह (field, locale) हट जाता है। Media के लिए file एक ingest निर्देश है (ऊपर ResourceCreate देखें) |
locale | (सुविधा) fields को स्वतः wrap करता है |
version | (वैकल्पिक) ResourceUpdate जैसा ही (optimistic locking) |
publish | update के बाद republish। डिफ़ॉल्ट true |
- किसी विशिष्ट locale या फ़ाइल को हटाना: मान के रूप में literal
nullदें। उदाहरण:"title": { "fr-FR": null }(fr-FR title हटाता है),"file": { "en-US": null }(en-US फ़ाइल हटाता है)। जो मान अभिव्यक्ति runtime पर null के रूप में मूल्यांकित होता है वह हटाना नहीं बल्कि एक error है (केवल literal null हटाता है)। - Media
fileको ingest निर्देश देने पर वह उस locale की फ़ाइल को प्रतिस्थापित कर देता है। यदि फ़ाइल नहीं दी जाती, तो वह बनी रहती है।
// केवल viewCount(en-US) को +1. title, अन्य locale आदि बाकी सब ज्यों-का-त्यों बने रहते हैं
{ "type": "ResourcePatch", "resource": "Content", "target": { "sys": { "id": "{ /payload/sys/id }" } },
"fields": { "viewCount": { "en-US": { "$+": [ "{ /payload/fields/viewCount }", 1 ] } } } }ResourceDelete
लक्ष्य को हटाता है। केवल Draft और Archived स्थिति को ही हटाया जा सकता है। Published या Changed होने पर delete अस्वीकृत होता है, इसलिए आपको पहले ResourceUnpublish करना होगा। Media की फ़ाइल की processing चल रही हो, तो delete अस्वीकृत हो जाता है। यह auto-unpublish नहीं करता (CMA/ACMA जैसा ही)।
| field | विवरण |
|---|---|
resource | "Content" या "Media" |
target | लक्ष्य ({ sys: { id } }, अनिवार्य) |
{ "type": "ResourceDelete", "resource": "Content", "target": { "sys": { "id": "{ /payload/sys/id }" } } }ResourcePublish, ResourceUnpublish, ResourceArchive, ResourceUnarchive
लक्ष्य की publish और archive स्थिति को स्वतंत्र रूप से नियंत्रित करता है। चारों के field एक समान हैं। हर कार्य की status पूर्वशर्त CMA/ACMA जैसी ही है। ResourcePublish, Archived से नहीं किया जा सकता और उसके लिए फ़ाइल की processing पूरी हो चुकी होनी चाहिए। ResourceUnpublish केवल Published·Changed से, ResourceArchive केवल Draft से, और ResourceUnarchive केवल Archived से किया जा सकता है।
| field | विवरण |
|---|---|
resource | "Content" या "Media" |
target | लक्ष्य ({ sys: { id } }, अनिवार्य) |
version | (वैकल्पिक) मान अभिव्यक्ति (Int)। optimistic locking। देने पर यह कार्य केवल तभी किया जाता है जब यह वर्तमान sys.version से मेल खाता हो |
{ "type": "ResourcePublish", "resource": "Content", "target": { "sys": { "id": "{ /payload/sys/id }" } } }
{ "type": "ResourceUnpublish", "resource": "Content", "target": { "sys": { "id": "{ /payload/sys/id }" } } }
{ "type": "ResourceArchive", "resource": "Media", "target": { "sys": { "id": "{ /m/sys/id }" } } }संसाधन पठन
ResourceRead और ResourceFind संसाधन पढ़कर मान में bind करते हैं, और ResourceCount केवल गिनती करता है। तीनों स्थिति को नहीं बदलते (propagateEvents नहीं होता)। ResourceForEach में भी क्वेरी स्वयं एक पठन है, पर यदि onEach में कोई संसाधन-राइट statement रखा जाए, तो हर आइटम पर वह write चलता है और स्थिति बदल जाती है।
चारों statements (ResourceRead·ResourceFind·ResourceForEach·ResourceCount) from (डिफ़ॉल्ट Current) से यह तय करते हैं कि कौन-सा संग्रहीत संस्करण पढ़ा जाए। Current वह नवीनतम draft है जिसे कंटेंट स्टूडियो देखता है (वह मान जो CMA/ACMA पढ़ता है), और Published वह publish स्नैपशॉट है (जो CDA/ACDA डिलीवर करता है, अर्थात अंतिम publish के समय का मान)। ServiceUser publish नहीं होता, इसलिए वह केवल Current लेता है (सदस्य डायरेक्टरी का पठन देखें)।
इसके अतिरिक्त, ResourceFind·ResourceForEach·ResourceCount advanced (डिफ़ॉल्ट true) से उन्नत खोज (Advanced Search) को चालू और बंद करते हैं। न लिखने पर यह चालू रहती है। यह केवल Content के लिए है, इसलिए Media और ServiceUser पठन में इसे अनदेखा कर दिया जाता है। चालू होने पर where में regex, near और within operators तथा फ़ुल-टेक्स्ट खोज का उपयोग किया जा सकता है (जिस LongText field में फ़ुल-टेक्स्ट खोज चालू है, वहाँ eq उस मान को समाहित करने वाले आइटम भी आंशिक एवं समरूप मिलान से ढूँढ लेता है), और order fields.* से sorting कर सकता है। बंद होने पर ये तीनों operators अस्वीकार कर दिए जाते हैं, text पर eq ठीक-ठीक मिलान होता है, और prefix तथा तुलना एवं सूची operators उन्नत खोज से निरपेक्ष रूप से काम करते हैं। अभी-अभी बनाया या बदला गया कोई आइटम उन्नत खोज में प्रतिबिंबित होने में थोड़ा समय (लगभग 1 सेकंड) लेता है, इसलिए ठीक उसके बाद चलने वाली उन्नत खोज query में वह छूट सकता है। डिफ़ॉल्ट रूप से यह चालू रहती है, इसलिए यह विलंब तब तक हर query पर लागू होता है जब तक advanced को false न रखा जाए। अभी-अभी लिखे गए किसी आइटम को तुरंत पढ़ने के लिए, id से ResourceRead (मुख्य संग्रह, प्रतिबिंबित होने में कोई विलंब नहीं) का उपयोग करें, या write द्वारा लौटाए गए sys.id से उसका पठन करें।
where का createdBy: ":self" का अर्थ है "केवल वही जो अभी कॉल करने वाले उपयोगकर्ता ने बनाया है"। पर जिस Script में अनाम कॉल की अनुमति है (anonymousCallEnabled), वहाँ इसका उपयोग नहीं किया जा सकता। उस स्थिति में :self कॉलर के बजाय लेखक पर हल होता है और चुपचाप लेखक के संसाधन खुल जाते हैं, इसलिए ऐसी परिभाषा सहेजने पर अस्वीकृत हो जाती है (अनाम कॉल देखें)।
where और order में कंटेंट field को fields.<field> के रूप में लिखा जाता है (अकेले नाम से यह पहचाना नहीं जाता)। fields.<field> पर Space की डिफ़ॉल्ट locale स्वतः लागू होती है, इसलिए locale सीधे नहीं जोड़ी जाती। नीचे दिए उदाहरणों के fields.status, fields.slug ज्यों-के-त्यों डिफ़ॉल्ट locale की क्वेरी हैं। किसी विशिष्ट (गैर-डिफ़ॉल्ट) locale की क्वेरी करने पर ही fields.<field>.<locale> (उदाहरण: fields.title.ko-KR) के रूप में स्पष्ट करें। sys.* (sys.createdAt आदि) और createdBy (:self) को fields. के बिना ज्यों-का-त्यों लिखें। विस्तृत नियम मान अभिव्यक्ति में where और order की locale में दिए गए हैं।
सदस्य डायरेक्टरी का पठन (ServiceUser)
ResourceRead·ResourceFind·ResourceForEach resource में "ServiceUser" लेकर उस Space की सदस्य डायरेक्टरी पढ़ते हैं (ResourceCount इसे नहीं लेता; नीचे ResourceCount देखें)। किसी ऑर्डर का स्वामी कौन है यह जाँचने, या ईमेल से सदस्य ढूँढकर उसकी sys.id अगले statement को देने वाले प्रवाह में इसका उपयोग करें। नीचे दिए नियम तीनों statements पर समान रूप से लागू होते हैं।
- केवल पठन होता है।
ResourceCreate·ResourceUpdate·ResourcePatch·ResourceDeleteतथा publish एवं archive statements"ServiceUser"नहीं लेते, और ऐसी परिभाषा सहेजते समय अस्वीकृत हो जाती है। यह कोई ऐसी चीज़ नहीं है जिसे अनुमति जोड़कर खोला जा सके; Script से सदस्य को बदलने का रास्ता ही नहीं है, इसलिए यह अनुमति की त्रुटि नहीं बल्कि गलत लिखे गए statement के रूप में अस्वीकृत होता है। - लेखक के पास सदस्य डायरेक्टरी की अनुमति हो, तभी सहेजा जाता है। Content और Media की तरह अनुमति map से जाँच नहीं होती, बल्कि यह देखा जाता है कि लेखक की SpaceRole के
settingsमेंSETTING_SERVICE_LOGIN(याSETTING_ALL) है या नहीं। कारण यह है कि सदस्य डायरेक्टरी बाकी सभी रास्तों पर भी Space सेटिंग के अधीन आने वाला संसाधन है। न होने पर सहेजना अस्वीकृत हो जाता है (सुरक्षा मॉडल देखें)। fromकेवलCurrentलेता है। सदस्य publish होने वाला संसाधन नहीं है, इसलिएPublishedदेने पर निष्पादन विफल हो जाता है।contentTypeऔरadvancedअनदेखा कर दिए जाते हैं। सदस्य डायरेक्टरी Content Type से नहीं बँटती (पूरे Space के लिए एक ही है), और उन्नत खोज भी केवल Content के लिए है।whereकाsys.emailकेवल ठीक-ठीक मिलान वाले operators लेता है (eq·ne·in·nin)। सदस्य का पता एन्क्रिप्ट होकर संग्रहीत होता है, इसलिए क्रम-तुलना याprefixका कोई अर्थ नहीं है। इनके अलावा कोई operator देने पर चुपचाप 0 परिणाम लौटाने के बजाय निष्पादन विफल हो जाता है।- परिणाम ServiceUser संसाधन स्वयं होता है। इसे
{ /<name>/sys/id }और{ /<name>/nickname }की तरह संदर्भित करें। इसकी संरचना ServiceUser संदर्भ में दी गई है। मिले हुए सदस्य को मेल भेजते समय पता निकालने के बजायEmailSendकेtoServiceUserमें उसकीsys.idदें (engine भेजने से ठीक पहले पते को resolve करता है, इसलिए सदस्य का पता Script के वेरिएबल स्थान में नहीं आता)।
// ईमेल से एक सदस्य ढूँढता है। न मिले तो null
{ "type": "ResourceFind", "resource": "ServiceUser",
"where": { "sys.email": { "eq": "{ /payload/fields/email }" } }, "name": "member" }ResourceRead
यह id से एकल आइटम पठन है (get-by-id)। परिणाम पूरे संसाधन को नाम में bind करता है।
| field | विवरण |
|---|---|
resource | "Content"·"Media"·"ServiceUser" |
target | लक्ष्य ({ sys: { id } })। id एक मान अभिव्यक्ति है |
from | (वैकल्पिक) Current (डिफ़ॉल्ट, नवीनतम draft) या Published (publish स्नैपशॉट)। ServiceUser के लिए केवल Current |
- परिणाम: bind संसाधन स्वयं होता है। इस statement को
nameदिया हो, तो उसे सीधे{ /<name>/sys/id }और{ /<name>/fields/<field>/<locale> }से संदर्भित करें (नीचे के उदाहरण में"name": "order"है, यानी{ /order/sys/id })। यह list नहीं है, इसलिए किसी array index से नहीं गुज़रना पड़ता। - यदि लक्ष्य मौजूद न हो तो error आता है। इसे संभालने के लिए
Tryमें लपेटा जा सकता है।
{ "type": "ResourceRead", "resource": "Content",
"target": { "sys": { "id": "{ /payload/fields/orderId }" } }, "name": "order" }ResourceFind
filter से पहला मेल खाता एकल आइटम पढ़ता है। कोई न हो तो null होता है। किसी अद्वितीय business key (slug, email, sku) से एक रिकॉर्ड ढूँढने के लिए इसका उपयोग करें।
| field | विवरण |
|---|---|
resource | "Content"·"Media"·"ServiceUser" |
contentType | खोज का दायरा Content Type ({ sys: { id } })। Content होने पर अनिवार्य। Media और ServiceUser में अनदेखा |
where | filter ({ "<field>": { "<op>": <मान> } })। उपलब्ध operators operator सूची के अनुसार हैं (regex/near/within के लिए advanced आवश्यक)। createdBy: ":self" समर्थित। ServiceUser का sys.email केवल eq·ne·in·nin लेता है (सदस्य डायरेक्टरी का पठन) |
order | कई मैच होने पर "पहला" तय करने वाला sort (उदाहरण: "-sys.createdAt") |
from | (वैकल्पिक) Current (डिफ़ॉल्ट, नवीनतम draft) या Published (publish स्नैपशॉट)। ServiceUser के लिए केवल Current |
advanced | (वैकल्पिक) उन्नत खोज (Advanced Search) से चलाएँ। केवल Content (Media और ServiceUser अनदेखा)। डिफ़ॉल्ट true। ऊपर संसाधन पठन टिप्पणी देखें। |
- परिणाम: पहले मेल खाते संसाधन को इस statement के
nameमें bind करता है। इसे सीधे{ /<name>/fields/<field>/<locale> }के रूप में संदर्भित करें। कोई न होने पर यहnullहोता है, इसलिए{ "==": [ "{ /<name> }", null ] }से अस्तित्व के आधार पर शाखा बनाएँ (find-then-upsert का आम pattern)।
{ "type": "ResourceFind", "resource": "Content", "contentType": { "sys": { "id": "ct_article" } },
"where": { "fields.slug": { "eq": "{ /payload/fields/slug }" } }, "name": "found" }ResourceForEach
filter से मेल खाते संसाधनों को आंतरिक रूप से पुनरावृत्त करते हुए हर आइटम पर onEach चलाता है। यह मान के रूप में उपयोग होने वाला कोई collection नहीं बनाता, बल्कि हर आइटम पर एक कार्य करने के लिए बना statement है। draft को थोक में publish करना, शर्त से मेल खाते Content को थोक में संशोधित करना, या हर आइटम को बाहर भेजना/सिंक करना जैसे दोहराए जाने वाले कार्यों में इसका उपयोग करें। केवल एक रिकॉर्ड पढ़ने के लिए ResourceRead (id) या ResourceFind (filter) का उपयोग करें।
| field | विवरण |
|---|---|
resource | "Content"·"Media"·"ServiceUser" (अनिवार्य) |
contentType | पुनरावृत्ति का दायरा Content Type ({ sys: { id } })। Content होने पर अनिवार्य। Media और ServiceUser में अनदेखा |
where | filter ({ "<field>": { "<op>": <मान> } })। अर्थ ResourceFind के where जैसा ही है (ServiceUser के sys.email की बाधा भी वही है)। उपलब्ध operators operator सूची के अनुसार हैं (regex/near/within के लिए advanced आवश्यक)। createdBy: ":self" समर्थित |
order | sort (उदाहरण: "sys.createdAt,sys.id")। न देने पर प्लेटफ़ॉर्म का डिफ़ॉल्ट क्रम |
from | Current (डिफ़ॉल्ट, नवीनतम draft) या Published (publish स्नैपशॉट)। ServiceUser के लिए केवल Current |
advanced | उन्नत खोज (Advanced Search) से पुनरावृत्ति। केवल Content (Media और ServiceUser अनदेखा)। डिफ़ॉल्ट true। ऊपर संसाधन पठन टिप्पणी देखें |
limit | (वैकल्पिक, 1 या अधिक) कुल संसाधित की जाने वाली संख्या की ऊपरी सीमा (यह page size नहीं है)। न देने पर प्लेटफ़ॉर्म सीमा (10,000 आइटम) तक पुनरावृत्ति |
name | (वैकल्पिक) वर्तमान आइटम को bind करने वाला नाम। हर पुनरावृत्ति पर यह नए सिरे से bind होता है और onEach के भीतर { /<name> } से संदर्भित होता है (Loop के name जैसा ही जीवनकाल; पुनरावृत्ति समाप्त होने के बाद भी अंतिम आइटम bound रहता है)। आइटम को संदर्भित न करने पर इसे छोड़ दें |
onEach | हर आइटम पर चलाने के लिए child statement array (अनिवार्य) |
- यह किसी collection को bind नहीं करता (
mapनहीं, बल्किforeach)। न{ items, next }होता है, न कोई cursor। पुनरावृत्ति का परिणाम मान के रूप में वापस नहीं मिलता, बल्कि हर आइटम परonEachचलता है। यदि सूची चाहिए, तोSetVarसे स्वयं इकट्ठा करें। यदि केवल गिनती चाहिए, तोResourceCountका उपयोग करें। limitन होने पर भी यह अनंत पुनरावृत्ति नहीं है। न देने पर यह प्लेटफ़ॉर्म सीमा (10,000 आइटम) तक चलता है, और मेल खाते आइटम शेष रहते हुए उस सीमा पर पहुँचने पर विफल हो जाता है (ताकि अछूते आइटम छोड़कर उसे सफलता के रूप में रिपोर्ट न किया जाए)। इसके विपरीत, घोषितlimitतक पहुँचना एक इच्छित विराम है, इसलिए यह सामान्य समाप्ति है। सीमा से अधिकlimitसहेजते समय अस्वीकृत कर दिया जाता है।- कोई cursor नहीं है। पूरा हो जाए तो सफलता, और बीच में रुक जाए (wall-clock/कोटा पार,
onEachकी अनसंभाली विफलता) तो विफलता, और error यह इंगित करता है कि किस आइटम पर और क्यों विफल हुआ। पुनरारंभ को लेखक अपने डेटा से व्यक्त करता है (whereको "असंसाधित" पर रखकर औरonEachके अंत में पूर्णता को चिह्नित करके, पुनः निष्पादन शेष आइटम से आगे बढ़ता है)। - समय बजट में यह गुणा के रूप में आता है। यह statement जो समय घोषित करता है वह
onEachद्वारा घोषित समय को संसाधित आइटम की संख्या (limit, न हो तो 10,000) से गुणा किया हुआ मान है (समय बजट)। चूँकि यह child रखने वाला एक composite statement है, यह स्वयं बाहरी कॉल leaf बजट में नहीं गिना जाता, बल्किonEachके भीतर के बाहरी कॉल statement बजट में गिने जाते हैं। onEachमें अन्य statement की तरह बाहरी कॉल (Http·EmailSend) या Media फ़ाइल ingest रखी जा सकती है (Loopकेbodyजैसा ही)। संसाधन क्वेरी के परिणाम को हर आइटम पर एक बार संसाधित करना ही इस statement के होने का कारण है।
// draft स्थिति वाली सभी पोस्ट ढूँढकर हर आइटम को publish करना
{ "type": "ResourceForEach", "resource": "Content", "contentType": { "sys": { "id": "ct_post" } },
"where": { "fields.status": { "eq": "draft" } }, "order": "sys.createdAt,sys.id",
"from": "Current", "advanced": false, "name": "post",
"onEach": [
{ "type": "ResourcePublish", "resource": "Content", "target": { "sys": { "id": "{ /post/sys/id }" } } }
] }ResourceCount
filter से मेल खाती केवल गिनती करता है। यह आइटम पढ़कर नहीं लाता, इसलिए जब सूची नहीं बल्कि संख्या चाहिए तब इसका उपयोग करें। बचा हुआ स्टॉक जाँचने, वही मान पहले से मौजूद है या नहीं यह तय करने, या सीमा पार हुई या नहीं यह जाँचने की जगह यही है।
| field | विवरण |
|---|---|
resource | "Content" या "ContentType" (अनिवार्य)। Media और ServiceUser गिने नहीं जा सकते, और ऐसा लिखने पर सहेजना अस्वीकृत हो जाता है |
contentType | गिनती का दायरा Content Type ({ sys: { id } })। Content होने पर अनिवार्य। Content Type गिनते समय अनदेखा (पूरे Space के लिए एक ही समुच्चय) |
where | filter। अर्थ ResourceFind के where जैसा ही है। मेल खाते सभी आइटम गिने जाते हैं |
from | (वैकल्पिक) Current (डिफ़ॉल्ट, नवीनतम draft) या Published (publish स्नैपशॉट) |
advanced | (वैकल्पिक) उन्नत खोज (Advanced Search) से चलाएँ। केवल Content (Content Type गिनते समय अनदेखा)। डिफ़ॉल्ट true। ऊपर संसाधन पठन टिप्पणी देखें |
name | (वैकल्पिक) गिनती को bind करने वाला नाम |
- परिणाम: मेल खाती गिनती को इस statement के
nameमें bind करता है। इसे{ /<name> }से संदर्भित करके तुलना और शाखा बनाने में उपयोग करें। - यह आइटम नहीं लौटाता। आइटम चाहिए तो
ResourceFind(पहला मेल खाता एकल आइटम) याResourceForEach(हर आइटम पर चलाना) का उपयोग करें। - गिनती पाने के लिए
ResourceForEachसे घूमते हुए मत गिनिए। पुनरावृत्ति समय बजट को आइटम की संख्या से गुणा करके लेती है (समय बजट), और मेल खाते आइटम शेष रहते हुए प्लेटफ़ॉर्म सीमा पर पहुँचने पर विफल हो जाती है। केवल गिनना हो, तो यह statement इसे एक ही बार में पूरा कर देता है। orderऔरlimitनहीं हैं। गिनने के लिए क्रम की आवश्यकता नहीं होती, और मेल खाते सभी आइटम गिने जाते हैं।
// इस पोस्ट पर कितनी टिप्पणियाँ आई हैं, यह गिनता है
{ "type": "ResourceCount", "resource": "Content", "contentType": { "sys": { "id": "ct_comment" } },
"where": { "fields.postId": { "eq": "{ /payload/sys/id }" } }, "name": "commentCount" }बाहरी
Http
बाहरी HTTP कॉल करता है। यह एक बाहरी कॉल है, इसलिए यह प्लान-वार बाहरी कॉल सीमा में गिना जाता है, और समय बजट में इसे timeoutMs (न हो तो 30 सेकंड) × (1 + retry) के रूप में गिना जाता है।
| field | विवरण |
|---|---|
method | "GET", "POST", "PUT", "PATCH", "DELETE" |
url | लक्ष्य URL (मान अभिव्यक्ति; { /ptr } डाला जा सकता है) |
headers | [{ "key", "value", "secret"? }]। value एक मान अभिव्यक्ति है। secret:true header को केवल CMA (administrator) के लिए माना जाता है: यह अंतिम उपयोगकर्ता को उजागर नहीं होता, और अनुरोध भेजे जाने से ठीक पहले ही decrypt किया जाता है। यहाँ Content-Type डालने पर body उसी प्रारूप में serialize होती है (नीचे) |
body | अनुरोध body (मान अभिव्यक्ति या JSON)। वह किस प्रारूप में भेजी जाती है, यह Content-Type header तय करता है |
timeoutMs | इस कॉल का timeout (ms) |
retry | response status 400 या उससे अधिक होने पर retry की संख्या। डिफ़ॉल्ट 0, अधिकतम सीमा 2 |
ignoreStatusCode | (retry पूरा होने के बाद का) अंतिम status 400 या उससे अधिक होने पर इस कॉल को विफल माना जाए या नहीं। डिफ़ॉल्ट false होने पर इसे विफलता माना जाता है और यह Try/catch का लक्ष्य बन जाता है। true होने पर इसे विफलता नहीं माना जाता और { status, body } को ज्यों-का-त्यों bind कर दिया जाता है (कॉलर स्वयं status के आधार पर शाखा बनाता है) |
responseType | response body को किस रूप में लेना है। "Json" (डिफ़ॉल्ट) उसे ऑब्जेक्ट या array में पार्स करता है, "Text" उसे string के रूप में लेता है |
- परिणाम:
{ status, body }। इस statement कोnameदिया हो, तो{ /<name>/status },{ /<name>/body/... }।bodyका रूपresponseTypeतय करता है। responseTypeकेवल सफल response पर लागू होता है। status 400 या उससे अधिक वाले response की body, घोषित मान चाहे जो हो, निदान के लिए बाइंड होती है (JSON होने पर पार्स किया गया मान, अन्यथा string)।"Json"घोषित है पर body JSON नहीं है, तो यह कॉल विफल होती है (Try/catchका लक्ष्य)। जो API JSON नहीं देती, उसकी response body को"Text"से लें, और मान के रूप में चाहिए तोParseJsonसे पार्स करें।"Text"को response केContent-Typeके charset से डिकोड किया जाता है, और charset न होने पर UTF-8 माना जाता है। body खाली होने पर दोनों स्थितियों मेंbodynullहोती है।- response आकार सीमा: response body अधिकतम 10MiB है। इससे अधिक होने पर यह कॉल अपवाद के साथ विफल होती है और इसे किसी भी अन्य रनटाइम विफलता की तरह
Try/catchसे संभाला जा सकता है (यह आकार-आधारित विफलता है, इसलिए इसेignoreStatusCodeसे नज़रअंदाज़ नहीं किया जाता)।
{ "type": "Http", "method": "POST", "url": "https://api.llm.com/v1/gen",
"headers": [ { "key": "Authorization", "value": "Bearer sk-...", "secret": true } ],
"body": { "prompt": "{ /payload/fields/prompt }" }, "timeoutMs": 15000, "retry": 1,
"responseType": "Json", "name": "resp" }body किस प्रारूप में भेजी जाती है
headers में दिया गया Content-Type, body का serialize प्रारूप तय करता है। तुलना में अक्षरों का case और ;charset=… जैसे पैरामीटर नज़रअंदाज़ कर केवल शुरुआती भाग देखा जाता है। header न हो या उसका मान खाली हो, तो application/json के रूप में भेजा जाता है। यह header केवल body होने पर ही जोड़ा जाता है, इसलिए body न हो तो लिखा हुआ header ज्यों-का-त्यों जाता है। एक ही key को कई बार देने पर केवल पहला मान उपयोग होता है और वे एक में मिला दिए जाते हैं।
जिस body को घोषित प्रारूप में नहीं रखा जा सकता, उसे रखे जा सकने वाले प्रारूप में सुधारकर भेजा जाता है। ऐसा नहीं होता कि header वास्तविक body से भिन्न बात कहे।
ये वे संयोजन हैं जिनमें घोषित मान ज्यों-का-त्यों जाता है।
घोषित Content-Type | body का रूप | जाने वाली body |
|---|---|---|
application/json | कुछ भी | JSON |
application/x-www-form-urlencoded | ऑब्जेक्ट·array | order[id]=A-2481&order[amount]=34000 |
text/plain | स्केलर | मान ज्यों-का-त्यों |
अन्य (text/xml आदि) | कुछ भी | JSON |
ये वे संयोजन हैं जिन्हें घोषित प्रारूप में नहीं रखा जा सकता, इसलिए इन्हें सुधार दिया जाता है।
घोषित Content-Type | body का रूप | वास्तव में जाने वाला Content-Type | जाने वाली body |
|---|---|---|---|
application/x-www-form-urlencoded | स्केलर | text/plain;charset=UTF-8 | मान ज्यों-का-त्यों |
text/plain | ऑब्जेक्ट·array | application/json | JSON |
ये दो पंक्तियाँ यह स्पष्ट करती हैं कि जोड़ी बेमेल होने पर अनुरोध किस रूप में जाता है, और ये इच्छित प्रारूप पाने का तरीका नहीं हैं। body मान अभिव्यक्ति से बनती हो, तो निष्पादन के समय की payload के अनुसार वह स्केलर हो सकती है, और तब यह सुधार बिना किसी त्रुटि के हो जाता है। प्राप्त करने वाला पक्ष प्रारूप पर आपत्ति करे, तो body के रूप और Content-Type में से किसी एक को अपनी मंशा के अनुसार ठीक करें।
form-urlencoded ऑब्जेक्ट को bracket key के रूप में और array को index के रूप में फैलाता है।
body | फैलने वाली key और मान |
|---|---|
{ "order": { "id": "A-2481", "amount": 34000 } } | order[id]=A-2481&order[amount]=34000 |
{ "tags": ["outerwear", "winter"] } | tags[0]=outerwear&tags[1]=winter |
{ "items": [{ "sku": "TUMBLER-500" }] } | items[0][sku]=TUMBLER-500 |
{ "memo": null } | memo= |
key और मान UTF-8 में percent-encode होकर जाते हैं। ऊपर की तालिका key की संरचना दिखाने के लिए decode किया हुआ रूप है। मान में & या + हो, तब भी उन्हें जोड़े का विभाजक या रिक्त स्थान नहीं समझा जाता और वे ज्यों-के-त्यों पहुँचते हैं।
नेस्टिंग को bracket key के रूप में फैलाने वाली यह लेखन-शैली व्यापक रूप से प्रचलित परिपाटी है, न कि प्रारूप का स्वयं का मानक। जाँच लें कि प्राप्त करने वाला पक्ष order[id] को नेस्टेड ऑब्जेक्ट में पुनर्स्थापित करता है या नहीं, और न करता हो तो body को सपाट key से बनाएँ।
{ "type": "Http", "method": "POST", "url": "https://api.example.com/oauth/token",
"headers": [ { "key": "Content-Type", "value": "application/x-www-form-urlencoded" } ],
"body": { "grant_type": "client_credentials", "client_id": "{ /vars/clientId }" },
"name": "token" }EmailSend
पंजीकृत EmailAccount के माध्यम से 1 मेल भेजता है। इसके field केवल वही हैं जो सीधे SMTP/MIME पर मैप होते हैं। कोई template id, शेड्यूल्ड भेजना, या प्रदाता-विशिष्ट विस्तार नहीं है (ऐसी सुविधा चाहिए तो Http से संबंधित मेल सेवा की API को सीधे कॉल करें)। भेजने वाला (from address) यहाँ तय नहीं होता, बल्कि account जिस EmailAccount को इंगित करता है, उससे आता है।
| field | विवरण |
|---|---|
account | भेजने वाला EmailAccount reference ({ sys: { id } }, अनिवार्य)। आमतौर पर एक literal id। मान अभिव्यक्ति के रूप में देने पर यह भेजने के समय resolve होता है, इसलिए सहेजते समय इसकी जाँच नहीं की जा सकती |
to | प्राप्तकर्ता का पता (मान अभिव्यक्ति)। to और toServiceUser में से ठीक एक ही का उपयोग करें |
toServiceUser | प्राप्तकर्ता को ServiceUser reference से निर्दिष्ट करना ({ sys: { id } }; उसका sys.id मान अभिव्यक्ति हो सकता है)। engine भेजने से ठीक पहले पते को resolve करता है, इसलिए सदस्य का पता Script के वेरिएबल स्थान में नहीं आता |
cc | cc प्राप्तकर्ता पतों का array (मान अभिव्यक्ति) |
bcc | गुप्त प्राप्तकर्ता पतों का array (मान अभिव्यक्ति) |
subject | विषय (मान अभिव्यक्ति, अनिवार्य) |
body | मुख्य भाग (मान अभिव्यक्ति, अनिवार्य)। यह हमेशा text/html के रूप में भेजा जाता है, इसलिए सादे टेक्स्ट के बजाय markup लिखें (लाइन-ब्रेक space बन जाते हैं, < को tag के रूप में समझा जाता है)। जो मान अभिव्यक्ति परिणाम इसमें interpolate होते हैं वे HTML-escape किए जाते हैं |
replyTo | (वैकल्पिक) Reply-To header (मान अभिव्यक्ति)। यह भेजने वाले से भिन्न हो सकता है (उदाहरण: no-reply से भेजना पर उत्तर support पते पर) |
timeoutMs | (वैकल्पिक, 1 या अधिक) इस भेजने का timeout (ms)। न देने पर प्लेटफ़ॉर्म का डिफ़ॉल्ट मान; ऊपरी सीमा से अधिक मान सहेजते समय अस्वीकृत |
- प्राप्तकर्ताओं की कुल संख्या अधिकतम 50 है।
to(1),ccऔरbccसबको मिलाकर गिना जाता है (SMTP envelope में cc/bcc का भेद नहीं होता और सब प्राप्तकर्ता के रूप में जाते हैं, इसलिए इन्हें कुल में गिना जाता है)। इससे अधिक होने पर सहेजने और निष्पादन में अस्वीकृत हो जाता है। कई लोगों को भेजने के लिएResourceForEach+EmailSendसे प्रति आइटम 1 मेल भेजें। - यह परिणाम को bind नहीं करता। सफलता का अर्थ केवल इतना है कि "प्रदाता ने मेल स्वीकार कर लिया", इसलिए लौटाने के लिए कोई मान नहीं होता और यह
nameनहीं लेता। यह retry भी नहीं करता (ईमेल non-idempotent है, इसलिए अस्पष्ट रूप से विफल होने के बाद retry करने पर डुप्लिकेट भेजना हो जाता है; इसीलिए यहHttpकेretryका पालन नहीं करता)। विफलता throw होती है औरTryकेcatchसे संभाली जाती है। - यह एक बाहरी कॉल है। यह प्लान-वार बाहरी कॉल सीमा में गिना जाता है, और समय बजट में इसे
timeoutMs(न हो तो 10 सेकंड) एक बार के रूप में गिना जाता है (यह retry नहीं करता, इसलिएHttpकी तरह संख्या से गुणा नहीं होता)। इसेResourceForEachकेonEachके भीतर उपयोग किया जा सकता है (बहु-मेल भेजने का मानक रूप)।
{ "type": "EmailSend", "account": { "sys": { "id": "eml_orders" } },
"to": "{ /order/fields/email/en-US }",
"subject": "आपका ऑर्डर प्राप्त हो गया (ऑर्डर नंबर { /order/sys/id })",
"body": "<p>आपका ऑर्डर प्राप्त हो गया है। शिपिंग शुरू होने पर हम आपको फिर सूचित करेंगे।</p>",
"replyTo": "support@my-shop.example" }वेरिएबल
SetVar
एक script-scoped परिवर्तनीय वेरिएबल घोषित या अपडेट करता है। इसे { /vars/<var> } के रूप में संदर्भित करें (JsonLogic में वेरिएबल घोषणा नहीं है, इसलिए इसे एक statement के रूप में दिया गया है)।
| field | विवरण |
|---|---|
var | वेरिएबल का नाम। { /vars/<var> } के रूप में संदर्भित |
value | मान अभिव्यक्ति। यह संचय करने के लिए स्वयं को संदर्भित कर सकता है |
{ "type": "SetVar", "var": "total", "value": 0 }
{ "type": "SetVar", "var": "total", "value": { "$+": [ "{ /vars/total }", "{ /row/qty }" ] } } // संचय
{ "type": "SetVar", "var": "ids", "value": { "$merge": [ "{ /vars/ids }", [ "{ /row/sys/id }" ] ] } } // array में इकट्ठा करनाकैश
Cache
उसी Script के अपने, थोड़ी देर जीने वाले कैश को पढ़ता और लिखता है। बाहरी कॉल के परिणाम जैसे वे मान, जिन्हें हर बार दोबारा लाना व्यर्थ है, उन्हें कुछ सेकंड तक रखकर अगली कॉल में दोबारा उपयोग करने की जगह यही है। यह बाहरी कॉल नहीं है, इसलिए यह प्रति परिभाषा बाहरी कॉल की संख्या में नहीं गिना जाता, और समय बजट में इसका कोई घोषित समय भी नहीं होता।
| field | विवरण |
|---|---|
action | "Set" (लिखना), "Get" (पढ़ना), "Delete" (हटाना) में से एक (अनिवार्य) |
key | कैश कुंजी (Cache Key) (अनिवार्य)। यह मान अभिव्यक्ति नहीं, बल्कि literal है (नीचे देखें)। अधिकतम 128 अक्षर, और इससे अधिक होने पर सहेजना अस्वीकृत हो जाता है |
value | सहेजा जाने वाला मान (केवल Set) |
ttl | कैश के जीवित रहने का समय (केवल Set, सेकंड में)। 1 से 30 के बीच, और छोड़ने पर 5 |
defaultValue | कैश किया गया डेटा न होने पर Get जिसे bind करेगा वह मान (केवल Get)। छोड़ने पर null |
name | परिणाम रखने वाला नाम। Get के लिए यह अनिवार्य है (पढ़े गए मान के जाने की कोई जगह न हो, तो उसे पढ़ने का कोई कारण नहीं)। Set सहेजे गए मान को और Delete हटाने का कार्य हुआ या नहीं इसे bind करता है, और इन दोनों में यह वैकल्पिक है |
- केवल उसी कार्य से संबंधित field लिखे जाते हैं।
Getमेंttlलिखने याSetमेंdefaultValueलिखने पर सहेजना अस्वीकृत हो जाता है। - जो नहीं है और जो समाप्त हो चुका है, इनमें कोई भेद नहीं होता। दोनों में
defaultValuebind होता है। जहाँnullसहेजा गया हो, वहाँ भी यही होता है। - संग्रह का दायरा वही एक Script है। उसी Space की दूसरी Script वही कैश कुंजी लिखे, तब भी वे एक-दूसरे का डेटा नहीं देख पातीं। उस Script को संशोधित करने या हटाने पर उस Script का सारा डेटा मिट जाता है।
keyएक literal है। अनुरोध से आई कैश कुंजी से डेटा चुनने देने पर कॉलर यह तय करने लगता है कि क्या पढ़ा जाएगा, और जिस Script ने हर सदस्य के लिए एक-एक डेटा रखा है वह एक सदस्य का मान दूसरे सदस्य को दे बैठती है। इसलिएkeyमें{ /pointer }हो, तो वह न मान में बदलता है और न अक्षर-दर-अक्षर उपयोग होता है। सहेजना ही अस्वीकृत हो जाता है।- इसे पुनरावृत्ति के भीतर नहीं रखा जा सकता।
LoopयाResourceForEachके block के भीतरCacheहोने पर सहेजना अस्वीकृत हो जाता है। कारण यह है कि नीचे दी गई संख्या की ऊपरी सीमा पुनरावृत्ति के भीतर कोई भी प्रतिबंध नहीं बन पाती। हर पुनरावृत्ति पर एक-एक डेटा लिखा जाता है, इसलिए परिभाषा में लिखे statement की संख्या और वास्तव में उपयोग होने वाली कैश कुंजियों की संख्या मेल नहीं खातीं। - प्रति परिभाषा 5 तक रखे जा सकते हैं (नेस्टिंग सहित, कार्य से निरपेक्ष रूप से जोड़कर)। इससे अधिक होने पर सहेजना अस्वीकृत हो जाता है।
- सहेजा जाने वाला मान 10,240 बाइट (10KiB) तक हो सकता है। इससे अधिक होने पर वह statement विफल हो जाता है (status 422)। यह अन्य रनटाइम विफलताओं जैसी ही है, इसलिए इसे
Try/catchसे स्थानीय रूप से संभाला जा सकता है।
// विनिमय दर को 30 सेकंड तक दोबारा उपयोग करना।
{ "type": "Cache", "action": "Get", "name": "cached", "key": "rates" }
// रखा हुआ मान हो, तो बिना बाहरी कॉल के उसे ज्यों-का-त्यों लौटा देना
{ "type": "If", "condition": { "!!": [ "{ /cached }" ] },
"then": [ { "type": "Return", "value": "{ /cached }" } ] }
{ "type": "Http", "name": "fetched", "method": "GET", "url": "https://api.example.com/rates" }
{ "type": "Cache", "action": "Set", "key": "rates", "value": "{ /fetched/body }", "ttl": 30 }
{ "type": "Return", "value": "{ /fetched/body }" }
// रखे हुए मान को समाप्ति से पहले हटा देना
{ "type": "Cache", "action": "Delete", "key": "rates" }मान पार्सिंग
ParseJson
JSON टेक्स्ट को उस मान में पार्स करता है जिसे वह दर्शाता है, और उसे एक नाम से बाइंड करता है। responseType: "Text" के साथ Http से मिली response body, payload में आई JSON string, या किसी field में string के रूप में रखी JSON को संभालने के लिए इसका उपयोग करें। यह बाहरी कॉल नहीं है, इसलिए यह बाहरी कॉल सीमा में नहीं गिना जाता, और समय बजट में इसका कोई घोषित समय भी नहीं होता।
| field | विवरण |
|---|---|
name | पार्स किए गए मान को रखने वाला नाम (अनिवार्य)। अन्य statements में यह वैकल्पिक है, पर यहाँ अनिवार्य है। यह statement अपने परिणाम को बाइंड करने के अलावा कुछ नहीं करता, इसलिए नाम के बिना यह बिना किसी प्रभाव वाला statement बन जाता है |
value | पार्स किया जाने वाला JSON टेक्स्ट (मान अभिव्यक्ति, अनिवार्य)। { /resp/body } की तरह पिछले चरण के मान की ओर संकेत करें, या JSON टेक्स्ट को literal के रूप में ज्यों-का-त्यों लिखें (literal के भीतर का { { पॉइंटर } टेम्पलेट के रूप में नहीं पढ़ा जाता) |
- परिणाम: पार्स किया गया मान स्वयं। ऑब्जेक्ट ऑब्जेक्ट रहता है, array array रहता है, और
42या"a"जैसा एकल मान भी पार्स हो जाता है। इसके बाद{ /<name>/... }से उसके भीतर संकेत करें। - पहले से पार्स किया गया मान आने पर वह जैसा है वैसा बाइंड होता है। जब
valueकिसी ऐसे मान में resolve होता है जो string नहीं है, तो पार्स करने के लिए कोई टेक्स्ट नहीं होता, इसलिए वह मान जैसा है वैसा बाइंड कर दिया जाता है। - पार्स किए गए टेक्स्ट के भीतर का
{ /pointer }दोबारा हल नहीं किया जाता। बाहर से मिली string में{ /payload/... }जैसा एक्सप्रेशन हो, तो भी वह मान से नहीं बदला जाता और टेक्स्ट ही रहता है। nullके दो मामलों में फ़र्क है। पार्स किया जाने वाला टेक्स्ट केवलnullशब्द हो तो यह सामान्य है और परिणाम भीnullहोता है। लेकिनvalueजिस जगह की ओर संकेत करता है वह खाली हो, यानी कोई मान ही न हो, तो पार्स करने के लिए कुछ नहीं होता और statement विफल हो जाता है।- विफलता: जब
valueबिना मान या केवल खाली स्थान में resolve होता है, और जब टेक्स्ट JSON नहीं होता। इसे अन्य रनटाइम विफलताओं की तरहTry/catchसे संभालें; त्रुटि संदेश में वह टेक्स्ट भी आता है जिसे पार्स करने की कोशिश हुई थी। - यह प्रति परिभाषा statement संख्या में 1 गिना जाता है, पर बाहरी कॉल की सीमा या
SetVarकी ऊपरी सीमा से इसका कोई संबंध नहीं है।
// 1) JSON न देने वाली API: Text से लेकर पार्स करना
{ "type": "Http", "method": "GET", "url": "https://api.partner.example/v1/quote",
"responseType": "Text", "name": "resp" },
{ "type": "ParseJson", "name": "quote", "value": "{ /resp/body }" },
// 2) payload में आई JSON string को पार्स करना
{ "type": "ParseJson", "name": "spec", "value": "{ /payload/fields/specJson }" }हस्ताक्षर सत्यापन और टेक्स्ट प्रोसेसिंग
ये वे statements हैं जो भुगतान प्रदाता द्वारा webhook से भेजे गए हस्ताक्षर की पुष्टि करते हैं, और उस हस्ताक्षर को जिस string में लपेटकर भेजा गया है उसे खोलते हैं। तीनों बाहरी कॉल नहीं बल्कि गणना हैं, इसलिए ये बाहरी कॉल सीमा में नहीं गिने जाते और समय बजट में इनका कोई घोषित समय भी नहीं होता; तथा इनमें कोई डेटा वाली जगह न होने से ये $ उपसर्ग नियम से निरपेक्ष हैं। तीनों को संयोजित करने वाला पूर्ण उदाहरण कुकबुक में webhook हस्ताक्षर सत्यापन में है।
तीनों statements में resolve हुए मान की लंबाई की एक ऊपरी सीमा है। यह एक्सप्रेशन की लंबाई नहीं, बल्कि उस एक्सप्रेशन द्वारा इंगित मान की लंबाई है ({ /rawPayload } के सोलह अक्षर कई दसियों KB की ओर संकेत करते हैं), और सीमा पार होने पर निष्पादन विफल हो जाता है, जिसे Try से संभाला जा सकता है। ठोस मान मान की लंबाई की ऊपरी सीमा में एक जगह दिए गए हैं।
Signature
प्राप्त हस्ताक्षर कोड secret से बने कोड के समान है या नहीं, यह जाँचकर उस उत्तर को एक Boolean मान के रूप में bind करता है। भुगतान प्रदाता (PG·MoR) webhook से जो हस्ताक्षर भेजते हैं, उनका सत्यापन इसी statement से किया जाता है।
| field | विवरण |
|---|---|
name | सत्यापन का परिणाम रखने वाला नाम (अनिवार्य)। { /<name> } true या false होता है। सत्यापन करके परिणाम का उपयोग न करना सत्यापन न करने के बराबर है, इसलिए इसे छोड़ा नहीं जा सकता |
algorithm | कोड बनाने वाला hash (अनिवार्य)। SHA1·SHA256·SHA384·SHA512 |
secret | सामने वाले पक्ष के साथ साझा की गई गुप्त key (मान अभिव्यक्ति, अनिवार्य) |
secretEncoding | secret किस रूप में लिखी गई है। Utf8 (डिफ़ॉल्ट, टेक्स्ट key)·Hex·Base64। hex या base64 में जारी हुई key को टेक्स्ट के रूप में रखने पर वह दूसरी key बन जाती है, जिससे देखने में विश्वसनीय लगने वाला कोड बनता है पर वह कभी मेल नहीं खाता |
value | वह संदेश जिस पर कोड की गणना होगी (मान अभिव्यक्ति, अनिवार्य)। यह सामने वाले पक्ष द्वारा हस्ताक्षरित bytes से अक्षर-दर-अक्षर समान होना चाहिए, इसलिए आमतौर पर यह { /rawPayload } होता है, या प्रदाता द्वारा header में साथ भेजी गई timestamp को उसके आगे जोड़ा हुआ रूप |
expected | कॉलर द्वारा भेजा गया कोड (मान अभिव्यक्ति, अनिवार्य)। उदाहरण: { /headers/x-signature } |
- परिणाम:
Boolean। इसके बादIfकी शर्त में{ /<name> }को ज्यों-का-त्यों लिखें। valueमें पार्स किया गया/payloadनहीं, बल्कि/rawPayloadलिखें। पार्स किए गए payload को दोबारा string बनाने पर space, अंकों का लेखन और escape सामान्यीकृत हो जाते हैं, जिससे वह सामने वाले पक्ष द्वारा हस्ताक्षरित bytes पर नहीं लौटता (Context रूट)।- आउटपुट का रूप निर्दिष्ट करने वाला कोई field नहीं है।
algorithmकोड की byte लंबाई तय कर देता है और समान लंबाई के hex एवं base64 की string लंबाई कभी नहीं टकराती, इसलिए सामने वाले पक्ष ने किस रूप में भेजा है यह बताए बिना भी engine bytes को पुनःप्राप्त कर लेता है। hex के छोटे-बड़े अक्षर, तथा base64 और base64url (padding हो या न हो) में भी इसी कारण भेद नहीं किया जाता। - विफलता और
falseमें यह भेद है कि वह मान कौन देता है।expectedन हो या कोड मेल न खाए, तो परिणाम केवलfalseहोता है, यह विफलता नहीं है। header न होने और कोड न मिलने की सूचना अलग-अलग देने पर भेजने वाले पक्ष को यह पता चल जाएगा कि इनमें से क्या गलत था।valueखाली हो, तो खाली संदेश पर गणना होती है। खाली body भी हस्ताक्षर का विषय है।secretन हो, या वहsecretEncodingमें घोषित रूप में न हो, तो यह विफलता है। तीनों में लेखक का अपना इनपुट केवल यही है। विफलता संदेश मेंsecretऔरvalueशामिल नहीं होते।
valueकी ऊपरी सीमा 65,536 अक्षर है (resolve हुए मान के आधार पर)। यह वास्तविक प्रदाताओं द्वारा भेजी जाने वाली webhook body के आकार के अनुरूप रखा गया मान है।- तुलना यह constant-time में तय करती है कि मान समान हैं या नहीं। आगे के कुछ bytes मेल खाए थे या नहीं, यह प्रतिक्रिया के समय से बाहर नहीं छनता।
secretएन्क्रिप्ट होकर संग्रहीत नहीं होती।Httpheader केsecret: true(एन्क्रिप्ट होकर संग्रहीत, भेजने से ठीक पहले डिक्रिप्ट) के विपरीत यह परिभाषा में लिखे रूप में ही बनी रहती है, इसलिए जो भूमिका उस Script को पढ़ सकती है उसे यह मान दिख जाता है। सदस्य (ServiceUser) Script की परिभाषा नहीं पढ़ सकते (रचना और पठन केवल CMA पर होते हैं)।
// पूरी body पर हस्ताक्षर करने वाला प्रदाता
{ "type": "Signature", "name": "verified", "algorithm": "SHA256",
"secret": "whsec_9f2c1b7ae4", "value": "{ /rawPayload }",
"expected": "{ /headers/x-webhook-signature }" }
// key को base64 में जारी करने वाला प्रदाता
{ "type": "Signature", "name": "verified", "algorithm": "SHA256",
"secret": "aGVsbG8td2VlZ2xvbw==", "secretEncoding": "Base64",
"value": "{ /rawPayload }", "expected": "{ /headers/webhook-signature }" }Hash
value का डाइजेस्ट बनाकर उसे encoding द्वारा तय रूप की string के रूप में bind करता है। इसका उपयोग HMAC के बजाय "कुछ field और गुप्त key को जोड़कर SHA256 की गणना" करने वाली हस्ताक्षर स्कीम को पुनःनिर्मित करने के लिए किया जाता है।
| field | विवरण |
|---|---|
name | डाइजेस्ट रखने वाला नाम (अनिवार्य) |
algorithm | MD5·SHA1·SHA256·SHA384·SHA512 (अनिवार्य)। MD5 उन पुरानी स्कीमों को पुनःनिर्मित करने के लिए है जो उसकी अपेक्षा करती हैं, यह नए बनाए जाने वाले हस्ताक्षर के लिए चुना जाने वाला मान नहीं है |
value | डाइजेस्ट किया जाने वाला संदेश (मान अभिव्यक्ति, अनिवार्य) |
encoding | परिणाम का रूप। Hex (डिफ़ॉल्ट)·HexUpper·Base64·Base64Url |
- इसमें
secretfield नहीं है। हर स्कीम में key आगे, पीछे या बीच में आ सकती है, इसलिए key को सीधेvalueके भीतर लिखना ही सभी जगहों को व्यक्त कर पाता है। - परिणाम: string। सामने वाले पक्ष द्वारा भेजे गए कोड से तुलना करते समय
{ "==": [ "{ /<name> }", "{ /headers/... }" ] }लिखें। यह तुलनाSignatureकी constant-time तुलना से भिन्न, एक सामान्य समता तुलना है। valueबिना मान के resolve हो या उसमें केवल खाली स्थान हो, तो यह विफलता है (क्योंकि यह लेखक का अपना एक्सप्रेशन है)।valueकी ऊपरी सीमा 128 अक्षर है। यह जुड़े हुए कुछ field रखने की जगह है, इसलिएSignatureसे बहुत संकरी है। पूरी webhook body पर गणना करनी हो, तोSignatureका उपयोग करें।
// SHA256(ऑर्डर नंबर + राशि + merchantKey) को बड़े अक्षरों वाले hex में
{ "type": "Hash", "name": "expectedSign", "algorithm": "SHA256", "encoding": "HexUpper",
"value": "{ /payload/orderId }{ /payload/amount }9f2c1b7ae4" }Regex
pattern को value पर लागू करके mode द्वारा माँगी गई चीज़ bind करता है। मान अभिव्यक्ति में string को काटने का कोई साधन नहीं है (केवल जोड़ने वाला cat और समावेश देखने वाला in है), इसलिए t=…,v1=… की तरह एक ही header में कई मान लपेटकर आने पर उसे खोलने के लिए इस statement का उपयोग किया जाता है।
| field | विवरण |
|---|---|
name | परिणाम रखने वाला नाम (अनिवार्य)। Capture में element को { /<name>/1 } से इंगित किया जाता है |
mode | "Match" मिलान हुआ या नहीं यह Boolean के रूप में, और "Capture" पहले मिलान को array के रूप में bind करता है (अनिवार्य) |
pattern | regex (अनिवार्य)। यह मान अभिव्यक्ति नहीं, बल्कि literal है (नीचे देखें)। flag को (?i) की तरह pattern के भीतर लिखा जाता है। अधिकतम 128 अक्षर, और इससे अधिक होने पर सहेजना अस्वीकृत हो जाता है |
value | जिस टेक्स्ट पर pattern लागू होगा (मान अभिव्यक्ति, अनिवार्य)। resolve हुआ मान 10,240 अक्षर (10KiB) से अधिक होने पर निष्पादन विफल हो जाता है |
- परिणाम:
MatchमेंBoolean, औरCaptureमें array याnull। array में index0पूरा मिलान होता है और1से capture group शुरू होते हैं, तथा जो group भाग नहीं लेते वेnullहोते हैं (खाली string नहीं, क्योंकि वह मिलान हुआ माना जाएगा)। pattern कहीं भी न दिखे, तोCaptureखाली array नहीं बल्किnullहोता है। - दोनों mode यही पूछते हैं कि "pattern कहीं दिखता है या नहीं"। पूरा टेक्स्ट pattern के समान होना चाहिए, तो
^…$से उसे बाँध दें।Matchसे जाँचकरCaptureसे निकालने वाले दोनों statements कभी अलग-अलग उत्तर न दें, इसलिए प्रश्न को समान रखा गया है। - इस engine में मान अभिव्यक्ति न होने वाले दो field में से एक
patternहै (दूसराCacheकीkeyहै)। अनुरोध से आए pattern को ज्यों-का-त्यों चलाने पर कॉलर यह चुनने लगता है कि कौन-सी अभिव्यक्ति चलेगी, और regex का backtracking उसे सेवा-अवरोध (denial of service) का साधन बना देता है। इसलिए pattern के भीतर का{ /pointer }भी मान में नहीं बदलता, बल्कि अक्षर-दर-अक्षर pattern का हिस्सा बन जाता है। - pattern निष्पादन शुरू होते समय पूरी परिभाषा में एक बार compile होता है। वह
LoopयाResourceForEachके भीतर हो, तो भी हर पुनरावृत्ति पर दोबारा compile नहीं होता, और अनुपयोगी pattern पहला statement कुछ भी करने से पहले ही विफल हो जाता है (Tryसे संभाला जा सकता है)।
// "t=1492774577,v1=<64 अक्षर hex>" को खोलकर { /sig/1 } = timestamp, { /sig/2 } = कोड
{ "type": "Regex", "name": "sig", "mode": "Capture",
"pattern": "^t=(\\d+),v1=([0-9a-f]{64})$", "value": "{ /headers/x-provider-signature }" }
// केवल प्रारूप की जाँच
{ "type": "Regex", "name": "isOrderId", "mode": "Match",
"pattern": "^ORD-\\d{8}-\\d{4}$", "value": "{ /payload/orderId }" }नियंत्रण प्रवाह
If
एक शर्तीय शाखा। condition JsonLogic है, और सत्य/असत्य सत्य और असत्य का निर्धारण नियमों का पालन करते हैं।
| field | विवरण |
|---|---|
condition | JsonLogic (boolean के रूप में मूल्यांकित) |
then | true होने पर चलाने के लिए Statement array |
else | (वैकल्पिक) false होने पर चलाने के लिए Statement array |
{ "type": "If",
"condition": { "<": [ "{ /wallet/fields/balance/en-US }", "{ /payload/fields/cost }" ] },
"then": [ { "type": "Return", "value": { "ok": false, "reason": "insufficient credit" } } ],
"else": [ /* ... */ ] }Loop
पुनरावृत्ति। एक mode चुनें: over (foreach), while (शर्त), या for (counted)। किसी भी mode में engine पुनरावृत्ति की एक ऊपरी सीमा लागू करता है (अनंत loop से बचने के लिए)। यह ऊपरी सीमा maxIterations से घोषित की जाती है, और न लिखने पर प्लेटफ़ॉर्म की ऊपरी सीमा लागू होती है। body के भीतर बाहरी कॉल (Http·EmailSend) और Media फ़ाइल ingest भी रखी जा सकती है, और बाहरी कॉल statement निष्पादन के समय हर पुनरावृत्ति पर वास्तव में कॉल किए जाते हैं। प्रति परिभाषा बाहरी कॉल की अधिकतम संख्या की सीमा ज्यों-की-त्यों लागू रहती है।
समय बजट में यह गुणा के रूप में आता है। यह statement जो समय घोषित करता है वह body द्वारा घोषित समय को maxIterations (न हो तो 10,000) से गुणा किया हुआ मान है (समय बजट)। body में कोई बाहरी कॉल न हो, तो घोषित समय 0 होता है, इसलिए 30 सेकंड का मूल बजट ही वास्तविक सीमा है।
| field | विवरण |
|---|---|
over | foreach: एक मान अभिव्यक्ति जो array के रूप में resolve होता है |
while | शर्त: JsonLogic (true रहने तक दोहराता है) |
for | counted: { "from", "to", "step"? }। from से to तक समावेशी; step डिफ़ॉल्ट 1 |
maxIterations | अधिकतम पुनरावृत्ति संख्या (वैकल्पिक)। न लिखने पर प्लेटफ़ॉर्म की ऊपरी सीमा 10,000 लागू होती है, और उससे बड़ा मान सहेजते समय अस्वीकृत हो जाता है |
name | (वैकल्पिक) वर्तमान आइटम (foreach) या index (while·for) को bind करने के लिए नाम ({ /<name> }) |
body | loop body के लिए Statement array |
// foreach
{ "type": "Loop", "over": "{ /payload/fields/items }", "name": "item", "maxIterations": 100,
"body": [ { "type": "ResourceCreate", "resource": "Content", "contentType": { "sys": { "id": "ct_item" } },
"fields": { "name": { "en-US": "{ /item/name }" } } } ] }
// while
{ "type": "Loop", "while": "{ /vars/hasMore }", "maxIterations": 1000, "body": [ /* ... */ ] }
// counted (1..10 step 2)
{ "type": "Loop", "for": { "from": 1, "to": 10, "step": 2 }, "name": "i", "maxIterations": 100, "body": [ /* ... */ ] }Parallel
शाखाओं को समवर्ती रूप से चलाता है और उनके join होने के बाद आगे बढ़ता है। शाखाओं के बीच reference संभव नहीं है (यदि कोई निर्भरता हो, तो उन्हें क्रमिक रूप से रखें)।
| field | विवरण |
|---|---|
branches | Statement[][]। हर element एक शाखा है (statements का array) |
{ "type": "Parallel", "branches": [
[ { "type": "Http", "method": "GET", "url": "https://api.a.com/x", "name": "a" } ],
[ { "type": "Http", "method": "GET", "url": "https://api.b.com/y", "name": "b" } ]
] }Return
यह सामान्य प्रोग्रामिंग वाला return है। यह Script का परिणाम कॉल करने वाले को लौटाता है और उस बिंदु पर सामान्य रूप से समाप्त हो जाता है।
| field | विवरण |
|---|---|
value | (वैकल्पिक) लौटाने के लिए मान अभिव्यक्ति |
isError | डिफ़ॉल्ट false। true होने पर value response के error के रूप में लौटता है (अन्यथा return के रूप में) |
statusCode | response status code। डिफ़ॉल्ट 200 |
- यदि
Returnतक कभी नहीं पहुँचा जाता, तो कोई return मान नहीं होता। परिणाम लौटाने के लिए,valueको स्पष्ट रूप से निर्दिष्ट करें। - चूँकि यह किसी अपवाद या throw नहीं, बल्कि एक सामान्य समाप्ति है, यह
catchका लक्ष्य नहीं है (Tryके भीतर भी यह पूरे Script को समाप्त कर देता है, परfinallyफिर भी चलता है)। - guard को भी इसी statement से व्यक्त किया जाता है।
IfकेthenमेंReturnरखने पर, शर्त का उल्लंघन होने पर वह मान लौटाता है और उसके बाद के statements नहीं चलाता। यहReturnके कई उपयोगों में से एक है।
{ "type": "Return", "value": { "orderId": "{ /order/sys/id }", "status": "paid" }, "statusCode": 201 }
{ "type": "Return", "value": { "reason": "payment failed" }, "isError": true, "statusCode": 402 }Try
अपवाद प्रबंधन।
| field | विवरण |
|---|---|
body | प्रयास करने के लिए Statement array |
catch | (वैकल्पिक) body विफल होने पर चलता है। /error पर { message } उजागर करता है (किस statement में विफलता हुई यह इसमें नहीं आता) |
finally | (वैकल्पिक) सफलता या विफलता की परवाह किए बिना हमेशा चलता है |
- यदि
catchइसे संभाल लेता है, तो Script बाधित नहीं होता। केवल ऐसी विफलता जिसका कोईcatchन हो, Script को बाधित करती है (क्षतिपूर्ति प्रयास सहित)। - क्या "विफलता" मानी जाती है, और क्षतिपूर्ति (compensation) की सीमाएँ, इनका वर्णन निष्पादन सिमेंटिक्स, बाधाएँ, सुरक्षा में किया गया है।
{ "type": "Try",
"body": [ { "type": "Http", "method": "POST", "url": "https://primary.api/gen", "name": "resp" },
{ "type": "ResourceCreate", "resource": "Content", "contentType": { "sys": { "id": "ct_result" } },
"fields": { "text": { "en-US": "{ /resp/body/text }" } } } ],
"catch": [ { "type": "ResourceCreate", "resource": "Content", "contentType": { "sys": { "id": "ct_result" } },
"fields": { "text": { "en-US": "Generation failed" }, "error": { "en-US": "{ /error/message }" } } } ],
"finally": [ /* हमेशा चलता है */ ] }संबंधित दस्तावेज़
- मान अभिव्यक्ति: वे मान-नियम जिनका ऊपर दिए गए सभी field पालन करते हैं।
- निष्पादन सिमेंटिक्स, बाधाएँ, सुरक्षा: निष्पादन क्रम, error, स्थैतिक बाधाएँ, और सुरक्षा।
- कुकबुक: इन statements को संयोजित करने वाले पूर्ण उदाहरण।
- Script अवलोकन: शीर्ष-स्तरीय संरचना और एक निष्पादन को मिलने वाला समय।
