@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.
Files changed (50) hide show
  1. package/README.md +84 -149
  2. package/embedded/README.md +1 -2
  3. package/lexer/db.js +8 -0
  4. package/lexer/mcp.js +2 -3
  5. package/lexer/realtime.js +8 -0
  6. package/lexer/realtime_server_trigger.js +1 -1
  7. package/onHover/functions.md +29 -1
  8. package/package.json +15 -5
  9. package/parser/agent_parser.js +3 -1
  10. package/parser/attributes/descriptionFieldAttribute.js +8 -1
  11. package/parser/attributes/docsFieldAttribute.js +8 -1
  12. package/parser/branch_parser.js +25 -9
  13. package/parser/channel_parser.js +9 -0
  14. package/parser/clauses/flexibleStringClause.js +8 -1
  15. package/parser/clauses/historyClause.js +1 -2
  16. package/parser/clauses/mcpMetadataClauses.js +12 -8
  17. package/parser/clauses/nakedStackFn.js +4 -0
  18. package/parser/clauses/viewClause.js +8 -4
  19. package/parser/definitions/columnDefinition.js +7 -2
  20. package/parser/definitions/enumColumnDefinition.js +7 -2
  21. package/parser/definitions/objectColumnDefinition.js +7 -2
  22. package/parser/error_trigger_parser.js +13 -1
  23. package/parser/functions/controls/switchCaseFn.js +3 -0
  24. package/parser/functions/controls/throwFn.js +28 -2
  25. package/parser/functions/db/dbAddFn.js +2 -1
  26. package/parser/functions/db/dbAddOrEditFn.js +2 -1
  27. package/parser/functions/db/dbEditFn.js +2 -1
  28. package/parser/functions/db/dbExternalFn.js +2 -0
  29. package/parser/functions/mcp/mcpElicitFn.js +1 -1
  30. package/parser/functions/mcp/mcpOauthFn.js +2 -4
  31. package/parser/functions/mcp/mcpProgressFn.js +2 -2
  32. package/parser/functions/realtime/realtimeKickFn.js +35 -0
  33. package/parser/functions/realtime/realtimePublishFn.js +2 -2
  34. package/parser/functions/realtime/register.js +2 -0
  35. package/parser/functions/realtimeFn.js +1 -0
  36. package/parser/functions/register.js +2 -0
  37. package/parser/functions/storage/storageCreateImageFn.js +3 -1
  38. package/parser/functions/workflowTestCallFn.js +47 -0
  39. package/parser/generic/stringArray.js +9 -2
  40. package/parser/mcp_primitive_parser.js +4 -4
  41. package/parser/mcp_server_parser.js +1 -2
  42. package/parser/mcp_server_trigger_parser.js +3 -1
  43. package/parser/message_parser.js +3 -3
  44. package/parser/microservice_parser.js +1 -2
  45. package/parser/parser.js +1 -1
  46. package/parser/policy/catalogue.js +2 -2
  47. package/parser/policy/policyLiteral.js +1 -1
  48. package/parser/policy/validatePolicyRule.js +10 -11
  49. package/parser/policy_parser.js +3 -3
  50. package/parser/realtime_channel_parser.js +1 -1
package/README.md CHANGED
@@ -1,28 +1,18 @@
1
- > [!IMPORTANT]
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
- # XanoScript Language Server
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
- A Language Server Protocol (LSP) implementation for [XanoScript](https://xano.com), built on [Chevrotain](https://chevrotain.io/).
7
+ Built on [Chevrotain](https://chevrotain.io/) and maintained by the Xano team.
24
8
 
25
- Maintained by the [Xano](https://xano.com) team.
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
- **Requirements:** Node.js 20+
23
+ Requires Node.js 20 or later.
34
24
 
35
- ## Features
25
+ ## Usage
36
26
 
37
- The language server provides full LSP support including:
27
+ The package ships two entry points:
38
28
 
39
- - **Code Completion** - Context-aware suggestions triggered by `.`, `:`, `$`, and `|`
40
- - **Syntax Highlighting** - Semantic token-based highlighting for XanoScript constructs
41
- - **Hover Information** - Documentation and type information on hover
42
- - **Diagnostics** - Real-time error detection and reporting
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
- ## Supported Object Types
34
+ Point any LSP client at `server.js` for `.xs` files. For example, with VS Code's `vscode-languageclient`:
45
35
 
46
- The parser supports the following XanoScript constructs:
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, and responses |
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 trigger definitions |
56
- | `workflow_test` | Test definitions for workflows |
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
- | `realtime_channel` | Realtime v1 channel definitions |
65
- | `realtime_trigger` | Realtime v1 trigger handlers |
66
- | `realtime_server` | Realtime v2 server definitions (the container that owns channels) |
67
- | `channel` | Realtime v2 channel definitions (path templates) |
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
- | `channel_trigger` | Realtime v2 channel triggers (join/leave lifecycle, deliver per-recipient) |
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
- # Run all tests (~1800 tests)
128
- npm test
82
+ ## Built-in function domains
129
83
 
130
- # Run specific test
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
- # Lint code
134
- npm run lint
86
+ ## Project structure
135
87
 
136
- # Fix lint issues
137
- npm run lint:fix
138
-
139
- # Generate TextMate language definition
140
- npm run tm
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
- ## Adding New Features
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
- Test files use `.spec.js` naming convention and mirror the source structure.
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
- ## CI/CD
113
+ ## Security
179
114
 
180
- On commit, pre-commit hooks run linting via Husky. The CI pipeline runs all tests and linting checks. Configuration is in `.github/workflows/ci.yml`.
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 License - see [LICENSE](LICENSE) for details.
119
+ [MIT](LICENSE)
@@ -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** (`src/tooling/js_embedding.ts`): TypeScript implementation used by VS Code extension
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 cloud-client's schema DSL
8
- // (`script/kind/schema/core/{prompt,resource,tool,mcp_server}.yaml` and
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` (DEV-7582). longer_alt is not
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", {
@@ -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.20.1",
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-labs/xs-language-server.git"
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-labs/xs-language-server/issues"
49
+ "url": "https://github.com/xano-inc/xanoscript-language-server/issues"
40
50
  },
41
- "homepage": "https://github.com/xano-labs/xs-language-server#readme",
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\"",
@@ -206,7 +206,9 @@ export function agentDeclaration($) {
206
206
  "api_version?": "[string]",
207
207
  "baseURL?": "[string]",
208
208
  "compatibility?": ["strict", "compatible", ""],
209
- "dynamic_retrival?": ["enabled", "disabled", ""],
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 { StringLiteral } from "../../lexer/literal.js";
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 { StringLiteral } from "../../lexer/literal.js";
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
  },
@@ -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: [{ name: "[string]" }],
20
- post: [{ name: "[string]" }],
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: [false, 10, 100, 1000, 10000, "all"],
37
- query: [false, 10, 100, 1000, 10000, "all"],
38
- task: [false, 10, 100, 1000, 10000, "all"],
39
- tool: [false, 10, 100, 1000, 10000, "all"],
40
- trigger: [false, 10, 100, 1000, 10000, "all"],
41
- middleware: [false, 10, 100, 1000, 10000, "all"],
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
  ],
@@ -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 { StringLiteral } from "../../lexer/literal.js";
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 (cloud-client
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