@xano/xanoscript-language-server 11.8.4 → 11.8.5

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 (56) hide show
  1. package/.claude/settings.local.json +2 -1
  2. package/cache/documentCache.js +58 -10
  3. package/lexer/db.js +1 -2
  4. package/lexer/security.js +16 -0
  5. package/onCompletion/onCompletion.js +61 -1
  6. package/onDefinition/onDefinition.js +150 -0
  7. package/onDefinition/onDefinition.spec.js +313 -0
  8. package/onDidChangeContent/onDidChangeContent.js +52 -5
  9. package/onHover/functions.md +28 -0
  10. package/package.json +1 -1
  11. package/parser/base_parser.js +61 -3
  12. package/parser/clauses/middlewareClause.js +16 -0
  13. package/parser/definitions/columnDefinition.js +5 -0
  14. package/parser/functions/api/apiCallFn.js +5 -3
  15. package/parser/functions/controls/functionCallFn.js +5 -3
  16. package/parser/functions/controls/functionRunFn.js +61 -5
  17. package/parser/functions/controls/taskCallFn.js +5 -3
  18. package/parser/functions/db/captureFieldName.js +63 -0
  19. package/parser/functions/db/dbAddFn.js +5 -3
  20. package/parser/functions/db/dbAddOrEditFn.js +13 -3
  21. package/parser/functions/db/dbBulkAddFn.js +5 -3
  22. package/parser/functions/db/dbBulkDeleteFn.js +5 -3
  23. package/parser/functions/db/dbBulkPatchFn.js +5 -3
  24. package/parser/functions/db/dbBulkUpdateFn.js +5 -3
  25. package/parser/functions/db/dbDelFn.js +10 -3
  26. package/parser/functions/db/dbEditFn.js +13 -3
  27. package/parser/functions/db/dbGetFn.js +10 -3
  28. package/parser/functions/db/dbHasFn.js +9 -3
  29. package/parser/functions/db/dbPatchFn.js +10 -3
  30. package/parser/functions/db/dbQueryFn.js +29 -3
  31. package/parser/functions/db/dbSchemaFn.js +5 -3
  32. package/parser/functions/db/dbTruncateFn.js +5 -3
  33. package/parser/functions/middlewareCallFn.js +3 -1
  34. package/parser/functions/security/register.js +19 -9
  35. package/parser/functions/security/securityCreateAuthTokenFn.js +22 -0
  36. package/parser/functions/security/securityJweDecodeLegacyFn.js +24 -0
  37. package/parser/functions/security/securityJweDecodeLegacyFn.spec.js +26 -0
  38. package/parser/functions/security/securityJweEncodeLegacyFn.js +24 -0
  39. package/parser/functions/security/securityJweEncodeLegacyFn.spec.js +25 -0
  40. package/parser/functions/securityFn.js +2 -0
  41. package/parser/functions/varFn.js +1 -1
  42. package/parser/generic/asVariable.js +2 -0
  43. package/parser/generic/assignableVariableAs.js +1 -0
  44. package/parser/generic/assignableVariableProperty.js +5 -2
  45. package/parser/tests/variable_test/coverage_check.xs +293 -0
  46. package/parser/variableScanner.js +64 -0
  47. package/parser/variableValidator.js +44 -0
  48. package/parser/variableValidator.spec.js +179 -0
  49. package/server.js +164 -10
  50. package/utils.js +32 -0
  51. package/utils.spec.js +93 -1
  52. package/workspace/crossFileValidator.js +166 -0
  53. package/workspace/crossFileValidator.spec.js +654 -0
  54. package/workspace/referenceTracking.spec.js +420 -0
  55. package/workspace/workspaceIndex.js +149 -0
  56. package/workspace/workspaceIndex.spec.js +189 -0
@@ -1,6 +1,8 @@
1
1
  import { DelToken } from "../../../lexer/db.js";
2
2
  import { StringLiteral } from "../../../lexer/literal.js";
3
3
  import { Identifier } from "../../../lexer/tokens.js";
4
+ import { getVarName } from "../../generic/utils.js";
5
+ import { captureFieldName } from "./captureFieldName.js";
4
6
 
5
7
  /**
6
8
  * @param {import('../base_parser.js').XanoBaseParser} $
@@ -9,14 +11,16 @@ export function dbDelFn($) {
9
11
  return () => {
10
12
  $.sectionStack.push("dbDelFn");
11
13
  const fnToken = $.CONSUME(DelToken); // "delete"
12
- $.OR({
14
+ const nameToken = $.OR({
13
15
  DEF: [
14
- { ALT: () => $.CONSUME(Identifier) }, // user
15
- { ALT: () => $.CONSUME1(StringLiteral) }, // "user table"
16
+ { ALT: () => $.CONSUME(Identifier) },
17
+ { ALT: () => $.CONSUME1(StringLiteral) },
16
18
  ],
17
19
  ERR_MSG: "Expected a table name",
18
20
  });
21
+ $.addReference("table", getVarName(nameToken), nameToken);
19
22
 
23
+ const captured = {};
20
24
  $.SUBRULE($.schemaParseAttributeFn, {
21
25
  ARGS: [
22
26
  fnToken,
@@ -26,9 +30,12 @@ export function dbDelFn($) {
26
30
  "description?": "[string]",
27
31
  "disabled?": "[boolean]",
28
32
  },
33
+ captured,
29
34
  ],
30
35
  });
31
36
 
37
+ $.ACTION(() => captureFieldName($, captured));
38
+
32
39
  $.sectionStack.pop();
33
40
  };
34
41
  }
@@ -1,6 +1,8 @@
1
1
  import { EditToken } from "../../../lexer/db.js";
2
2
  import { StringLiteral } from "../../../lexer/literal.js";
3
3
  import { Identifier } from "../../../lexer/tokens.js";
4
+ import { getVarName } from "../../generic/utils.js";
5
+ import { captureDataKeys,captureFieldName } from "./captureFieldName.js";
4
6
  import { addonSchema } from "./schema.js";
5
7
 
6
8
  /**
@@ -10,14 +12,16 @@ export function dbEditFn($) {
10
12
  return () => {
11
13
  $.sectionStack.push("dbEditFn");
12
14
  const fnToken = $.CONSUME(EditToken); // "edit"
13
- $.OR({
15
+ const nameToken = $.OR({
14
16
  DEF: [
15
- { ALT: () => $.CONSUME(Identifier) }, // user
16
- { ALT: () => $.CONSUME1(StringLiteral) }, // "user table"
17
+ { ALT: () => $.CONSUME(Identifier) },
18
+ { ALT: () => $.CONSUME1(StringLiteral) },
17
19
  ],
18
20
  ERR_MSG: "Expected a table name",
19
21
  });
22
+ $.addReference("table", getVarName(nameToken), nameToken);
20
23
 
24
+ const captured = {};
21
25
  $.SUBRULE($.schemaParseAttributeFn, {
22
26
  ARGS: [
23
27
  fnToken,
@@ -31,9 +35,15 @@ export function dbEditFn($) {
31
35
  "addon?": [addonSchema],
32
36
  "mock?": { "![string]": "[expression]" },
33
37
  },
38
+ captured,
34
39
  ],
35
40
  });
36
41
 
42
+ $.ACTION(() => {
43
+ captureFieldName($, captured);
44
+ captureDataKeys($, captured);
45
+ });
46
+
37
47
  $.SUBRULE($.asVariable, { ARGS: [fnToken] });
38
48
  $.sectionStack.pop();
39
49
  };
@@ -1,6 +1,8 @@
1
1
  import { GetToken } from "../../../lexer/db.js";
2
2
  import { StringLiteral } from "../../../lexer/literal.js";
3
3
  import { Identifier } from "../../../lexer/tokens.js";
4
+ import { getVarName } from "../../generic/utils.js";
5
+ import { captureFieldName } from "./captureFieldName.js";
4
6
  import { addonSchema } from "./schema.js";
5
7
 
6
8
  /**
@@ -10,14 +12,16 @@ export function dbGetFn($) {
10
12
  return () => {
11
13
  $.sectionStack.push("dbGetFn");
12
14
  const fnToken = $.CONSUME(GetToken); // "get"
13
- $.OR({
15
+ const nameToken = $.OR({
14
16
  DEF: [
15
- { ALT: () => $.CONSUME(Identifier) }, // user
16
- { ALT: () => $.CONSUME1(StringLiteral) }, // "user table"
17
+ { ALT: () => $.CONSUME(Identifier) },
18
+ { ALT: () => $.CONSUME1(StringLiteral) },
17
19
  ],
18
20
  ERR_MSG: "Expected a table name",
19
21
  });
22
+ $.addReference("table", getVarName(nameToken), nameToken);
20
23
 
24
+ const captured = {};
21
25
  $.SUBRULE($.schemaParseAttributeFn, {
22
26
  ARGS: [
23
27
  fnToken,
@@ -31,9 +35,12 @@ export function dbGetFn($) {
31
35
  "addon?": [addonSchema],
32
36
  "mock?": { "![string]": "[expression]" },
33
37
  },
38
+ captured,
34
39
  ],
35
40
  });
36
41
 
42
+ $.ACTION(() => captureFieldName($, captured));
43
+
37
44
  $.SUBRULE($.asVariable, { ARGS: [fnToken] });
38
45
  $.sectionStack.pop();
39
46
  };
@@ -1,6 +1,8 @@
1
1
  import { HasToken } from "../../../lexer/db.js";
2
2
  import { StringLiteral } from "../../../lexer/literal.js";
3
3
  import { Identifier } from "../../../lexer/tokens.js";
4
+ import { getVarName } from "../../generic/utils.js";
5
+ import { captureFieldName } from "./captureFieldName.js";
4
6
 
5
7
  /**
6
8
  * @param {import('../base_parser.js').XanoBaseParser} $
@@ -9,13 +11,15 @@ export function dbHasFn($) {
9
11
  return () => {
10
12
  $.sectionStack.push("dbHasFn");
11
13
  const fnToken = $.CONSUME(HasToken); // "has"
12
- $.OR({
14
+ const nameToken = $.OR({
13
15
  DEF: [
14
- { ALT: () => $.CONSUME(Identifier) }, // user
15
- { ALT: () => $.CONSUME1(StringLiteral) }, // "user table"
16
+ { ALT: () => $.CONSUME(Identifier) },
17
+ { ALT: () => $.CONSUME1(StringLiteral) },
16
18
  ],
17
19
  ERR_MSG: "Expected a table name",
18
20
  });
21
+ $.addReference("table", getVarName(nameToken), nameToken);
22
+ const captured = {};
19
23
  $.SUBRULE($.schemaParseAttributeFn, {
20
24
  ARGS: [
21
25
  fnToken,
@@ -26,8 +30,10 @@ export function dbHasFn($) {
26
30
  "disabled?": "[boolean]",
27
31
  "mock?": { "![string]": "[expression]" },
28
32
  },
33
+ captured,
29
34
  ],
30
35
  });
36
+ $.ACTION(() => captureFieldName($, captured));
31
37
  $.SUBRULE($.asVariable, { ARGS: [fnToken] });
32
38
  $.sectionStack.pop();
33
39
  };
@@ -1,6 +1,8 @@
1
1
  import { PatchToken } from "../../../lexer/db.js";
2
2
  import { StringLiteral } from "../../../lexer/literal.js";
3
3
  import { Identifier } from "../../../lexer/tokens.js";
4
+ import { getVarName } from "../../generic/utils.js";
5
+ import { captureFieldName } from "./captureFieldName.js";
4
6
  import { addonSchema } from "./schema.js";
5
7
 
6
8
  /**
@@ -10,14 +12,16 @@ export function dbPatchFn($) {
10
12
  return () => {
11
13
  $.sectionStack.push("dbPatchFn");
12
14
  const fnToken = $.CONSUME(PatchToken); // "patch"
13
- $.OR({
15
+ const nameToken = $.OR({
14
16
  DEF: [
15
- { ALT: () => $.CONSUME(Identifier) }, // user
16
- { ALT: () => $.CONSUME1(StringLiteral) }, // "user table"
17
+ { ALT: () => $.CONSUME(Identifier) },
18
+ { ALT: () => $.CONSUME1(StringLiteral) },
17
19
  ],
18
20
  ERR_MSG: "Expected a table name",
19
21
  });
22
+ $.addReference("table", getVarName(nameToken), nameToken);
20
23
 
24
+ const captured = {};
21
25
  $.SUBRULE($.schemaParseAttributeFn, {
22
26
  ARGS: [
23
27
  fnToken,
@@ -30,9 +34,12 @@ export function dbPatchFn($) {
30
34
  "addon?": [addonSchema],
31
35
  "mock?": { "![string]": "[expression]" },
32
36
  },
37
+ captured,
33
38
  ],
34
39
  });
35
40
 
41
+ $.ACTION(() => captureFieldName($, captured));
42
+
36
43
  $.SUBRULE($.asVariable, { ARGS: [fnToken] });
37
44
  $.sectionStack.pop();
38
45
  };
@@ -1,6 +1,7 @@
1
1
  import { QueryToken } from "../../../lexer/db.js";
2
2
  import { StringLiteral } from "../../../lexer/literal.js";
3
3
  import { Identifier } from "../../../lexer/tokens.js";
4
+ import { getVarName } from "../../generic/utils.js";
4
5
  import { addonSchema } from "./schema.js";
5
6
 
6
7
  /**
@@ -10,11 +11,13 @@ export function dbQueryFn($) {
10
11
  return () => {
11
12
  $.sectionStack.push("dbQueryFn");
12
13
  const fnToken = $.CONSUME(QueryToken); // "query"
13
- $.OR([
14
- { ALT: () => $.CONSUME(Identifier) }, // user
15
- { ALT: () => $.CONSUME1(StringLiteral) }, // "user table"
14
+ const nameToken = $.OR([
15
+ { ALT: () => $.CONSUME(Identifier) },
16
+ { ALT: () => $.CONSUME1(StringLiteral) },
16
17
  ]);
18
+ $.addReference("table", getVarName(nameToken), nameToken);
17
19
 
20
+ const captured = {};
18
21
  $.SUBRULE($.schemaParseAttributeFn, {
19
22
  ARGS: [
20
23
  fnToken,
@@ -51,9 +54,32 @@ export function dbQueryFn($) {
51
54
  "where?": "[query]",
52
55
  "additional_where?": "[query]",
53
56
  },
57
+ captured,
54
58
  ],
55
59
  });
56
60
 
61
+ $.ACTION(() => {
62
+ // Extract join table references
63
+ if (captured.join) {
64
+ for (const [k, v] of Object.entries(captured.join)) {
65
+ if (k === "key" || k === "value") continue;
66
+ const tableEntry = v?.table;
67
+ if (tableEntry?.value) {
68
+ $.addReference("table", getVarName(tableEntry.value), tableEntry.value);
69
+ }
70
+ }
71
+ }
72
+ // Extract addon name references
73
+ if (captured.addon?.value && Array.isArray(captured.addon.value)) {
74
+ for (const item of captured.addon.value) {
75
+ const nameEntry = item.name;
76
+ if (nameEntry?.value) {
77
+ $.addReference("function", getVarName(nameEntry.value), nameEntry.value);
78
+ }
79
+ }
80
+ }
81
+ });
82
+
57
83
  // db.query rule is used within an addon declaration, but
58
84
  // in this context we don't allow "as" variable assignment
59
85
  const isAddonContext = $.sectionStack.includes("addonDeclaration");
@@ -1,6 +1,7 @@
1
1
  import { SchemaToken } from "../../../lexer/db.js";
2
2
  import { StringLiteral } from "../../../lexer/literal.js";
3
3
  import { Identifier } from "../../../lexer/tokens.js";
4
+ import { getVarName } from "../../generic/utils.js";
4
5
 
5
6
  /**
6
7
  * @param {import('../base_parser.js').XanoBaseParser} $
@@ -12,10 +13,11 @@ export function dbSchemaFn($) {
12
13
 
13
14
  $.sectionStack.push("dbSchemaFn");
14
15
  const fnToken = $.CONSUME(SchemaToken); // "schema"
15
- $.OR([
16
- { ALT: () => $.CONSUME(Identifier) }, // user
17
- { ALT: () => $.CONSUME1(StringLiteral) }, // "user table"
16
+ const nameToken = $.OR([
17
+ { ALT: () => $.CONSUME(Identifier) },
18
+ { ALT: () => $.CONSUME1(StringLiteral) },
18
19
  ]);
20
+ $.addReference("table", getVarName(nameToken), nameToken);
19
21
  $.SUBRULE($.functionAttrReq, {
20
22
  ARGS: [fnToken, requiredAttrs, optionalAttrs],
21
23
  });
@@ -1,6 +1,7 @@
1
1
  import { TruncateToken } from "../../../lexer/db.js";
2
2
  import { StringLiteral } from "../../../lexer/literal.js";
3
3
  import { Identifier } from "../../../lexer/tokens.js";
4
+ import { getVarName } from "../../generic/utils.js";
4
5
 
5
6
  /**
6
7
  * @param {import('../base_parser.js').XanoBaseParser} $
@@ -9,13 +10,14 @@ export function dbTruncateFn($) {
9
10
  return () => {
10
11
  $.sectionStack.push("dbTruncateFn");
11
12
  const fnToken = $.CONSUME(TruncateToken); // "truncate"
12
- $.OR({
13
+ const nameToken = $.OR({
13
14
  DEF: [
14
- { ALT: () => $.CONSUME(Identifier) }, // user
15
- { ALT: () => $.CONSUME1(StringLiteral) }, // "user table"
15
+ { ALT: () => $.CONSUME(Identifier) },
16
+ { ALT: () => $.CONSUME1(StringLiteral) },
16
17
  ],
17
18
  ERR_MSG: "Expected a table name",
18
19
  });
20
+ $.addReference("table", getVarName(nameToken), nameToken);
19
21
 
20
22
  $.SUBRULE($.schemaParseAttributeFn, {
21
23
  ARGS: [
@@ -2,6 +2,7 @@ import { CallToken } from "../../lexer/action.js";
2
2
  import { StringLiteral } from "../../lexer/literal.js";
3
3
  import { MiddlewareToken } from "../../lexer/middleware.js";
4
4
  import { DotToken, Identifier } from "../../lexer/tokens.js";
5
+ import { getVarName } from "../generic/utils.js";
5
6
 
6
7
  /**
7
8
  *
@@ -15,10 +16,11 @@ export function middlewareCallFn($) {
15
16
  $.CONSUME(DotToken); // "."
16
17
  const fnToken = $.CONSUME(CallToken); // "call"
17
18
 
18
- $.OR([
19
+ const nameToken = $.OR([
19
20
  { ALT: () => $.CONSUME(Identifier) }, // user
20
21
  { ALT: () => $.CONSUME1(StringLiteral) }, // "user auth"
21
22
  ]);
23
+ $.addReference("middleware", getVarName(nameToken), nameToken);
22
24
 
23
25
  $.OPTION(() => {
24
26
  $.SUBRULE($.schemaParseAttributeFn, {
@@ -8,7 +8,9 @@ import { securityCreateUuidFn } from "./securityCreateUuidFn.js";
8
8
  import { securityDecryptFn } from "./securityDecryptFn.js";
9
9
  import { securityEncryptFn } from "./securityEncryptFn.js";
10
10
  import { securityJweDecodeFn } from "./securityJweDecodeFn.js";
11
+ import { securityJweDecodeLegacyFn } from "./securityJweDecodeLegacyFn.js";
11
12
  import { securityJweEncodeFn } from "./securityJweEncodeFn.js";
13
+ import { securityJweEncodeLegacyFn } from "./securityJweEncodeLegacyFn.js";
12
14
  import { securityJwsDecodeFn } from "./securityJwsDecodeFn.js";
13
15
  import { securityJwsEncodeFn } from "./securityJwsEncodeFn.js";
14
16
  import { securityRandomBytesFn } from "./securityRandomBytesFn.js";
@@ -21,44 +23,52 @@ import { securityRandomNumberFn } from "./securityRandomNumberFn.js";
21
23
  export const register = ($) => {
22
24
  $.securityCheckPasswordFn = $.RULE(
23
25
  "securityCheckPasswordFn",
24
- securityCheckPasswordFn($)
26
+ securityCheckPasswordFn($),
25
27
  );
26
28
  $.securityCreateAuthTokenFn = $.RULE(
27
29
  "securityCreateAuthTokenFn",
28
- securityCreateAuthTokenFn($)
30
+ securityCreateAuthTokenFn($),
29
31
  );
30
32
  $.securityCreateCurveKeyFn = $.RULE(
31
33
  "securityCreateCurveKeyFn",
32
- securityCreateCurveKeyFn($)
34
+ securityCreateCurveKeyFn($),
33
35
  );
34
36
  $.securityCreatePasswordFn = $.RULE(
35
37
  "securityCreatePasswordFn",
36
- securityCreatePasswordFn($)
38
+ securityCreatePasswordFn($),
37
39
  );
38
40
  $.securityCreateRsaKeyFn = $.RULE(
39
41
  "securityCreateRsaKeyFn",
40
- securityCreateRsaKeyFn($)
42
+ securityCreateRsaKeyFn($),
41
43
  );
42
44
  $.securityCreateSecretKeyFn = $.RULE(
43
45
  "securityCreateSecretKeyFn",
44
- securityCreateSecretKeyFn($)
46
+ securityCreateSecretKeyFn($),
45
47
  );
46
48
  $.securityCreateUuidFn = $.RULE(
47
49
  "securityCreateUuidFn",
48
- securityCreateUuidFn($)
50
+ securityCreateUuidFn($),
49
51
  );
50
52
  $.securityDecryptFn = $.RULE("securityDecryptFn", securityDecryptFn($));
51
53
  $.securityEncryptFn = $.RULE("securityEncryptFn", securityEncryptFn($));
52
54
  $.securityJweDecodeFn = $.RULE("securityJweDecodeFn", securityJweDecodeFn($));
53
55
  $.securityJweEncodeFn = $.RULE("securityJweEncodeFn", securityJweEncodeFn($));
56
+ $.securityJweDecodeLegacyFn = $.RULE(
57
+ "securityJweDecodeLegacyFn",
58
+ securityJweDecodeLegacyFn($),
59
+ );
60
+ $.securityJweEncodeLegacyFn = $.RULE(
61
+ "securityJweEncodeLegacyFn",
62
+ securityJweEncodeLegacyFn($),
63
+ );
54
64
  $.securityJwsDecodeFn = $.RULE("securityJwsDecodeFn", securityJwsDecodeFn($));
55
65
  $.securityJwsEncodeFn = $.RULE("securityJwsEncodeFn", securityJwsEncodeFn($));
56
66
  $.securityRandomBytesFn = $.RULE(
57
67
  "securityRandomBytesFn",
58
- securityRandomBytesFn($)
68
+ securityRandomBytesFn($),
59
69
  );
60
70
  $.securityRandomNumberFn = $.RULE(
61
71
  "securityRandomNumberFn",
62
- securityRandomNumberFn($)
72
+ securityRandomNumberFn($),
63
73
  );
64
74
  };
@@ -1,4 +1,8 @@
1
+ import { SingleQuotedStringLiteral,StringLiteral } from "../../../lexer/literal.js";
1
2
  import { CreateAuthTokenToken } from "../../../lexer/security.js";
3
+ import { getVarName } from "../../generic/utils.js";
4
+
5
+ const stringTokens = new Set([StringLiteral.name, SingleQuotedStringLiteral.name]);
2
6
 
3
7
  /**
4
8
  * @param {import('../../base_parser.js').XanoBaseParser} $
@@ -8,6 +12,7 @@ export function securityCreateAuthTokenFn($) {
8
12
  $.sectionStack.push("securityCreateAuthTokenFn");
9
13
  const fnToken = $.CONSUME(CreateAuthTokenToken); // "create_auth_token"
10
14
 
15
+ const captured = {};
11
16
  $.SUBRULE($.schemaParseAttributeFn, {
12
17
  ARGS: [
13
18
  fnToken,
@@ -19,9 +24,26 @@ export function securityCreateAuthTokenFn($) {
19
24
  "description?": "[string]",
20
25
  "disabled?": "[boolean]",
21
26
  },
27
+ captured,
22
28
  ],
23
29
  });
24
30
 
31
+ $.ACTION(() => {
32
+ if (!captured.table) return;
33
+ const keyOffset = captured.table.key?.startOffset;
34
+ if (keyOffset == null) return;
35
+ const tokens = $.input;
36
+ for (let i = 0; i < tokens.length - 2; i++) {
37
+ if (tokens[i].startOffset === keyOffset) {
38
+ const valueToken = tokens[i + 2];
39
+ if (valueToken && stringTokens.has(valueToken.tokenType.name)) {
40
+ $.addReference("table", getVarName(valueToken), valueToken);
41
+ }
42
+ break;
43
+ }
44
+ }
45
+ });
46
+
25
47
  $.SUBRULE($.asVariable, { ARGS: [fnToken] });
26
48
  $.sectionStack.pop();
27
49
  };
@@ -0,0 +1,24 @@
1
+ import { EqualToken, LCurly, RCurly } from "../../../lexer/control.js";
2
+ import { JweDecodeLegacyToken } from "../../../lexer/security.js";
3
+ import { Identifier, NewlineToken } from "../../../lexer/tokens.js";
4
+
5
+ /**
6
+ * @param {import('../../base_parser.js').XanoBaseParser} $
7
+ */
8
+ export function securityJweDecodeLegacyFn($) {
9
+ return () => {
10
+ $.sectionStack.push("securityJweDecodeLegacyFn");
11
+ const fnToken = $.CONSUME(JweDecodeLegacyToken); // "jwe_decode_legacy"
12
+ $.CONSUME(LCurly); // "{"
13
+ $.MANY(() => {
14
+ $.AT_LEAST_ONE(() => $.CONSUME(NewlineToken));
15
+ $.CONSUME1(Identifier); // "field_name"
16
+ $.CONSUME(EqualToken); // "="
17
+ $.SUBRULE($.expressionFn);
18
+ });
19
+ $.MANY1(() => $.CONSUME1(NewlineToken));
20
+ $.CONSUME(RCurly); // "}"
21
+ $.SUBRULE($.asVariable, { ARGS: [fnToken] });
22
+ $.sectionStack.pop();
23
+ };
24
+ }
@@ -0,0 +1,26 @@
1
+ import { expect } from "chai";
2
+ import { describe, it } from "mocha";
3
+ import { lexDocument } from "../../../lexer/lexer.js";
4
+ import { parser } from "../../test_parser.js";
5
+
6
+ function parse(inputText) {
7
+ parser.reset();
8
+ const lexResult = lexDocument(inputText);
9
+ parser.input = lexResult.tokens;
10
+ parser.securityJweDecodeLegacyFn();
11
+ return parser;
12
+ }
13
+
14
+ describe("securityJweDecodeLegacyFn", () => {
15
+ it("securityJweDecodeLegacyFn accepts attributes and store value in a variable", () => {
16
+ const parser = parse(`jwe_decode_legacy {
17
+ token = $input.magic_token
18
+ key = $env.magic_jwt_secret
19
+ audience = "Xano"
20
+ key_algorithm = "A256KW"
21
+ content_algorithm = "A256CBC-HS512"
22
+ } as $decoded_magic_token`);
23
+ console.log(parser.errors);
24
+ expect(parser.errors).to.be.empty;
25
+ });
26
+ });
@@ -0,0 +1,24 @@
1
+ import { EqualToken, LCurly, RCurly } from "../../../lexer/control.js";
2
+ import { JweEncodeLegacyToken } from "../../../lexer/security.js";
3
+ import { Identifier, NewlineToken } from "../../../lexer/tokens.js";
4
+
5
+ /**
6
+ * @param {import('../../base_parser.js').XanoBaseParser} $
7
+ */
8
+ export function securityJweEncodeLegacyFn($) {
9
+ return () => {
10
+ $.sectionStack.push("securityJweEncodeLegacyFn");
11
+ const fnToken = $.CONSUME(JweEncodeLegacyToken); // "jwe_encode_legacy"
12
+ $.CONSUME(LCurly); // "{"
13
+ $.MANY(() => {
14
+ $.AT_LEAST_ONE(() => $.CONSUME(NewlineToken));
15
+ $.CONSUME1(Identifier); // "field_name"
16
+ $.CONSUME(EqualToken); // "="
17
+ $.SUBRULE($.expressionFn);
18
+ });
19
+ $.MANY1(() => $.CONSUME1(NewlineToken));
20
+ $.CONSUME(RCurly); // "}"
21
+ $.SUBRULE($.asVariable, { ARGS: [fnToken] });
22
+ $.sectionStack.pop();
23
+ };
24
+ }
@@ -0,0 +1,25 @@
1
+ import { expect } from "chai";
2
+ import { describe, it } from "mocha";
3
+ import { lexDocument } from "../../../lexer/lexer.js";
4
+ import { parser } from "../../test_parser.js";
5
+
6
+ function parse(inputText) {
7
+ parser.reset();
8
+ const lexResult = lexDocument(inputText);
9
+ parser.input = lexResult.tokens;
10
+ parser.securityJweEncodeLegacyFn();
11
+ return parser;
12
+ }
13
+
14
+ describe("securityJweEncodeLegacyFn", () => {
15
+ it("securityJweEncodeLegacyFn accepts attributes and store value in a variable", () => {
16
+ const parser = parse(`jwe_encode_legacy {
17
+ payload = $jwt_payload
18
+ audience = "Xano"
19
+ key = $env.magic_jwt_secret
20
+ key_algorithm = "A256KW"
21
+ content_algorithm = "A256CBC-HS512"
22
+ } as $jwt`);
23
+ expect(parser.errors).to.be.empty;
24
+ });
25
+ });
@@ -20,6 +20,8 @@ export function securityFn($) {
20
20
  { ALT: () => $.SUBRULE($.securityEncryptFn) }, // security.encrypt
21
21
  { ALT: () => $.SUBRULE($.securityJweDecodeFn) }, // security.jwe_decode
22
22
  { ALT: () => $.SUBRULE($.securityJweEncodeFn) }, // security.jwe_encode
23
+ { ALT: () => $.SUBRULE($.securityJweDecodeLegacyFn) }, // security.jwe_decode_legacy
24
+ { ALT: () => $.SUBRULE($.securityJweEncodeLegacyFn) }, // security.jwe_encode_legacy
23
25
  { ALT: () => $.SUBRULE($.securityJwsDecodeFn) }, // security.jws_decode
24
26
  { ALT: () => $.SUBRULE($.securityJwsEncodeFn) }, // security.jws_encode
25
27
  { ALT: () => $.SUBRULE($.securityRandomBytesFn) }, // security.random_bytes
@@ -68,7 +68,7 @@ export function varFn($) {
68
68
  // we can directly add the variable here but
69
69
  // not necessary for the `assignableVariableProperty` below
70
70
  // which will add it on its own
71
- $.addVariable(variable.image, "unknown");
71
+ $.addVariable(variable.image, "unknown", variable);
72
72
  }
73
73
  },
74
74
  },
@@ -13,7 +13,9 @@ export function asVariable($) {
13
13
  $.OPTION(() => {
14
14
  hasAs = true;
15
15
  $.CONSUME(AsToken); // "as"
16
+ $.__assignableIsDeclaration = true;
16
17
  $.SUBRULE($.assignableVariableProperty);
18
+ $.__assignableIsDeclaration = false;
17
19
  });
18
20
 
19
21
  if (!hasAs && parent) {
@@ -45,6 +45,7 @@ export function assignableVariableAs($) {
45
45
  )
46
46
  );
47
47
  }
48
+ $.addVariable(variableName, "unknown", variableToken);
48
49
  }
49
50
  };
50
51
  }
@@ -128,8 +128,11 @@ export function assignableVariableProperty($) {
128
128
  },
129
129
  });
130
130
 
131
- if (variableName) {
132
- $.addVariable(variableName, "unknown");
131
+ // Only register as a declaration when used in an "as $var" context.
132
+ // Other callers (var.update, math.*, text.*) are usages, not declarations,
133
+ // and the token scanner will pick them up automatically.
134
+ if (variableName && $.__assignableIsDeclaration) {
135
+ $.addVariable(variableName, "unknown", variableToken);
133
136
  }
134
137
  };
135
138
  }