@xano/developer-mcp 1.0.35 → 1.0.37
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.
- package/README.md +21 -4
- package/dist/xanoscript.js +40 -5
- package/dist/xanoscript.test.js +9 -2
- package/dist/xanoscript_docs/README.md +46 -42
- package/dist/xanoscript_docs/addons.md +10 -0
- package/dist/xanoscript_docs/agents.md +15 -0
- package/dist/xanoscript_docs/apis.md +45 -24
- package/dist/xanoscript_docs/cheatsheet.md +252 -0
- package/dist/xanoscript_docs/database.md +23 -0
- package/dist/xanoscript_docs/docs_index.json +241 -0
- package/dist/xanoscript_docs/frontend.md +10 -0
- package/dist/xanoscript_docs/functions.md +4 -0
- package/dist/xanoscript_docs/integrations/cloud-storage.md +142 -0
- package/dist/xanoscript_docs/integrations/external-apis.md +201 -0
- package/dist/xanoscript_docs/integrations/redis.md +194 -0
- package/dist/xanoscript_docs/integrations/search.md +242 -0
- package/dist/xanoscript_docs/integrations/utilities.md +331 -0
- package/dist/xanoscript_docs/integrations.md +55 -901
- package/dist/xanoscript_docs/mcp-servers.md +10 -0
- package/dist/xanoscript_docs/performance.md +15 -0
- package/dist/xanoscript_docs/quickstart.md +22 -88
- package/dist/xanoscript_docs/run.md +10 -0
- package/dist/xanoscript_docs/security.md +26 -0
- package/dist/xanoscript_docs/streaming.md +10 -0
- package/dist/xanoscript_docs/syntax.md +56 -0
- package/dist/xanoscript_docs/tables.md +15 -0
- package/dist/xanoscript_docs/tasks.md +11 -0
- package/dist/xanoscript_docs/tools.md +15 -0
- package/dist/xanoscript_docs/triggers.md +57 -192
- package/dist/xanoscript_docs/types.md +4 -0
- package/dist/xanoscript_docs/{testing.md → unit-testing.md} +15 -3
- package/dist/xanoscript_docs/workflow-tests.md +333 -0
- package/package.json +1 -1
|
@@ -6,6 +6,29 @@ applyTo: "function/**/*.xs, api/**/*.xs, task/**/*.xs, tool/**/*.xs"
|
|
|
6
6
|
|
|
7
7
|
Complete reference for XanoScript database operations.
|
|
8
8
|
|
|
9
|
+
> **TL;DR:** Use `db.get` for single record by ID, `db.query` for filtered lists, `db.has` to check existence, `db.add` to insert, `db.edit` for inline updates, `db.patch` for dynamic fields, `db.del` to delete.
|
|
10
|
+
|
|
11
|
+
## Choosing an Operation
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
Need to...
|
|
15
|
+
├── Read data?
|
|
16
|
+
│ ├── Single record by ID? → db.get
|
|
17
|
+
│ ├── Check if exists? → db.has
|
|
18
|
+
│ └── Filtered list? → db.query
|
|
19
|
+
├── Write data?
|
|
20
|
+
│ ├── New record? → db.add
|
|
21
|
+
│ ├── Update known fields? → db.edit
|
|
22
|
+
│ └── Update dynamic fields? → db.patch
|
|
23
|
+
├── Delete data?
|
|
24
|
+
│ ├── Single record? → db.del
|
|
25
|
+
│ └── All records? → db.truncate
|
|
26
|
+
└── Complex query?
|
|
27
|
+
├── Join tables? → db.query with join
|
|
28
|
+
├── Aggregate? → db.query with evals
|
|
29
|
+
└── Transaction? → db.transaction
|
|
30
|
+
```
|
|
31
|
+
|
|
9
32
|
## Quick Reference
|
|
10
33
|
|
|
11
34
|
| Operation | Purpose | Returns |
|
|
@@ -0,0 +1,241 @@
|
|
|
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
|
+
"unit-testing": {
|
|
132
|
+
"file": "unit-testing.md",
|
|
133
|
+
"purpose": "Unit tests, mocks, and assertions",
|
|
134
|
+
"aliases": ["tests", "unit-tests", "mocks", "assertions"]
|
|
135
|
+
},
|
|
136
|
+
"workflow-tests": {
|
|
137
|
+
"file": "workflow-tests.md",
|
|
138
|
+
"purpose": "End-to-end workflow tests",
|
|
139
|
+
"aliases": ["e2e", "workflow", "integration-tests"]
|
|
140
|
+
},
|
|
141
|
+
"debugging": {
|
|
142
|
+
"file": "debugging.md",
|
|
143
|
+
"purpose": "Logging and debugging",
|
|
144
|
+
"aliases": ["logs", "debug", "trace"]
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
"filters": {
|
|
149
|
+
"trim": { "file": "syntax.md", "category": "string" },
|
|
150
|
+
"ltrim": { "file": "syntax.md", "category": "string" },
|
|
151
|
+
"rtrim": { "file": "syntax.md", "category": "string" },
|
|
152
|
+
"to_lower": { "file": "syntax.md", "category": "string" },
|
|
153
|
+
"to_upper": { "file": "syntax.md", "category": "string" },
|
|
154
|
+
"capitalize": { "file": "syntax.md", "category": "string" },
|
|
155
|
+
"substr": { "file": "syntax.md", "category": "string" },
|
|
156
|
+
"split": { "file": "syntax.md", "category": "string" },
|
|
157
|
+
"replace": { "file": "syntax.md", "category": "string" },
|
|
158
|
+
"contains": { "file": "syntax.md", "category": "string" },
|
|
159
|
+
"strlen": { "file": "syntax.md", "category": "string" },
|
|
160
|
+
"first": { "file": "syntax.md", "category": "array" },
|
|
161
|
+
"last": { "file": "syntax.md", "category": "array" },
|
|
162
|
+
"count": { "file": "syntax.md", "category": "array" },
|
|
163
|
+
"map": { "file": "syntax.md", "category": "array" },
|
|
164
|
+
"filter": { "file": "syntax.md", "category": "array" },
|
|
165
|
+
"find": { "file": "syntax.md", "category": "array" },
|
|
166
|
+
"reduce": { "file": "syntax.md", "category": "array" },
|
|
167
|
+
"push": { "file": "syntax.md", "category": "array" },
|
|
168
|
+
"pop": { "file": "syntax.md", "category": "array" },
|
|
169
|
+
"join": { "file": "syntax.md", "category": "array" },
|
|
170
|
+
"sort": { "file": "syntax.md", "category": "array" },
|
|
171
|
+
"unique": { "file": "syntax.md", "category": "array" },
|
|
172
|
+
"get": { "file": "syntax.md", "category": "object" },
|
|
173
|
+
"set": { "file": "syntax.md", "category": "object" },
|
|
174
|
+
"has": { "file": "syntax.md", "category": "object" },
|
|
175
|
+
"keys": { "file": "syntax.md", "category": "object" },
|
|
176
|
+
"values": { "file": "syntax.md", "category": "object" },
|
|
177
|
+
"to_int": { "file": "syntax.md", "category": "type" },
|
|
178
|
+
"to_text": { "file": "syntax.md", "category": "type" },
|
|
179
|
+
"to_bool": { "file": "syntax.md", "category": "type" },
|
|
180
|
+
"to_decimal": { "file": "syntax.md", "category": "type" },
|
|
181
|
+
"json_encode": { "file": "syntax.md", "category": "type" },
|
|
182
|
+
"json_decode": { "file": "syntax.md", "category": "type" },
|
|
183
|
+
"round": { "file": "syntax.md", "category": "math" },
|
|
184
|
+
"abs": { "file": "syntax.md", "category": "math" },
|
|
185
|
+
"ceil": { "file": "syntax.md", "category": "math" },
|
|
186
|
+
"floor": { "file": "syntax.md", "category": "math" },
|
|
187
|
+
"add": { "file": "syntax.md", "category": "math" },
|
|
188
|
+
"subtract": { "file": "syntax.md", "category": "math" }
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
"constructs": {
|
|
192
|
+
"table": { "file": "tables.md", "triggers": "triggers.md" },
|
|
193
|
+
"function": { "file": "functions.md", "testing": "unit-testing.md" },
|
|
194
|
+
"query": { "file": "apis.md", "auth": "security.md" },
|
|
195
|
+
"api_group": { "file": "apis.md" },
|
|
196
|
+
"task": { "file": "tasks.md" },
|
|
197
|
+
"agent": { "file": "agents.md", "tools": "tools.md" },
|
|
198
|
+
"tool": { "file": "tools.md", "mcp": "mcp-servers.md" },
|
|
199
|
+
"mcp_server": { "file": "mcp-servers.md", "triggers": "triggers.md" },
|
|
200
|
+
"table_trigger": { "file": "triggers.md", "section": "table-trigger" },
|
|
201
|
+
"realtime_trigger": { "file": "triggers.md", "section": "realtime-trigger" },
|
|
202
|
+
"workspace_trigger": { "file": "triggers.md", "section": "workspace-trigger" },
|
|
203
|
+
"agent_trigger": { "file": "triggers.md", "section": "agent-trigger" },
|
|
204
|
+
"mcp_server_trigger": { "file": "triggers.md", "section": "mcp-server-trigger" },
|
|
205
|
+
"addon": { "file": "addons.md" },
|
|
206
|
+
"middleware": { "file": "middleware.md" },
|
|
207
|
+
"realtime_channel": { "file": "realtime.md" }
|
|
208
|
+
},
|
|
209
|
+
|
|
210
|
+
"operations": {
|
|
211
|
+
"db.query": { "file": "database.md" },
|
|
212
|
+
"db.get": { "file": "database.md" },
|
|
213
|
+
"db.has": { "file": "database.md" },
|
|
214
|
+
"db.add": { "file": "database.md" },
|
|
215
|
+
"db.edit": { "file": "database.md" },
|
|
216
|
+
"db.patch": { "file": "database.md" },
|
|
217
|
+
"db.del": { "file": "database.md" },
|
|
218
|
+
"db.truncate": { "file": "database.md" },
|
|
219
|
+
"api.request": { "file": "integrations/external-apis.md" },
|
|
220
|
+
"function.run": { "file": "functions.md" },
|
|
221
|
+
"redis.get": { "file": "integrations/redis.md" },
|
|
222
|
+
"redis.set": { "file": "integrations/redis.md" },
|
|
223
|
+
"storage.s3_put": { "file": "integrations/cloud-storage.md" },
|
|
224
|
+
"storage.s3_get": { "file": "integrations/cloud-storage.md" }
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
"tasks": {
|
|
228
|
+
"authentication": ["security.md", "apis.md"],
|
|
229
|
+
"authorization": ["security.md"],
|
|
230
|
+
"rate_limiting": ["security.md", "integrations/redis.md"],
|
|
231
|
+
"error_handling": ["syntax.md", "quickstart.md"],
|
|
232
|
+
"pagination": ["database.md", "apis.md"],
|
|
233
|
+
"file_upload": ["integrations/cloud-storage.md", "streaming.md"],
|
|
234
|
+
"caching": ["performance.md", "integrations/redis.md"],
|
|
235
|
+
"search": ["integrations/search.md"],
|
|
236
|
+
"email": ["integrations/utilities.md"],
|
|
237
|
+
"scheduled_jobs": ["tasks.md"],
|
|
238
|
+
"realtime": ["realtime.md", "triggers.md"],
|
|
239
|
+
"ai_agents": ["agents.md", "tools.md", "mcp-servers.md"]
|
|
240
|
+
}
|
|
241
|
+
}
|
|
@@ -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
|
|
@@ -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 |
|