@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
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* language server checks the policy's block shape only.
|
|
10
10
|
*
|
|
11
11
|
* A host fills it:
|
|
12
|
-
* -
|
|
12
|
+
* - The Xano editor sends its own live answer (`source: "live"`); a check-level problem is then an
|
|
13
13
|
* error, because the instance refuses the same save.
|
|
14
14
|
* - The Node server and offline tools load the generated snapshot (`catalogueSnapshot.js`,
|
|
15
15
|
* `source: "snapshot"`); a check-level problem is then a warning, because the snapshot can
|
|
@@ -30,7 +30,7 @@ let version = 0;
|
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* Replace the catalogue.
|
|
33
|
-
* @param {Object|Object[]|null} catalogue `{items, document}` as the platform serves it,
|
|
33
|
+
* @param {Object|Object[]|null} catalogue `{items, document}` as the platform serves it, the editor's
|
|
34
34
|
* `{checks, document}`, or a bare list of checks; null clears it
|
|
35
35
|
* @param {{source?: "live"|"snapshot", generatedAt?: string|null}} [options]
|
|
36
36
|
*/
|
|
@@ -45,7 +45,7 @@ export const isA = (token, type) => !!token && tokenMatcher(token, type);
|
|
|
45
45
|
/** A catalogue entry's own property, never an inherited one (`constructor`, `toString`). */
|
|
46
46
|
export const own = (object, key) => object && Object.hasOwn(object, key) ? object[key] : undefined;
|
|
47
47
|
|
|
48
|
-
/**
|
|
48
|
+
/** As the platform reads a string: double quotes use C escapes, single quotes only \\ and \'. */
|
|
49
49
|
export function policyStringValue(image) {
|
|
50
50
|
if (image.startsWith('"""') || image.startsWith("'''")) {
|
|
51
51
|
return image.slice(3, -3).replace(/^\r?\n/, "").replace(/\r?\n[ ]*$/, "");
|
|
@@ -6,8 +6,7 @@ import { policyLiteralValue } from "./policyLiteral.js";
|
|
|
6
6
|
* Everything here is read from the catalogue the host loaded (see `catalogue.js`): the check
|
|
7
7
|
* ids, each check's params with their types, closed value sets, nested fields, `required`,
|
|
8
8
|
* `requires_one_of`, `minimum` and `non_empty`, and the scope fields that apply to it. Nothing
|
|
9
|
-
* names a check. The findings are worded like the platform's refusals (
|
|
10
|
-
* `coerce`, `unknownCheck`) without their `rule[i] ("KEY.Rn"): params:` prefix, since a diagnostic
|
|
9
|
+
* names a check. The findings are worded like the platform's refusals without their `rule[i] ("KEY.Rn"): params:` prefix, since a diagnostic
|
|
11
10
|
* already points at the place; they are a preview, and the platform's own answer on save decides.
|
|
12
11
|
* Where the platform stops at the first refusal, this reports every problem, one per param.
|
|
13
12
|
*
|
|
@@ -15,17 +14,17 @@ import { policyLiteralValue } from "./policyLiteral.js";
|
|
|
15
14
|
* holds at most `STRING_MAX_LENGTH` characters, and a name longer than `NEAREST_MAX_LENGTH` bytes
|
|
16
15
|
* gets no near miss.
|
|
17
16
|
*
|
|
18
|
-
* Check-specific rules the catalogue does not publish (
|
|
17
|
+
* Check-specific rules the catalogue does not publish (per-check validation,
|
|
19
18
|
* renamed ids and params, statement wildcards) are left to the platform.
|
|
20
19
|
*
|
|
21
20
|
* Whether a value is a literal at all, and duplicate names, are the block's shape, not the
|
|
22
21
|
* catalogue's: the parser reports those (policy_parser.js) and this skips such values.
|
|
23
22
|
*/
|
|
24
23
|
|
|
25
|
-
/**
|
|
24
|
+
/** The platform's limit on the longest string a string or string[] param may hold, in characters. */
|
|
26
25
|
const STRING_MAX_LENGTH = 1024;
|
|
27
26
|
|
|
28
|
-
/**
|
|
27
|
+
/** The platform's limit on the longest name, in bytes, a near miss is looked for. */
|
|
29
28
|
const NEAREST_MAX_LENGTH = 128;
|
|
30
29
|
|
|
31
30
|
/** Edit distance, as PHP's `levenshtein` (insert, delete and replace all cost 1). */
|
|
@@ -49,7 +48,7 @@ function levenshtein(a, b) {
|
|
|
49
48
|
}
|
|
50
49
|
|
|
51
50
|
/**
|
|
52
|
-
* The closest names to a misspelling, nearest first, at most two
|
|
51
|
+
* The closest names to a misspelling, nearest first, at most two, as the platform suggests them: within
|
|
53
52
|
* three edits, or one containing the other. A name longer than `NEAREST_MAX_LENGTH` bytes gets
|
|
54
53
|
* none, since edit distance costs the product of the two lengths per candidate.
|
|
55
54
|
* @param {string} wanted
|
|
@@ -79,7 +78,7 @@ export function didYouMean(name, candidates) {
|
|
|
79
78
|
return near.length ? `Did you mean ${near.map((n) => `"${n}"`).join(" or ")}? ` : "";
|
|
80
79
|
}
|
|
81
80
|
|
|
82
|
-
/**
|
|
81
|
+
/** Whether a param counts as provided: set when not null/false, not an empty or blank string, not an empty list or object. */
|
|
83
82
|
function provided(value) {
|
|
84
83
|
if (value === null || value === undefined || value === false) return false;
|
|
85
84
|
if (typeof value === "string") return value.trim() !== "";
|
|
@@ -89,7 +88,7 @@ function provided(value) {
|
|
|
89
88
|
}
|
|
90
89
|
|
|
91
90
|
/**
|
|
92
|
-
* A param's value as the platform validates it
|
|
91
|
+
* A param's value as the platform validates it: one left out, or written
|
|
93
92
|
* as `null` when its type is not `any`, is its default.
|
|
94
93
|
*/
|
|
95
94
|
const inForce = (literal, schema, name) =>
|
|
@@ -107,7 +106,7 @@ export function unknownCheckMessage(id, ids) {
|
|
|
107
106
|
}
|
|
108
107
|
|
|
109
108
|
/**
|
|
110
|
-
*
|
|
109
|
+
* Whether a value has its param's declared type and values.
|
|
111
110
|
* @returns {{token: Object, message: string}|null}
|
|
112
111
|
*/
|
|
113
112
|
function coerce(node, spec, checkId, name) {
|
|
@@ -124,7 +123,7 @@ function coerce(node, spec, checkId, name) {
|
|
|
124
123
|
if (!whole || (minimum !== undefined && node.value < minimum)) {
|
|
125
124
|
return fail(`be a whole number${minimum !== undefined ? ` of at least ${minimum}` : ""}`);
|
|
126
125
|
}
|
|
127
|
-
//
|
|
126
|
+
// The platform's integer limit: past 2^53 - 1 a whole number is no longer exact.
|
|
128
127
|
if (Math.abs(node.value) > Number.MAX_SAFE_INTEGER) {
|
|
129
128
|
return fail(`be a whole number no larger than ${Number.MAX_SAFE_INTEGER}`);
|
|
130
129
|
}
|
|
@@ -188,7 +187,7 @@ function closedProperties(spec) {
|
|
|
188
187
|
|
|
189
188
|
/**
|
|
190
189
|
* Why a set scope field cannot change what a rule of this check selects, or null when it can,
|
|
191
|
-
* read from the check's published `scope_fields` (the same reading as
|
|
190
|
+
* read from the check's published `scope_fields` (the same reading as the Xano editor's rule form).
|
|
192
191
|
*/
|
|
193
192
|
function inapplicableScope(check, name, literal) {
|
|
194
193
|
const field = (check.scope_fields ?? []).find((item) => item?.name === name);
|
package/parser/policy_parser.js
CHANGED
|
@@ -21,10 +21,10 @@ import { didYouMean, validatePolicyRule } from "./policy/validatePolicyRule.js";
|
|
|
21
21
|
// rule { <field> = <literal> } # repeating; `check` names a catalogue item, `params` its params
|
|
22
22
|
// }
|
|
23
23
|
//
|
|
24
|
-
// with the comment, named-rule and literal-value rules
|
|
24
|
+
// with the comment, named-rule and literal-value rules the platform enforces. It knows no
|
|
25
25
|
// field: which fields a policy and a rule may set, their types, value sets and defaults, the retired
|
|
26
26
|
// fields and reserved blocks, the key pattern and when a rule is required all come from the
|
|
27
|
-
// catalogue's `document
|
|
27
|
+
// catalogue's `document`, and every check from its `items`. With no
|
|
28
28
|
// catalogue loaded, only the shape is checked. See parser/policy/catalogue.js.
|
|
29
29
|
|
|
30
30
|
/** The platform's refusal of a named rule, after its `rule[<i>]: ` prefix. */
|
|
@@ -287,7 +287,7 @@ function fieldProblem(name, node, spec) {
|
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
/**
|
|
290
|
-
* A rule's params: an object of literal values (
|
|
290
|
+
* A rule's params: an object of literal values (a name written twice is already
|
|
291
291
|
* reported by the object grammar). The catalogue then says what the object may hold.
|
|
292
292
|
*/
|
|
293
293
|
function checkParamsShape(node, report) {
|
|
@@ -33,7 +33,7 @@ export function realtimeChannelDeclaration($) {
|
|
|
33
33
|
anonymous_clients: "[boolean]",
|
|
34
34
|
nested_channels: "[boolean]",
|
|
35
35
|
// The CLI pull emits `message_history: history ?? 0` (an arbitrary
|
|
36
|
-
// integer
|
|
36
|
+
// integer), so
|
|
37
37
|
// accept any numeric value rather than a fixed enum. Kept typed
|
|
38
38
|
// ("[number]") so a non-numeric value still surfaces a diagnostic.
|
|
39
39
|
message_history: "[number]",
|