@xano/developer-mcp 1.0.34 → 1.0.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +17 -2
  2. package/dist/tools/index.d.ts +2 -15
  3. package/dist/tools/index.js +2 -2
  4. package/dist/tools/validate_xanoscript.d.ts +84 -9
  5. package/dist/tools/validate_xanoscript.js +345 -31
  6. package/dist/xanoscript.js +31 -1
  7. package/dist/xanoscript.test.js +6 -0
  8. package/dist/xanoscript_docs/README.md +56 -43
  9. package/dist/xanoscript_docs/addons.md +10 -0
  10. package/dist/xanoscript_docs/agents.md +15 -0
  11. package/dist/xanoscript_docs/apis.md +45 -24
  12. package/dist/xanoscript_docs/cheatsheet.md +252 -0
  13. package/dist/xanoscript_docs/database.md +37 -0
  14. package/dist/xanoscript_docs/docs_index.json +236 -0
  15. package/dist/xanoscript_docs/frontend.md +10 -0
  16. package/dist/xanoscript_docs/functions.md +18 -0
  17. package/dist/xanoscript_docs/integrations/cloud-storage.md +142 -0
  18. package/dist/xanoscript_docs/integrations/external-apis.md +201 -0
  19. package/dist/xanoscript_docs/integrations/redis.md +194 -0
  20. package/dist/xanoscript_docs/integrations/search.md +242 -0
  21. package/dist/xanoscript_docs/integrations/utilities.md +331 -0
  22. package/dist/xanoscript_docs/integrations.md +55 -901
  23. package/dist/xanoscript_docs/mcp-servers.md +10 -0
  24. package/dist/xanoscript_docs/performance.md +15 -0
  25. package/dist/xanoscript_docs/quickstart.md +288 -41
  26. package/dist/xanoscript_docs/run.md +10 -0
  27. package/dist/xanoscript_docs/security.md +26 -0
  28. package/dist/xanoscript_docs/streaming.md +10 -0
  29. package/dist/xanoscript_docs/syntax.md +78 -0
  30. package/dist/xanoscript_docs/tables.md +15 -0
  31. package/dist/xanoscript_docs/tasks.md +11 -0
  32. package/dist/xanoscript_docs/tools.md +15 -0
  33. package/dist/xanoscript_docs/triggers.md +57 -192
  34. package/dist/xanoscript_docs/types.md +18 -0
  35. package/package.json +1 -1
@@ -0,0 +1,236 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "description": "Machine-readable index for XanoScript documentation",
4
+
5
+ "topics": {
6
+ "cheatsheet": {
7
+ "file": "cheatsheet.md",
8
+ "purpose": "Quick reference for 20 most common operations",
9
+ "priority": 1,
10
+ "aliases": ["quick", "common", "basics", "start"]
11
+ },
12
+ "quickstart": {
13
+ "file": "quickstart.md",
14
+ "purpose": "Common patterns and mistakes to avoid",
15
+ "priority": 2,
16
+ "aliases": ["start", "getting-started", "patterns", "mistakes"]
17
+ },
18
+ "syntax": {
19
+ "file": "syntax.md",
20
+ "purpose": "Operators, filters, expressions, error handling",
21
+ "priority": 3,
22
+ "aliases": ["filters", "operators", "expressions"]
23
+ },
24
+ "types": {
25
+ "file": "types.md",
26
+ "purpose": "Data types, validation, input blocks",
27
+ "priority": 4,
28
+ "aliases": ["validation", "input", "data-types"]
29
+ },
30
+ "database": {
31
+ "file": "database.md",
32
+ "purpose": "All db.* operations",
33
+ "priority": 5,
34
+ "aliases": ["db", "crud", "query", "sql"]
35
+ },
36
+ "tables": {
37
+ "file": "tables.md",
38
+ "purpose": "Table schema definitions",
39
+ "aliases": ["schema", "fields", "indexes"]
40
+ },
41
+ "apis": {
42
+ "file": "apis.md",
43
+ "purpose": "HTTP endpoint definitions",
44
+ "aliases": ["endpoints", "http", "rest", "query"]
45
+ },
46
+ "functions": {
47
+ "file": "functions.md",
48
+ "purpose": "Reusable function stacks",
49
+ "aliases": ["fn", "reusable", "stack"]
50
+ },
51
+ "triggers": {
52
+ "file": "triggers.md",
53
+ "purpose": "Event-driven handlers",
54
+ "aliases": ["events", "hooks", "handlers"]
55
+ },
56
+ "agents": {
57
+ "file": "agents.md",
58
+ "purpose": "AI agent configuration",
59
+ "aliases": ["ai", "llm", "chatbot"]
60
+ },
61
+ "tools": {
62
+ "file": "tools.md",
63
+ "purpose": "AI tools for agents",
64
+ "aliases": ["ai-tools", "agent-tools"]
65
+ },
66
+ "integrations": {
67
+ "file": "integrations.md",
68
+ "purpose": "External service integrations (index)",
69
+ "aliases": ["external", "services", "cloud"]
70
+ },
71
+ "integrations/cloud-storage": {
72
+ "file": "integrations/cloud-storage.md",
73
+ "purpose": "AWS S3, Azure Blob, GCP Storage",
74
+ "aliases": ["s3", "azure", "gcp", "files", "upload"]
75
+ },
76
+ "integrations/search": {
77
+ "file": "integrations/search.md",
78
+ "purpose": "Elasticsearch, Algolia",
79
+ "aliases": ["elasticsearch", "algolia", "full-text"]
80
+ },
81
+ "integrations/redis": {
82
+ "file": "integrations/redis.md",
83
+ "purpose": "Caching, rate limiting, queues",
84
+ "aliases": ["cache", "rate-limit", "queue"]
85
+ },
86
+ "integrations/external-apis": {
87
+ "file": "integrations/external-apis.md",
88
+ "purpose": "api.request patterns",
89
+ "aliases": ["http", "api", "request", "fetch"]
90
+ },
91
+ "integrations/utilities": {
92
+ "file": "integrations/utilities.md",
93
+ "purpose": "Email, Zip, Lambda",
94
+ "aliases": ["email", "zip", "lambda", "archive"]
95
+ },
96
+ "security": {
97
+ "file": "security.md",
98
+ "purpose": "Authentication, authorization, security patterns",
99
+ "aliases": ["auth", "authorization", "permissions"]
100
+ },
101
+ "performance": {
102
+ "file": "performance.md",
103
+ "purpose": "Optimization best practices",
104
+ "aliases": ["optimization", "speed", "caching"]
105
+ },
106
+ "mcp-servers": {
107
+ "file": "mcp-servers.md",
108
+ "purpose": "MCP server configuration",
109
+ "aliases": ["mcp", "model-context-protocol"]
110
+ },
111
+ "tasks": {
112
+ "file": "tasks.md",
113
+ "purpose": "Scheduled job definitions",
114
+ "aliases": ["scheduled", "jobs", "cron"]
115
+ },
116
+ "streaming": {
117
+ "file": "streaming.md",
118
+ "purpose": "Streaming data handling",
119
+ "aliases": ["stream", "large-files"]
120
+ },
121
+ "realtime": {
122
+ "file": "realtime.md",
123
+ "purpose": "Real-time channel configuration",
124
+ "aliases": ["websocket", "channels", "pubsub"]
125
+ },
126
+ "middleware": {
127
+ "file": "middleware.md",
128
+ "purpose": "Request interceptors",
129
+ "aliases": ["interceptors", "hooks"]
130
+ },
131
+ "testing": {
132
+ "file": "testing.md",
133
+ "purpose": "Unit testing",
134
+ "aliases": ["tests", "unit-tests"]
135
+ },
136
+ "debugging": {
137
+ "file": "debugging.md",
138
+ "purpose": "Logging and debugging",
139
+ "aliases": ["logs", "debug", "trace"]
140
+ }
141
+ },
142
+
143
+ "filters": {
144
+ "trim": { "file": "syntax.md", "category": "string" },
145
+ "ltrim": { "file": "syntax.md", "category": "string" },
146
+ "rtrim": { "file": "syntax.md", "category": "string" },
147
+ "to_lower": { "file": "syntax.md", "category": "string" },
148
+ "to_upper": { "file": "syntax.md", "category": "string" },
149
+ "capitalize": { "file": "syntax.md", "category": "string" },
150
+ "substr": { "file": "syntax.md", "category": "string" },
151
+ "split": { "file": "syntax.md", "category": "string" },
152
+ "replace": { "file": "syntax.md", "category": "string" },
153
+ "contains": { "file": "syntax.md", "category": "string" },
154
+ "strlen": { "file": "syntax.md", "category": "string" },
155
+ "first": { "file": "syntax.md", "category": "array" },
156
+ "last": { "file": "syntax.md", "category": "array" },
157
+ "count": { "file": "syntax.md", "category": "array" },
158
+ "map": { "file": "syntax.md", "category": "array" },
159
+ "filter": { "file": "syntax.md", "category": "array" },
160
+ "find": { "file": "syntax.md", "category": "array" },
161
+ "reduce": { "file": "syntax.md", "category": "array" },
162
+ "push": { "file": "syntax.md", "category": "array" },
163
+ "pop": { "file": "syntax.md", "category": "array" },
164
+ "join": { "file": "syntax.md", "category": "array" },
165
+ "sort": { "file": "syntax.md", "category": "array" },
166
+ "unique": { "file": "syntax.md", "category": "array" },
167
+ "get": { "file": "syntax.md", "category": "object" },
168
+ "set": { "file": "syntax.md", "category": "object" },
169
+ "has": { "file": "syntax.md", "category": "object" },
170
+ "keys": { "file": "syntax.md", "category": "object" },
171
+ "values": { "file": "syntax.md", "category": "object" },
172
+ "to_int": { "file": "syntax.md", "category": "type" },
173
+ "to_text": { "file": "syntax.md", "category": "type" },
174
+ "to_bool": { "file": "syntax.md", "category": "type" },
175
+ "to_decimal": { "file": "syntax.md", "category": "type" },
176
+ "json_encode": { "file": "syntax.md", "category": "type" },
177
+ "json_decode": { "file": "syntax.md", "category": "type" },
178
+ "round": { "file": "syntax.md", "category": "math" },
179
+ "abs": { "file": "syntax.md", "category": "math" },
180
+ "ceil": { "file": "syntax.md", "category": "math" },
181
+ "floor": { "file": "syntax.md", "category": "math" },
182
+ "add": { "file": "syntax.md", "category": "math" },
183
+ "subtract": { "file": "syntax.md", "category": "math" }
184
+ },
185
+
186
+ "constructs": {
187
+ "table": { "file": "tables.md", "triggers": "triggers.md" },
188
+ "function": { "file": "functions.md", "testing": "testing.md" },
189
+ "query": { "file": "apis.md", "auth": "security.md" },
190
+ "api_group": { "file": "apis.md" },
191
+ "task": { "file": "tasks.md" },
192
+ "agent": { "file": "agents.md", "tools": "tools.md" },
193
+ "tool": { "file": "tools.md", "mcp": "mcp-servers.md" },
194
+ "mcp_server": { "file": "mcp-servers.md", "triggers": "triggers.md" },
195
+ "table_trigger": { "file": "triggers.md", "section": "table-trigger" },
196
+ "realtime_trigger": { "file": "triggers.md", "section": "realtime-trigger" },
197
+ "workspace_trigger": { "file": "triggers.md", "section": "workspace-trigger" },
198
+ "agent_trigger": { "file": "triggers.md", "section": "agent-trigger" },
199
+ "mcp_server_trigger": { "file": "triggers.md", "section": "mcp-server-trigger" },
200
+ "addon": { "file": "addons.md" },
201
+ "middleware": { "file": "middleware.md" },
202
+ "realtime_channel": { "file": "realtime.md" }
203
+ },
204
+
205
+ "operations": {
206
+ "db.query": { "file": "database.md" },
207
+ "db.get": { "file": "database.md" },
208
+ "db.has": { "file": "database.md" },
209
+ "db.add": { "file": "database.md" },
210
+ "db.edit": { "file": "database.md" },
211
+ "db.patch": { "file": "database.md" },
212
+ "db.del": { "file": "database.md" },
213
+ "db.truncate": { "file": "database.md" },
214
+ "api.request": { "file": "integrations/external-apis.md" },
215
+ "function.run": { "file": "functions.md" },
216
+ "redis.get": { "file": "integrations/redis.md" },
217
+ "redis.set": { "file": "integrations/redis.md" },
218
+ "storage.s3_put": { "file": "integrations/cloud-storage.md" },
219
+ "storage.s3_get": { "file": "integrations/cloud-storage.md" }
220
+ },
221
+
222
+ "tasks": {
223
+ "authentication": ["security.md", "apis.md"],
224
+ "authorization": ["security.md"],
225
+ "rate_limiting": ["security.md", "integrations/redis.md"],
226
+ "error_handling": ["syntax.md", "quickstart.md"],
227
+ "pagination": ["database.md", "apis.md"],
228
+ "file_upload": ["integrations/cloud-storage.md", "streaming.md"],
229
+ "caching": ["performance.md", "integrations/redis.md"],
230
+ "search": ["integrations/search.md"],
231
+ "email": ["integrations/utilities.md"],
232
+ "scheduled_jobs": ["tasks.md"],
233
+ "realtime": ["realtime.md", "triggers.md"],
234
+ "ai_agents": ["agents.md", "tools.md", "mcp-servers.md"]
235
+ }
236
+ }
@@ -286,3 +286,13 @@ The tool will:
286
286
  2. **Centralize API calls** - Single `api.js` file
287
287
  3. **Store tokens securely** - localStorage for web, secure storage for mobile
288
288
  4. **Test incrementally** - Migrate one feature at a time
289
+
290
+ ---
291
+
292
+ ## Related Topics
293
+
294
+ | Topic | Description |
295
+ |-------|-------------|
296
+ | `apis` | Backend API endpoints |
297
+ | `workspace` | Workspace configuration |
298
+ | `security` | CORS and authentication |
@@ -6,6 +6,10 @@ applyTo: "function/**/*.xs"
6
6
 
7
7
  Reusable logic blocks in XanoScript.
8
8
 
9
+ > **TL;DR:** Define with `function "name" { input { } stack { } response = $result }`. Call with `function.run "name" { input = { } } as $result`. Empty input blocks need braces on separate lines.
10
+
11
+ ---
12
+
9
13
  ## Quick Reference
10
14
 
11
15
  ```xs
@@ -465,3 +469,17 @@ foreach ($items) {
465
469
  5. **Keep stacks shallow** - Avoid deeply nested conditionals
466
470
  6. **Use group for organization** - Visually group related statements for readability
467
471
  7. **Use remove sparingly** - Consider filtering arrays instead
472
+
473
+ ---
474
+
475
+ ## Related Topics
476
+
477
+ Explore more with `xanoscript_docs({ topic: "<topic>" })`:
478
+
479
+ | Topic | Description |
480
+ |-------|-------------|
481
+ | `types` | Input types, filters, and validation |
482
+ | `syntax` | Expressions, operators, and control flow |
483
+ | `quickstart` | Common patterns and examples |
484
+ | `database` | Database operations in function stacks |
485
+ | `testing` | Unit testing functions |
@@ -0,0 +1,142 @@
1
+ ---
2
+ applyTo: "function/**/*.xs, api/**/*.xs, task/**/*.xs"
3
+ ---
4
+
5
+ # Cloud Storage Integrations
6
+
7
+ > **TL;DR:** `cloud.aws.s3.*` for AWS, `cloud.azure.storage.*` for Azure, `cloud.google.storage.*` for GCP. All support upload, read, delete, and signed URLs.
8
+
9
+ ## Quick Reference
10
+
11
+ | Provider | Prefix | Operations |
12
+ |----------|--------|------------|
13
+ | AWS S3 | `cloud.aws.s3.*` | upload_file, read_file, sign_url, list_directory, delete_file |
14
+ | Azure Blob | `cloud.azure.storage.*` | upload_file, read_file, sign_url |
15
+ | Google Cloud | `cloud.google.storage.*` | upload_file, read_file, sign_url |
16
+
17
+ ---
18
+
19
+ ## AWS S3
20
+
21
+ ### Upload File
22
+ ```xs
23
+ cloud.aws.s3.upload_file {
24
+ bucket = "my-bucket"
25
+ region = "us-east-1"
26
+ key = $env.AWS_ACCESS_KEY
27
+ secret = $env.AWS_SECRET_KEY
28
+ file_key = "uploads/" ~ $input.filename
29
+ file = $input.file
30
+ } as $result
31
+ ```
32
+
33
+ ### Read File
34
+ ```xs
35
+ cloud.aws.s3.read_file {
36
+ bucket = "my-bucket"
37
+ region = "us-east-1"
38
+ key = $env.AWS_ACCESS_KEY
39
+ secret = $env.AWS_SECRET_KEY
40
+ file_key = "data/config.json"
41
+ } as $file
42
+ ```
43
+
44
+ ### Sign URL
45
+ ```xs
46
+ cloud.aws.s3.sign_url {
47
+ bucket = "my-bucket"
48
+ region = "us-east-1"
49
+ key = $env.AWS_ACCESS_KEY
50
+ secret = $env.AWS_SECRET_KEY
51
+ file_key = "private/document.pdf"
52
+ ttl = 300
53
+ } as $signed_url
54
+ ```
55
+
56
+ ### List Directory
57
+ ```xs
58
+ cloud.aws.s3.list_directory {
59
+ bucket = "my-bucket"
60
+ region = "us-east-1"
61
+ key = $env.AWS_ACCESS_KEY
62
+ secret = $env.AWS_SECRET_KEY
63
+ prefix = "uploads/"
64
+ } as $files
65
+ ```
66
+
67
+ ### Delete File
68
+ ```xs
69
+ cloud.aws.s3.delete_file {
70
+ bucket = "my-bucket"
71
+ region = "us-east-1"
72
+ key = $env.AWS_ACCESS_KEY
73
+ secret = $env.AWS_SECRET_KEY
74
+ file_key = "temp/old-file.txt"
75
+ }
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Azure Blob Storage
81
+
82
+ ```xs
83
+ cloud.azure.storage.upload_file {
84
+ account_name = $env.AZURE_ACCOUNT
85
+ account_key = $env.AZURE_KEY
86
+ container_name = "files"
87
+ filePath = "uploads/doc.pdf"
88
+ file = $input.file
89
+ }
90
+
91
+ cloud.azure.storage.read_file {
92
+ account_name = $env.AZURE_ACCOUNT
93
+ account_key = $env.AZURE_KEY
94
+ container_name = "files"
95
+ filePath = "data/config.json"
96
+ } as $file
97
+
98
+ cloud.azure.storage.sign_url {
99
+ account_name = $env.AZURE_ACCOUNT
100
+ account_key = $env.AZURE_KEY
101
+ container_name = "private"
102
+ path = "document.pdf"
103
+ ttl = 300
104
+ } as $url
105
+ ```
106
+
107
+ ---
108
+
109
+ ## Google Cloud Storage
110
+
111
+ ```xs
112
+ cloud.google.storage.upload_file {
113
+ service_account = $env.GCP_SERVICE_ACCOUNT
114
+ bucket = "my-bucket"
115
+ filePath = "uploads/file.pdf"
116
+ file = $input.file
117
+ }
118
+
119
+ cloud.google.storage.read_file {
120
+ service_account = $env.GCP_SERVICE_ACCOUNT
121
+ bucket = "my-bucket"
122
+ filePath = "data/config.json"
123
+ } as $file
124
+
125
+ cloud.google.storage.sign_url {
126
+ service_account = $env.GCP_SERVICE_ACCOUNT
127
+ bucket = "my-bucket"
128
+ filePath = "private/doc.pdf"
129
+ method = "GET"
130
+ ttl = 300
131
+ } as $url
132
+ ```
133
+
134
+ ---
135
+
136
+ ## Related Topics
137
+
138
+ | Topic | Description |
139
+ |-------|-------------|
140
+ | `streaming` | Streaming large files |
141
+ | `integrations` | All integrations index |
142
+ | `integrations/utilities` | Local storage operations |
@@ -0,0 +1,201 @@
1
+ ---
2
+ applyTo: "function/**/*.xs, api/**/*.xs, task/**/*.xs"
3
+ ---
4
+
5
+ # External APIs
6
+
7
+ > **TL;DR:** Use `api.request` for HTTP requests to external APIs. The `params` parameter is for the **request body** (not query params). Response in `$result.response.result`.
8
+
9
+ ## Quick Reference
10
+
11
+ ```xs
12
+ api.request {
13
+ url = "https://api.example.com/endpoint"
14
+ method = "POST" // GET, POST, PUT, PATCH, DELETE
15
+ params = $payload // Request body for POST/PUT/PATCH
16
+ headers = ["Content-Type: application/json", "Authorization: Bearer " ~ $env.API_KEY]
17
+ timeout = 30 // Timeout in seconds
18
+ } as $api_result
19
+
20
+ // Access response
21
+ $api_result.response.status // HTTP status code (200, 404, etc.)
22
+ $api_result.response.result // Response body (auto-parsed JSON)
23
+ $api_result.response.headers // Response headers array
24
+ ```
25
+
26
+ > **Important:** The `params` parameter is used for the **request body** (POST/PUT/PATCH), not query parameters. This naming is counterintuitive but consistent across XanoScript.
27
+
28
+ > **Note:** The `headers` parameter expects an array of text strings, where each string contains the header name and value separated by a colon (e.g., `["Content-Type: application/json", "X-Custom-Header: value"]`).
29
+
30
+ ---
31
+
32
+ ## GET Request
33
+
34
+ ```xs
35
+ api.request {
36
+ url = "https://api.example.com/users?page=1&limit=10"
37
+ method = "GET"
38
+ headers = ["Authorization: Bearer " ~ $env.API_KEY]
39
+ } as $api_result
40
+
41
+ var $users { value = $api_result.response.result }
42
+ ```
43
+
44
+ ---
45
+
46
+ ## POST Request with JSON Body
47
+
48
+ ```xs
49
+ var $payload {
50
+ value = {
51
+ name: $input.name,
52
+ email: $input.email
53
+ }
54
+ }
55
+
56
+ api.request {
57
+ url = "https://api.example.com/users"
58
+ method = "POST"
59
+ params = $payload
60
+ headers = ["Content-Type: application/json", "Authorization: Bearer " ~ $env.API_KEY]
61
+ } as $api_result
62
+
63
+ // Check for success
64
+ precondition ($api_result.response.status == 201) {
65
+ error_type = "standard"
66
+ error = "Failed to create user: " ~ ($api_result.response.result|json_encode)
67
+ }
68
+ ```
69
+
70
+ ---
71
+
72
+ ## Error Handling Pattern
73
+
74
+ ```xs
75
+ api.request {
76
+ url = "https://api.example.com/data"
77
+ method = "GET"
78
+ timeout = 30
79
+ } as $api_result
80
+
81
+ conditional {
82
+ if ($api_result.response.status >= 200 && $api_result.response.status < 300) {
83
+ var $data { value = $api_result.response.result }
84
+ }
85
+ elseif ($api_result.response.status == 404) {
86
+ throw { name = "NotFound", value = "Resource not found" }
87
+ }
88
+ else {
89
+ throw {
90
+ name = "APIError",
91
+ value = "API returned status " ~ ($api_result.response.status|to_text)
92
+ }
93
+ }
94
+ }
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Response Structure
100
+
101
+ The `api.request` statement returns an object with both request and response details:
102
+
103
+ ```json
104
+ {
105
+ "request": {
106
+ "url": "", // The URL that was requested
107
+ "method": "", // HTTP method used (GET, POST, etc.)
108
+ "headers": [], // Array of request headers sent
109
+ "params": [] // Parameters sent with the request
110
+ },
111
+ "response": {
112
+ "headers": [], // Array of response headers received
113
+ "result": "", // Response body (can be any format: JSON, string, null, boolean, etc.)
114
+ "status": 200 // HTTP status code
115
+ }
116
+ }
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Accessing Response Data
122
+
123
+ ```xs
124
+ api.request {
125
+ url = "https://api.example.com/users"
126
+ method = "GET"
127
+ } as $api_result
128
+
129
+ // Access the response body
130
+ var $data { value = $api_result.response.result }
131
+
132
+ // Check status code
133
+ precondition ($api_result.response.status == 200) {
134
+ error_type = "standard"
135
+ error = "API request failed"
136
+ }
137
+
138
+ // Access a specific header
139
+ var $content_type { value = $api_result.response.headers|first }
140
+ ```
141
+
142
+ ---
143
+
144
+ ## Common Patterns
145
+
146
+ ### Retry Logic
147
+
148
+ ```xs
149
+ var $retries { value = 0 }
150
+ var $success { value = false }
151
+
152
+ while ($retries < 3 && $success == false) {
153
+ try_catch {
154
+ try {
155
+ api.request {
156
+ url = "https://api.example.com/data"
157
+ method = "GET"
158
+ timeout = 10
159
+ } as $api_result
160
+
161
+ conditional {
162
+ if ($api_result.response.status == 200) {
163
+ var.update $success { value = true }
164
+ }
165
+ }
166
+ }
167
+ catch {
168
+ var.update $retries { value = $retries + 1 }
169
+ util.sleep { value = 2 }
170
+ }
171
+ }
172
+ }
173
+ ```
174
+
175
+ ### Webhook Callback
176
+
177
+ ```xs
178
+ api.request {
179
+ url = $env.WEBHOOK_URL
180
+ method = "POST"
181
+ params = {
182
+ event: "order.created",
183
+ data: $order,
184
+ timestamp: now
185
+ }
186
+ headers = [
187
+ "Content-Type: application/json",
188
+ "X-Webhook-Signature: " ~ $signature
189
+ ]
190
+ }
191
+ ```
192
+
193
+ ---
194
+
195
+ ## Related Topics
196
+
197
+ | Topic | Description |
198
+ |-------|-------------|
199
+ | `syntax` | Error handling with try_catch |
200
+ | `integrations/utilities` | Lambda invocation |
201
+ | `integrations` | All integrations index |