@xano/xanoscript-language-server 12.20.1 → 12.22.0
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 +84 -149
- package/embedded/README.md +1 -2
- package/lexer/db.js +8 -0
- package/lexer/mcp.js +2 -3
- package/lexer/realtime.js +8 -0
- package/lexer/realtime_server_trigger.js +1 -1
- package/onHover/functions.md +29 -1
- package/package.json +15 -5
- package/parser/agent_parser.js +3 -1
- package/parser/attributes/descriptionFieldAttribute.js +8 -1
- package/parser/attributes/docsFieldAttribute.js +8 -1
- package/parser/branch_parser.js +25 -9
- package/parser/channel_parser.js +9 -0
- package/parser/clauses/flexibleStringClause.js +8 -1
- package/parser/clauses/historyClause.js +1 -2
- package/parser/clauses/mcpMetadataClauses.js +12 -8
- package/parser/clauses/nakedStackFn.js +4 -0
- package/parser/clauses/viewClause.js +8 -4
- package/parser/definitions/columnDefinition.js +7 -2
- package/parser/definitions/enumColumnDefinition.js +7 -2
- package/parser/definitions/objectColumnDefinition.js +7 -2
- package/parser/error_trigger_parser.js +13 -1
- package/parser/functions/controls/switchCaseFn.js +3 -0
- package/parser/functions/controls/throwFn.js +28 -2
- package/parser/functions/db/dbAddFn.js +2 -1
- package/parser/functions/db/dbAddOrEditFn.js +2 -1
- package/parser/functions/db/dbEditFn.js +2 -1
- package/parser/functions/db/dbExternalFn.js +2 -0
- package/parser/functions/mcp/mcpElicitFn.js +1 -1
- package/parser/functions/mcp/mcpOauthFn.js +2 -4
- package/parser/functions/mcp/mcpProgressFn.js +2 -2
- package/parser/functions/realtime/realtimeKickFn.js +35 -0
- package/parser/functions/realtime/realtimePublishFn.js +2 -2
- package/parser/functions/realtime/register.js +2 -0
- package/parser/functions/realtimeFn.js +1 -0
- package/parser/functions/register.js +2 -0
- package/parser/functions/storage/storageCreateImageFn.js +3 -1
- package/parser/functions/workflowTestCallFn.js +47 -0
- package/parser/generic/stringArray.js +9 -2
- package/parser/mcp_primitive_parser.js +4 -4
- package/parser/mcp_server_parser.js +1 -2
- package/parser/mcp_server_trigger_parser.js +3 -1
- package/parser/message_parser.js +3 -3
- package/parser/microservice_parser.js +1 -2
- package/parser/parser.js +1 -1
- package/parser/policy/catalogue.js +2 -2
- package/parser/policy/policyLiteral.js +1 -1
- package/parser/policy/validatePolicyRule.js +10 -11
- package/parser/policy_parser.js +3 -3
- package/parser/realtime_channel_parser.js +1 -1
package/README.md
CHANGED
|
@@ -1,28 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
> **This repository has moved to [xano-inc/xanoscript-language-server](https://github.com/xano-inc/xanoscript-language-server).**
|
|
3
|
-
> This copy is no longer maintained. Open new issues and pull requests there.
|
|
1
|
+
# XanoScript Language Server
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
██╗ ██╗███████╗ ██╗ █████╗ ███╗ ██╗ ██████╗ ██╗ ██╗ █████╗ ██████╗ ███████╗
|
|
7
|
-
╚██╗██╔╝██╔════╝ ██║ ██╔══██╗████╗ ██║██╔════╝ ██║ ██║██╔══██╗██╔════╝ ██╔════╝
|
|
8
|
-
╚███╔╝ ███████╗ ██║ ███████║██╔██╗ ██║██║ ███╗██║ ██║███████║██║ ███╗█████╗
|
|
9
|
-
██╔██╗ ╚════██║ ██║ ██╔══██║██║╚██╗██║██║ ██║██║ ██║██╔══██║██║ ██║██╔══╝
|
|
10
|
-
██╔╝ ██╗███████║ ███████╗██║ ██║██║ ╚████║╚██████╔╝╚██████╔╝██║ ██║╚██████╔╝███████╗
|
|
11
|
-
╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝
|
|
12
|
-
|
|
13
|
-
███████╗███████╗██████╗ ██╗ ██╗███████╗██████╗
|
|
14
|
-
██╔════╝██╔════╝██╔══██╗██║ ██║██╔════╝██╔══██╗
|
|
15
|
-
███████╗█████╗ ██████╔╝██║ ██║█████╗ ██████╔╝
|
|
16
|
-
╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██╔══╝ ██╔══██╗
|
|
17
|
-
███████║███████╗██║ ██║ ╚████╔╝ ███████╗██║ ██║
|
|
18
|
-
╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚══════╝╚═╝ ╚═╝
|
|
19
|
-
```
|
|
3
|
+
The [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) implementation for XanoScript, the language that describes a [Xano](https://www.xano.com) backend: its APIs, functions, tables, tasks, agents, MCP servers and policies.
|
|
20
4
|
|
|
21
|
-
|
|
5
|
+
Xano is one platform to build, run and govern AI-built software. This server brings the platform's rules into the editor, so you and your coding agent see the problems a push would refuse while you write the code.
|
|
22
6
|
|
|
23
|
-
|
|
7
|
+
Built on [Chevrotain](https://chevrotain.io/) and maintained by the Xano team.
|
|
24
8
|
|
|
25
|
-
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Diagnostics** - Errors and warnings as you type, including cross-file references, variable usage and workspace policy checks
|
|
12
|
+
- **Completion** - Context-aware suggestions, triggered by `.`, `:`, `$` and `|`
|
|
13
|
+
- **Hover** - Documentation for statements, filters, input variables and policy checks
|
|
14
|
+
- **Go to definition** - Jump to a referenced function, task, query or table, or to where a variable is set
|
|
15
|
+
- **Semantic highlighting** - Token-based highlighting for every XanoScript construct
|
|
26
16
|
|
|
27
17
|
## Installation
|
|
28
18
|
|
|
@@ -30,155 +20,100 @@ Maintained by the [Xano](https://xano.com) team.
|
|
|
30
20
|
npm install @xano/xanoscript-language-server
|
|
31
21
|
```
|
|
32
22
|
|
|
33
|
-
|
|
23
|
+
Requires Node.js 20 or later.
|
|
34
24
|
|
|
35
|
-
##
|
|
25
|
+
## Usage
|
|
36
26
|
|
|
37
|
-
The
|
|
27
|
+
The package ships two entry points:
|
|
38
28
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
-
|
|
29
|
+
| Entry point | Runtime | Transport |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| `server.js` | Node.js | stdio / IPC, via `vscode-languageserver/node` |
|
|
32
|
+
| `language-server-worker.js` | Browser (Web Worker) | `postMessage`, via `vscode-languageserver/browser` |
|
|
43
33
|
|
|
44
|
-
|
|
34
|
+
Point any LSP client at `server.js` for `.xs` files. For example, with VS Code's `vscode-languageclient`:
|
|
45
35
|
|
|
46
|
-
|
|
36
|
+
```js
|
|
37
|
+
const serverModule = require.resolve("@xano/xanoscript-language-server/server.js");
|
|
38
|
+
|
|
39
|
+
const client = new LanguageClient(
|
|
40
|
+
"xanoscript",
|
|
41
|
+
"XanoScript",
|
|
42
|
+
{
|
|
43
|
+
run: { module: serverModule, transport: TransportKind.ipc },
|
|
44
|
+
debug: { module: serverModule, transport: TransportKind.ipc },
|
|
45
|
+
},
|
|
46
|
+
{ documentSelector: [{ scheme: "file", language: "xanoscript" }] }
|
|
47
|
+
);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Policy checks
|
|
51
|
+
|
|
52
|
+
XanoScript `policy` files are checked against Xano's policy check catalogue. The server ships a snapshot of it (`parser/policy/catalogueSnapshot.js`), so what it reports is a warning: your instance may be newer than the snapshot. A host that can fetch the live catalogue can load it with `setPolicyCatalogue()` from `parser/policy/catalogue.js`.
|
|
53
|
+
|
|
54
|
+
## Supported object types
|
|
47
55
|
|
|
48
56
|
| Type | Description |
|
|
49
57
|
|------|-------------|
|
|
50
|
-
| `query` | API endpoints with HTTP verbs, input validation
|
|
51
|
-
| `function` | Reusable logic blocks with testing capabilities |
|
|
52
|
-
| `task` | Scheduled operations with cron-like triggers |
|
|
58
|
+
| `query` | API endpoints with HTTP verbs, input validation and responses |
|
|
53
59
|
| `api_group` | Collections of related API endpoints |
|
|
60
|
+
| `function` | Reusable logic blocks with tests |
|
|
61
|
+
| `task` | Scheduled operations with cron-like triggers |
|
|
54
62
|
| `table` | Database schema definitions with column types |
|
|
55
|
-
| `table_trigger` | Database table
|
|
56
|
-
| `workflow_test` |
|
|
57
|
-
| `addon` | Add-on definitions |
|
|
58
|
-
| `agent` | AI agent definitions |
|
|
59
|
-
| `agent_trigger` | Agent trigger handlers |
|
|
60
|
-
| `branch` | Branch logic |
|
|
61
|
-
| `mcp_server` | MCP server definitions |
|
|
62
|
-
| `mcp_server_trigger` | MCP server trigger handlers |
|
|
63
|
+
| `table_trigger` | Database table triggers |
|
|
64
|
+
| `workflow_test` | Workflow test definitions |
|
|
63
65
|
| `middleware` | Middleware definitions |
|
|
64
|
-
| `
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
67
|
-
| `
|
|
66
|
+
| `addon` | Add-on definitions |
|
|
67
|
+
| `branch` | Branch definitions |
|
|
68
|
+
| `workspace` / `workspace_trigger` | Workspace definitions and triggers |
|
|
69
|
+
| `error_trigger` | Error trigger handlers |
|
|
70
|
+
| `agent` / `agent_trigger` | AI agent definitions and triggers |
|
|
71
|
+
| `tool` | Tool definitions, including MCP tool metadata |
|
|
72
|
+
| `mcp_server` / `mcp_server_trigger` | MCP server definitions and connection triggers |
|
|
73
|
+
| `prompt` / `resource` | MCP prompts and resources |
|
|
74
|
+
| `policy` | Workspace policies and their rules |
|
|
75
|
+
| `microservice` | Container and Helm microservice deployments |
|
|
76
|
+
| `realtime_channel` / `realtime_trigger` | Realtime v1 channels and triggers |
|
|
77
|
+
| `realtime_server` / `realtime_server_trigger` | Realtime v2 servers and connection triggers |
|
|
78
|
+
| `channel` / `channel_trigger` | Realtime v2 channels and join/leave triggers |
|
|
68
79
|
| `message` | Realtime v2 channel message handlers |
|
|
69
|
-
| `
|
|
70
|
-
| `realtime_server_trigger` | Realtime v2 connection lifecycle triggers (connect/disconnect) |
|
|
71
|
-
| `tool` | Tool definitions |
|
|
72
|
-
| `workspace` | Workspace definitions |
|
|
73
|
-
| `workspace_trigger` | Workspace trigger handlers |
|
|
74
|
-
|
|
75
|
-
## Built-in Function Domains
|
|
76
|
-
|
|
77
|
-
XanoScript includes functions organized by domain:
|
|
78
|
-
|
|
79
|
-
- **ai** - AI and machine learning operations
|
|
80
|
-
- **api** - External API calls and HTTP requests
|
|
81
|
-
- **array** - Array manipulation and iteration
|
|
82
|
-
- **cloud** - Cloud service integrations
|
|
83
|
-
- **controls** - Flow control (conditionals, loops, etc.)
|
|
84
|
-
- **db** - Database queries and operations
|
|
85
|
-
- **debug** - Debugging and logging utilities
|
|
86
|
-
- **expect** - Testing assertions
|
|
87
|
-
- **math** - Mathematical operations
|
|
88
|
-
- **object** - Object manipulation
|
|
89
|
-
- **redis** - Redis cache operations
|
|
90
|
-
- **schema** - Schema operations
|
|
91
|
-
- **security** - Authentication and security functions
|
|
92
|
-
- **storage** - File storage operations
|
|
93
|
-
- **stream** - Streaming data operations
|
|
94
|
-
- **text** - String manipulation
|
|
95
|
-
- **util** - General utilities
|
|
96
|
-
- **var** - Variable operations
|
|
97
|
-
- **zip** - Compression utilities
|
|
98
|
-
|
|
99
|
-
## Project Structure
|
|
100
|
-
|
|
101
|
-
```
|
|
102
|
-
├── server.js # LSP server entry point
|
|
103
|
-
├── lexer/ # Lexical analysis
|
|
104
|
-
│ ├── lexer.js # Chevrotain lexer implementation
|
|
105
|
-
│ ├── tokens.js # Main token registry
|
|
106
|
-
│ └── [domain].js # Domain-specific tokens (api, db, cloud, etc.)
|
|
107
|
-
├── parser/ # Syntax parsing
|
|
108
|
-
│ ├── base_parser.js # Core XanoBaseParser
|
|
109
|
-
│ ├── [type]_parser.js # Object type parsers
|
|
110
|
-
│ ├── attributes/ # Field attributes (description, disabled, sensitive)
|
|
111
|
-
│ ├── clauses/ # Language blocks (stack, input, response, etc.)
|
|
112
|
-
│ ├── definitions/ # Type and column definitions
|
|
113
|
-
│ ├── functions/ # Built-in functions by domain
|
|
114
|
-
│ └── generic/ # Reusable parsing components
|
|
115
|
-
├── onCompletion/ # Code completion logic
|
|
116
|
-
├── onDidChangeContent/ # Diagnostics and error reporting
|
|
117
|
-
├── onHover/ # Hover documentation
|
|
118
|
-
└── onSemanticCheck/ # Semantic token highlighting
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
## Development
|
|
122
|
-
|
|
123
|
-
```sh
|
|
124
|
-
# Install dependencies
|
|
125
|
-
npm install
|
|
80
|
+
| `run` | Run job and service definitions |
|
|
126
81
|
|
|
127
|
-
|
|
128
|
-
npm test
|
|
82
|
+
## Built-in function domains
|
|
129
83
|
|
|
130
|
-
|
|
131
|
-
npm test -- -g "test name"
|
|
84
|
+
`ai`, `api`, `array`, `cloud`, `controls`, `datadog`, `db`, `debug`, `expect`, `math`, `mcp`, `object`, `realtime`, `redis`, `schema`, `security`, `storage`, `stream`, `text`, `util`, `var`, `zip`
|
|
132
85
|
|
|
133
|
-
|
|
134
|
-
npm run lint
|
|
86
|
+
## Project structure
|
|
135
87
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
#
|
|
140
|
-
|
|
88
|
+
```
|
|
89
|
+
├── server.js # Node LSP entry point
|
|
90
|
+
├── language-server-worker.js # Browser (Web Worker) entry point
|
|
91
|
+
├── lexer/ # Token definitions
|
|
92
|
+
├── parser/ # Grammar rules
|
|
93
|
+
│ ├── base_parser.js # Core XanoBaseParser
|
|
94
|
+
│ ├── [type]_parser.js # One parser per object type
|
|
95
|
+
│ ├── attributes/ # Field attributes (description, disabled, sensitive)
|
|
96
|
+
│ ├── clauses/ # Blocks (stack, input, response, ...)
|
|
97
|
+
│ ├── definitions/ # Type and column definitions
|
|
98
|
+
│ ├── functions/ # Built-in statements by domain
|
|
99
|
+
│ ├── generic/ # Shared parsing components
|
|
100
|
+
│ └── policy/ # Policy check catalogue
|
|
101
|
+
├── onCompletion/ # Completion
|
|
102
|
+
├── onDefinition/ # Go to definition
|
|
103
|
+
├── onDidChangeContent/ # Diagnostics
|
|
104
|
+
├── onHover/ # Hover documentation
|
|
105
|
+
├── onSemanticCheck/ # Semantic tokens
|
|
106
|
+
└── workspace/ # Cross-file index and validation
|
|
141
107
|
```
|
|
142
108
|
|
|
143
|
-
##
|
|
144
|
-
|
|
145
|
-
### New Object Type
|
|
146
|
-
|
|
147
|
-
1. Create a new parser in `parser/` (e.g., `my_object_parser.js`)
|
|
148
|
-
2. Follow existing parser patterns (see `query_parser.js`, `function_parser.js`)
|
|
149
|
-
3. Register it in `server.js`
|
|
150
|
-
|
|
151
|
-
### New Keyword/Function
|
|
152
|
-
|
|
153
|
-
We have a hierarchy for the different statements XanoScript uses:
|
|
154
|
-
|
|
155
|
-
1. **Parser** - Top level (Query parser, Function parser, etc.)
|
|
156
|
-
2. **Clause** - Main blocks in a given object type (stack, response, input, etc.)
|
|
157
|
-
3. **Functions** - Statements like `debug.log` or `db.query`
|
|
158
|
-
4. **Attributes/Definitions** - Components used to define functions
|
|
159
|
-
5. **Generic** - Shared language toolset
|
|
160
|
-
|
|
161
|
-
To add a new function:
|
|
162
|
-
|
|
163
|
-
1. Add token definition in appropriate `lexer/` file
|
|
164
|
-
2. Create function implementation in `parser/functions/[domain]/`
|
|
165
|
-
3. Register in parent clause or parser
|
|
166
|
-
4. Add comprehensive tests in corresponding `.spec.js` file
|
|
167
|
-
|
|
168
|
-
## Testing
|
|
169
|
-
|
|
170
|
-
The language server is heavily tested and should remain that way. Tests should be:
|
|
171
|
-
|
|
172
|
-
- Easy to copy, paste, and extend
|
|
173
|
-
- Straightforward and easy to read
|
|
174
|
-
- Avoid dynamic generation (no loops)
|
|
109
|
+
## Contributing
|
|
175
110
|
|
|
176
|
-
|
|
111
|
+
This repository receives one commit per release. Development happens elsewhere, so pull requests are turned off here. Found a bug? [Open an issue](https://github.com/xano-inc/xanoscript-language-server/issues/new?template=bug_report.yml). [CONTRIBUTING.md](CONTRIBUTING.md) says what makes a report quick to fix.
|
|
177
112
|
|
|
178
|
-
##
|
|
113
|
+
## Security
|
|
179
114
|
|
|
180
|
-
|
|
115
|
+
To report a vulnerability, see [SECURITY.md](SECURITY.md). Please don't open a public issue.
|
|
181
116
|
|
|
182
117
|
## License
|
|
183
118
|
|
|
184
|
-
MIT
|
|
119
|
+
[MIT](LICENSE)
|
package/embedded/README.md
CHANGED
|
@@ -81,7 +81,7 @@ This works in any context (not just `api.lambda`), making it flexible for future
|
|
|
81
81
|
## Client-Side vs Server-Side
|
|
82
82
|
|
|
83
83
|
- **Server-side** (this folder): JavaScript implementation used by language server
|
|
84
|
-
- **Client-side
|
|
84
|
+
- **Client-side**: the editor extension creates the virtual documents with the same extraction logic
|
|
85
85
|
- Both implement the same extraction logic but in their respective environments
|
|
86
86
|
|
|
87
87
|
## Testing
|
|
@@ -89,7 +89,6 @@ This works in any context (not just `api.lambda`), making it flexible for future
|
|
|
89
89
|
All modules are ES6 modules and can be tested independently:
|
|
90
90
|
|
|
91
91
|
```bash
|
|
92
|
-
cd language-server
|
|
93
92
|
node -e "import('./embedded/embeddedContent.js').then(m => console.log(m.extractEmbeddedJS('code = \"\"\"\\nconsole.log()\\n\"\"\"')))"
|
|
94
93
|
```
|
|
95
94
|
|
package/lexer/db.js
CHANGED
|
@@ -145,6 +145,12 @@ export const OracleToken = createTokenByName("oracle", {
|
|
|
145
145
|
categories: [Identifier],
|
|
146
146
|
});
|
|
147
147
|
|
|
148
|
+
// db.external.snowflake
|
|
149
|
+
export const SnowflakeToken = createTokenByName("snowflake", {
|
|
150
|
+
longer_alt: Identifier,
|
|
151
|
+
categories: [Identifier],
|
|
152
|
+
});
|
|
153
|
+
|
|
148
154
|
export const DbTokens = [
|
|
149
155
|
DbToken,
|
|
150
156
|
QueryToken,
|
|
@@ -169,6 +175,7 @@ export const DbTokens = [
|
|
|
169
175
|
MysqlToken,
|
|
170
176
|
PostgresToken,
|
|
171
177
|
OracleToken,
|
|
178
|
+
SnowflakeToken,
|
|
172
179
|
WhereToken,
|
|
173
180
|
];
|
|
174
181
|
|
|
@@ -183,6 +190,7 @@ export function mapTokenToType(token) {
|
|
|
183
190
|
case MysqlToken.name:
|
|
184
191
|
case PostgresToken.name:
|
|
185
192
|
case OracleToken.name:
|
|
193
|
+
case SnowflakeToken.name:
|
|
186
194
|
case QueryToken.name:
|
|
187
195
|
case GetToken.name:
|
|
188
196
|
case AddToken.name:
|
package/lexer/mcp.js
CHANGED
|
@@ -4,9 +4,8 @@ import { createTokenByName } from "./utils.js";
|
|
|
4
4
|
// MCP 2026-07-28 authoring keywords: the `prompt` and `resource` object kinds,
|
|
5
5
|
// the tool/prompt/resource metadata keys, and the `mcp.elicit` / `mcp.progress`
|
|
6
6
|
// statements, plus the per-server `oauth` block and the `mcp.oauth.complete` /
|
|
7
|
-
// `mcp.oauth.request` / `mcp.oauth.revoke` statements. Grounded against
|
|
8
|
-
//
|
|
9
|
-
// `script/kind/schema/statement/mcp.{elicit,progress}.yaml`).
|
|
7
|
+
// `mcp.oauth.request` / `mcp.oauth.revoke` statements. Grounded against the Xano
|
|
8
|
+
// backend's XanoScript schema.
|
|
10
9
|
//
|
|
11
10
|
// Ordering note: a keyword with `longer_alt: Identifier` loses to an EARLIER
|
|
12
11
|
// shorter token, so `prompts` must precede `prompt`, and `resource` is lexed
|
package/lexer/realtime.js
CHANGED
|
@@ -19,10 +19,17 @@ export const PublishToken = createTokenByName("publish", {
|
|
|
19
19
|
categories: [Identifier],
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
+
// kick
|
|
23
|
+
export const KickToken = createTokenByName("kick", {
|
|
24
|
+
longer_alt: Identifier,
|
|
25
|
+
categories: [Identifier],
|
|
26
|
+
});
|
|
27
|
+
|
|
22
28
|
export const RealtimeStatementTokens = [
|
|
23
29
|
RealtimeToken,
|
|
24
30
|
GetSessionToken,
|
|
25
31
|
PublishToken,
|
|
32
|
+
KickToken,
|
|
26
33
|
];
|
|
27
34
|
|
|
28
35
|
export function mapTokenToType(token) {
|
|
@@ -30,6 +37,7 @@ export function mapTokenToType(token) {
|
|
|
30
37
|
case RealtimeToken.name:
|
|
31
38
|
case GetSessionToken.name:
|
|
32
39
|
case PublishToken.name:
|
|
40
|
+
case KickToken.name:
|
|
33
41
|
return "function";
|
|
34
42
|
default:
|
|
35
43
|
return null;
|
|
@@ -14,7 +14,7 @@ export const RealtimeServerTriggerToken = createTokenByName(
|
|
|
14
14
|
// longer_alt lists the trigger token so `realtime_server_trigger` wins over the
|
|
15
15
|
// shorter `realtime_server` prefix, AND Identifier so a name that merely EXTENDS
|
|
16
16
|
// the keyword (e.g. `realtime_server_0`, the default scaffold name) tokenizes as
|
|
17
|
-
// one identifier instead of keyword + leftover `_0
|
|
17
|
+
// one identifier instead of keyword + leftover `_0`. longer_alt is not
|
|
18
18
|
// transitive, so Identifier must be listed here directly — matching the
|
|
19
19
|
// [ServerDetailsToken, Identifier] precedent in channel.js.
|
|
20
20
|
export const RealtimeServerToken = createTokenByName("realtime_server", {
|
package/onHover/functions.md
CHANGED
|
@@ -460,6 +460,18 @@ trigger.call "onNewOrder" {
|
|
|
460
460
|
|
|
461
461
|
- `trigger.call` can call any trigger defined within your workspace, table, realtime, agentic or API triggers.
|
|
462
462
|
|
|
463
|
+
# workflow_test.call
|
|
464
|
+
|
|
465
|
+
```xs
|
|
466
|
+
workflow_test.call "sign up" {
|
|
467
|
+
datasource = "test"
|
|
468
|
+
} as $signup
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
**Note:** `workflow_test.call` is only available within `workflow_test`.
|
|
472
|
+
|
|
473
|
+
Runs another workflow test as a step of this one, so a chain of tests can build on each other. `datasource` optionally picks the datasource the called test runs against.
|
|
474
|
+
|
|
463
475
|
# tool.call
|
|
464
476
|
|
|
465
477
|
```xs
|
|
@@ -1167,6 +1179,19 @@ db.external.postgres.direct_query {
|
|
|
1167
1179
|
|
|
1168
1180
|
Performs a SQL query directly on an external PostgreSQL database. The `response_type` indicates if the result is a `list` or a `single` record. The `connection_string` establishes the database connection, and `arg` provides values for placeholders. The results are stored in the `as` variable, here `$recent_customers`.
|
|
1169
1181
|
|
|
1182
|
+
# db.external.snowflake.direct_query
|
|
1183
|
+
|
|
1184
|
+
```xs
|
|
1185
|
+
db.external.snowflake.direct_query {
|
|
1186
|
+
sql = "SELECT * FROM customers WHERE customers.last_purchase > ?"
|
|
1187
|
+
response_type = "list"
|
|
1188
|
+
connection_string = $env.SNOWFLAKE_CONNECTION_STRING
|
|
1189
|
+
arg = $input.date_threshold
|
|
1190
|
+
} as $recent_customers
|
|
1191
|
+
```
|
|
1192
|
+
|
|
1193
|
+
Performs a SQL query directly on an external Snowflake database. The `response_type` indicates if the result is a `list` or a `single` record. The `connection_string` establishes the database connection, and `arg` provides values for placeholders. The results are stored in the `as` variable, here `$recent_customers`.
|
|
1194
|
+
|
|
1170
1195
|
# debug.stop
|
|
1171
1196
|
|
|
1172
1197
|
```xs
|
|
@@ -1985,10 +2010,13 @@ Removes characters (default is whitespace, or as specified by `value`) from both
|
|
|
1985
2010
|
throw {
|
|
1986
2011
|
name = "ValidationError"
|
|
1987
2012
|
value = "Invalid user input provided"
|
|
2013
|
+
status = 400
|
|
1988
2014
|
}
|
|
1989
2015
|
```
|
|
1990
2016
|
|
|
1991
|
-
Throws an error and halts the script’s execution immediately. The `name` parameter specifies the error type (e.g., `"ValidationError"`), and `value` provides a custom error message to describe the issue.
|
|
2017
|
+
Throws an error and halts the script’s execution immediately. The `name` parameter specifies the error type (e.g., `"ValidationError"`), and `value` provides a custom error message to describe the issue. A `try_catch` can catch it.
|
|
2018
|
+
|
|
2019
|
+
`status` (optional, a whole number from 100 to 599) is the HTTP status the request answers with when nothing catches the throw, including a throw inside a function run with `function.run`. Without it, an uncaught throw answers 200. A caught throw never changes the status.
|
|
1992
2020
|
|
|
1993
2021
|
# try_catch
|
|
1994
2022
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xano/xanoscript-language-server",
|
|
3
|
-
"version": "12.
|
|
4
|
-
"description": "Language Server Protocol implementation for XanoScript",
|
|
3
|
+
"version": "12.22.0",
|
|
4
|
+
"description": "Language Server Protocol implementation for XanoScript, the language of Xano backends",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"xano",
|
|
7
|
+
"xanoscript",
|
|
8
|
+
"language-server",
|
|
9
|
+
"lsp",
|
|
10
|
+
"chevrotain"
|
|
11
|
+
],
|
|
5
12
|
"type": "module",
|
|
6
13
|
"main": "server.js",
|
|
7
14
|
"files": [
|
|
@@ -31,14 +38,17 @@
|
|
|
31
38
|
],
|
|
32
39
|
"repository": {
|
|
33
40
|
"type": "git",
|
|
34
|
-
"url": "git+https://github.com/xano-
|
|
41
|
+
"url": "git+https://github.com/xano-inc/xanoscript-language-server.git"
|
|
35
42
|
},
|
|
36
43
|
"author": "Xano <support@xano.com>",
|
|
37
44
|
"license": "MIT",
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=20"
|
|
47
|
+
},
|
|
38
48
|
"bugs": {
|
|
39
|
-
"url": "https://github.com/xano-
|
|
49
|
+
"url": "https://github.com/xano-inc/xanoscript-language-server/issues"
|
|
40
50
|
},
|
|
41
|
-
"homepage": "https://github.com/xano-
|
|
51
|
+
"homepage": "https://github.com/xano-inc/xanoscript-language-server#readme",
|
|
42
52
|
"scripts": {
|
|
43
53
|
"test-one": "mocha",
|
|
44
54
|
"test": "mocha \"**/*.spec.js\"",
|
package/parser/agent_parser.js
CHANGED
|
@@ -206,7 +206,9 @@ export function agentDeclaration($) {
|
|
|
206
206
|
"api_version?": "[string]",
|
|
207
207
|
"baseURL?": "[string]",
|
|
208
208
|
"compatibility?": ["strict", "compatible", ""],
|
|
209
|
-
|
|
209
|
+
// Free-form JSON text in the Studio form, written back
|
|
210
|
+
// verbatim, so any string is valid.
|
|
211
|
+
"dynamic_retrival?": "[string]",
|
|
210
212
|
"headers?": "[string]",
|
|
211
213
|
"include_thoughts?": "[boolean]",
|
|
212
214
|
"model?": "[string]",
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { EqualToken } from "../../lexer/control.js";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
SingleQuotedStringLiteral,
|
|
4
|
+
StringLiteral,
|
|
5
|
+
} from "../../lexer/literal.js";
|
|
3
6
|
import { MultiLineStringToken } from "../../lexer/multiline.js";
|
|
4
7
|
import { DescriptionToken } from "../../lexer/tokens.js";
|
|
5
8
|
|
|
@@ -15,6 +18,10 @@ export function descriptionFieldAttribute($) {
|
|
|
15
18
|
{
|
|
16
19
|
ALT: () => $.CONSUME(StringLiteral), // e.g., "A description of the field"
|
|
17
20
|
},
|
|
21
|
+
{
|
|
22
|
+
// the platform writes a value holding a double quote as '...'
|
|
23
|
+
ALT: () => $.CONSUME(SingleQuotedStringLiteral),
|
|
24
|
+
},
|
|
18
25
|
{
|
|
19
26
|
ALT: () => $.CONSUME(MultiLineStringToken), // e.g., "fieldDescription"
|
|
20
27
|
},
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { EqualToken } from "../../lexer/control.js";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
SingleQuotedStringLiteral,
|
|
4
|
+
StringLiteral,
|
|
5
|
+
} from "../../lexer/literal.js";
|
|
3
6
|
import { MultiLineStringToken } from "../../lexer/multiline.js";
|
|
4
7
|
import { DocsToken } from "../../lexer/tokens.js";
|
|
5
8
|
|
|
@@ -15,6 +18,10 @@ export function docsFieldAttribute($) {
|
|
|
15
18
|
{
|
|
16
19
|
ALT: () => $.CONSUME(StringLiteral), // e.g., "A docs of the field"
|
|
17
20
|
},
|
|
21
|
+
{
|
|
22
|
+
// the platform writes a value holding a double quote as '...'
|
|
23
|
+
ALT: () => $.CONSUME(SingleQuotedStringLiteral),
|
|
24
|
+
},
|
|
18
25
|
{
|
|
19
26
|
ALT: () => $.CONSUME(MultiLineStringToken), // e.g., "fieldDocs"
|
|
20
27
|
},
|
package/parser/branch_parser.js
CHANGED
|
@@ -15,30 +15,46 @@ export function branchDeclaration($) {
|
|
|
15
15
|
]);
|
|
16
16
|
$.validateDeclarationName(nameToken, "branch");
|
|
17
17
|
|
|
18
|
+
// Mirrors the branch document the platform writes on pull. A middleware
|
|
19
|
+
// entry carries `active: false` when the middleware is disabled.
|
|
20
|
+
const middlewareEntry = { name: "[string]", "active?": "[boolean]" };
|
|
18
21
|
const middlewareSchema = {
|
|
19
|
-
pre: [
|
|
20
|
-
post: [
|
|
22
|
+
pre: [middlewareEntry],
|
|
23
|
+
post: [middlewareEntry],
|
|
21
24
|
};
|
|
22
25
|
|
|
26
|
+
// `0` is a valid limit, and the backend writes `task: 0` (not `false`)
|
|
27
|
+
// for a disabled task history.
|
|
28
|
+
const historyValues = [false, 0, 10, 100, 1000, 10000, "all"];
|
|
29
|
+
|
|
23
30
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
24
31
|
ARGS: [
|
|
25
32
|
parent,
|
|
26
33
|
{
|
|
27
|
-
color: "[string]",
|
|
28
34
|
"description?": "[string]",
|
|
35
|
+
// Omitted by the backend when the branch has no color.
|
|
36
|
+
"color?": "[string]",
|
|
29
37
|
middleware: {
|
|
30
38
|
function: middlewareSchema,
|
|
31
39
|
query: middlewareSchema,
|
|
32
40
|
task: middlewareSchema,
|
|
33
41
|
tool: middlewareSchema,
|
|
42
|
+
// Always written by the platform.
|
|
43
|
+
"message?": middlewareSchema,
|
|
44
|
+
// Written only when the branch has some.
|
|
45
|
+
"prompt?": middlewareSchema,
|
|
46
|
+
"resource?": middlewareSchema,
|
|
34
47
|
},
|
|
35
48
|
history: {
|
|
36
|
-
function:
|
|
37
|
-
query:
|
|
38
|
-
task:
|
|
39
|
-
tool:
|
|
40
|
-
trigger:
|
|
41
|
-
middleware:
|
|
49
|
+
function: historyValues,
|
|
50
|
+
query: historyValues,
|
|
51
|
+
task: historyValues,
|
|
52
|
+
tool: historyValues,
|
|
53
|
+
trigger: historyValues,
|
|
54
|
+
middleware: historyValues,
|
|
55
|
+
// Written only when they differ from the default.
|
|
56
|
+
"prompt?": historyValues,
|
|
57
|
+
"resource?": historyValues,
|
|
42
58
|
},
|
|
43
59
|
},
|
|
44
60
|
],
|
package/parser/channel_parser.js
CHANGED
|
@@ -22,6 +22,7 @@ export function channelDeclaration($) {
|
|
|
22
22
|
let hasMiddleware = false;
|
|
23
23
|
let hasInput = false;
|
|
24
24
|
let hasDescription = false;
|
|
25
|
+
let hasDocs = false;
|
|
25
26
|
let hasGuid = false;
|
|
26
27
|
let hasTags = false;
|
|
27
28
|
let hasActive = false;
|
|
@@ -156,6 +157,14 @@ export function channelDeclaration($) {
|
|
|
156
157
|
$.SUBRULE($.inputClause);
|
|
157
158
|
},
|
|
158
159
|
},
|
|
160
|
+
{
|
|
161
|
+
// written by the platform when the channel has docs
|
|
162
|
+
GATE: () => !hasDocs,
|
|
163
|
+
ALT: () => {
|
|
164
|
+
hasDocs = true;
|
|
165
|
+
$.SUBRULE($.docsFieldAttribute);
|
|
166
|
+
},
|
|
167
|
+
},
|
|
159
168
|
{
|
|
160
169
|
GATE: () => !hasDescription,
|
|
161
170
|
ALT: () => {
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { EqualToken } from "../../lexer/control.js";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
SingleQuotedStringLiteral,
|
|
4
|
+
StringLiteral,
|
|
5
|
+
} from "../../lexer/literal.js";
|
|
3
6
|
import { MultiLineStringToken } from "../../lexer/multiline.js";
|
|
4
7
|
import { InstructionsToken } from "../../lexer/tool.js";
|
|
5
8
|
|
|
@@ -26,6 +29,10 @@ export function flexibleStringClause($) {
|
|
|
26
29
|
{
|
|
27
30
|
ALT: () => $.CONSUME(StringLiteral), // e.g., "A instructions of the field"
|
|
28
31
|
},
|
|
32
|
+
{
|
|
33
|
+
// the platform writes a value holding a double quote as '...'
|
|
34
|
+
ALT: () => $.CONSUME(SingleQuotedStringLiteral),
|
|
35
|
+
},
|
|
29
36
|
{
|
|
30
37
|
ALT: () => $.CONSUME(MultiLineStringToken), // e.g., "fieldinstructions"
|
|
31
38
|
},
|
|
@@ -5,8 +5,7 @@ import { HistoryToken } from "../../lexer/tokens.js";
|
|
|
5
5
|
/**
|
|
6
6
|
* Parses the history clause.
|
|
7
7
|
*
|
|
8
|
-
* `history` mirrors the backend serializer
|
|
9
|
-
* helper/script/transform via `Transform::onSchemaRequestHistory`): the value is
|
|
8
|
+
* `history` mirrors the backend serializer: the value is
|
|
10
9
|
* `false` (disabled), `"inherit"` (hand-authored sentinel), `"all"` (unbounded),
|
|
11
10
|
* or ANY non-negative integer message limit — not a fixed set of magic numbers.
|
|
12
11
|
* It is split across two OR branches because `schemaParseEnumFn` refuses an enum
|