@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.
- package/.claude/settings.local.json +2 -1
- package/cache/documentCache.js +58 -10
- package/lexer/db.js +1 -2
- package/lexer/security.js +16 -0
- package/onCompletion/onCompletion.js +61 -1
- package/onDefinition/onDefinition.js +150 -0
- package/onDefinition/onDefinition.spec.js +313 -0
- package/onDidChangeContent/onDidChangeContent.js +52 -5
- package/onHover/functions.md +28 -0
- package/package.json +1 -1
- package/parser/base_parser.js +61 -3
- package/parser/clauses/middlewareClause.js +16 -0
- package/parser/definitions/columnDefinition.js +5 -0
- package/parser/functions/api/apiCallFn.js +5 -3
- package/parser/functions/controls/functionCallFn.js +5 -3
- package/parser/functions/controls/functionRunFn.js +61 -5
- package/parser/functions/controls/taskCallFn.js +5 -3
- package/parser/functions/db/captureFieldName.js +63 -0
- package/parser/functions/db/dbAddFn.js +5 -3
- package/parser/functions/db/dbAddOrEditFn.js +13 -3
- package/parser/functions/db/dbBulkAddFn.js +5 -3
- package/parser/functions/db/dbBulkDeleteFn.js +5 -3
- package/parser/functions/db/dbBulkPatchFn.js +5 -3
- package/parser/functions/db/dbBulkUpdateFn.js +5 -3
- package/parser/functions/db/dbDelFn.js +10 -3
- package/parser/functions/db/dbEditFn.js +13 -3
- package/parser/functions/db/dbGetFn.js +10 -3
- package/parser/functions/db/dbHasFn.js +9 -3
- package/parser/functions/db/dbPatchFn.js +10 -3
- package/parser/functions/db/dbQueryFn.js +29 -3
- package/parser/functions/db/dbSchemaFn.js +5 -3
- package/parser/functions/db/dbTruncateFn.js +5 -3
- package/parser/functions/middlewareCallFn.js +3 -1
- package/parser/functions/security/register.js +19 -9
- package/parser/functions/security/securityCreateAuthTokenFn.js +22 -0
- package/parser/functions/security/securityJweDecodeLegacyFn.js +24 -0
- package/parser/functions/security/securityJweDecodeLegacyFn.spec.js +26 -0
- package/parser/functions/security/securityJweEncodeLegacyFn.js +24 -0
- package/parser/functions/security/securityJweEncodeLegacyFn.spec.js +25 -0
- package/parser/functions/securityFn.js +2 -0
- package/parser/functions/varFn.js +1 -1
- package/parser/generic/asVariable.js +2 -0
- package/parser/generic/assignableVariableAs.js +1 -0
- package/parser/generic/assignableVariableProperty.js +5 -2
- package/parser/tests/variable_test/coverage_check.xs +293 -0
- package/parser/variableScanner.js +64 -0
- package/parser/variableValidator.js +44 -0
- package/parser/variableValidator.spec.js +179 -0
- package/server.js +164 -10
- package/utils.js +32 -0
- package/utils.spec.js +93 -1
- package/workspace/crossFileValidator.js +166 -0
- package/workspace/crossFileValidator.spec.js +654 -0
- package/workspace/referenceTracking.spec.js +420 -0
- package/workspace/workspaceIndex.js +149 -0
- 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) },
|
|
15
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
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) },
|
|
16
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
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) },
|
|
16
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
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) },
|
|
15
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
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) },
|
|
16
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
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) },
|
|
15
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
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) },
|
|
17
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
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) },
|
|
15
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
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) {
|
|
@@ -128,8 +128,11 @@ export function assignableVariableProperty($) {
|
|
|
128
128
|
},
|
|
129
129
|
});
|
|
130
130
|
|
|
131
|
-
|
|
132
|
-
|
|
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
|
}
|