@xano/xanoscript-language-server 12.11.0 → 12.13.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 +1 -1
- package/lexer/realtime.js +12 -1
- package/package.json +1 -1
- package/parser/channel_parser.js +2 -8
- package/parser/channel_trigger_parser.js +3 -8
- package/parser/functions/realtime/realtimePublishFn.js +39 -0
- package/parser/functions/realtime/register.js +2 -0
- package/parser/functions/realtimeFn.js +1 -0
- package/parser/message_parser.js +2 -8
package/README.md
CHANGED
|
@@ -62,7 +62,7 @@ The parser supports the following XanoScript constructs:
|
|
|
62
62
|
| `realtime_server` | Realtime v2 server definitions (the container that owns channels) |
|
|
63
63
|
| `channel` | Realtime v2 channel definitions (path templates) |
|
|
64
64
|
| `message` | Realtime v2 channel message handlers |
|
|
65
|
-
| `channel_trigger` | Realtime v2 channel
|
|
65
|
+
| `channel_trigger` | Realtime v2 channel triggers (join/leave lifecycle, deliver per-recipient) |
|
|
66
66
|
| `realtime_server_trigger` | Realtime v2 connection lifecycle triggers (connect/disconnect) |
|
|
67
67
|
| `tool` | Tool definitions |
|
|
68
68
|
| `workspace` | Workspace definitions |
|
package/lexer/realtime.js
CHANGED
|
@@ -13,12 +13,23 @@ export const GetSessionToken = createTokenByName("get_session", {
|
|
|
13
13
|
categories: [Identifier],
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
// publish
|
|
17
|
+
export const PublishToken = createTokenByName("publish", {
|
|
18
|
+
longer_alt: Identifier,
|
|
19
|
+
categories: [Identifier],
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export const RealtimeStatementTokens = [
|
|
23
|
+
RealtimeToken,
|
|
24
|
+
GetSessionToken,
|
|
25
|
+
PublishToken,
|
|
26
|
+
];
|
|
17
27
|
|
|
18
28
|
export function mapTokenToType(token) {
|
|
19
29
|
switch (token) {
|
|
20
30
|
case RealtimeToken.name:
|
|
21
31
|
case GetSessionToken.name:
|
|
32
|
+
case PublishToken.name:
|
|
22
33
|
return "function";
|
|
23
34
|
default:
|
|
24
35
|
return null;
|
package/package.json
CHANGED
package/parser/channel_parser.js
CHANGED
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
DeliveryToken,
|
|
5
5
|
PublishToken,
|
|
6
6
|
RateLimitToken,
|
|
7
|
-
ServerToken,
|
|
8
7
|
} from "../lexer/channel.js";
|
|
9
8
|
import { ChannelToken } from "../lexer/columns.js";
|
|
10
9
|
import { EqualToken, LCurly, RCurly } from "../lexer/control.js";
|
|
@@ -46,12 +45,7 @@ export function channelDeclaration($) {
|
|
|
46
45
|
GATE: () => !hasServer,
|
|
47
46
|
ALT: () => {
|
|
48
47
|
hasServer = true;
|
|
49
|
-
|
|
50
|
-
$.CONSUME(EqualToken); // "="
|
|
51
|
-
const result = $.CONSUME2(StringLiteral); // "server_name"
|
|
52
|
-
if (result.image === `""`) {
|
|
53
|
-
$.addMissingError(subParent, "server cannot be empty");
|
|
54
|
-
}
|
|
48
|
+
$.SUBRULE($.realtimeServerClause);
|
|
55
49
|
},
|
|
56
50
|
},
|
|
57
51
|
{
|
|
@@ -178,7 +172,7 @@ export function channelDeclaration($) {
|
|
|
178
172
|
});
|
|
179
173
|
|
|
180
174
|
if (!hasServer) {
|
|
181
|
-
$.addMissingError(parent, "{} is missing a
|
|
175
|
+
$.addMissingError(parent, "{} is missing a realtime_server clause");
|
|
182
176
|
}
|
|
183
177
|
|
|
184
178
|
$.MANY1(() => $.CONSUME1(NewlineToken)); // optional new line
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ServerToken } from "../lexer/channel.js";
|
|
2
1
|
import { ChannelTriggerToken } from "../lexer/channel_trigger.js";
|
|
3
2
|
import { EqualToken, LCurly, RCurly } from "../lexer/control.js";
|
|
4
3
|
import { StringLiteral } from "../lexer/literal.js";
|
|
@@ -50,6 +49,7 @@ export function channelTriggerDeclaration($) {
|
|
|
50
49
|
{
|
|
51
50
|
"join?": "[boolean]",
|
|
52
51
|
"leave?": "[boolean]",
|
|
52
|
+
"deliver?": "[boolean]",
|
|
53
53
|
},
|
|
54
54
|
],
|
|
55
55
|
});
|
|
@@ -68,12 +68,7 @@ export function channelTriggerDeclaration($) {
|
|
|
68
68
|
GATE: () => !hasServer,
|
|
69
69
|
ALT: () => {
|
|
70
70
|
hasServer = true;
|
|
71
|
-
|
|
72
|
-
$.CONSUME3(EqualToken); // "="
|
|
73
|
-
const result = $.CONSUME2(StringLiteral); // "server_name"
|
|
74
|
-
if (result.image === `""`) {
|
|
75
|
-
$.addMissingError(subParent, "server cannot be empty");
|
|
76
|
-
}
|
|
71
|
+
$.SUBRULE($.realtimeServerClause);
|
|
77
72
|
},
|
|
78
73
|
},
|
|
79
74
|
{
|
|
@@ -136,7 +131,7 @@ export function channelTriggerDeclaration($) {
|
|
|
136
131
|
});
|
|
137
132
|
|
|
138
133
|
if (!hasServer) {
|
|
139
|
-
$.addMissingError(parent, "{} is missing a
|
|
134
|
+
$.addMissingError(parent, "{} is missing a realtime_server clause");
|
|
140
135
|
}
|
|
141
136
|
|
|
142
137
|
if (!hasChannel) {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { PublishToken } from "../../../lexer/realtime.js";
|
|
2
|
+
|
|
3
|
+
// realtime.publish {
|
|
4
|
+
// realtime_server = "main"
|
|
5
|
+
// channel = "rooms/42"
|
|
6
|
+
// message = "chat" // optional — becomes the delivered frame's `type`
|
|
7
|
+
// data = $payload
|
|
8
|
+
// auth_table = "user" // optional — asserted identity (attribution only)
|
|
9
|
+
// auth_id = $auth.id // optional
|
|
10
|
+
// }
|
|
11
|
+
//
|
|
12
|
+
// Injects a server-authored event onto a realtime v2 channel (cloud-client
|
|
13
|
+
// mvp:realtime_publish). `realtime_server` + `channel` + `data` are required;
|
|
14
|
+
// `message`/`auth_table`/`auth_id` are optional. Flat attrs (the PHP transform
|
|
15
|
+
// maps auth_table/auth_id into the nested context.auth.{dbo_id,row_id} shape).
|
|
16
|
+
// Unlike realtime.get_session it has NO `as $var` binding.
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {import('../../base_parser.js').XanoBaseParser} $
|
|
20
|
+
*/
|
|
21
|
+
export function realtimePublishFn($) {
|
|
22
|
+
const requiredAttrs = ["realtime_server", "channel", "data"];
|
|
23
|
+
const optionalAttrs = [
|
|
24
|
+
"message",
|
|
25
|
+
"auth_table",
|
|
26
|
+
"auth_id",
|
|
27
|
+
"description",
|
|
28
|
+
"disabled",
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
return () => {
|
|
32
|
+
$.sectionStack.push("realtimePublishFn");
|
|
33
|
+
const fnToken = $.CONSUME(PublishToken); // "publish"
|
|
34
|
+
$.SUBRULE($.functionAttrReq, {
|
|
35
|
+
ARGS: [fnToken, requiredAttrs, optionalAttrs],
|
|
36
|
+
});
|
|
37
|
+
$.sectionStack.pop();
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { realtimeGetSessionFn } from "./realtimeGetSessionFn.js";
|
|
2
|
+
import { realtimePublishFn } from "./realtimePublishFn.js";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Registers all the parsers in this folder
|
|
@@ -9,4 +10,5 @@ export const register = ($) => {
|
|
|
9
10
|
"realtimeGetSessionFn",
|
|
10
11
|
realtimeGetSessionFn($),
|
|
11
12
|
);
|
|
13
|
+
$.realtimePublishFn = $.RULE("realtimePublishFn", realtimePublishFn($));
|
|
12
14
|
};
|
package/parser/message_parser.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ServerToken } from "../lexer/channel.js";
|
|
2
1
|
import { EqualToken, LCurly, RCurly } from "../lexer/control.js";
|
|
3
2
|
import { StringLiteral } from "../lexer/literal.js";
|
|
4
3
|
import { DeliverToToken, MessageToken } from "../lexer/message.js";
|
|
@@ -48,12 +47,7 @@ export function messageDeclaration($) {
|
|
|
48
47
|
GATE: () => !hasServer,
|
|
49
48
|
ALT: () => {
|
|
50
49
|
hasServer = true;
|
|
51
|
-
|
|
52
|
-
$.CONSUME3(EqualToken); // "="
|
|
53
|
-
const result = $.CONSUME3(StringLiteral); // "server_name"
|
|
54
|
-
if (result.image === `""`) {
|
|
55
|
-
$.addMissingError(subParent, "server cannot be empty");
|
|
56
|
-
}
|
|
50
|
+
$.SUBRULE($.realtimeServerClause);
|
|
57
51
|
},
|
|
58
52
|
},
|
|
59
53
|
{
|
|
@@ -142,7 +136,7 @@ export function messageDeclaration($) {
|
|
|
142
136
|
if (!hasServer) {
|
|
143
137
|
$.addMissingError(
|
|
144
138
|
parent,
|
|
145
|
-
`{} ${nameToken.image} is missing a
|
|
139
|
+
`{} ${nameToken.image} is missing a realtime_server clause`,
|
|
146
140
|
);
|
|
147
141
|
}
|
|
148
142
|
|