@xano/developer-mcp 1.0.26 → 1.0.27

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 (75) hide show
  1. package/dist/xanoscript_docs/README.md +78 -64
  2. package/dist/xanoscript_docs/apis.md +81 -27
  3. package/dist/xanoscript_docs/branch.md +13 -13
  4. package/dist/xanoscript_docs/database.md +57 -17
  5. package/dist/xanoscript_docs/functions.md +43 -71
  6. package/dist/xanoscript_docs/performance.md +14 -23
  7. package/dist/xanoscript_docs/tables.md +47 -1
  8. package/dist/xanoscript_docs/tools.md +9 -7
  9. package/dist/xanoscript_docs/types.md +12 -10
  10. package/package.json +1 -1
  11. package/dist/api_docs/format.d.ts +0 -5
  12. package/dist/api_docs/format.js +0 -171
  13. package/dist/api_docs/index.d.ts +0 -52
  14. package/dist/api_docs/index.js +0 -111
  15. package/dist/api_docs/topics/agent.d.ts +0 -2
  16. package/dist/api_docs/topics/agent.js +0 -142
  17. package/dist/api_docs/topics/api.d.ts +0 -2
  18. package/dist/api_docs/topics/api.js +0 -176
  19. package/dist/api_docs/topics/apigroup.d.ts +0 -2
  20. package/dist/api_docs/topics/apigroup.js +0 -124
  21. package/dist/api_docs/topics/authentication.d.ts +0 -2
  22. package/dist/api_docs/topics/authentication.js +0 -61
  23. package/dist/api_docs/topics/branch.d.ts +0 -2
  24. package/dist/api_docs/topics/branch.js +0 -73
  25. package/dist/api_docs/topics/file.d.ts +0 -2
  26. package/dist/api_docs/topics/file.js +0 -70
  27. package/dist/api_docs/topics/function.d.ts +0 -2
  28. package/dist/api_docs/topics/function.js +0 -164
  29. package/dist/api_docs/topics/history.d.ts +0 -2
  30. package/dist/api_docs/topics/history.js +0 -149
  31. package/dist/api_docs/topics/mcp_server.d.ts +0 -2
  32. package/dist/api_docs/topics/mcp_server.js +0 -139
  33. package/dist/api_docs/topics/middleware.d.ts +0 -2
  34. package/dist/api_docs/topics/middleware.js +0 -156
  35. package/dist/api_docs/topics/realtime.d.ts +0 -2
  36. package/dist/api_docs/topics/realtime.js +0 -112
  37. package/dist/api_docs/topics/start.d.ts +0 -2
  38. package/dist/api_docs/topics/start.js +0 -107
  39. package/dist/api_docs/topics/table.d.ts +0 -2
  40. package/dist/api_docs/topics/table.js +0 -195
  41. package/dist/api_docs/topics/task.d.ts +0 -2
  42. package/dist/api_docs/topics/task.js +0 -165
  43. package/dist/api_docs/topics/tool.d.ts +0 -2
  44. package/dist/api_docs/topics/tool.js +0 -150
  45. package/dist/api_docs/topics/workflows.d.ts +0 -2
  46. package/dist/api_docs/topics/workflows.js +0 -131
  47. package/dist/api_docs/topics/workspace.d.ts +0 -2
  48. package/dist/api_docs/topics/workspace.js +0 -153
  49. package/dist/api_docs/types.d.ts +0 -79
  50. package/dist/api_docs/types.js +0 -4
  51. package/dist/templates/init-workspace.d.ts +0 -10
  52. package/dist/templates/init-workspace.js +0 -278
  53. package/dist/templates/xanoscript-index.d.ts +0 -11
  54. package/dist/templates/xanoscript-index.js +0 -72
  55. package/dist/xanoscript_docs/ephemeral.md +0 -330
  56. package/dist/xanoscript_docs_auto/README.md +0 -119
  57. package/dist/xanoscript_docs_auto/agents.md +0 -446
  58. package/dist/xanoscript_docs_auto/apis.md +0 -517
  59. package/dist/xanoscript_docs_auto/control-flow.md +0 -543
  60. package/dist/xanoscript_docs_auto/database.md +0 -551
  61. package/dist/xanoscript_docs_auto/debugging.md +0 -527
  62. package/dist/xanoscript_docs_auto/filters.md +0 -464
  63. package/dist/xanoscript_docs_auto/functions.md +0 -431
  64. package/dist/xanoscript_docs_auto/integrations.md +0 -657
  65. package/dist/xanoscript_docs_auto/mcp-servers.md +0 -408
  66. package/dist/xanoscript_docs_auto/operators.md +0 -368
  67. package/dist/xanoscript_docs_auto/syntax.md +0 -287
  68. package/dist/xanoscript_docs_auto/tables.md +0 -447
  69. package/dist/xanoscript_docs_auto/tasks.md +0 -479
  70. package/dist/xanoscript_docs_auto/testing.md +0 -574
  71. package/dist/xanoscript_docs_auto/tools.md +0 -485
  72. package/dist/xanoscript_docs_auto/triggers.md +0 -595
  73. package/dist/xanoscript_docs_auto/types.md +0 -323
  74. package/dist/xanoscript_docs_auto/variables.md +0 -462
  75. package/dist/xanoscript_docs_auto/version.json +0 -5
@@ -1,278 +0,0 @@
1
- /**
2
- * Template for init_workspace tool documentation
3
- * Edit this file to update the workspace initialization guide
4
- */
5
- export function generateInitWorkspaceTemplate(objectTypes) {
6
- const objectTypesTable = objectTypes
7
- .map(({ type, path, endpoint }) => `| \`${type}\` | \`${path}/\` | \`${endpoint}\` |`)
8
- .join("\n");
9
- return `# Xano Workspace Initialization Guide
10
-
11
- This guide explains how to set up a local development workspace that syncs with the Xano Headless API.
12
-
13
- ## Directory Structure
14
-
15
- Initialize your workspace with these directories:
16
-
17
- \`\`\`
18
- your-project/
19
- ├── .xano/
20
- │ └── registry.json # Tracks all objects and their sync state
21
- ├── functions/ # Custom reusable functions
22
- │ ├── calculate_total.xs
23
- │ └── validate_email.xs
24
- ├── tables/ # Database table schemas
25
- │ ├── user.xs
26
- │ └── order.xs
27
- ├── tasks/ # Scheduled background tasks
28
- │ └── cleanup_sessions.xs
29
- ├── apis/ # API groups and endpoints
30
- │ └── auth/ # API group directory
31
- │ ├── api_group.xs # Group definition
32
- │ ├── POST_login.xs # Endpoint: POST /auth/login
33
- │ └── GET_me.xs # Endpoint: GET /auth/me
34
- ├── tools/ # AI-callable tools
35
- ├── agents/ # AI agents
36
- ├── middlewares/ # Request/response middleware
37
- ├── addons/ # Query addons
38
- ├── mcp_servers/ # MCP servers
39
- └── realtime/ # Realtime channels
40
- \`\`\`
41
-
42
- ## Object Types
43
-
44
- | Type | Directory | API Endpoint |
45
- |------|-----------|--------------|
46
- ${objectTypesTable}
47
-
48
- ## File Naming Convention
49
-
50
- Files should follow snake_case naming with the \`.xs\` extension:
51
- - \`{name}.xs\` - Basic format (e.g., \`calculate_total.xs\`)
52
- - \`{id}_{name}.xs\` - With ID prefix for disambiguation (e.g., \`42_calculate_total.xs\`)
53
- - API endpoints: \`{VERB}_{path}.xs\` (e.g., \`POST_login.xs\`, \`GET_users_id.xs\`)
54
-
55
- ## Registry Format
56
-
57
- The \`.xano/registry.json\` file tracks the sync state between local files and the Xano API:
58
-
59
- \`\`\`json
60
- {
61
- "workspace_id": 12345,
62
- "workspace_name": "My Project",
63
- "branch": "",
64
- "base_url": "https://your-instance.xano.io/api:headless",
65
- "created_at": "2025-01-15T10:30:00Z",
66
- "updated_at": "2025-01-15T10:30:00Z",
67
- "objects": [
68
- {
69
- "id": 1,
70
- "type": "function",
71
- "name": "calculate_total",
72
- "path": "functions/calculate_total.xs",
73
- "sha256": "abc123...",
74
- "status": "unchanged",
75
- "original": "ZnVuY3Rpb24gY2FsY3VsYXRlX3RvdGFsIHsgLi4uIH0=",
76
- "updated_at": "2025-01-15T10:30:00Z"
77
- },
78
- {
79
- "id": 0,
80
- "type": "function",
81
- "name": "new_function",
82
- "path": "functions/new_function.xs",
83
- "status": "new"
84
- }
85
- ]
86
- }
87
- \`\`\`
88
-
89
- ### Registry Record Fields
90
-
91
- | Field | Description |
92
- |-------|-------------|
93
- | \`id\` | Xano object ID (0 = new, not yet synced) |
94
- | \`type\` | Object type (function, table, task, etc.) |
95
- | \`name\` | Object name extracted from XanoScript |
96
- | \`path\` | Relative file path from workspace root |
97
- | \`sha256\` | SHA256 hash of file content for change detection |
98
- | \`status\` | Sync status: "new", "unchanged", "changed", "deleted" |
99
- | \`original\` | Base64-encoded original content (for conflict detection) |
100
- | \`updated_at\` | Last sync timestamp |
101
-
102
- ### Status Values
103
-
104
- | Status | Description |
105
- |--------|-------------|
106
- | \`new\` | Created locally, not yet pushed to Xano |
107
- | \`unchanged\` | In sync with remote |
108
- | \`changed\` | Modified locally since last sync |
109
- | \`deleted\` | Marked for deletion (file removed locally) |
110
-
111
- ## Fetching Objects from the API
112
-
113
- Use the Headless API to fetch objects.
114
-
115
- ### List Objects
116
-
117
- \`\`\`
118
- GET /workspace/{workspace_id}/{type}
119
- Headers:
120
- Authorization: Bearer {token}
121
-
122
- Query Parameters:
123
- - branch: Branch label (empty = live branch)
124
- - page: Page number (default: 1)
125
- - per_page: Items per page (default: 50, max: 10000)
126
- - search: Text search filter
127
- - sort: Sort field (created_at, updated_at, name)
128
- - order: asc or desc
129
- \`\`\`
130
-
131
- ### Get Single Object with XanoScript
132
-
133
- \`\`\`
134
- GET /workspace/{workspace_id}/{type}/{id}
135
- Headers:
136
- Authorization: Bearer {token}
137
-
138
- Query Parameters:
139
- - branch: Branch label
140
- \`\`\`
141
-
142
- The response includes the \`xanoscript\` field with the code content:
143
- \`\`\`json
144
- {
145
- "id": 1,
146
- "name": "calculate_total",
147
- "xanoscript": {
148
- "status": "ok",
149
- "value": "function calculate_total { ... }"
150
- }
151
- }
152
- \`\`\`
153
-
154
- ### API Endpoints (Nested Under API Groups)
155
-
156
- **Important:** API endpoints are nested resources under API groups. You must first fetch API groups to obtain their IDs, then use those IDs to fetch the endpoints within each group.
157
-
158
- \`\`\`
159
- # 1. First, list API groups
160
- GET /workspace/{workspace_id}/apigroup
161
-
162
- # 2. Then, list endpoints for each group using the apigroup_id
163
- GET /workspace/{workspace_id}/apigroup/{apigroup_id}/api
164
-
165
- # 3. Get a single endpoint
166
- GET /workspace/{workspace_id}/apigroup/{apigroup_id}/api/{api_id}
167
- \`\`\`
168
-
169
- This hierarchical structure is reflected in the local directory layout:
170
- \`\`\`
171
- apis/
172
- └── auth/ # API group (apigroup_id required)
173
- ├── api_group.xs # Group definition
174
- ├── POST_login.xs # Endpoint within this group
175
- └── GET_me.xs # Another endpoint
176
- \`\`\`
177
-
178
- API groups contain endpoints that share common configuration.
179
-
180
- ## Pull Workflow
181
-
182
- 1. **Fetch object list** from API (paginated)
183
- 2. **For each object**, get the full definition including XanoScript
184
- 3. **Generate file path** based on type and name
185
- 4. **Write file** to the appropriate directory
186
- 5. **Update registry** with object metadata and SHA256 hash
187
-
188
- ### Example Pull Request Sequence
189
-
190
- \`\`\`javascript
191
- // 1. List all functions
192
- const response = await fetch(
193
- \`\${baseUrl}/workspace/\${workspaceId}/function?branch=\${branch}&per_page=100\`,
194
- { headers: { Authorization: \`Bearer \${token}\` } }
195
- );
196
- const { items, nextPage } = await response.json();
197
-
198
- // 2. For each function, save to file
199
- for (const func of items) {
200
- const xanoscript = func.xanoscript?.value || '';
201
- const fileName = \`\${snakeCase(func.name)}.xs\`;
202
- const filePath = \`functions/\${fileName}\`;
203
-
204
- // Write file
205
- await writeFile(filePath, xanoscript);
206
-
207
- // Add to registry
208
- registry.objects.push({
209
- id: func.id,
210
- type: 'function',
211
- name: func.name,
212
- path: filePath,
213
- sha256: sha256(xanoscript),
214
- status: 'unchanged',
215
- original: btoa(xanoscript),
216
- updated_at: func.updated_at
217
- });
218
- }
219
- \`\`\`
220
-
221
- ## Push Workflow
222
-
223
- 1. **Read registry** to find changed/new objects
224
- 2. **For each changed file**, read content and detect changes
225
- 3. **Create or update** via API with XanoScript content
226
- 4. **Update registry** with new IDs and hashes
227
-
228
- ### Example Push Request
229
-
230
- \`\`\`javascript
231
- // Create new function
232
- const response = await fetch(
233
- \`\${baseUrl}/workspace/\${workspaceId}/function?branch=\${branch}\`,
234
- {
235
- method: 'POST',
236
- headers: {
237
- 'Authorization': \`Bearer \${token}\`,
238
- 'Content-Type': 'text/x-xanoscript'
239
- },
240
- body: xanoscriptContent
241
- }
242
- );
243
-
244
- // Update existing function
245
- const response = await fetch(
246
- \`\${baseUrl}/workspace/\${workspaceId}/function/\${functionId}?publish=true\`,
247
- {
248
- method: 'PUT',
249
- headers: {
250
- 'Authorization': \`Bearer \${token}\`,
251
- 'Content-Type': 'text/x-xanoscript'
252
- },
253
- body: xanoscriptContent
254
- }
255
- );
256
- \`\`\`
257
-
258
- ## XanoScript Documentation References
259
-
260
- For writing XanoScript code, use:
261
-
262
- - \`xanoscript_docs()\` - Full documentation index
263
- - \`xanoscript_docs({ topic: "functions" })\` - Function syntax
264
- - \`xanoscript_docs({ topic: "tables" })\` - Table schema syntax
265
- - \`xanoscript_docs({ topic: "apis" })\` - API endpoint syntax
266
- - \`xanoscript_docs({ topic: "syntax" })\` - Language reference
267
-
268
- ## Validating XanoScript
269
-
270
- Before pushing changes, validate the XanoScript syntax:
271
-
272
- \`\`\`
273
- validate_xanoscript({ code: "function foo { ... }" })
274
- \`\`\`
275
-
276
- This will check for syntax errors and return line/column positions for any issues.
277
- `;
278
- }
@@ -1,11 +0,0 @@
1
- /**
2
- * Template for xanoscript_docs index documentation
3
- * Edit this file to update the XanoScript documentation index
4
- *
5
- * NOTE: This template is currently unused. The actual documentation is served
6
- * directly from the XANOSCRIPT_DOCS_V2 config in index.ts.
7
- */
8
- export interface XanoscriptIndexParams {
9
- version: string;
10
- }
11
- export declare function generateXanoscriptIndexTemplate(params: XanoscriptIndexParams): string;
@@ -1,72 +0,0 @@
1
- /**
2
- * Template for xanoscript_docs index documentation
3
- * Edit this file to update the XanoScript documentation index
4
- *
5
- * NOTE: This template is currently unused. The actual documentation is served
6
- * directly from the XANOSCRIPT_DOCS_V2 config in index.ts.
7
- */
8
- export function generateXanoscriptIndexTemplate(params) {
9
- const { version } = params;
10
- return `# XanoScript Documentation Index
11
- Version: ${version}
12
-
13
- Use \`xanoscript_docs({ topic: "<topic>" })\` to retrieve documentation.
14
-
15
- ## Core Language
16
- | Topic | Description |
17
- |-------|-------------|
18
- | \`syntax\` | Expressions, operators, filters, system variables |
19
- | \`types\` | Data types, validation, input blocks |
20
- | \`functions\` | Reusable function stacks, async, loops |
21
- | \`schema\` | Runtime schema parsing and validation |
22
-
23
- ## Data
24
- | Topic | Description |
25
- |-------|-------------|
26
- | \`tables\` | Database schema definitions with indexes and relationships |
27
- | \`database\` | All db.* operations: query, get, add, edit, patch, delete |
28
- | \`addons\` | Reusable subqueries for fetching related data |
29
- | \`streaming\` | Streaming data from files, requests, and responses |
30
-
31
- ## APIs & Endpoints
32
- | Topic | Description |
33
- |-------|-------------|
34
- | \`apis\` | HTTP endpoint definitions with authentication and CRUD patterns |
35
- | \`tasks\` | Scheduled and cron jobs |
36
- | \`triggers\` | Event-driven handlers (table, realtime, workspace, agent, MCP) |
37
- | \`realtime\` | Real-time channels and events for push updates |
38
-
39
- ## AI & Agents
40
- | Topic | Description |
41
- |-------|-------------|
42
- | \`agents\` | AI agent configuration with LLM providers and tools |
43
- | \`tools\` | AI tools for agents and MCP servers |
44
- | \`mcp-servers\` | MCP server definitions exposing tools |
45
-
46
- ## Integrations
47
- | Topic | Description |
48
- |-------|-------------|
49
- | \`integrations\` | Cloud storage, Redis, security, and external APIs |
50
-
51
- ## Configuration
52
- | Topic | Description |
53
- |-------|-------------|
54
- | \`workspace\` | Workspace-level settings: environment variables, preferences, realtime |
55
- | \`branch\` | Branch-level settings: middleware, history retention, visual styling |
56
- | \`middleware\` | Request/response interceptors for functions, queries, tasks, and tools |
57
-
58
- ## Development
59
- | Topic | Description |
60
- |-------|-------------|
61
- | \`testing\` | Unit tests, mocks, and assertions |
62
- | \`debugging\` | Logging, inspecting, and debugging XanoScript execution |
63
- | \`frontend\` | Static frontend development and deployment |
64
- | \`run\` | Run job and service configurations for the Xano Job Runner |
65
-
66
- ## Best Practices
67
- | Topic | Description |
68
- |-------|-------------|
69
- | \`performance\` | Performance optimization best practices |
70
- | \`security\` | Security best practices for authentication and authorization |
71
- `;
72
- }
@@ -1,330 +0,0 @@
1
- ---
2
- applyTo: "ephemeral/**/*.xs"
3
- ---
4
-
5
- # Ephemeral Environments
6
-
7
- Temporary Xano workspaces for testing and one-off operations.
8
-
9
- ## Quick Reference
10
-
11
- | Type | Purpose | Lifecycle |
12
- |------|---------|-----------|
13
- | **Service** | Temporary workspace with DB/APIs | Runs until shut down |
14
- | **Job** | One-time operation | Executes once, then shuts down |
15
-
16
- ### Directory Structure
17
- ```
18
- ephemeral/
19
- ├── my-service/
20
- │ ├── workspace.xs
21
- │ ├── tables/
22
- │ ├── functions/
23
- │ └── apis/
24
- └── my-job/
25
- ├── workspace.xs
26
- ├── tables/
27
- └── functions/
28
- ```
29
-
30
- ---
31
-
32
- ## Ephemeral Service
33
-
34
- A temporary workspace with database, functions, and API endpoints.
35
-
36
- ### workspace.xs
37
- ```xs
38
- workspace my_service {
39
- env = {
40
- api_key: "test-key"
41
- debug: "true"
42
- }
43
- }
44
- ```
45
-
46
- ### Table with Seed Data
47
- ```xs
48
- table event {
49
- auth = false
50
- schema {
51
- int id
52
- timestamp created_at?=now
53
- text name filters=trim
54
- }
55
- index = [
56
- {type: "primary", field: [{name: "id"}]}
57
- ]
58
- items = [
59
- {"id": 1, "name": "Event 1"}
60
- {"id": 2, "name": "Event 2"}
61
- ]
62
- }
63
- ```
64
-
65
- ### API Group
66
- ```xs
67
- api_group events {
68
- canonical = "events-api"
69
- }
70
- ```
71
-
72
- ### Endpoints
73
- ```xs
74
- query list verb=GET {
75
- api_group = "events"
76
- stack {
77
- db.query event {
78
- return = { type: "list" }
79
- } as $events
80
- }
81
- response = $events
82
- }
83
-
84
- query add verb=POST {
85
- api_group = "events"
86
- input { text name filters=trim }
87
- stack {
88
- db.add event {
89
- data = { name: $input.name }
90
- } as $event
91
- }
92
- response = $event
93
- }
94
- ```
95
-
96
- ---
97
-
98
- ## Ephemeral Job
99
-
100
- One-time operation with setup and cleanup hooks.
101
-
102
- ### Reserved Functions
103
- | Function | Purpose | Required |
104
- |----------|---------|----------|
105
- | `$main` | Primary logic | Yes |
106
- | `$pre` | Setup/validation | No |
107
- | `$post` | Cleanup/notification | No |
108
-
109
- ### Execution Order
110
- 1. `$pre` (if defined)
111
- 2. `$main`
112
- 3. `$post` (if defined)
113
- 4. Environment shuts down
114
-
115
- ### $main Function
116
- ```xs
117
- function "$main" {
118
- input {
119
- json args // Runtime arguments
120
- json pre // Result from $pre
121
- }
122
- stack {
123
- db.query authors {
124
- return = { type: "count" }
125
- } as $count
126
-
127
- precondition ($count > 0) {
128
- error = "No authors found"
129
- }
130
-
131
- db.add authors {
132
- data = { name: "New Author" }
133
- }
134
- }
135
- response = { processed: true }
136
- }
137
- ```
138
-
139
- ### $pre Function (optional)
140
- ```xs
141
- function "$pre" {
142
- input { json args }
143
- stack {
144
- // Validation or setup
145
- precondition ($input.args.required_field != null) {
146
- error = "Missing required field"
147
- }
148
- }
149
- response = { validated: true }
150
- }
151
- ```
152
-
153
- ### $post Function (optional)
154
- ```xs
155
- function "$post" {
156
- input {
157
- json args
158
- json pre
159
- json main
160
- }
161
- stack {
162
- // Send notification or cleanup
163
- api.request {
164
- url = $env.WEBHOOK_URL
165
- method = "POST"
166
- params = {
167
- status: "complete",
168
- result: $input.main
169
- }
170
- }
171
- }
172
- response = null
173
- }
174
- ```
175
-
176
- ---
177
-
178
- ## Complete Service Example
179
-
180
- ```
181
- ephemeral/event-tracker/
182
- ├── workspace.xs
183
- ├── tables/
184
- │ └── event.xs
185
- └── apis/
186
- ├── api_group.xs
187
- ├── list.xs
188
- ├── add.xs
189
- └── clear.xs
190
- ```
191
-
192
- ### workspace.xs
193
- ```xs
194
- workspace event_tracker {
195
- env = { api_key: "test" }
196
- }
197
- ```
198
-
199
- ### tables/event.xs
200
- ```xs
201
- table event {
202
- auth = false
203
- schema {
204
- int id
205
- timestamp created_at?=now
206
- text name
207
- }
208
- index = [
209
- {type: "primary", field: [{name: "id"}]}
210
- ]
211
- items = []
212
- }
213
- ```
214
-
215
- ### apis/list.xs
216
- ```xs
217
- query list verb=GET {
218
- api_group = "events"
219
- stack {
220
- db.query event {
221
- sort = { created_at: "desc" }
222
- return = { type: "list" }
223
- } as $events
224
- }
225
- response = $events
226
- }
227
- ```
228
-
229
- ---
230
-
231
- ## Complete Job Example
232
-
233
- ```
234
- ephemeral/data-migration/
235
- ├── workspace.xs
236
- ├── tables/
237
- │ └── users.xs
238
- └── functions/
239
- ├── $main.xs
240
- └── $post.xs
241
- ```
242
-
243
- ### workspace.xs
244
- ```xs
245
- workspace data_migration {
246
- env = { webhook_url: "https://webhook.site/xxx" }
247
- }
248
- ```
249
-
250
- ### tables/users.xs
251
- ```xs
252
- table users {
253
- auth = false
254
- schema {
255
- int id
256
- text name
257
- text email
258
- timestamp migrated_at?
259
- }
260
- index = [
261
- {type: "primary", field: [{name: "id"}]}
262
- ]
263
- items = [
264
- {"id": 1, "name": "Alice", "email": "alice@example.com"}
265
- {"id": 2, "name": "Bob", "email": "bob@example.com"}
266
- ]
267
- }
268
- ```
269
-
270
- ### functions/$main.xs
271
- ```xs
272
- function "$main" {
273
- input { json args, json pre }
274
- stack {
275
- db.query users {
276
- where = $db.users.migrated_at == null
277
- } as $pending
278
-
279
- foreach ($pending) {
280
- each as $user {
281
- db.edit users {
282
- field_name = "id"
283
- field_value = $user.id
284
- data = { migrated_at: now }
285
- }
286
- }
287
- }
288
- }
289
- response = { migrated: $pending|count }
290
- }
291
- ```
292
-
293
- ### functions/$post.xs
294
- ```xs
295
- function "$post" {
296
- input { json args, json pre, json main }
297
- stack {
298
- api.request {
299
- url = $env.webhook_url
300
- method = "POST"
301
- params = { result: $input.main }
302
- }
303
- }
304
- response = null
305
- }
306
- ```
307
-
308
- ---
309
-
310
- ## Deploying
311
-
312
- ### Deploy Service
313
- ```
314
- publish_ephemeral_service name="my-api" directory="ephemeral/my-service" mode="service"
315
- ```
316
-
317
- ### Run Job
318
- ```
319
- publish_ephemeral_service name="migration" directory="ephemeral/my-job" mode="job"
320
- ```
321
-
322
- ---
323
-
324
- ## Best Practices
325
-
326
- 1. **Keep isolated** - Self-contained with own tables/functions
327
- 2. **Seed test data** - Use `items` in table definitions
328
- 3. **Handle cleanup** - Use `$post` for notifications/cleanup
329
- 4. **Validate in $pre** - Check preconditions before main logic
330
- 5. **Name clearly** - Indicate purpose: `auth-test`, `data-migration`