@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
@@ -9,7 +9,7 @@
9
9
  * language server checks the policy's block shape only.
10
10
  *
11
11
  * A host fills it:
12
- * - Studio sends its own live answer (`source: "live"`); a check-level problem is then an
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, Studio's
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
- /** Native Parser::stripQuotes: double quotes use C escapes, single quotes only \\ and \'. */
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 (`Registry::validateParams`,
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 (`Check::validate`, `authoredRefusal`,
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
- /** `Registry::STRING_MAX_LENGTH`: the longest string a string or string[] param may hold, in characters. */
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
- /** `Registry::NEAREST_MAX_LENGTH`: the longest name, in bytes, a near miss is looked for. */
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 (`Registry::nearest`): within
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
- /** `Registry::provided`: set when not null/false, not an empty or blank string, not an empty list or object. */
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 (`Registry::validateParams`): one left out, or written
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
- * `Registry::coerce`: whether a value has its param's declared type and values.
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
- // `Registry::INTEGER_MAX`: past 2^53 - 1 a whole number is no longer exact.
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 Studio's rule form).
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);
@@ -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 of cloud-client's Script.php. It knows no
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` (helper/mvp/policy/Document.php), and every check from its `items`. With no
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 (Script::literal; a name written twice is already
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 — see cloud-client RealtimeChannel.php `onSettings`), so
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]",