@xano/xanoscript-language-server 12.16.3 → 12.16.4
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/lexer/microservice.js +169 -0
- package/lexer/tokens.js +6 -0
- package/package.json +1 -1
- package/parser/microservice_parser.js +413 -0
- package/parser/parser.js +3 -0
- package/parser/register.js +42 -0
- package/utils.js +1 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { Identifier } from "./identifier.js";
|
|
2
|
+
import { createTokenByName } from "./utils.js";
|
|
3
|
+
|
|
4
|
+
// Tokens for the top-level `microservice <name> { ... }` entity.
|
|
5
|
+
//
|
|
6
|
+
// The `microservice` keyword itself is NOT defined here — it reuses
|
|
7
|
+
// `MicroserviceToken` from `lexer/api.js` (also used by the inline
|
|
8
|
+
// `api.microservice` statement). Defining a second token for the same keyword
|
|
9
|
+
// would create two token types matching "microservice" and break lexing.
|
|
10
|
+
//
|
|
11
|
+
// Common words (`config`, `env`, `command`, `arg`, `ports`, `resources`, ...)
|
|
12
|
+
// all carry `longer_alt: Identifier` + `categories: [Identifier]` so they still
|
|
13
|
+
// behave as ordinary identifiers everywhere else in the grammar.
|
|
14
|
+
|
|
15
|
+
// ── Block keywords (introduce nested `{ ... }` blocks) ──
|
|
16
|
+
|
|
17
|
+
// "deployment"
|
|
18
|
+
export const DeploymentToken = createTokenByName("deployment", {
|
|
19
|
+
longer_alt: Identifier,
|
|
20
|
+
categories: [Identifier],
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// "container"
|
|
24
|
+
export const ContainerToken = createTokenByName("container", {
|
|
25
|
+
longer_alt: Identifier,
|
|
26
|
+
categories: [Identifier],
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// "config"
|
|
30
|
+
export const ConfigToken = createTokenByName("config", {
|
|
31
|
+
longer_alt: Identifier,
|
|
32
|
+
categories: [Identifier],
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// "volume"
|
|
36
|
+
export const VolumeToken = createTokenByName("volume", {
|
|
37
|
+
longer_alt: Identifier,
|
|
38
|
+
categories: [Identifier],
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// "ingress"
|
|
42
|
+
export const IngressToken = createTokenByName("ingress", {
|
|
43
|
+
longer_alt: Identifier,
|
|
44
|
+
categories: [Identifier],
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// "chart"
|
|
48
|
+
export const ChartToken = createTokenByName("chart", {
|
|
49
|
+
longer_alt: Identifier,
|
|
50
|
+
categories: [Identifier],
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// ── Leaf attribute keywords (`key = value`) ──
|
|
54
|
+
|
|
55
|
+
// "kind"
|
|
56
|
+
export const KindToken = createTokenByName("kind", {
|
|
57
|
+
longer_alt: Identifier,
|
|
58
|
+
categories: [Identifier],
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// "tenant_deploy"
|
|
62
|
+
export const TenantDeployToken = createTokenByName("tenant_deploy", {
|
|
63
|
+
longer_alt: Identifier,
|
|
64
|
+
categories: [Identifier],
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// "replicas"
|
|
68
|
+
export const ReplicasToken = createTokenByName("replicas", {
|
|
69
|
+
longer_alt: Identifier,
|
|
70
|
+
categories: [Identifier],
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// "docker"
|
|
74
|
+
export const DockerToken = createTokenByName("docker", {
|
|
75
|
+
longer_alt: Identifier,
|
|
76
|
+
categories: [Identifier],
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// "strategy"
|
|
80
|
+
export const StrategyToken = createTokenByName("strategy", {
|
|
81
|
+
longer_alt: Identifier,
|
|
82
|
+
categories: [Identifier],
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// "pull_secret"
|
|
86
|
+
export const PullSecretToken = createTokenByName("pull_secret", {
|
|
87
|
+
longer_alt: Identifier,
|
|
88
|
+
categories: [Identifier],
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// "command"
|
|
92
|
+
export const CommandToken = createTokenByName("command", {
|
|
93
|
+
longer_alt: Identifier,
|
|
94
|
+
categories: [Identifier],
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// "arg"
|
|
98
|
+
export const ArgToken = createTokenByName("arg", {
|
|
99
|
+
longer_alt: Identifier,
|
|
100
|
+
categories: [Identifier],
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// "env"
|
|
104
|
+
export const EnvToken = createTokenByName("env", {
|
|
105
|
+
longer_alt: Identifier,
|
|
106
|
+
categories: [Identifier],
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// "ports"
|
|
110
|
+
export const PortsToken = createTokenByName("ports", {
|
|
111
|
+
longer_alt: Identifier,
|
|
112
|
+
categories: [Identifier],
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// "resources"
|
|
116
|
+
export const ResourcesToken = createTokenByName("resources", {
|
|
117
|
+
longer_alt: Identifier,
|
|
118
|
+
categories: [Identifier],
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
export const MicroserviceTokens = [
|
|
122
|
+
DeploymentToken,
|
|
123
|
+
ContainerToken,
|
|
124
|
+
ConfigToken,
|
|
125
|
+
VolumeToken,
|
|
126
|
+
IngressToken,
|
|
127
|
+
ChartToken,
|
|
128
|
+
KindToken,
|
|
129
|
+
TenantDeployToken,
|
|
130
|
+
ReplicasToken,
|
|
131
|
+
DockerToken,
|
|
132
|
+
StrategyToken,
|
|
133
|
+
PullSecretToken,
|
|
134
|
+
CommandToken,
|
|
135
|
+
ArgToken,
|
|
136
|
+
EnvToken,
|
|
137
|
+
PortsToken,
|
|
138
|
+
ResourcesToken,
|
|
139
|
+
];
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Maps a token name to a semantic type
|
|
143
|
+
* @param {string} token the token name
|
|
144
|
+
*/
|
|
145
|
+
export function mapTokenToType(token) {
|
|
146
|
+
switch (token) {
|
|
147
|
+
case DeploymentToken.name:
|
|
148
|
+
case ContainerToken.name:
|
|
149
|
+
case ConfigToken.name:
|
|
150
|
+
case VolumeToken.name:
|
|
151
|
+
case IngressToken.name:
|
|
152
|
+
case ChartToken.name:
|
|
153
|
+
return "keyword";
|
|
154
|
+
case KindToken.name:
|
|
155
|
+
case TenantDeployToken.name:
|
|
156
|
+
case ReplicasToken.name:
|
|
157
|
+
case DockerToken.name:
|
|
158
|
+
case StrategyToken.name:
|
|
159
|
+
case PullSecretToken.name:
|
|
160
|
+
case CommandToken.name:
|
|
161
|
+
case ArgToken.name:
|
|
162
|
+
case EnvToken.name:
|
|
163
|
+
case PortsToken.name:
|
|
164
|
+
case ResourcesToken.name:
|
|
165
|
+
return "variable";
|
|
166
|
+
default:
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
}
|
package/lexer/tokens.js
CHANGED
|
@@ -96,6 +96,10 @@ import {
|
|
|
96
96
|
mapTokenToType as mapMessageTokenToType,
|
|
97
97
|
MessageTokens,
|
|
98
98
|
} from "./message.js";
|
|
99
|
+
import {
|
|
100
|
+
mapTokenToType as mapMicroserviceTokenToType,
|
|
101
|
+
MicroserviceTokens,
|
|
102
|
+
} from "./microservice.js";
|
|
99
103
|
import {
|
|
100
104
|
mapTokenToType as mapMiddlewareTokenToType,
|
|
101
105
|
MiddlewareTokens,
|
|
@@ -386,6 +390,7 @@ export const allTokens = uniq([
|
|
|
386
390
|
...AgentTriggerTokens,
|
|
387
391
|
...McpServerTriggerTokens,
|
|
388
392
|
...McpServerTokens,
|
|
393
|
+
...MicroserviceTokens,
|
|
389
394
|
...RealtimeServerTriggerTokens,
|
|
390
395
|
...RealtimeTriggerTokens,
|
|
391
396
|
...ChannelTriggerTokens,
|
|
@@ -501,6 +506,7 @@ const tokenMappers = [
|
|
|
501
506
|
mapMcpServerTokenToType,
|
|
502
507
|
mapMcpServerTriggerTokenToType,
|
|
503
508
|
mapMessageTokenToType,
|
|
509
|
+
mapMicroserviceTokenToType,
|
|
504
510
|
mapMiddlewareTokenToType,
|
|
505
511
|
mapMultilineTokenToType,
|
|
506
512
|
mapObjectTokenToType,
|
package/package.json
CHANGED
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
import { MicroserviceToken } from "../lexer/api.js";
|
|
2
|
+
import { ImageToken } from "../lexer/columns.js";
|
|
3
|
+
import { EqualToken, LCurly, RCurly } from "../lexer/control.js";
|
|
4
|
+
import { StringLiteral } from "../lexer/literal.js";
|
|
5
|
+
import {
|
|
6
|
+
ArgToken,
|
|
7
|
+
ChartToken,
|
|
8
|
+
CommandToken,
|
|
9
|
+
ConfigToken,
|
|
10
|
+
ContainerToken,
|
|
11
|
+
DeploymentToken,
|
|
12
|
+
DockerToken,
|
|
13
|
+
EnvToken,
|
|
14
|
+
IngressToken,
|
|
15
|
+
KindToken,
|
|
16
|
+
PortsToken,
|
|
17
|
+
PullSecretToken,
|
|
18
|
+
ReplicasToken,
|
|
19
|
+
ResourcesToken,
|
|
20
|
+
StrategyToken,
|
|
21
|
+
TenantDeployToken,
|
|
22
|
+
VolumeToken,
|
|
23
|
+
} from "../lexer/microservice.js";
|
|
24
|
+
import { Identifier, NewlineToken, TypeToken } from "../lexer/tokens.js";
|
|
25
|
+
|
|
26
|
+
// Grammar for the top-level `microservice <name> { ... }` entity.
|
|
27
|
+
//
|
|
28
|
+
// Grounded against cloud-client's authoritative XanoScript schema DSL
|
|
29
|
+
// (extensions/MVP/includes/xano/script/kind/schema/{core,component}/*.yaml):
|
|
30
|
+
//
|
|
31
|
+
// microservice <name> {
|
|
32
|
+
// description|guid|kind|tenant_deploy = "..." # static:text (optional)
|
|
33
|
+
// config <name> { type? value? } # REPEATING
|
|
34
|
+
// volume <name> { size? class? } # REPEATING
|
|
35
|
+
// ingress <name> { domain? path? } # REPEATING
|
|
36
|
+
// chart { ref? version? values? } # single
|
|
37
|
+
// deployment { # single
|
|
38
|
+
// replicas? = 1 docker? = "..." strategy? = "..."
|
|
39
|
+
// container <name> { # REPEATING
|
|
40
|
+
// image? pull_secret? type? = "..."
|
|
41
|
+
// command? arg? env? = [ {...} ] ports? = [ {...} ] resources? = {...}
|
|
42
|
+
// volume <name> { type? persistent? emptyDir? config? } # REPEATING
|
|
43
|
+
// }
|
|
44
|
+
// }
|
|
45
|
+
// }
|
|
46
|
+
//
|
|
47
|
+
// Blocks that mix leaf attributes with nested/repeating sub-blocks
|
|
48
|
+
// (microservice, deployment, container) use explicit gated OR-loops — mirroring
|
|
49
|
+
// channel_parser.js / mcp_server_parser.js. Leaf-only blocks
|
|
50
|
+
// (config/volume/ingress/chart/container_volume) delegate their `key = value`
|
|
51
|
+
// body to schemaParseAttributeFn, which validates the key set for free.
|
|
52
|
+
|
|
53
|
+
export function microserviceDeclaration($) {
|
|
54
|
+
return () => {
|
|
55
|
+
let hasDescription = false;
|
|
56
|
+
let hasGuid = false;
|
|
57
|
+
let hasKind = false;
|
|
58
|
+
let hasTenantDeploy = false;
|
|
59
|
+
let hasDeployment = false;
|
|
60
|
+
let hasChart = false;
|
|
61
|
+
|
|
62
|
+
$.sectionStack.push("microserviceDeclaration");
|
|
63
|
+
// Allow leading comments and newlines before the microservice declaration
|
|
64
|
+
$.SUBRULE($.optionalCommentBlockFn);
|
|
65
|
+
$.CONSUME(MicroserviceToken); // "microservice"
|
|
66
|
+
const nameToken = $.OR([
|
|
67
|
+
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
68
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
69
|
+
]);
|
|
70
|
+
$.validateDeclarationName(nameToken, "microservice");
|
|
71
|
+
$.CONSUME(LCurly); // "{"
|
|
72
|
+
$.MANY(() => {
|
|
73
|
+
$.AT_LEAST_ONE(() => $.CONSUME(NewlineToken)); // at least one new line
|
|
74
|
+
$.OR2([
|
|
75
|
+
{
|
|
76
|
+
ALT: () => $.SUBRULE($.commentBlockFn),
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
GATE: () => !hasDescription,
|
|
80
|
+
ALT: () => {
|
|
81
|
+
hasDescription = true;
|
|
82
|
+
$.SUBRULE($.descriptionFieldAttribute);
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
GATE: () => !hasGuid,
|
|
87
|
+
ALT: () => {
|
|
88
|
+
hasGuid = true;
|
|
89
|
+
$.SUBRULE($.guidFieldAttribute);
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
GATE: () => !hasKind,
|
|
94
|
+
ALT: () => {
|
|
95
|
+
hasKind = true;
|
|
96
|
+
const t = $.CONSUME(KindToken); // "kind"
|
|
97
|
+
$.CONSUME(EqualToken); // "="
|
|
98
|
+
$.SUBRULE($.schemaFn, { ARGS: [t, "[string]"] });
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
GATE: () => !hasTenantDeploy,
|
|
103
|
+
ALT: () => {
|
|
104
|
+
hasTenantDeploy = true;
|
|
105
|
+
const t = $.CONSUME(TenantDeployToken); // "tenant_deploy"
|
|
106
|
+
$.CONSUME1(EqualToken); // "="
|
|
107
|
+
$.SUBRULE1($.schemaFn, { ARGS: [t, "[string]"] });
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
GATE: () => !hasDeployment,
|
|
112
|
+
ALT: () => {
|
|
113
|
+
hasDeployment = true;
|
|
114
|
+
$.SUBRULE($.microserviceDeploymentClause);
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
GATE: () => !hasChart,
|
|
119
|
+
ALT: () => {
|
|
120
|
+
hasChart = true;
|
|
121
|
+
$.SUBRULE($.microserviceChartClause);
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
// config / volume / ingress are repeating — no single-shot gate.
|
|
125
|
+
{
|
|
126
|
+
ALT: () => $.SUBRULE($.microserviceConfigClause),
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
ALT: () => $.SUBRULE($.microserviceVolumeClause),
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
ALT: () => $.SUBRULE($.microserviceIngressClause),
|
|
133
|
+
},
|
|
134
|
+
]);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// All fields are optional — only the declaration name is required.
|
|
138
|
+
|
|
139
|
+
$.MANY1(() => $.CONSUME1(NewlineToken)); // optional new line
|
|
140
|
+
$.CONSUME(RCurly); // "}"
|
|
141
|
+
$.MANY2(() => $.CONSUME2(NewlineToken)); // optional new line
|
|
142
|
+
$.sectionStack.pop();
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// deployment { replicas? docker? strategy? container <name> { ... } }
|
|
147
|
+
export function microserviceDeploymentClause($) {
|
|
148
|
+
return () => {
|
|
149
|
+
let hasReplicas = false;
|
|
150
|
+
let hasDocker = false;
|
|
151
|
+
let hasStrategy = false;
|
|
152
|
+
|
|
153
|
+
$.CONSUME(DeploymentToken); // "deployment"
|
|
154
|
+
$.CONSUME(LCurly); // "{"
|
|
155
|
+
$.MANY(() => {
|
|
156
|
+
$.AT_LEAST_ONE(() => $.CONSUME(NewlineToken));
|
|
157
|
+
$.OR([
|
|
158
|
+
{
|
|
159
|
+
ALT: () => $.SUBRULE($.commentBlockFn),
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
GATE: () => !hasReplicas,
|
|
163
|
+
ALT: () => {
|
|
164
|
+
hasReplicas = true;
|
|
165
|
+
const t = $.CONSUME(ReplicasToken); // "replicas"
|
|
166
|
+
$.CONSUME(EqualToken); // "="
|
|
167
|
+
$.SUBRULE($.schemaFn, { ARGS: [t, "[number]"] });
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
GATE: () => !hasDocker,
|
|
172
|
+
ALT: () => {
|
|
173
|
+
hasDocker = true;
|
|
174
|
+
const t = $.CONSUME(DockerToken); // "docker"
|
|
175
|
+
$.CONSUME1(EqualToken); // "="
|
|
176
|
+
$.SUBRULE1($.schemaFn, { ARGS: [t, "[string]"] });
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
GATE: () => !hasStrategy,
|
|
181
|
+
ALT: () => {
|
|
182
|
+
hasStrategy = true;
|
|
183
|
+
const t = $.CONSUME(StrategyToken); // "strategy"
|
|
184
|
+
$.CONSUME2(EqualToken); // "="
|
|
185
|
+
$.SUBRULE2($.schemaFn, { ARGS: [t, "[string]"] });
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
// container is repeating — no single-shot gate.
|
|
189
|
+
{
|
|
190
|
+
ALT: () => $.SUBRULE($.microserviceContainerClause),
|
|
191
|
+
},
|
|
192
|
+
]);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
$.MANY1(() => $.CONSUME1(NewlineToken));
|
|
196
|
+
$.CONSUME(RCurly); // "}"
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// container <name> { image? pull_secret? type? command? arg? env? ports? resources? volume <name> { ... } }
|
|
201
|
+
export function microserviceContainerClause($) {
|
|
202
|
+
return () => {
|
|
203
|
+
let hasImage = false;
|
|
204
|
+
let hasPullSecret = false;
|
|
205
|
+
let hasType = false;
|
|
206
|
+
let hasCommand = false;
|
|
207
|
+
let hasArg = false;
|
|
208
|
+
let hasEnv = false;
|
|
209
|
+
let hasPorts = false;
|
|
210
|
+
let hasResources = false;
|
|
211
|
+
|
|
212
|
+
$.CONSUME(ContainerToken); // "container"
|
|
213
|
+
const nameToken = $.OR([
|
|
214
|
+
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
215
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
216
|
+
]);
|
|
217
|
+
$.validateDeclarationName(nameToken, "container");
|
|
218
|
+
$.CONSUME(LCurly); // "{"
|
|
219
|
+
$.MANY(() => {
|
|
220
|
+
$.AT_LEAST_ONE(() => $.CONSUME(NewlineToken));
|
|
221
|
+
$.OR2([
|
|
222
|
+
{
|
|
223
|
+
ALT: () => $.SUBRULE($.commentBlockFn),
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
GATE: () => !hasImage,
|
|
227
|
+
ALT: () => {
|
|
228
|
+
hasImage = true;
|
|
229
|
+
const t = $.CONSUME(ImageToken); // "image"
|
|
230
|
+
$.CONSUME(EqualToken); // "="
|
|
231
|
+
$.SUBRULE($.schemaFn, { ARGS: [t, "[string]"] });
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
GATE: () => !hasPullSecret,
|
|
236
|
+
ALT: () => {
|
|
237
|
+
hasPullSecret = true;
|
|
238
|
+
const t = $.CONSUME(PullSecretToken); // "pull_secret"
|
|
239
|
+
$.CONSUME1(EqualToken); // "="
|
|
240
|
+
$.SUBRULE1($.schemaFn, { ARGS: [t, "[string]"] });
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
GATE: () => !hasType,
|
|
245
|
+
ALT: () => {
|
|
246
|
+
hasType = true;
|
|
247
|
+
const t = $.CONSUME(TypeToken); // "type"
|
|
248
|
+
$.CONSUME2(EqualToken); // "="
|
|
249
|
+
$.SUBRULE2($.schemaFn, { ARGS: [t, "[string]"] });
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
GATE: () => !hasCommand,
|
|
254
|
+
ALT: () => {
|
|
255
|
+
hasCommand = true;
|
|
256
|
+
const t = $.CONSUME(CommandToken); // "command"
|
|
257
|
+
$.CONSUME3(EqualToken); // "="
|
|
258
|
+
// !static:objects { name } -> [ { name: "..." } ]
|
|
259
|
+
$.SUBRULE3($.schemaFn, { ARGS: [t, [{ name: "[string]" }]] });
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
GATE: () => !hasArg,
|
|
264
|
+
ALT: () => {
|
|
265
|
+
hasArg = true;
|
|
266
|
+
const t = $.CONSUME(ArgToken); // "arg"
|
|
267
|
+
$.CONSUME4(EqualToken); // "="
|
|
268
|
+
// !static:objects { name } -> [ { name: "..." } ]
|
|
269
|
+
$.SUBRULE4($.schemaFn, { ARGS: [t, [{ name: "[string]" }]] });
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
GATE: () => !hasEnv,
|
|
274
|
+
ALT: () => {
|
|
275
|
+
hasEnv = true;
|
|
276
|
+
const t = $.CONSUME(EnvToken); // "env"
|
|
277
|
+
$.CONSUME5(EqualToken); // "="
|
|
278
|
+
// !static:objects { name, value?, from_env? }
|
|
279
|
+
// -> [ { name: "...", value: "..." },
|
|
280
|
+
// { name: "...", from_env: "WORKSPACE_VAR" } ]
|
|
281
|
+
//
|
|
282
|
+
// `value` is a literal; `from_env` names a WORKSPACE environment
|
|
283
|
+
// variable resolved at DEPLOY time (so the secret never enters the
|
|
284
|
+
// document). The two are mutually exclusive — the server rejects an
|
|
285
|
+
// entry carrying both — but that is a semantic rule, not a shape
|
|
286
|
+
// one, so the grammar accepts either key and leaves the diagnostic
|
|
287
|
+
// to the backend transform.
|
|
288
|
+
$.SUBRULE5($.schemaFn, {
|
|
289
|
+
ARGS: [
|
|
290
|
+
t,
|
|
291
|
+
[{ name: "[string]", "value?": "[string]", "from_env?": "[string]" }],
|
|
292
|
+
],
|
|
293
|
+
});
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
GATE: () => !hasPorts,
|
|
298
|
+
ALT: () => {
|
|
299
|
+
hasPorts = true;
|
|
300
|
+
const t = $.CONSUME(PortsToken); // "ports"
|
|
301
|
+
$.CONSUME6(EqualToken); // "="
|
|
302
|
+
// static:object[] -> [ { ...any } ]
|
|
303
|
+
$.SUBRULE6($.schemaFn, { ARGS: [t, [{ "[string]?": "[constant]" }]] });
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
GATE: () => !hasResources,
|
|
308
|
+
ALT: () => {
|
|
309
|
+
hasResources = true;
|
|
310
|
+
const t = $.CONSUME(ResourcesToken); // "resources"
|
|
311
|
+
$.CONSUME7(EqualToken); // "="
|
|
312
|
+
// static:object -> { ...any }
|
|
313
|
+
$.SUBRULE7($.schemaFn, { ARGS: [t, { "[string]?": "[constant]" }] });
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
// volume is repeating — no single-shot gate.
|
|
317
|
+
{
|
|
318
|
+
ALT: () => $.SUBRULE($.microserviceContainerVolumeClause),
|
|
319
|
+
},
|
|
320
|
+
]);
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
$.MANY1(() => $.CONSUME1(NewlineToken));
|
|
324
|
+
$.CONSUME(RCurly); // "}"
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// container-level volume <name> { type? persistent? emptyDir? config? }
|
|
329
|
+
export function microserviceContainerVolumeClause($) {
|
|
330
|
+
return () => {
|
|
331
|
+
const parent = $.CONSUME(VolumeToken); // "volume"
|
|
332
|
+
const nameToken = $.OR([
|
|
333
|
+
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
334
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
335
|
+
]);
|
|
336
|
+
$.validateDeclarationName(nameToken, "volume");
|
|
337
|
+
$.SUBRULE($.schemaParseAttributeFn, {
|
|
338
|
+
ARGS: [
|
|
339
|
+
parent,
|
|
340
|
+
{
|
|
341
|
+
"type?": "[string]",
|
|
342
|
+
"persistent?": { "[string]?": "[constant]" },
|
|
343
|
+
"emptyDir?": { "[string]?": "[constant]" },
|
|
344
|
+
"config?": { "[string]?": "[constant]" },
|
|
345
|
+
},
|
|
346
|
+
],
|
|
347
|
+
});
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// microservice-level config <name> { type? value? }
|
|
352
|
+
export function microserviceConfigClause($) {
|
|
353
|
+
return () => {
|
|
354
|
+
const parent = $.CONSUME(ConfigToken); // "config"
|
|
355
|
+
const nameToken = $.OR([
|
|
356
|
+
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
357
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
358
|
+
]);
|
|
359
|
+
$.validateDeclarationName(nameToken, "config");
|
|
360
|
+
$.SUBRULE($.schemaParseAttributeFn, {
|
|
361
|
+
ARGS: [parent, { "type?": "[string]", "value?": "[string]" }],
|
|
362
|
+
});
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// microservice-level volume <name> { size? class? }
|
|
367
|
+
export function microserviceVolumeClause($) {
|
|
368
|
+
return () => {
|
|
369
|
+
const parent = $.CONSUME(VolumeToken); // "volume"
|
|
370
|
+
const nameToken = $.OR([
|
|
371
|
+
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
372
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
373
|
+
]);
|
|
374
|
+
$.validateDeclarationName(nameToken, "volume");
|
|
375
|
+
$.SUBRULE($.schemaParseAttributeFn, {
|
|
376
|
+
ARGS: [parent, { "size?": "[string]", "class?": "[string]" }],
|
|
377
|
+
});
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// ingress <name> { domain? path? = [ { service? path? } ] }
|
|
382
|
+
export function microserviceIngressClause($) {
|
|
383
|
+
return () => {
|
|
384
|
+
const parent = $.CONSUME(IngressToken); // "ingress"
|
|
385
|
+
const nameToken = $.OR([
|
|
386
|
+
{ ALT: () => $.CONSUME(StringLiteral) },
|
|
387
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
388
|
+
]);
|
|
389
|
+
$.validateDeclarationName(nameToken, "ingress");
|
|
390
|
+
$.SUBRULE($.schemaParseAttributeFn, {
|
|
391
|
+
ARGS: [
|
|
392
|
+
parent,
|
|
393
|
+
{
|
|
394
|
+
"domain?": "[string]",
|
|
395
|
+
"path?": [{ "service?": "[string]", "path?": "[string]" }],
|
|
396
|
+
},
|
|
397
|
+
],
|
|
398
|
+
});
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// chart { ref? version? values? }
|
|
403
|
+
export function microserviceChartClause($) {
|
|
404
|
+
return () => {
|
|
405
|
+
const parent = $.CONSUME(ChartToken); // "chart"
|
|
406
|
+
$.SUBRULE($.schemaParseAttributeFn, {
|
|
407
|
+
ARGS: [
|
|
408
|
+
parent,
|
|
409
|
+
{ "ref?": "[string]", "version?": "[string]", "values?": "[string]" },
|
|
410
|
+
],
|
|
411
|
+
});
|
|
412
|
+
};
|
|
413
|
+
}
|
package/parser/parser.js
CHANGED
|
@@ -57,6 +57,9 @@ export function xanoscriptParser(text, scheme, preTokenized = null) {
|
|
|
57
57
|
case "message":
|
|
58
58
|
parser.messageDeclaration();
|
|
59
59
|
return parser;
|
|
60
|
+
case "microservice":
|
|
61
|
+
parser.microserviceDeclaration();
|
|
62
|
+
return parser;
|
|
60
63
|
case "middleware":
|
|
61
64
|
parser.middlewareDeclaration();
|
|
62
65
|
return parser;
|
package/parser/register.js
CHANGED
|
@@ -16,6 +16,16 @@ import { mcpServerDeclaration } from "./mcp_server_parser.js";
|
|
|
16
16
|
import { mcpServerTriggerDeclaration } from "./mcp_server_trigger_parser.js";
|
|
17
17
|
import { messageDeclaration } from "./message_parser.js";
|
|
18
18
|
import { register as register_metadata } from "./metadata/register.js";
|
|
19
|
+
import {
|
|
20
|
+
microserviceChartClause,
|
|
21
|
+
microserviceConfigClause,
|
|
22
|
+
microserviceContainerClause,
|
|
23
|
+
microserviceContainerVolumeClause,
|
|
24
|
+
microserviceDeclaration,
|
|
25
|
+
microserviceDeploymentClause,
|
|
26
|
+
microserviceIngressClause,
|
|
27
|
+
microserviceVolumeClause,
|
|
28
|
+
} from "./microservice_parser.js";
|
|
19
29
|
import { middlewareDeclaration } from "./middleware_parser.js";
|
|
20
30
|
import { queryDeclaration } from "./query_parser.js";
|
|
21
31
|
import { realtimeChannelDeclaration } from "./realtime_channel_parser.js";
|
|
@@ -75,6 +85,38 @@ export const register = ($) => {
|
|
|
75
85
|
mcpServerTriggerDeclaration($)
|
|
76
86
|
);
|
|
77
87
|
$.messageDeclaration = $.RULE("messageDeclaration", messageDeclaration($));
|
|
88
|
+
$.microserviceDeclaration = $.RULE(
|
|
89
|
+
"microserviceDeclaration",
|
|
90
|
+
microserviceDeclaration($)
|
|
91
|
+
);
|
|
92
|
+
$.microserviceDeploymentClause = $.RULE(
|
|
93
|
+
"microserviceDeploymentClause",
|
|
94
|
+
microserviceDeploymentClause($)
|
|
95
|
+
);
|
|
96
|
+
$.microserviceContainerClause = $.RULE(
|
|
97
|
+
"microserviceContainerClause",
|
|
98
|
+
microserviceContainerClause($)
|
|
99
|
+
);
|
|
100
|
+
$.microserviceContainerVolumeClause = $.RULE(
|
|
101
|
+
"microserviceContainerVolumeClause",
|
|
102
|
+
microserviceContainerVolumeClause($)
|
|
103
|
+
);
|
|
104
|
+
$.microserviceConfigClause = $.RULE(
|
|
105
|
+
"microserviceConfigClause",
|
|
106
|
+
microserviceConfigClause($)
|
|
107
|
+
);
|
|
108
|
+
$.microserviceVolumeClause = $.RULE(
|
|
109
|
+
"microserviceVolumeClause",
|
|
110
|
+
microserviceVolumeClause($)
|
|
111
|
+
);
|
|
112
|
+
$.microserviceIngressClause = $.RULE(
|
|
113
|
+
"microserviceIngressClause",
|
|
114
|
+
microserviceIngressClause($)
|
|
115
|
+
);
|
|
116
|
+
$.microserviceChartClause = $.RULE(
|
|
117
|
+
"microserviceChartClause",
|
|
118
|
+
microserviceChartClause($)
|
|
119
|
+
);
|
|
78
120
|
$.middlewareDeclaration = $.RULE(
|
|
79
121
|
"middlewareDeclaration",
|
|
80
122
|
middlewareDeclaration($)
|
package/utils.js
CHANGED