@xano/developer-mcp 1.0.8 → 1.0.10

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.
@@ -0,0 +1,342 @@
1
+ ---
2
+ applyTo: "**/*.xs"
3
+ ---
4
+
5
+ # Debugging
6
+
7
+ Tools for logging, inspecting, and debugging XanoScript execution.
8
+
9
+ ## Quick Reference
10
+
11
+ | Operation | Purpose |
12
+ |-----------|---------|
13
+ | `debug.log` | Log message to console |
14
+ | `debug.stop` | Stop execution at point |
15
+ | Request history | View past executions |
16
+
17
+ ---
18
+
19
+ ## debug.log
20
+
21
+ Log messages and values for debugging.
22
+
23
+ ```xs
24
+ debug.log { value = "Starting process" }
25
+
26
+ debug.log { value = $user }
27
+
28
+ debug.log { value = { step: "validation", data: $input } }
29
+ ```
30
+
31
+ ### With Labels
32
+
33
+ ```xs
34
+ debug.log {
35
+ label = "User Data"
36
+ value = $user
37
+ }
38
+
39
+ debug.log {
40
+ label = "Query Result"
41
+ value = $products
42
+ }
43
+ ```
44
+
45
+ ### Conditional Logging
46
+
47
+ ```xs
48
+ conditional {
49
+ if ($env.DEBUG == "true") {
50
+ debug.log {
51
+ label = "Debug Info"
52
+ value = {
53
+ input: $input,
54
+ auth: $auth,
55
+ timestamp: now
56
+ }
57
+ }
58
+ }
59
+ }
60
+ ```
61
+
62
+ ---
63
+
64
+ ## debug.stop
65
+
66
+ Halt execution at a specific point for inspection.
67
+
68
+ ```xs
69
+ debug.log { value = "Before database call" }
70
+
71
+ db.query "user" {
72
+ where = $db.user.id == $input.user_id
73
+ } as $user
74
+
75
+ debug.stop // Execution pauses here
76
+
77
+ // Code below does not run
78
+ db.edit "user" { ... }
79
+ ```
80
+
81
+ ### Conditional Stop
82
+
83
+ ```xs
84
+ conditional {
85
+ if ($user == null) {
86
+ debug.log { value = "User not found, stopping" }
87
+ debug.stop
88
+ }
89
+ }
90
+ ```
91
+
92
+ ### With Data Inspection
93
+
94
+ ```xs
95
+ debug.log {
96
+ label = "State at stop point"
97
+ value = {
98
+ input: $input,
99
+ user: $user,
100
+ calculated: $total
101
+ }
102
+ }
103
+ debug.stop
104
+ ```
105
+
106
+ ---
107
+
108
+ ## Logging Patterns
109
+
110
+ ### Request Tracing
111
+
112
+ ```xs
113
+ function "process_order" {
114
+ input { int order_id }
115
+ stack {
116
+ var $trace_id { value = |uuid }
117
+
118
+ debug.log {
119
+ label = "TRACE_START"
120
+ value = { trace_id: $trace_id, order_id: $input.order_id }
121
+ }
122
+
123
+ // ... processing ...
124
+
125
+ debug.log {
126
+ label = "TRACE_END"
127
+ value = { trace_id: $trace_id, status: "success" }
128
+ }
129
+ }
130
+ }
131
+ ```
132
+
133
+ ### Error Context
134
+
135
+ ```xs
136
+ try_catch {
137
+ try {
138
+ function.run "risky_operation" { input = $data }
139
+ }
140
+ catch {
141
+ debug.log {
142
+ label = "ERROR"
143
+ value = {
144
+ operation: "risky_operation",
145
+ input: $data,
146
+ error: $error.message,
147
+ stack: $error.stack
148
+ }
149
+ }
150
+ throw { name = $error.name, value = $error.message }
151
+ }
152
+ }
153
+ ```
154
+
155
+ ### Performance Timing
156
+
157
+ ```xs
158
+ var $start { value = now|to_ms }
159
+
160
+ db.query "product" { ... } as $products
161
+
162
+ var $query_time { value = (now|to_ms) - $start }
163
+
164
+ debug.log {
165
+ label = "PERF"
166
+ value = {
167
+ operation: "product_query",
168
+ duration_ms: $query_time,
169
+ record_count: $products|count
170
+ }
171
+ }
172
+ ```
173
+
174
+ ### Step-by-Step
175
+
176
+ ```xs
177
+ debug.log { value = "Step 1: Validating input" }
178
+ // validation code
179
+
180
+ debug.log { value = "Step 2: Fetching user" }
181
+ db.get "user" { ... } as $user
182
+
183
+ debug.log { value = "Step 3: Processing order" }
184
+ // order processing
185
+
186
+ debug.log { value = "Step 4: Sending notification" }
187
+ // notification code
188
+
189
+ debug.log { value = "Complete" }
190
+ ```
191
+
192
+ ---
193
+
194
+ ## Inspecting Variables
195
+
196
+ ### Object Inspection
197
+
198
+ ```xs
199
+ debug.log {
200
+ label = "User object"
201
+ value = $user
202
+ }
203
+
204
+ // Logs full object structure:
205
+ // {
206
+ // id: 123,
207
+ // name: "John",
208
+ // email: "john@example.com",
209
+ // ...
210
+ // }
211
+ ```
212
+
213
+ ### Array Inspection
214
+
215
+ ```xs
216
+ debug.log {
217
+ label = "Products"
218
+ value = {
219
+ count: $products|count,
220
+ first: $products|first,
221
+ last: $products|last,
222
+ sample: $products|slice:0:3
223
+ }
224
+ }
225
+ ```
226
+
227
+ ### Expression Evaluation
228
+
229
+ ```xs
230
+ debug.log {
231
+ label = "Calculated values"
232
+ value = {
233
+ total: $items|map:$$.price * $$.quantity|sum,
234
+ tax: ($items|map:$$.price * $$.quantity|sum) * 0.08,
235
+ item_count: $items|count
236
+ }
237
+ }
238
+ ```
239
+
240
+ ---
241
+
242
+ ## Environment-Based Debugging
243
+
244
+ ### Development Only
245
+
246
+ ```xs
247
+ conditional {
248
+ if ($env.ENVIRONMENT == "development") {
249
+ debug.log { value = "Development mode: verbose logging enabled" }
250
+ debug.log { value = $input }
251
+ }
252
+ }
253
+ ```
254
+
255
+ ### Debug Flag
256
+
257
+ ```xs
258
+ // Enable with environment variable DEBUG=true
259
+ conditional {
260
+ if ($env.DEBUG|to_bool == true) {
261
+ debug.log {
262
+ label = "Debug"
263
+ value = { step: "after_query", data: $result }
264
+ }
265
+ }
266
+ }
267
+ ```
268
+
269
+ ---
270
+
271
+ ## Request History
272
+
273
+ View past request executions in the Xano dashboard:
274
+
275
+ 1. Navigate to API endpoint or function
276
+ 2. Click "Request History"
277
+ 3. View inputs, outputs, and debug logs
278
+ 4. Inspect step-by-step execution
279
+
280
+ ### What's Captured
281
+
282
+ - Input parameters
283
+ - Output response
284
+ - All debug.log messages
285
+ - Execution time per step
286
+ - Database queries executed
287
+ - External API calls made
288
+ - Errors and stack traces
289
+
290
+ ---
291
+
292
+ ## Debugging Strategies
293
+
294
+ ### Isolate the Problem
295
+
296
+ ```xs
297
+ // Comment out sections to isolate issues
298
+ debug.log { value = "Checkpoint 1" }
299
+ // potentially problematic code
300
+ debug.log { value = "Checkpoint 2" }
301
+ ```
302
+
303
+ ### Validate Assumptions
304
+
305
+ ```xs
306
+ debug.log {
307
+ label = "Assumption check"
308
+ value = {
309
+ user_exists: $user != null,
310
+ has_permission: $user.role == "admin",
311
+ input_valid: $input.amount > 0
312
+ }
313
+ }
314
+ ```
315
+
316
+ ### Compare Expected vs Actual
317
+
318
+ ```xs
319
+ var $expected { value = 100 }
320
+ var $actual { value = $items|count }
321
+
322
+ debug.log {
323
+ label = "Comparison"
324
+ value = {
325
+ expected: $expected,
326
+ actual: $actual,
327
+ match: $expected == $actual
328
+ }
329
+ }
330
+ ```
331
+
332
+ ---
333
+
334
+ ## Best Practices
335
+
336
+ 1. **Remove debug.stop in production** - Causes execution to halt
337
+ 2. **Use labels consistently** - Makes log searching easier
338
+ 3. **Log at boundaries** - Function entry/exit, external calls
339
+ 4. **Include context** - IDs, timestamps, relevant state
340
+ 5. **Don't log sensitive data** - Passwords, tokens, PII
341
+ 6. **Use environment flags** - Enable verbose logging conditionally
342
+ 7. **Check request history** - Built-in debugging in dashboard
@@ -292,6 +292,176 @@ function "validate_email_unique" {
292
292
 
293
293
  ---
294
294
 
295
+ ## Async Operations
296
+
297
+ ### await
298
+
299
+ Wait for an asynchronous operation to complete.
300
+
301
+ ```xs
302
+ stack {
303
+ api.request {
304
+ url = "https://api.example.com/data"
305
+ method = "GET"
306
+ async = true
307
+ } as $request
308
+
309
+ await $request as $response
310
+ }
311
+ ```
312
+
313
+ ### group (Parallel Execution)
314
+
315
+ Execute multiple operations in parallel and wait for all to complete.
316
+
317
+ ```xs
318
+ stack {
319
+ group {
320
+ api.request {
321
+ url = "https://api.example.com/users"
322
+ method = "GET"
323
+ } as $users
324
+
325
+ api.request {
326
+ url = "https://api.example.com/products"
327
+ method = "GET"
328
+ } as $products
329
+
330
+ api.request {
331
+ url = "https://api.example.com/orders"
332
+ method = "GET"
333
+ } as $orders
334
+ }
335
+
336
+ // All three requests complete before continuing
337
+ var $combined {
338
+ value = {
339
+ users: $users.body,
340
+ products: $products.body,
341
+ orders: $orders.body
342
+ }
343
+ }
344
+ }
345
+ ```
346
+
347
+ ### Parallel Database Queries
348
+
349
+ ```xs
350
+ stack {
351
+ group {
352
+ db.query "user" {
353
+ where = $db.user.is_active == true
354
+ return = { type: "count" }
355
+ } as $active_users
356
+
357
+ db.query "order" {
358
+ where = $db.order.created_at >= $input.start_date
359
+ return = { type: "count" }
360
+ } as $order_count
361
+
362
+ db.query "product" {
363
+ where = $db.product.stock == 0
364
+ return = { type: "count" }
365
+ } as $out_of_stock
366
+ }
367
+
368
+ response = {
369
+ active_users: $active_users,
370
+ orders: $order_count,
371
+ out_of_stock: $out_of_stock
372
+ }
373
+ }
374
+ ```
375
+
376
+ ---
377
+
378
+ ## Advanced Loop Patterns
379
+
380
+ ### remove (In-Loop Deletion)
381
+
382
+ Remove the current element during foreach iteration.
383
+
384
+ ```xs
385
+ stack {
386
+ var $items { value = $input.items }
387
+
388
+ foreach ($items) {
389
+ each as $item {
390
+ conditional {
391
+ if ($item.expired == true) {
392
+ remove
393
+ }
394
+ }
395
+ }
396
+ }
397
+
398
+ // $items now excludes expired items
399
+ }
400
+ ```
401
+
402
+ ### as (Variable Aliasing)
403
+
404
+ Alias loop variables for clearer access.
405
+
406
+ ```xs
407
+ foreach ($orders) {
408
+ each as $order {
409
+ // $order available here
410
+ foreach ($order.items) {
411
+ each as $item {
412
+ // Both $order and $item available
413
+ db.add "order_item" {
414
+ data = {
415
+ order_id: $order.id,
416
+ product_id: $item.product_id,
417
+ quantity: $item.quantity
418
+ }
419
+ }
420
+ }
421
+ }
422
+ }
423
+ }
424
+ ```
425
+
426
+ ### Loop Control
427
+
428
+ ```xs
429
+ foreach ($items) {
430
+ each as $item {
431
+ conditional {
432
+ if ($item.skip) {
433
+ continue // Skip to next iteration
434
+ }
435
+ }
436
+
437
+ conditional {
438
+ if ($item.stop) {
439
+ break // Exit loop entirely
440
+ }
441
+ }
442
+
443
+ // Process item
444
+ }
445
+ }
446
+ ```
447
+
448
+ ### Loop with Index
449
+
450
+ ```xs
451
+ foreach ($items) {
452
+ each as $item, $index {
453
+ db.add "item" {
454
+ data = {
455
+ value: $item,
456
+ position: $index
457
+ }
458
+ }
459
+ }
460
+ }
461
+ ```
462
+
463
+ ---
464
+
295
465
  ## Best Practices
296
466
 
297
467
  1. **Single responsibility** - Each function does one thing well
@@ -299,3 +469,5 @@ function "validate_email_unique" {
299
469
  3. **Organize in folders** - Group related functions: `utils/`, `auth/`, `orders/`
300
470
  4. **Return early** - Use return for guard clauses
301
471
  5. **Keep stacks shallow** - Avoid deeply nested conditionals
472
+ 6. **Use group for parallel calls** - Improves performance for independent operations
473
+ 7. **Use remove sparingly** - Consider filtering arrays instead