@xano/developer-mcp 1.0.33 → 1.0.35

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,653 @@
1
+ ---
2
+ applyTo: "**/*.xs"
3
+ ---
4
+
5
+ # Quickstart & Common Patterns
6
+
7
+ Essential patterns for XanoScript development. Use this as a quick reference for frequently-used code patterns.
8
+
9
+ ## Quick Reference
10
+
11
+ ### Reserved Variable Names
12
+
13
+ These variable names are reserved and cannot be used:
14
+
15
+ | Variable | Description |
16
+ |----------|-------------|
17
+ | `$response` | API/function response (auto-populated) |
18
+ | `$output` | Output value |
19
+ | `$input` | Input parameters from request/function call |
20
+ | `$auth` | Authenticated user context |
21
+ | `$env` | Environment variables and request context |
22
+ | `$db` | Database table reference for queries |
23
+ | `$this` | Current context reference |
24
+ | `$result` | Used in reduce operations |
25
+
26
+ ```xs
27
+ // ❌ Wrong - using reserved variable name
28
+ var $response { value = "test" } // Error: $response is reserved
29
+
30
+ // ✅ Correct - use a different name
31
+ var $api_response { value = "test" }
32
+ var $my_result { value = "test" }
33
+ ```
34
+
35
+ ### Type Names (Common Aliases)
36
+
37
+ XanoScript uses specific type names. Common aliases from other languages won't work.
38
+
39
+ > **Full reference:** For complete type details and validation, see `xanoscript_docs({ topic: "types" })`.
40
+
41
+ | ❌ Wrong | ✅ Correct | Description |
42
+ |----------|------------|-------------|
43
+ | `boolean` | `bool` | Boolean true/false |
44
+ | `integer` | `int` | 32-bit integer |
45
+ | `string` | `text` | UTF-8 string |
46
+ | `number` | `decimal` | Floating-point number |
47
+ | `float` | `decimal` | Floating-point number |
48
+ | `array` | `type[]` | Array (e.g., `text[]`, `int[]`) |
49
+ | `list` | `type[]` | Array (e.g., `text[]`, `int[]`) |
50
+
51
+ ```xs
52
+ // ❌ Wrong - invalid type names
53
+ input {
54
+ boolean is_active // Error: use "bool"
55
+ integer count // Error: use "int"
56
+ string name // Error: use "text"
57
+ }
58
+
59
+ // ✅ Correct - proper XanoScript types
60
+ input {
61
+ bool is_active
62
+ int count
63
+ text name
64
+ }
65
+ ```
66
+
67
+ ### Variable Declaration
68
+ ```xs
69
+ var $name { value = "initial value" }
70
+ var $count { value = 0 }
71
+ var $data { value = { key: "value" } }
72
+ ```
73
+
74
+ ### Conditional Logic
75
+ ```xs
76
+ conditional {
77
+ if (`$status == "active"`) {
78
+ var $result { value = "Active user" }
79
+ }
80
+ elseif (`$status == "pending"`) {
81
+ var $result { value = "Pending approval" }
82
+ }
83
+ else {
84
+ var $result { value = "Unknown status" }
85
+ }
86
+ }
87
+ ```
88
+
89
+ ### API Request with Error Handling
90
+ ```xs
91
+ api.request {
92
+ url = "https://api.example.com/data"
93
+ method = "POST"
94
+ params = $payload // Note: "params" is used for request body, NOT "body"
95
+ headers = ["Content-Type: application/json", "Authorization: Bearer " ~ $env.API_KEY]
96
+ } as $api_result
97
+
98
+ precondition ($api_result.response.status == 200) {
99
+ error_type = "standard"
100
+ error = "API request failed"
101
+ }
102
+
103
+ var $data { value = $api_result.response.result }
104
+ ```
105
+
106
+ ### api.request Response Structure
107
+ The response object contains:
108
+ ```xs
109
+ $result.response.status // HTTP status code (200, 404, 500, etc.)
110
+ $result.response.result // Parsed response body (JSON decoded)
111
+ $result.response.headers // Response headers object
112
+ ```
113
+
114
+ ### While Loop
115
+ ```xs
116
+ stack {
117
+ var $counter { value = 0 }
118
+ while ($counter < 10) {
119
+ each {
120
+ var.update $counter { value = $counter + 1 }
121
+ debug.log { value = "Iteration: " ~ ($counter|to_text) }
122
+ }
123
+ }
124
+ }
125
+ ```
126
+
127
+ ### String Concatenation
128
+ ```xs
129
+ var $greeting { value = "Hello, " ~ $input.name ~ "!" }
130
+
131
+ // With filters (use parentheses)
132
+ var $message { value = "Status: " ~ ($status|to_text) ~ " - " ~ ($data|json_encode) }
133
+ ```
134
+
135
+ ### Input Block Syntax
136
+
137
+ > **Full reference:** For complete input types and validation options, see `xanoscript_docs({ topic: "types" })`.
138
+
139
+ ```xs
140
+ input {
141
+ // Required input
142
+ text name
143
+
144
+ // Optional input (can be omitted)
145
+ text nickname?
146
+
147
+ // Optional with default value
148
+ text role?="user"
149
+
150
+ // With filters applied
151
+ email contact filters=trim|lower
152
+
153
+ // Optional with default AND filters
154
+ text search?="" filters=trim
155
+
156
+ // Array type
157
+ text[] tags filters=trim
158
+
159
+ // Nested object with schema
160
+ object address {
161
+ schema {
162
+ text street
163
+ text city
164
+ text country?="US"
165
+ }
166
+ }
167
+ }
168
+ ```
169
+
170
+ ### Error Types Reference
171
+
172
+ > **Full reference:** For try-catch, throw, and preconditions, see `xanoscript_docs({ topic: "syntax" })`.
173
+
174
+ | Type | HTTP Status | Use Case |
175
+ |------|-------------|----------|
176
+ | `inputerror` | 400 Bad Request | Invalid input data |
177
+ | `accessdenied` | 403 Forbidden | Authorization failure |
178
+ | `notfound` | 404 Not Found | Resource doesn't exist |
179
+ | `standard` | 500 Internal Server Error | General errors |
180
+
181
+ ### Quick Filter Reference
182
+
183
+ > **Full reference:** For the complete list of filters with examples, see `xanoscript_docs({ topic: "syntax" })`.
184
+
185
+ **String Filters:**
186
+ ```xs
187
+ $s|trim // Remove whitespace
188
+ $s|to_lower // Lowercase
189
+ $s|to_upper // Uppercase
190
+ $s|substr:1:3 // Substring from index 1, length 3
191
+ $s|split:"," // Split by delimiter → array
192
+ $s|replace:"old":"new" // Replace text
193
+ $s|contains:"text" // Check if contains → bool
194
+ $s|strlen // String length
195
+ ```
196
+
197
+ **Array Filters:**
198
+ ```xs
199
+ $arr|first // First element
200
+ $arr|last // Last element
201
+ $arr|count // Array length
202
+ $arr|push:$item // Add to end
203
+ $arr|pop // Remove & return last
204
+ $arr|join:"," // Join to string
205
+ $arr|map:$$.name // Transform elements
206
+ $arr|filter:$$.active // Filter elements
207
+ $arr|find:$$.id == 5 // Find first match
208
+ ```
209
+
210
+ **Object Filters:**
211
+ ```xs
212
+ $obj|get:"key" // Get property value
213
+ $obj|get:"key":"default" // With default if missing
214
+ $obj|set:"key":"value" // Set property
215
+ $obj|has:"key" // Check if key exists → bool
216
+ $obj|keys // Get all keys → array
217
+ $obj|values // Get all values → array
218
+ ```
219
+
220
+ **Type Conversion:**
221
+ ```xs
222
+ $val|to_text // Convert to string
223
+ $val|to_int // Convert to integer
224
+ $val|to_decimal // Convert to decimal
225
+ $val|to_bool // Convert to boolean
226
+ $val|json_encode // Object → JSON string
227
+ $str|json_decode // JSON string → object
228
+ ```
229
+
230
+ **Null Handling:**
231
+ ```xs
232
+ $val|first_notnull:"default" // Default if null
233
+ $val|first_notempty:"default" // Default if empty
234
+ $val ?? "default" // Nullish coalescing (same as first_notnull)
235
+ ```
236
+
237
+ **Encoding:**
238
+ ```xs
239
+ $s|url_encode // URL encode
240
+ $s|url_decode // URL decode
241
+ $s|base64_encode // Base64 encode
242
+ $s|base64_decode // Base64 decode
243
+ ```
244
+
245
+ ---
246
+
247
+ ## Common Patterns
248
+
249
+ ### 1. Input Validation
250
+
251
+ ```xs
252
+ // Required field check
253
+ precondition ($input.email != null && $input.email != "") {
254
+ error_type = "inputerror"
255
+ error = "Email is required"
256
+ }
257
+
258
+ // Format validation
259
+ precondition ($input.email|contains:"@") {
260
+ error_type = "inputerror"
261
+ error = "Invalid email format"
262
+ }
263
+ ```
264
+
265
+ ### 2. Database CRUD
266
+
267
+ > **Full reference:** For all db.* operations including transactions, see `xanoscript_docs({ topic: "database" })`.
268
+
269
+ ```xs
270
+ // Create
271
+ db.add "user" {
272
+ data = { name: $input.name, email: $input.email }
273
+ } as $new_user
274
+
275
+ // Read one
276
+ db.get "user" {
277
+ where = $db.user.id == $input.id
278
+ } as $user
279
+
280
+ // Read many
281
+ db.query "user" {
282
+ where = $db.user.is_active == true
283
+ order = [{ field: created_at, direction: desc }]
284
+ paging = { limit: 10, offset: 0 }
285
+ } as $users
286
+
287
+ // Update
288
+ db.edit "user" {
289
+ where = $db.user.id == $input.id
290
+ data = { name: $input.name }
291
+ }
292
+
293
+ // Delete
294
+ db.delete "user" {
295
+ where = $db.user.id == $input.id
296
+ }
297
+ ```
298
+
299
+ ### 3. Optional Field Handling
300
+
301
+ ```xs
302
+ // Build object with optional fields
303
+ var $data { value = { required_field: $input.required } }
304
+
305
+ conditional {
306
+ if ($input.optional_field != null) {
307
+ var.update $data { value = $data|set:"optional_field":$input.optional_field }
308
+ }
309
+ }
310
+
311
+ // Or use set_ifnotnull
312
+ var $data {
313
+ value = { required: $input.required }|set_ifnotnull:"optional":$input.optional
314
+ }
315
+ ```
316
+
317
+ ### 4. Loop Through Array
318
+
319
+ ```xs
320
+ // Using each
321
+ each ($items as $item) {
322
+ debug.log { value = $item.name }
323
+ }
324
+
325
+ // Using map filter
326
+ var $names { value = $items|map:$$.name }
327
+
328
+ // Using filter
329
+ var $active_items { value = $items|filter:$$.is_active == true }
330
+ ```
331
+
332
+ ### 5. Error Handling with Try-Catch
333
+
334
+ > **Full reference:** For all error handling patterns, see `xanoscript_docs({ topic: "syntax" })`.
335
+
336
+ ```xs
337
+ try_catch {
338
+ try {
339
+ api.request {
340
+ url = "https://api.example.com/risky"
341
+ method = "GET"
342
+ } as $result
343
+ }
344
+ catch {
345
+ debug.log { value = "Request failed, using fallback" }
346
+ var $result { value = { response: { result: null } } }
347
+ }
348
+ }
349
+ ```
350
+
351
+ ### 6. Authentication Check
352
+
353
+ > **Full reference:** For security best practices, see `xanoscript_docs({ topic: "security" })`.
354
+
355
+ ```xs
356
+ // Require authenticated user
357
+ precondition ($auth.id != null) {
358
+ error_type = "accessdenied"
359
+ error = "Authentication required"
360
+ }
361
+
362
+ // Check user owns resource
363
+ db.get "post" {
364
+ where = $db.post.id == $input.post_id
365
+ } as $post
366
+
367
+ precondition ($post.user_id == $auth.id) {
368
+ error_type = "accessdenied"
369
+ error = "You can only edit your own posts"
370
+ }
371
+ ```
372
+
373
+ ### 7. Pagination
374
+
375
+ ```xs
376
+ var $page { value = $input.page ?? 1 }
377
+ var $limit { value = $input.limit ?? 20 }
378
+ var $offset { value = ($page - 1) * $limit }
379
+
380
+ db.query "item" {
381
+ where = $db.item.is_active == true
382
+ order = [{ field: created_at, direction: desc }]
383
+ paging = { limit: $limit, offset: $offset }
384
+ count = true
385
+ } as $result
386
+
387
+ response = {
388
+ items: $result.items,
389
+ total: $result.count,
390
+ page: $page,
391
+ pages: ($result.count / $limit)|ceil
392
+ }
393
+ ```
394
+
395
+ ### 8. Building Complex Objects
396
+
397
+ ```xs
398
+ // Step by step
399
+ var $response { value = {} }
400
+ var.update $response { value = $response|set:"user":$user }
401
+ var.update $response { value = $response|set:"posts":$posts }
402
+ var.update $response { value = $response|set:"stats":{ count: $posts|count } }
403
+
404
+ // Or all at once
405
+ var $response {
406
+ value = {
407
+ user: $user,
408
+ posts: $posts,
409
+ stats: { count: $posts|count }
410
+ }
411
+ }
412
+ ```
413
+
414
+ ### 9. Date/Time Operations
415
+
416
+ > **Full reference:** For all date/time filters, see `xanoscript_docs({ topic: "syntax" })`.
417
+
418
+ ```xs
419
+ // Current timestamp
420
+ var $now { value = now }
421
+
422
+ // Format for display
423
+ var $formatted { value = now|format_timestamp:"Y-m-d H:i:s":"UTC" }
424
+
425
+ // Relative time
426
+ var $yesterday { value = now|transform_timestamp:"-1 day" }
427
+ var $next_week { value = now|transform_timestamp:"+7 days" }
428
+
429
+ // Compare dates
430
+ db.query "event" {
431
+ where = $db.event.start_date >= now
432
+ } as $upcoming_events
433
+ ```
434
+
435
+ ### 10. JSON API Response
436
+
437
+ > **Full reference:** For external API patterns, see `xanoscript_docs({ topic: "integrations" })`.
438
+
439
+ ```xs
440
+ api.request {
441
+ url = "https://api.openai.com/v1/chat/completions"
442
+ method = "POST"
443
+ params = {
444
+ model: "gpt-4",
445
+ messages: [{ role: "user", content: $input.prompt }]
446
+ }
447
+ headers = [
448
+ "Content-Type: application/json",
449
+ "Authorization: Bearer " ~ $env.OPENAI_API_KEY
450
+ ]
451
+ } as $api_result
452
+
453
+ conditional {
454
+ if ($api_result.response.status == 200) {
455
+ var $answer { value = $api_result.response.result.choices|first|get:"message"|get:"content" }
456
+ }
457
+ else {
458
+ throw {
459
+ name = "APIError",
460
+ value = "OpenAI API error: " ~ ($api_result.response.status|to_text)
461
+ }
462
+ }
463
+ }
464
+ ```
465
+
466
+ ---
467
+
468
+ ## Common Mistakes
469
+
470
+ ### 1. Using `else if` instead of `elseif`
471
+ ```xs
472
+ // ❌ Wrong
473
+ conditional {
474
+ if (...) { }
475
+ else if (...) { } // Parse error!
476
+ }
477
+
478
+ // ✅ Correct
479
+ conditional {
480
+ if (...) { }
481
+ elseif (...) { }
482
+ }
483
+ ```
484
+
485
+ ### 2. Missing parentheses in filter concatenation
486
+ ```xs
487
+ // ❌ Wrong - parse error
488
+ var $msg { value = $status|to_text ~ " - " ~ $data|json_encode }
489
+
490
+ // ✅ Correct - wrap filtered expressions in parentheses
491
+ var $msg { value = ($status|to_text) ~ " - " ~ ($data|json_encode) }
492
+ ```
493
+
494
+ ### 3. Missing parentheses in filter comparisons
495
+ ```xs
496
+ // ❌ Wrong - parse error
497
+ if ($array|count > 0) { }
498
+
499
+ // ✅ Correct - wrap filter expression in parentheses
500
+ if (($array|count) > 0) { }
501
+ ```
502
+
503
+ ### 4. Using `body` instead of `params` for api.request
504
+ ```xs
505
+ // ❌ Wrong - "body" is not valid
506
+ api.request {
507
+ url = "..."
508
+ method = "POST"
509
+ body = $payload
510
+ }
511
+
512
+ // ✅ Correct - use "params" for request body
513
+ api.request {
514
+ url = "..."
515
+ method = "POST"
516
+ params = $payload
517
+ }
518
+ ```
519
+
520
+ ### 5. Using `default` filter (doesn't exist)
521
+ ```xs
522
+ // ❌ Wrong - no "default" filter exists
523
+ var $value { value = $input.optional|default:"fallback" }
524
+
525
+ // ✅ Correct - use first_notnull or ?? operator
526
+ var $value { value = $input.optional|first_notnull:"fallback" }
527
+ // or
528
+ var $value { value = $input.optional ?? "fallback" }
529
+
530
+ // For object key access with default, use get with 3rd parameter
531
+ var $val { value = $obj|get:"key":"default_value" }
532
+ ```
533
+
534
+ ### 6. Using reserved variable names
535
+ ```xs
536
+ // ❌ Wrong - $response is reserved
537
+ var $response { value = "test" }
538
+
539
+ // ✅ Correct - use a different name
540
+ var $api_response { value = "test" }
541
+ ```
542
+
543
+ ### 7. Wrong type names
544
+ ```xs
545
+ // ❌ Wrong - invalid type names
546
+ input {
547
+ boolean active // Use "bool"
548
+ integer count // Use "int"
549
+ string name // Use "text"
550
+ }
551
+
552
+ // ✅ Correct
553
+ input {
554
+ bool active
555
+ int count
556
+ text name
557
+ }
558
+ ```
559
+
560
+ ### 8. Object literal syntax (using = instead of :)
561
+ ```xs
562
+ // ❌ Wrong - object literals use : not =
563
+ var $data { value = { customer = $id } }
564
+
565
+ // ✅ Correct - use : for object properties
566
+ var $data { value = { customer: $id } }
567
+ ```
568
+
569
+ ### 9. Throw block with commas
570
+ ```xs
571
+ // ❌ Wrong - throw blocks don't use commas
572
+ throw {
573
+ name = "Error",
574
+ value = "message"
575
+ }
576
+
577
+ // ✅ Correct - no commas between properties
578
+ throw {
579
+ name = "Error"
580
+ value = "message"
581
+ }
582
+ ```
583
+
584
+ ### 10. Using $env in run.job input blocks
585
+ ```xs
586
+ // ❌ Wrong - $env not allowed in input blocks
587
+ run.job "my_job" {
588
+ input {
589
+ text api_key = $env.API_KEY
590
+ }
591
+ }
592
+
593
+ // ✅ Correct - access $env in the stack instead
594
+ run.job "my_job" {
595
+ stack {
596
+ var $api_key { value = $env.API_KEY }
597
+ }
598
+ }
599
+ ```
600
+
601
+ ### 11. Using `object` type without schema
602
+ ```xs
603
+ // ❌ Wrong - object requires a schema
604
+ input {
605
+ object data // Error: needs schema
606
+ }
607
+
608
+ // ✅ Correct - use json for arbitrary data
609
+ input {
610
+ json data // Accepts any JSON
611
+ }
612
+
613
+ // ✅ Or define a schema for object
614
+ input {
615
+ object data {
616
+ schema {
617
+ text name
618
+ int id
619
+ }
620
+ }
621
+ }
622
+ ```
623
+
624
+ ### 12. While loop outside of stack block
625
+ ```xs
626
+ // ❌ Wrong - while must be inside stack
627
+ while (true) {
628
+ each { ... }
629
+ }
630
+
631
+ // ✅ Correct - wrap in stack block
632
+ stack {
633
+ while (true) {
634
+ each { ... }
635
+ }
636
+ }
637
+ ```
638
+
639
+ ---
640
+
641
+ ## Related Topics
642
+
643
+ Explore more with `xanoscript_docs({ topic: "<topic>" })`:
644
+
645
+ | Topic | Description |
646
+ |-------|-------------|
647
+ | `syntax` | Complete filter reference, operators, system variables |
648
+ | `types` | Data types, input validation, schema definitions |
649
+ | `database` | All db.* operations: query, get, add, edit, delete |
650
+ | `functions` | Reusable function stacks, async patterns, loops |
651
+ | `apis` | HTTP endpoints, authentication, CRUD patterns |
652
+ | `security` | Security best practices and authentication |
653
+ | `integrations` | External API patterns (OpenAI, Stripe, etc.) |