@cratis/screenplay-language 4.51.0 → 4.53.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 (190) hide show
  1. package/dist/TypeReferenceSymbol.d.ts +8 -0
  2. package/dist/TypeReferenceSymbol.d.ts.map +1 -0
  3. package/dist/bundles/chunk-7WJEZ72S.js +4463 -0
  4. package/dist/bundles/chunk-7WJEZ72S.js.map +7 -0
  5. package/dist/bundles/index.js +1410 -0
  6. package/dist/bundles/index.js.map +7 -0
  7. package/dist/bundles/sub-languages/capture/index.js +677 -0
  8. package/dist/bundles/sub-languages/capture/index.js.map +7 -0
  9. package/dist/bundles/sub-languages/projection/index.js +1647 -0
  10. package/dist/bundles/sub-languages/projection/index.js.map +7 -0
  11. package/dist/code-actions.d.ts +3 -0
  12. package/dist/code-actions.d.ts.map +1 -0
  13. package/dist/completion-items.d.ts +1 -0
  14. package/dist/completion-items.d.ts.map +1 -1
  15. package/dist/completion-planner.d.ts.map +1 -1
  16. package/dist/completions.d.ts.map +1 -1
  17. package/dist/diagnostic-codes.d.ts +3 -0
  18. package/dist/diagnostic-codes.d.ts.map +1 -1
  19. package/dist/diagnostics.d.ts.map +1 -1
  20. package/dist/hover-content.d.ts.map +1 -1
  21. package/dist/index.d.ts +3 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/keyword-docs.d.ts.map +1 -1
  24. package/dist/language.d.ts +1 -0
  25. package/dist/language.d.ts.map +1 -1
  26. package/dist/production-destinations.d.ts.map +1 -1
  27. package/dist/symbols.d.ts +4 -0
  28. package/dist/symbols.d.ts.map +1 -1
  29. package/dist/tokens.d.ts.map +1 -1
  30. package/dist/validation.d.ts +1 -0
  31. package/dist/validation.d.ts.map +1 -1
  32. package/package.json +13 -9
  33. package/DestinationHint.ts +0 -8
  34. package/ProductionSymbol.ts +0 -11
  35. package/completion-items.ts +0 -261
  36. package/completion-planner.ts +0 -167
  37. package/completions.ts +0 -156
  38. package/diagnostic-codes.ts +0 -43
  39. package/diagnostics.ts +0 -55
  40. package/dist/DestinationHint.js +0 -4
  41. package/dist/DestinationHint.js.map +0 -1
  42. package/dist/ProductionSymbol.js +0 -4
  43. package/dist/ProductionSymbol.js.map +0 -1
  44. package/dist/completion-items.js +0 -228
  45. package/dist/completion-items.js.map +0 -1
  46. package/dist/completion-planner.js +0 -143
  47. package/dist/completion-planner.js.map +0 -1
  48. package/dist/completions.js +0 -101
  49. package/dist/completions.js.map +0 -1
  50. package/dist/diagnostic-codes.js +0 -41
  51. package/dist/diagnostic-codes.js.map +0 -1
  52. package/dist/diagnostics.js +0 -50
  53. package/dist/diagnostics.js.map +0 -1
  54. package/dist/document-context.js +0 -85
  55. package/dist/document-context.js.map +0 -1
  56. package/dist/event-analysis-source.js +0 -19
  57. package/dist/event-analysis-source.js.map +0 -1
  58. package/dist/event-context-catalog.js +0 -116
  59. package/dist/event-context-catalog.js.map +0 -1
  60. package/dist/event-context.js +0 -88
  61. package/dist/event-context.js.map +0 -1
  62. package/dist/file-imports.js +0 -58
  63. package/dist/file-imports.js.map +0 -1
  64. package/dist/file-references.js +0 -70
  65. package/dist/file-references.js.map +0 -1
  66. package/dist/hover-content.js +0 -98
  67. package/dist/hover-content.js.map +0 -1
  68. package/dist/hover.js +0 -15
  69. package/dist/hover.js.map +0 -1
  70. package/dist/index.js +0 -61
  71. package/dist/index.js.map +0 -1
  72. package/dist/inlay-hints.js +0 -15
  73. package/dist/inlay-hints.js.map +0 -1
  74. package/dist/inline-event-validation.js +0 -131
  75. package/dist/inline-event-validation.js.map +0 -1
  76. package/dist/keyword-docs.js +0 -148
  77. package/dist/keyword-docs.js.map +0 -1
  78. package/dist/language.js +0 -196
  79. package/dist/language.js.map +0 -1
  80. package/dist/production-destinations.js +0 -32
  81. package/dist/production-destinations.js.map +0 -1
  82. package/dist/sub-language-registry.js +0 -18
  83. package/dist/sub-language-registry.js.map +0 -1
  84. package/dist/sub-languages/capture/CompletionProvider.js +0 -332
  85. package/dist/sub-languages/capture/CompletionProvider.js.map +0 -1
  86. package/dist/sub-languages/capture/HoverProvider.js +0 -87
  87. package/dist/sub-languages/capture/HoverProvider.js.map +0 -1
  88. package/dist/sub-languages/capture/Validator.js +0 -72
  89. package/dist/sub-languages/capture/Validator.js.map +0 -1
  90. package/dist/sub-languages/capture/index.js +0 -58
  91. package/dist/sub-languages/capture/index.js.map +0 -1
  92. package/dist/sub-languages/capture/language.js +0 -160
  93. package/dist/sub-languages/capture/language.js.map +0 -1
  94. package/dist/sub-languages/cdl.js +0 -74
  95. package/dist/sub-languages/cdl.js.map +0 -1
  96. package/dist/sub-languages/pdl.js +0 -73
  97. package/dist/sub-languages/pdl.js.map +0 -1
  98. package/dist/sub-languages/projection/CodeActionProvider.js +0 -93
  99. package/dist/sub-languages/projection/CodeActionProvider.js.map +0 -1
  100. package/dist/sub-languages/projection/CompletionProvider.js +0 -595
  101. package/dist/sub-languages/projection/CompletionProvider.js.map +0 -1
  102. package/dist/sub-languages/projection/HoverProvider.js +0 -333
  103. package/dist/sub-languages/projection/HoverProvider.js.map +0 -1
  104. package/dist/sub-languages/projection/Validator.js +0 -388
  105. package/dist/sub-languages/projection/Validator.js.map +0 -1
  106. package/dist/sub-languages/projection/index.js +0 -160
  107. package/dist/sub-languages/projection/index.js.map +0 -1
  108. package/dist/sub-languages/projection/language.js +0 -171
  109. package/dist/sub-languages/projection/language.js.map +0 -1
  110. package/dist/symbols.js +0 -275
  111. package/dist/symbols.js.map +0 -1
  112. package/dist/themes/screenplay-dark.js +0 -30
  113. package/dist/themes/screenplay-dark.js.map +0 -1
  114. package/dist/themes/screenplay-light.js +0 -30
  115. package/dist/themes/screenplay-light.js.map +0 -1
  116. package/dist/tokens.js +0 -147
  117. package/dist/tokens.js.map +0 -1
  118. package/dist/validation.js +0 -248
  119. package/dist/validation.js.map +0 -1
  120. package/document-context.ts +0 -93
  121. package/event-analysis-source.ts +0 -18
  122. package/event-context-catalog.ts +0 -135
  123. package/event-context.ts +0 -119
  124. package/file-imports.ts +0 -70
  125. package/file-references.ts +0 -87
  126. package/for_documentContext/when_stripping_comments.ts +0 -32
  127. package/for_eventContext/when_resolving_generated_catalog_vectors.ts +0 -15
  128. package/for_eventGenerations/when_editing_event_generations.ts +0 -57
  129. package/for_fileImports/when_finding_file_imports.ts +0 -38
  130. package/for_fileReferences/when_recognizing_an_absolute_path/with_paths_of_every_shape.ts +0 -26
  131. package/for_fileReferences/when_scanning_a_document/inside_a_code_fence.ts +0 -26
  132. package/for_fileReferences/when_scanning_a_document/with_a_bare_file_keyword.ts +0 -19
  133. package/for_fileReferences/when_scanning_a_document/with_a_file_directive.ts +0 -30
  134. package/for_fileReferences/when_scanning_a_document/with_a_property_named_file.ts +0 -25
  135. package/for_fileReferences/when_scanning_a_document/with_a_trailing_comment.ts +0 -25
  136. package/for_fileReferences/when_scanning_a_document/with_directives_on_several_constructs.ts +0 -41
  137. package/for_importablePaths/when_listing_what_a_document_can_import.ts +0 -34
  138. package/for_inlineEvents/when_analyzing_many_inline_events.ts +0 -59
  139. package/for_inlineEvents/when_authoring_inline_events.ts +0 -149
  140. package/for_inlineEvents/when_completing_many_events.ts +0 -49
  141. package/for_inlineEvents/when_indexing_command_production_ownership.ts +0 -79
  142. package/for_planCompletions/when_completing_a_file_import.ts +0 -26
  143. package/for_planCompletions/when_completing_a_specification_query.ts +0 -24
  144. package/for_planCompletions/when_completing_a_specification_step.ts +0 -42
  145. package/for_planCompletions/when_completing_an_absent_read_model.ts +0 -14
  146. package/for_planCompletions/when_completing_reaction_reads.ts +0 -36
  147. package/for_projectionCompletionProvider/when_completing_an_event_context_path.ts +0 -102
  148. package/for_projectionHoverProvider/when_hovering_an_event_context_path.ts +0 -44
  149. package/for_projectionValidator/when_validating_a_projection_with_variants.ts +0 -128
  150. package/for_projectionValidator/when_validating_event_context_paths.ts +0 -31
  151. package/for_scanDocument/when_scanning_a_query/with_a_dotted_return_type.ts +0 -34
  152. package/for_scanDocument/when_scanning_aliased_reads.ts +0 -33
  153. package/for_scanDocument/when_scanning_many_commands.ts +0 -47
  154. package/for_tokens/when_highlighting_a_file_import.ts +0 -18
  155. package/for_tokens/when_highlighting_event_metadata.ts +0 -63
  156. package/for_tokens/when_highlighting_specification_steps.ts +0 -28
  157. package/for_validateLines/when_validating_a_document/with_a_problem_of_every_coded_kind.ts +0 -77
  158. package/for_validateLines/when_validating_a_document/with_an_unknown_policy.ts +0 -33
  159. package/for_validateLines/when_validating_a_file_placed_by_an_import/with_names_declared_in_other_files.ts +0 -43
  160. package/for_validateLines/when_validating_event_context_paths/in_a_projection.ts +0 -97
  161. package/for_validateLines/when_validating_file_imports/at_every_level.ts +0 -36
  162. package/for_validateLines/when_validating_production_destinations/with_an_available_identifier.ts +0 -120
  163. package/hover-content.ts +0 -117
  164. package/hover.ts +0 -23
  165. package/index.ts +0 -125
  166. package/inlay-hints.ts +0 -17
  167. package/inline-event-validation.ts +0 -115
  168. package/keyword-docs.ts +0 -152
  169. package/language.ts +0 -212
  170. package/production-destinations.ts +0 -32
  171. package/sub-language-registry.ts +0 -42
  172. package/sub-languages/capture/CompletionProvider.ts +0 -365
  173. package/sub-languages/capture/HoverProvider.ts +0 -99
  174. package/sub-languages/capture/Validator.ts +0 -97
  175. package/sub-languages/capture/index.ts +0 -72
  176. package/sub-languages/capture/language.ts +0 -176
  177. package/sub-languages/cdl.ts +0 -76
  178. package/sub-languages/pdl.ts +0 -75
  179. package/sub-languages/projection/CodeActionProvider.ts +0 -123
  180. package/sub-languages/projection/CompletionProvider.ts +0 -660
  181. package/sub-languages/projection/HoverProvider.ts +0 -377
  182. package/sub-languages/projection/Validator.ts +0 -441
  183. package/sub-languages/projection/index.ts +0 -223
  184. package/sub-languages/projection/language.ts +0 -193
  185. package/symbols.ts +0 -374
  186. package/themes/screenplay-dark.ts +0 -33
  187. package/themes/screenplay-light.ts +0 -33
  188. package/tokens.ts +0 -174
  189. package/validation.ts +0 -443
  190. package/vitest.setup.ts +0 -5
@@ -0,0 +1,4463 @@
1
+ // language.ts
2
+ var languageId = "screenplay";
3
+ var languageExtensionPoint = {
4
+ id: languageId,
5
+ extensions: [".play"],
6
+ aliases: ["Screenplay", "screenplay", "play"],
7
+ mimetypes: ["text/x-screenplay"]
8
+ };
9
+ var constructKeywords = [
10
+ "domain",
11
+ "import",
12
+ "concept",
13
+ "type",
14
+ "policy",
15
+ "persona",
16
+ "authentication",
17
+ "module",
18
+ "layout",
19
+ "theme",
20
+ "ui",
21
+ "feature",
22
+ "slice",
23
+ "event",
24
+ "command",
25
+ "query",
26
+ "projection",
27
+ "capture",
28
+ "reaction",
29
+ "reducer",
30
+ "trigger",
31
+ "screen",
32
+ "dialog",
33
+ "form",
34
+ "contribute",
35
+ "constraint",
36
+ "specification",
37
+ "seed",
38
+ "behavior"
39
+ ];
40
+ var clauseKeywords = [
41
+ "description",
42
+ "template",
43
+ "profile",
44
+ "require",
45
+ "authenticated",
46
+ "role",
47
+ "claim",
48
+ "subject",
49
+ "authorize",
50
+ "validate",
51
+ "produces",
52
+ "reads",
53
+ // A clause in command bodies and reaction trigger bodies; @reads remains a value.
54
+ "as",
55
+ "handler",
56
+ "performer",
57
+ "observable",
58
+ "identifier",
59
+ "reason",
60
+ "from",
61
+ "when",
62
+ "given",
63
+ "then",
64
+ "arguments",
65
+ "result",
66
+ "clock",
67
+ // A specification step - 'given clock' and 'when clock' state an instant.
68
+ "exactly",
69
+ "error",
70
+ "message",
71
+ "not",
72
+ "empty",
73
+ "rule",
74
+ "matches",
75
+ "all",
76
+ "max",
77
+ "min",
78
+ "length",
79
+ "today",
80
+ "true",
81
+ "false",
82
+ "and",
83
+ "or",
84
+ "by",
85
+ "filter",
86
+ "data",
87
+ "via",
88
+ "action",
89
+ "navigate",
90
+ "to",
91
+ "label",
92
+ "section",
93
+ "table",
94
+ "summary",
95
+ "title",
96
+ "column",
97
+ "field",
98
+ "on",
99
+ "unique",
100
+ "file",
101
+ "concurrency",
102
+ "eventSource",
103
+ "sourceType",
104
+ "streamType",
105
+ "streamId",
106
+ "tag",
107
+ "for",
108
+ "readmodel",
109
+ "no",
110
+ "when",
111
+ "every",
112
+ "at",
113
+ "where",
114
+ "invokes",
115
+ "contains",
116
+ "starts",
117
+ "with",
118
+ "provider",
119
+ // Interaction: the words a behavior body uses. The built-in interaction kinds ('click', 'submit', and
120
+ // friends) are only reserved inside an `on` clause, so they are clause words rather than constructs -
121
+ // an identifier of the same name elsewhere in a document remains an identifier.
122
+ "uses",
123
+ "parameter",
124
+ "order",
125
+ "execute",
126
+ "open",
127
+ "close",
128
+ "refresh",
129
+ "set",
130
+ "notify",
131
+ "confirm",
132
+ "raise",
133
+ "interval",
134
+ "success",
135
+ "failure",
136
+ "click",
137
+ "double",
138
+ "select",
139
+ "submit",
140
+ "change",
141
+ "load",
142
+ "unload",
143
+ "enter",
144
+ "leave",
145
+ "info",
146
+ "warning"
147
+ ];
148
+ var codeBlockTags = ["csharp", "typescript", "react", "html", "sql"];
149
+ var contextRoots = [
150
+ "command",
151
+ "arguments",
152
+ "tenant",
153
+ "causedBy",
154
+ "causation",
155
+ "occurred",
156
+ "identity"
157
+ ];
158
+ var causedByProperties = ["subject", "name", "userName"];
159
+ var identityProperties = ["id", "name", "userName", "isAuthenticated", "roles", "claims"];
160
+ var sliceTypes = ["StateChange", "StateView", "Automation", "Translate"];
161
+ var primitiveTypes = ["Uuid", "String", "Int", "Decimal", "Bool", "Date", "DateTime"];
162
+ var conceptAttributes = ["@pii", "@sensitive"];
163
+ var languageConfiguration = {
164
+ comments: {
165
+ lineComment: "//"
166
+ },
167
+ brackets: [
168
+ ["(", ")"],
169
+ ["[", "]"]
170
+ ],
171
+ autoClosingPairs: [
172
+ { open: "(", close: ")" },
173
+ { open: "[", close: "]" },
174
+ { open: '"', close: '"' }
175
+ ],
176
+ surroundingPairs: [
177
+ { open: "(", close: ")" },
178
+ { open: "[", close: "]" },
179
+ { open: '"', close: '"' }
180
+ ],
181
+ folding: {
182
+ offSide: true
183
+ },
184
+ indentationRules: {
185
+ increaseIndentPattern: /^\s*(module|feature|slice|policy|persona|authentication|provider|event|command|query|type|screen|projection|capture|reaction|trigger|constraint|specification|layout|template|validate|produces|handler|performer|rule|section|concurrency|seed|for|when|then|arguments|result|every|at)\b.*$/,
186
+ // Dedents are always explicit in an offside language — never auto-dedent.
187
+ decreaseIndentPattern: /(?!)/
188
+ }
189
+ };
190
+
191
+ // TypeReferenceSymbol.ts
192
+ function typeReferenceSymbol(text) {
193
+ const match = /^([\w.]+)(\[\])?(\?|\s+optional)?$/.exec(text);
194
+ return { name: match?.[1] ?? text, isCollection: match?.[2] !== void 0, isOptional: match?.[3] !== void 0 };
195
+ }
196
+ function typeReferenceText(type) {
197
+ return `${type.name}${type.isCollection ? "[]" : ""}${type.isOptional ? " optional" : ""}`;
198
+ }
199
+
200
+ // document-context.ts
201
+ function withoutComment(line) {
202
+ let inString = false;
203
+ let inTemplate = false;
204
+ for (let index = 0; index < line.length; index++) {
205
+ const character = line[index];
206
+ if (character === "\\" && inString && index + 1 < line.length) {
207
+ index++;
208
+ } else if (character === '"' && !inTemplate) {
209
+ inString = !inString;
210
+ } else if (character === "`" && !inString) {
211
+ inTemplate = !inTemplate;
212
+ } else if (!inString && !inTemplate && character === "/" && line[index + 1] === "/") {
213
+ return line.slice(0, index);
214
+ }
215
+ }
216
+ return line;
217
+ }
218
+ function indentOf(line) {
219
+ return line.length - line.trimStart().length;
220
+ }
221
+ function firstWord(line) {
222
+ return line.trim().split(/\s+/)[0] ?? "";
223
+ }
224
+ function fenceMap(lines) {
225
+ const map = new Array(lines.length).fill(false);
226
+ let open = false;
227
+ for (let index = 0; index < lines.length; index++) {
228
+ if (/^\s*```(?:[a-z]+)?\s*$/.test(lines[index]) && (!open || /^\s*```\s*$/.test(lines[index]))) {
229
+ map[index] = true;
230
+ open = !open;
231
+ continue;
232
+ }
233
+ map[index] = open;
234
+ }
235
+ return map;
236
+ }
237
+ function enclosingChain(lines, fences, lineIndex, indent) {
238
+ const chain = [];
239
+ let currentIndent = indent;
240
+ for (let index = lineIndex - 1; index >= 0 && currentIndent > 0; index--) {
241
+ if (fences[index]) continue;
242
+ const line = withoutComment(lines[index]);
243
+ if (line.trim().length === 0) continue;
244
+ const lineIndent = indentOf(line);
245
+ if (lineIndent < currentIndent) {
246
+ chain.push(firstWord(line));
247
+ currentIndent = lineIndent;
248
+ }
249
+ }
250
+ return chain;
251
+ }
252
+ function nearestEnclosingLine(lines, fences, lineIndex, indent) {
253
+ for (let index = lineIndex - 1; index >= 0 && indent > 0; index--) {
254
+ if (fences[index]) continue;
255
+ const line = withoutComment(lines[index]);
256
+ if (line.trim().length === 0) continue;
257
+ if (indentOf(line) < indent) {
258
+ return line.trim();
259
+ }
260
+ }
261
+ return void 0;
262
+ }
263
+
264
+ // event-analysis-source.ts
265
+ function eventAnalysisSource(lines) {
266
+ let fenced = false;
267
+ return lines.map((line) => {
268
+ if (fenced) {
269
+ if (line.trim() === "```") fenced = false;
270
+ return line;
271
+ }
272
+ const text = withoutComment(line);
273
+ if (/^\s*```(?:[a-z]+)?\s*$/.test(text)) fenced = true;
274
+ return text.trimEnd();
275
+ });
276
+ }
277
+
278
+ // symbols.ts
279
+ var conceptPattern = /^concept\s+(\w+)\s*:\s*(\w+)((?:\s+@\w+)*)\s*$/;
280
+ var propertyPattern = /^\s*(@?[a-z_]\w*)\s+([\w.]+(?:\[\])?(?:\?|\s+optional)?)(\s+identifier)?\s*$/;
281
+ var attributeReasonPattern = /^([a-z_]\w*)\s+reason\s+"((?:[^"\\]|\\.)*)"\s*$/;
282
+ var readPattern = /^\s*reads\s+([A-Z]\w*)(?:\s+as\s+([a-z_]\w*))?(?:\s+by\s+([a-z_]\w*))?\s*$/;
283
+ var commandReserved = ["authorize", "produces", "reads"];
284
+ var authorizationContinuation = /^(?:(?:or|and)\s+)?[A-Za-z_(][\p{L}\p{Mn}\p{Nd}\p{Pc}\s()]*$/u;
285
+ var eventReserved = clauseKeywords.filter((keyword) => !["id", "description", "documentation"].includes(keyword));
286
+ var queryParameterPattern = /^\s*(?:by|filter)\s+([a-z_]\w*)\s+([\w.]+(?:\[\])?(?:\?|\s+optional)?)(?:\s+from\s+.+)?\s*$/;
287
+ function propertyTypeReference(property) {
288
+ return property.typeReference ?? typeReferenceSymbol(property.type);
289
+ }
290
+ function propertiesIn(lines, body, reserved3) {
291
+ return body.map((index) => ({ index, match: lines[index].match(propertyPattern) })).filter((entry) => entry.match !== null).filter(({ match }) => match[1].startsWith("@") || match[1] === "as" || !reserved3.includes(match[1])).map(({ index, match }) => ({
292
+ name: match[1].replace(/^@/, ""),
293
+ type: match[2],
294
+ typeReference: typeReferenceSymbol(match[2]),
295
+ isIdentifier: match[3] !== void 0,
296
+ line: index
297
+ }));
298
+ }
299
+ function collectBody(lines, fences, start, indent) {
300
+ const body = [];
301
+ for (let index = start + 1; index < lines.length; index++) {
302
+ if (fences[index]) {
303
+ continue;
304
+ }
305
+ const line = lines[index];
306
+ if (line.trim().length === 0) continue;
307
+ if (indentOf(line) <= indent) break;
308
+ body.push(index);
309
+ }
310
+ return body;
311
+ }
312
+ function directBody(lines, fences, start, indent) {
313
+ const body = collectBody(lines, fences, start, indent).filter((index) => !fences[index] && !/^\s*(?:\/\/|#)/.test(lines[index]));
314
+ if (!/^\s*command\b/.test(lines[start])) return body;
315
+ let blockIndent;
316
+ let authorization = false;
317
+ return body.filter((index) => {
318
+ const childIndent = indentOf(lines[index]);
319
+ const text = lines[index].trim();
320
+ if (blockIndent !== void 0 && childIndent > blockIndent && (!authorization || authorizationContinuation.test(text))) return false;
321
+ const property = text !== "validate csharp" && propertiesIn(lines, [index], commandReserved).length > 0;
322
+ const leaf = property || /^description(?:\s|$)/.test(text);
323
+ blockIndent = leaf ? void 0 : childIndent;
324
+ authorization = /^authorize(?:\s|$)/.test(text);
325
+ return true;
326
+ });
327
+ }
328
+ function scanDocument(lines) {
329
+ const symbols = {
330
+ imports: [],
331
+ concepts: [],
332
+ types: [],
333
+ policies: [],
334
+ events: [],
335
+ commands: [],
336
+ queries: [],
337
+ screens: [],
338
+ triggers: []
339
+ };
340
+ lines = eventAnalysisSource(lines);
341
+ const fences = fenceMap(lines);
342
+ const eventLines = lines;
343
+ const eventFences = fences;
344
+ const eventPropertyLines = lines.map((line) => line.replace(/\s*=(?!=|>).*/, ""));
345
+ for (let index = 0; index < lines.length; index++) {
346
+ if (fences[index]) continue;
347
+ const line = lines[index];
348
+ const trimmed = line.trim();
349
+ const indent = indentOf(line);
350
+ const importMatch = eventLines[index].trim().match(/^import\s+([\w.]+)\s*$/);
351
+ if (importMatch && indent === 0) {
352
+ const qualifiedName = importMatch[1];
353
+ const shortName = qualifiedName.split(".").pop() ?? qualifiedName;
354
+ symbols.imports.push({ qualifiedName, shortName, line: index });
355
+ continue;
356
+ }
357
+ const conceptMatch = trimmed.match(conceptPattern);
358
+ if (conceptMatch) {
359
+ const body = collectBody(lines, fences, index, indent).map((i) => lines[i].trim());
360
+ const attributeReasons = {};
361
+ for (const line2 of body) {
362
+ const reason = line2.match(attributeReasonPattern);
363
+ if (reason && attributeReasons[reason[1]] === void 0) {
364
+ attributeReasons[reason[1]] = reason[2];
365
+ }
366
+ }
367
+ const enumValues = conceptMatch[2] === "Enum" ? body.filter((line2) => !attributeReasonPattern.test(line2)) : [];
368
+ symbols.concepts.push({
369
+ name: conceptMatch[1],
370
+ primitive: conceptMatch[2],
371
+ attributes: conceptMatch[3].trim().split(/\s+/).filter(Boolean),
372
+ attributeReasons,
373
+ enumValues,
374
+ line: index
375
+ });
376
+ continue;
377
+ }
378
+ const typeMatch = trimmed.match(/^type\s+(\w+)\s*$/);
379
+ if (typeMatch) {
380
+ symbols.types.push({
381
+ name: typeMatch[1],
382
+ properties: propertiesIn(lines, collectBody(lines, fences, index, indent), clauseKeywords),
383
+ line: index
384
+ });
385
+ continue;
386
+ }
387
+ const policyMatch = trimmed.match(/^policy\s+(\w+)\s*$/);
388
+ if (policyMatch) {
389
+ const requires = collectBody(lines, fences, index, indent).filter((i) => !fences[i]).map((i) => lines[i].trim());
390
+ symbols.policies.push({ name: policyMatch[1], requires, line: index });
391
+ continue;
392
+ }
393
+ const eventMatch = eventLines[index].trim().match(/^(?:produces\s+)?event\s+(\w+)(?:\s+generation\s+(\d+))?\s*$/);
394
+ if (eventMatch) {
395
+ symbols.events.push({
396
+ name: eventMatch[1],
397
+ ...eventMatch[2] ? { generation: Number(eventMatch[2]) } : {},
398
+ inline: trimmed.startsWith("produces "),
399
+ properties: propertiesIn(
400
+ trimmed.startsWith("produces ") ? eventPropertyLines : eventLines,
401
+ directBody(eventLines, eventFences, index, indent),
402
+ eventReserved
403
+ ),
404
+ line: index
405
+ });
406
+ continue;
407
+ }
408
+ const commandMatch = eventLines[index].trim().match(/^command\s+(\w+)\s*$/);
409
+ if (commandMatch) {
410
+ const body = directBody(lines, fences, index, indent);
411
+ const productionHeaders = body.filter((line2) => /^\s*produces\b/.test(lines[line2]));
412
+ symbols.commands.push({
413
+ name: commandMatch[1],
414
+ properties: propertiesIn(lines, body.filter((line2) => lines[line2].trim() !== "validate csharp"), commandReserved),
415
+ productionHeaders,
416
+ produces: productionHeaders.flatMap((line2) => {
417
+ const header10 = eventLines[line2].trim();
418
+ const inline = /^produces\s+event\b/.test(header10);
419
+ const conditional2 = /^produces\s+when\b/.test(header10);
420
+ const eventLine = conditional2 ? directBody(eventLines, eventFences, line2, indentOf(eventLines[line2]))[0] : line2;
421
+ if (eventLine === void 0) return [];
422
+ const name = conditional2 ? eventLines[eventLine].trim() : header10.match(inline ? /^produces\s+event\s+([A-Za-z_]\w*)(?:\s+generation\s+\d+)?\s*$/ : /^produces\s+([A-Z]\w*)\s*$/)?.[1];
423
+ if (name === void 0 || !/^[A-Za-z_]\w*$/.test(name)) return [];
424
+ const children = directBody(eventLines, eventFences, eventLine, indentOf(eventLines[eventLine]));
425
+ const targets = children.map((index2) => eventLines[index2].trim().match(/^for(?:\s+(.*))?$/)).filter((match) => match !== null);
426
+ const target = targets.length === 0 ? void 0 : targets.length === 1 ? targets[0][1] ?? "" : "";
427
+ const mappings = children.flatMap((index2) => {
428
+ const match = eventLines[index2].trim().match(inline ? /^(@?[a-z_]\w*)\s+[\w.]+(?:\[\])?(?:\?|\s+optional)?\s*=(?!=|>)\s*(.+)$/ : /^(@?[\w.]+)\s*=(?!=|>)\s*(.+)$/);
429
+ return match === null ? [] : [{ name: match[1].replace(/^@/, ""), source: match[2], line: index2 }];
430
+ });
431
+ return [{ name, inline, conditional: conditional2, line: line2, target, mappings }];
432
+ }),
433
+ reads: body.filter((line2) => !fences[line2]).map((line2) => ({ line: line2, match: lines[line2].match(readPattern) })).filter((entry) => entry.match !== null).map(({ line: line2, match }) => ({
434
+ view: match[1],
435
+ ...match[2] ? { alias: match[2] } : {},
436
+ ...match[3] ? { by: match[3] } : {},
437
+ line: line2
438
+ })),
439
+ line: index
440
+ });
441
+ continue;
442
+ }
443
+ const queryMatch = trimmed.match(/^query\s+(\w+)\s*=>\s*(?:observable\s+)?([\w.]+(?:\[\])?(?:\?|\s+optional)?)\s*$/);
444
+ if (queryMatch) {
445
+ const parameters = collectBody(lines, fences, index, indent).map((i) => ({ index: i, match: lines[i].match(queryParameterPattern) })).filter(
446
+ (entry) => entry.match !== null
447
+ ).map(({ index: line2, match }) => ({
448
+ name: match[1],
449
+ type: match[2],
450
+ typeReference: typeReferenceSymbol(match[2]),
451
+ isIdentifier: false,
452
+ line: line2
453
+ }));
454
+ symbols.queries.push({
455
+ name: queryMatch[1],
456
+ returnType: queryMatch[2],
457
+ returnTypeReference: typeReferenceSymbol(queryMatch[2]),
458
+ parameters,
459
+ line: index
460
+ });
461
+ continue;
462
+ }
463
+ const screenMatch = trimmed.match(/^screen\s+(\w+)\s*$/);
464
+ if (screenMatch) {
465
+ symbols.screens.push({ name: screenMatch[1], line: index });
466
+ continue;
467
+ }
468
+ const triggerMatch = trimmed.match(/^trigger\s+(\w+)\s*$/);
469
+ if (triggerMatch && indent === 0) {
470
+ symbols.triggers.push({ name: triggerMatch[1], line: index });
471
+ }
472
+ }
473
+ return symbols;
474
+ }
475
+ function mergeSymbols(...documents) {
476
+ return {
477
+ imports: documents.flatMap((document) => document.imports),
478
+ concepts: documents.flatMap((document) => document.concepts),
479
+ types: documents.flatMap((document) => document.types),
480
+ policies: documents.flatMap((document) => document.policies),
481
+ events: documents.flatMap((document) => document.events),
482
+ commands: documents.flatMap((document) => document.commands),
483
+ queries: documents.flatMap((document) => document.queries),
484
+ screens: documents.flatMap((document) => document.screens),
485
+ triggers: documents.flatMap((document) => document.triggers)
486
+ };
487
+ }
488
+ function knownEventNames(symbols) {
489
+ return [
490
+ ...symbols.events.map((event) => event.name),
491
+ ...symbols.imports.map((imported) => imported.shortName)
492
+ ];
493
+ }
494
+ var builtInTriggerNames = ["Startup", "Shutdown"];
495
+ function knownTriggerNames(symbols) {
496
+ return [
497
+ ...knownEventNames(symbols),
498
+ ...symbols.triggers.map((trigger) => trigger.name),
499
+ ...builtInTriggerNames
500
+ ];
501
+ }
502
+ function knownTypeNames(symbols, primitives) {
503
+ return [
504
+ ...primitives,
505
+ ...symbols.concepts.map((concept) => concept.name),
506
+ ...symbols.types.map((type) => type.name),
507
+ ...symbols.imports.map((imported) => imported.shortName)
508
+ ];
509
+ }
510
+
511
+ // event-context-catalog.ts
512
+ var eventContextRootType = "EventContext";
513
+ var eventContextTypes = {
514
+ "EventContext": [
515
+ { name: "eventType", type: "EventType", kind: "composite", description: "The type of the event - its identifier, generation and whether it is a tombstone." },
516
+ { name: "eventSourceType", type: "EventSourceType", kind: "value", description: "The type of the event source the event was appended to." },
517
+ { name: "eventSourceId", type: "EventSourceId", kind: "value", description: "The identifier of the event source the event was appended to - the value $eventSourceId resolves." },
518
+ { name: "eventStreamType", type: "EventStreamType", kind: "value", description: "The type of the event stream the event belongs to." },
519
+ { name: "eventStreamId", type: "EventStreamId", kind: "value", description: "The identifier of the event stream the event belongs to." },
520
+ { name: "sequenceNumber", type: "EventSequenceNumber", kind: "value", description: "The position of the event in its event sequence." },
521
+ { name: "occurred", type: "DateTimeOffset", kind: "value", description: "When the event occurred - the time it was appended unless one was given." },
522
+ { name: "eventStore", type: "EventStoreName", kind: "value", description: "The name of the event store the event belongs to." },
523
+ { name: "namespace", type: "EventStoreNamespaceName", kind: "value", description: "The namespace within the event store the event belongs to." },
524
+ { name: "correlationId", type: "CorrelationId", kind: "value", description: "The correlation identifier the event was appended with." },
525
+ { name: "causation", type: "IEnumerable<Causation>", kind: "collection", description: "The chain of causes that led to the event - a collection, not addressable below." },
526
+ { name: "causedBy", type: "Identity", kind: "composite", description: "The identity that caused the event." },
527
+ { name: "tags", type: "IEnumerable<Tag>", kind: "collection", description: "The tags the event was appended with - a collection, not addressable below." },
528
+ { name: "hash", type: "EventHash", kind: "value", description: "The hash of the event content." },
529
+ { name: "observationState", type: "EventObservationState", kind: "value", description: "Whether the observer sees the event for the first time or again on replay - differs between live processing and replay." },
530
+ { name: "subject", type: "Subject", kind: "value", description: "The compliance subject the event is about - the event source identifier unless one was given." },
531
+ { name: "subjectIsEventSourceId", type: "bool", kind: "value", description: "Whether the subject is the event source identifier." }
532
+ ],
533
+ "EventType": [
534
+ { name: "id", type: "EventTypeId", kind: "value", description: "The identifier of the event type." },
535
+ { name: "generation", type: "EventTypeGeneration", kind: "value", description: "The generation of the event type." },
536
+ { name: "tombstone", type: "bool", kind: "value", description: "Whether the event is a tombstone event." }
537
+ ],
538
+ "EventSourceType": [
539
+ { name: "value", type: "string", kind: "value", description: "The underlying string value." }
540
+ ],
541
+ "EventSourceId": [
542
+ { name: "value", type: "string", kind: "value", description: "The underlying string value." }
543
+ ],
544
+ "EventStreamType": [
545
+ { name: "value", type: "string", kind: "value", description: "The underlying string value." }
546
+ ],
547
+ "EventStreamId": [
548
+ { name: "value", type: "string", kind: "value", description: "The underlying string value." }
549
+ ],
550
+ "EventSequenceNumber": [
551
+ { name: "value", type: "ulong", kind: "value", description: "The underlying ulong value." }
552
+ ],
553
+ "DateTimeOffset": [
554
+ { name: "Week", type: "int", kind: "function", description: "The ISO 8601 week of the year the value falls in." }
555
+ ],
556
+ "EventStoreName": [
557
+ { name: "value", type: "string", kind: "value", description: "The underlying string value." }
558
+ ],
559
+ "EventStoreNamespaceName": [
560
+ { name: "value", type: "string", kind: "value", description: "The underlying string value." }
561
+ ],
562
+ "CorrelationId": [
563
+ { name: "value", type: "Guid", kind: "value", description: "The underlying Guid value." }
564
+ ],
565
+ "Identity": [
566
+ { name: "subject", type: "string", kind: "value", description: "The subject identifier of the identity." },
567
+ { name: "name", type: "string", kind: "value", description: "The display name of the identity." },
568
+ { name: "userName", type: "string", kind: "value", description: "The user name of the identity." },
569
+ { name: "onBehalfOf", type: "Identity", kind: "composite", description: "The identity this identity acted on behalf of, if any - an identity with the same members." }
570
+ ],
571
+ "EventHash": [
572
+ { name: "value", type: "string", kind: "value", description: "The underlying string value." }
573
+ ],
574
+ "Subject": [
575
+ { name: "value", type: "string", kind: "value", description: "The underlying string value." }
576
+ ],
577
+ "EventTypeId": [
578
+ { name: "value", type: "string", kind: "value", description: "The underlying string value." }
579
+ ],
580
+ "EventTypeGeneration": [
581
+ { name: "value", type: "uint", kind: "value", description: "The underlying uint value." }
582
+ ]
583
+ };
584
+ var eventContextPaths = [
585
+ { path: "eventType", name: "eventType", type: "EventType", kind: "composite", description: "The type of the event - its identifier, generation and whether it is a tombstone." },
586
+ { path: "eventType.id", name: "id", type: "EventTypeId", kind: "value", description: "The identifier of the event type." },
587
+ { path: "eventType.id.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
588
+ { path: "eventType.generation", name: "generation", type: "EventTypeGeneration", kind: "value", description: "The generation of the event type." },
589
+ { path: "eventType.generation.value", name: "value", type: "uint", kind: "value", description: "The underlying uint value." },
590
+ { path: "eventType.tombstone", name: "tombstone", type: "bool", kind: "value", description: "Whether the event is a tombstone event." },
591
+ { path: "eventSourceType", name: "eventSourceType", type: "EventSourceType", kind: "value", description: "The type of the event source the event was appended to." },
592
+ { path: "eventSourceType.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
593
+ { path: "eventSourceId", name: "eventSourceId", type: "EventSourceId", kind: "value", description: "The identifier of the event source the event was appended to - the value $eventSourceId resolves." },
594
+ { path: "eventSourceId.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
595
+ { path: "eventStreamType", name: "eventStreamType", type: "EventStreamType", kind: "value", description: "The type of the event stream the event belongs to." },
596
+ { path: "eventStreamType.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
597
+ { path: "eventStreamId", name: "eventStreamId", type: "EventStreamId", kind: "value", description: "The identifier of the event stream the event belongs to." },
598
+ { path: "eventStreamId.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
599
+ { path: "sequenceNumber", name: "sequenceNumber", type: "EventSequenceNumber", kind: "value", description: "The position of the event in its event sequence." },
600
+ { path: "sequenceNumber.value", name: "value", type: "ulong", kind: "value", description: "The underlying ulong value." },
601
+ { path: "occurred", name: "occurred", type: "DateTimeOffset", kind: "value", description: "When the event occurred - the time it was appended unless one was given." },
602
+ { path: "occurred.Week", name: "Week", type: "int", kind: "function", description: "The ISO 8601 week of the year the value falls in." },
603
+ { path: "eventStore", name: "eventStore", type: "EventStoreName", kind: "value", description: "The name of the event store the event belongs to." },
604
+ { path: "eventStore.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
605
+ { path: "namespace", name: "namespace", type: "EventStoreNamespaceName", kind: "value", description: "The namespace within the event store the event belongs to." },
606
+ { path: "namespace.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
607
+ { path: "correlationId", name: "correlationId", type: "CorrelationId", kind: "value", description: "The correlation identifier the event was appended with." },
608
+ { path: "correlationId.value", name: "value", type: "Guid", kind: "value", description: "The underlying Guid value." },
609
+ { path: "causation", name: "causation", type: "IEnumerable<Causation>", kind: "collection", description: "The chain of causes that led to the event - a collection, not addressable below." },
610
+ { path: "causedBy", name: "causedBy", type: "Identity", kind: "composite", description: "The identity that caused the event." },
611
+ { path: "causedBy.subject", name: "subject", type: "string", kind: "value", description: "The subject identifier of the identity." },
612
+ { path: "causedBy.name", name: "name", type: "string", kind: "value", description: "The display name of the identity." },
613
+ { path: "causedBy.userName", name: "userName", type: "string", kind: "value", description: "The user name of the identity." },
614
+ { path: "causedBy.onBehalfOf", name: "onBehalfOf", type: "Identity", kind: "composite", description: "The identity this identity acted on behalf of, if any - an identity with the same members." },
615
+ { path: "tags", name: "tags", type: "IEnumerable<Tag>", kind: "collection", description: "The tags the event was appended with - a collection, not addressable below." },
616
+ { path: "hash", name: "hash", type: "EventHash", kind: "value", description: "The hash of the event content." },
617
+ { path: "hash.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
618
+ { path: "observationState", name: "observationState", type: "EventObservationState", kind: "value", description: "Whether the observer sees the event for the first time or again on replay - differs between live processing and replay." },
619
+ { path: "subject", name: "subject", type: "Subject", kind: "value", description: "The compliance subject the event is about - the event source identifier unless one was given." },
620
+ { path: "subject.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
621
+ { path: "subjectIsEventSourceId", name: "subjectIsEventSourceId", type: "bool", kind: "value", description: "Whether the subject is the event source identifier." }
622
+ ];
623
+
624
+ // event-context.ts
625
+ function namesEventContextMember(member, segment) {
626
+ if (member.kind === "function") {
627
+ return segment === member.name || segment === `${member.name}()`;
628
+ }
629
+ const declared = member.name[0].toUpperCase() + member.name.slice(1);
630
+ return segment === declared || segment.length > 0 && segment[0].toUpperCase() + segment.slice(1) === declared;
631
+ }
632
+ var eventContextMembers = eventContextTypes[eventContextRootType];
633
+ function eventContextMembersAfter(segments) {
634
+ let members = eventContextMembers;
635
+ for (const segment of segments) {
636
+ const member = members.find((candidate) => namesEventContextMember(candidate, segment));
637
+ if (!member || member.kind === "collection" || member.kind === "function") {
638
+ return void 0;
639
+ }
640
+ members = eventContextTypes[member.type] ?? [];
641
+ }
642
+ return members;
643
+ }
644
+ function eventContextMemberAt(segments) {
645
+ if (segments.length === 0) {
646
+ return void 0;
647
+ }
648
+ const members = eventContextMembersAfter(segments.slice(0, -1));
649
+ return members?.find((member) => namesEventContextMember(member, segments[segments.length - 1]));
650
+ }
651
+ function resolveEventContextPath(path) {
652
+ let current;
653
+ let expected = eventContextMembers;
654
+ for (const segment of path.split(".")) {
655
+ if (segment.length === 0) {
656
+ return { status: "missing", member: current, expected };
657
+ }
658
+ if (current?.kind === "collection") {
659
+ return { status: "belowCollection", member: current, segment, expected: [] };
660
+ }
661
+ const next = expected.find((member) => namesEventContextMember(member, segment));
662
+ if (!next) {
663
+ return { status: current ? "unknownSubPath" : "unknownMember", member: current, segment, expected };
664
+ }
665
+ current = next;
666
+ expected = next.kind === "function" ? [] : eventContextTypes[next.type] ?? [];
667
+ }
668
+ return { status: "known", member: current, expected: [] };
669
+ }
670
+ function describeEventContext() {
671
+ return [
672
+ "**$eventContext**",
673
+ "",
674
+ "Metadata about the event being projected. Paths are checked against the event-context catalog; `causation` and `tags` are collections and cannot be addressed below.",
675
+ "",
676
+ "**Members:**",
677
+ ...eventContextMembers.map((member) => `- \`${member.name}\` (${member.type}) - ${member.description}`)
678
+ ].join("\n");
679
+ }
680
+ function describeEventContextMember(path, member) {
681
+ const below = member.kind === "collection" || member.kind === "function" ? [] : eventContextTypes[member.type] ?? [];
682
+ const lines = [`**$eventContext.${path}**: \`${member.type}\``, "", member.description];
683
+ if (below.length > 0) {
684
+ lines.push("", `**Members:** ${below.map((child) => `\`${child.name}\``).join(", ")}`);
685
+ }
686
+ return lines.join("\n");
687
+ }
688
+
689
+ // production-destinations.ts
690
+ function productionDestinations(command) {
691
+ const identifiers = command.properties.filter((property) => property.isIdentifier && !propertyTypeReference(property).isOptional && !propertyTypeReference(property).isCollection);
692
+ const identifier = identifiers.length === 1 ? identifiers[0].name : void 0;
693
+ const productions = command.produces ?? [];
694
+ const mixed = productions.some((production) => production.target !== void 0 && production.target !== identifier) || productions.some((production) => production.inline && production.target === void 0) && productions.some((production) => !production.inline && production.target === void 0);
695
+ return { identifier, mixed };
696
+ }
697
+ function destinationHints(lines) {
698
+ const source = eventAnalysisSource(lines);
699
+ return scanDocument(source).commands.flatMap((command) => {
700
+ const { identifier, mixed } = productionDestinations(command);
701
+ if (mixed || command.productionHeaders?.length !== command.produces?.length) return [];
702
+ const hasPromotedDestination = command.produces?.some((sibling) => sibling.target !== void 0 || sibling.inline);
703
+ return (command.produces ?? []).flatMap((production) => {
704
+ if (production.target !== void 0 || production.inline && (identifier === void 0 || /\bgeneration\b/.test(source[production.line]))) return [];
705
+ if (!production.inline && hasPromotedDestination) return [];
706
+ return [{ line: production.line, column: source[production.line].length + 1, label: production.inline ? `for ${identifier}` : "for <new event source>" }];
707
+ });
708
+ });
709
+ }
710
+
711
+ // diagnostic-codes.ts
712
+ var diagnosticCodes = {
713
+ eventSourceIdInPayload: "PLAY0469",
714
+ explicitProducesTargetsRequired: "PLAY0470",
715
+ redundantEventId: "PLAY0471",
716
+ invalidEventId: "PLAY0472",
717
+ inlineEventCollision: "PLAY0473",
718
+ inlineEventOutsideCommand: "PLAY0474",
719
+ inlineEventGeneration: "PLAY0475",
720
+ reservedProductionMetadata: "PLAY0476",
721
+ invalidEventDocumentation: "PLAY0477",
722
+ tabIndentation: "PLAY0006",
723
+ unknownPrimitiveType: "PLAY0008",
724
+ unknownSliceType: "PLAY0028",
725
+ duplicateCommandIdentifier: "PLAY0036",
726
+ unknownContextPath: "PLAY0153",
727
+ unknownContextCausedByProperty: "PLAY0154",
728
+ unknownContextIdentityProperty: "PLAY0155",
729
+ unclosedCodeBlock: "PLAY0164",
730
+ unknownType: "PLAY0165",
731
+ unknownEvent: "PLAY0166",
732
+ unknownPolicy: "PLAY0167",
733
+ duplicateDeclaration: "PLAY0168",
734
+ unknownEventContextMember: "PLAY0295",
735
+ unknownEventContextPath: "PLAY0296",
736
+ eventContextPathBelowCollection: "PLAY0297",
737
+ missingEventContextPath: "PLAY0298",
738
+ unresolvedDynamicKeySource: "PLAY0299",
739
+ invalidFileImport: "PLAY0454",
740
+ omittedProductionDestination: "PLAY0478",
741
+ legacyOptionalSuffix: "PLAY0479",
742
+ invalidOptionalModifierOrder: "PLAY0480",
743
+ optionalReadsNotSupported: "PLAY0481"
744
+ };
745
+
746
+ // file-imports.ts
747
+ var fileImportPattern = /^import(\s+)"([^"\\]+)"\s*(?:\/\/.*)?$/;
748
+ var quotedImportPattern = /^import\s+"/;
749
+ function isFileImportLine(line) {
750
+ return quotedImportPattern.test(line.trim());
751
+ }
752
+ function fileImportOn(line, lineIndex) {
753
+ const indent = indentOf(line);
754
+ const match = line.slice(indent).match(fileImportPattern);
755
+ if (!match) return void 0;
756
+ const startColumn = indent + "import".length + match[1].length + 2;
757
+ return { pattern: match[2], line: lineIndex, startColumn, endColumn: startColumn + match[2].length };
758
+ }
759
+ function fileImports(lines) {
760
+ const fences = fenceMap(lines);
761
+ const found = [];
762
+ for (let index = 0; index < lines.length; index++) {
763
+ if (fences[index]) continue;
764
+ const fileImport = fileImportOn(lines[index], index);
765
+ if (fileImport) found.push(fileImport);
766
+ }
767
+ return found;
768
+ }
769
+ var folderOf = (path) => path.split("/").slice(0, -1);
770
+ function relativeTo(from, path) {
771
+ const segments = path.split("/");
772
+ let common = 0;
773
+ while (common < from.length && common < segments.length - 1 && from[common] === segments[common]) common++;
774
+ return [...from.slice(common).map(() => ".."), ...segments.slice(common)].join("/");
775
+ }
776
+ function importablePaths(documentPath, files) {
777
+ const from = folderOf(documentPath);
778
+ const paths = /* @__PURE__ */ new Set();
779
+ for (const file of files.filter((candidate) => candidate !== documentPath && candidate.toLowerCase().endsWith(".play"))) {
780
+ const relative = relativeTo(from, file);
781
+ const folders = folderOf(relative);
782
+ paths.add(relative);
783
+ paths.add([...folders, "*.play"].join("/"));
784
+ for (let depth = 0; depth <= folders.length; depth++) {
785
+ paths.add([...folders.slice(0, depth), "**", "*.play"].join("/"));
786
+ }
787
+ }
788
+ return [...paths].sort();
789
+ }
790
+
791
+ // ../../Compiler/dist/Diagnostics/DiagnosticCodes.js
792
+ var DiagnosticCodes = {
793
+ InvalidProducesDeclaration: "PLAY0042",
794
+ ProducesWhenWithoutEvent: "PLAY0043",
795
+ InvalidPropertyMapping: "PLAY0044",
796
+ DuplicateProducesTarget: "PLAY0193",
797
+ EventSourceIdInPayload: "PLAY0469",
798
+ ExplicitProducesTargetsRequired: "PLAY0470",
799
+ RedundantEventId: "PLAY0471",
800
+ InvalidEventId: "PLAY0472",
801
+ InlineEventCollision: "PLAY0473",
802
+ InlineEventOutsideCommand: "PLAY0474",
803
+ InlineEventGeneration: "PLAY0475",
804
+ ReservedProductionMetadata: "PLAY0476",
805
+ InvalidEventDocumentation: "PLAY0477",
806
+ UnknownTopLevelConstruct: "PLAY0001",
807
+ InvalidDomainDeclaration: "PLAY0002",
808
+ DuplicateDomain: "PLAY0003",
809
+ DomainNotFirst: "PLAY0004",
810
+ InvalidImportDeclaration: "PLAY0005",
811
+ TabIndentation: "PLAY0006",
812
+ InvalidConceptDeclaration: "PLAY0007",
813
+ UnknownPrimitiveType: "PLAY0008",
814
+ InvalidEnumerationValue: "PLAY0009",
815
+ UnknownConceptDirective: "PLAY0010",
816
+ ValidateReadAsEnumerationBlock: "PLAY0011",
817
+ AttributeReasonWithoutAttribute: "PLAY0012",
818
+ DuplicateAttributeReason: "PLAY0013",
819
+ InvalidTypeDeclaration: "PLAY0014",
820
+ TypeWithoutProperties: "PLAY0015",
821
+ InvalidPropertyDeclaration: "PLAY0016",
822
+ IdentifierOutsideCommand: "PLAY0017",
823
+ InvalidEventDeclaration: "PLAY0018",
824
+ IdentifierOnEventProperty: "PLAY0019",
825
+ TagPropertyReadAsTag: "PLAY0020",
826
+ InvalidModuleDeclaration: "PLAY0021",
827
+ UnknownModuleDirective: "PLAY0022",
828
+ InvalidFeatureDeclaration: "PLAY0023",
829
+ UnknownFeatureDirective: "PLAY0024",
830
+ InvalidSliceDeclaration: "PLAY0027",
831
+ UnknownSliceType: "PLAY0028",
832
+ UnknownSliceDirective: "PLAY0029",
833
+ InvalidPersonaDeclaration: "PLAY0030",
834
+ InvalidPersonaPolicyReference: "PLAY0031",
835
+ UnknownPersonaDirective: "PLAY0032",
836
+ InvalidCommandDeclaration: "PLAY0033",
837
+ UnknownCommandDirective: "PLAY0034",
838
+ DuplicateCommandIdentifier: "PLAY0036",
839
+ InvalidQueryDeclaration: "PLAY0047",
840
+ UnknownQueryDirective: "PLAY0048",
841
+ InvalidQueryParameter: "PLAY0049",
842
+ InvalidProjectionDeclaration: "PLAY0056",
843
+ EmptyProjection: "PLAY0057",
844
+ UnknownProjectionDirective: "PLAY0058",
845
+ FromWithoutEvent: "PLAY0061",
846
+ InvalidEventReference: "PLAY0062",
847
+ InvalidJoinDeclaration: "PLAY0063",
848
+ JoinWithoutEvent: "PLAY0064",
849
+ InvalidChildrenDeclaration: "PLAY0065",
850
+ InvalidNestedDeclaration: "PLAY0066",
851
+ NestedBlockWithoutFrom: "PLAY0067",
852
+ InvalidRemoveDeclaration: "PLAY0068",
853
+ UnknownRemoveDirective: "PLAY0069",
854
+ InvalidClearDeclaration: "PLAY0070",
855
+ ClearWithOutsideNestedBlock: "PLAY0071",
856
+ InvalidSpecificationDeclaration: "PLAY0094",
857
+ UnknownSpecificationDirective: "PLAY0095",
858
+ InvalidSpecificationWhen: "PLAY0096",
859
+ DuplicateSpecificationWhen: "PLAY0097",
860
+ InvalidThenError: "PLAY0098",
861
+ InvalidReadModelStep: "PLAY0099",
862
+ InvalidEventStep: "PLAY0100",
863
+ InvalidSpecificationValue: "PLAY0101",
864
+ InvalidScreenDeclaration: "PLAY0102",
865
+ UnknownScreenDirective: "PLAY0103",
866
+ InvalidDataDirective: "PLAY0104",
867
+ InvalidActionDirective: "PLAY0105",
868
+ UnknownActionDirective: "PLAY0106",
869
+ InvalidNavigation: "PLAY0107",
870
+ InvalidScreenLayoutSlot: "PLAY0108",
871
+ InvalidTitleDirective: "PLAY0109",
872
+ UnknownTableDirective: "PLAY0110",
873
+ UnknownSummaryDirective: "PLAY0111",
874
+ AuthorizeWithoutPolicy: "PLAY0122",
875
+ InvalidPolicyReference: "PLAY0123",
876
+ InvalidConstraintDeclaration: "PLAY0132",
877
+ ConstraintWithoutRule: "PLAY0133",
878
+ InvalidConstraintBody: "PLAY0134",
879
+ DuplicateConstraintBody: "PLAY0135",
880
+ InvalidReactionDeclaration: "PLAY0136",
881
+ InvalidReactionTrigger: "PLAY0137",
882
+ ReactionWithoutTrigger: "PLAY0138",
883
+ InvalidValidateDeclaration: "PLAY0140",
884
+ InvalidValidationRule: "PLAY0141",
885
+ InvalidRuleName: "PLAY0143",
886
+ InvalidDescription: "PLAY0145",
887
+ EmptyDescription: "PLAY0146",
888
+ DuplicateDescription: "PLAY0147",
889
+ TagWithoutValue: "PLAY0148",
890
+ InvalidTagValue: "PLAY0149",
891
+ UnknownContextPath: "PLAY0153",
892
+ UnknownContextCausedByProperty: "PLAY0154",
893
+ UnknownContextIdentityProperty: "PLAY0155",
894
+ ExpectedCodeFence: "PLAY0163",
895
+ UnclosedCodeBlock: "PLAY0164",
896
+ DuplicateDeclaration: "PLAY0168",
897
+ RepeatedSingularDeclarationAcrossFiles: "PLAY0172",
898
+ RepeatedDeclarationAcrossFiles: "PLAY0173",
899
+ ConflictingDescriptionAcrossFiles: "PLAY0174",
900
+ UnexpectedTokenInAuthorize: "PLAY0184",
901
+ UnclosedAuthorizeGroup: "PLAY0185",
902
+ InvalidReadModelDeclaration: "PLAY0186",
903
+ InvalidInvokesDeclaration: "PLAY0194",
904
+ InvalidScopeDeclaration: "PLAY0199",
905
+ DuplicateScope: "PLAY0200",
906
+ InvalidIntervalTrigger: "PLAY0249",
907
+ InvalidScheduleTrigger: "PLAY0250",
908
+ DuplicateReactionTrigger: "PLAY0253",
909
+ InvalidSpecificationEventSource: "PLAY0275",
910
+ DuplicateSpecificationEventSource: "PLAY0276",
911
+ InvalidProjectionVariantDeclaration: "PLAY0277",
912
+ InvalidEntersOnDeclaration: "PLAY0279",
913
+ NestedProjectionVariantNotAllowed: "PLAY0280",
914
+ InvalidStructuredValue: "PLAY0291",
915
+ DuplicateStructuredValueMember: "PLAY0294",
916
+ ConflictingSpecificationActions: "PLAY0358",
917
+ InvalidSpecificationEventOrder: "PLAY0359",
918
+ InvalidValidationSeverity: "PLAY0368",
919
+ VariantRequiresEnteringEvent: "PLAY0382",
920
+ DuplicateProjectionVariant: "PLAY0384",
921
+ DuplicateVariantEnteringEvent: "PLAY0385",
922
+ InvalidSpecificationDenied: "PLAY0388",
923
+ DuplicateAuthorizationAcrossFiles: "PLAY0394",
924
+ FileConstraintOnlySupportsUniqueness: "PLAY0396",
925
+ LegacyInlineCodeFence: "PLAY0397",
926
+ InvalidEventGeneration: "PLAY0446",
927
+ InvalidFileImport: "PLAY0454",
928
+ FileImportMatchesNothing: "PLAY0455",
929
+ ImportedFileNotFound: "PLAY0456",
930
+ ConflictingImportPlacement: "PLAY0457",
931
+ ImportCycle: "PLAY0458",
932
+ ModuleInPlacedFile: "PLAY0459",
933
+ UnexpectedInPlacedFile: "PLAY0460",
934
+ InvalidSpecificationClock: "PLAY0461",
935
+ InvalidSpecificationTrigger: "PLAY0462",
936
+ InvalidSpecificationCapture: "PLAY0463",
937
+ InvalidSpecificationQueryAction: "PLAY0464",
938
+ LegacyOptionalSuffix: "PLAY0479",
939
+ InvalidOptionalModifierOrder: "PLAY0480",
940
+ OptionalReadsNotSupported: "PLAY0481",
941
+ InvalidTriggerData: "PLAY0246"
942
+ };
943
+
944
+ // ../../Compiler/dist/Files/PlayPlacement.js
945
+ var documentPlacement = [];
946
+ var isDocumentPlacement = (placement) => placement.length === 0;
947
+ function describePlacement(placement) {
948
+ if (placement.length === 0)
949
+ return "the application";
950
+ if (placement.length === 1)
951
+ return `module '${placement[0]}'`;
952
+ return `feature '${placement.join(".")}'`;
953
+ }
954
+
955
+ // ../../Compiler/dist/Text/patterns.js
956
+ var wordCharacters = "\\p{L}\\p{Mn}\\p{Nd}\\p{Pc}";
957
+ function pattern(source) {
958
+ let result = "";
959
+ let inClass = false;
960
+ for (let index = 0; index < source.length; index++) {
961
+ const current = source[index];
962
+ if (current === "\\" && index + 1 < source.length) {
963
+ const next = source[index + 1];
964
+ index++;
965
+ if (next === "w") {
966
+ result += inClass ? wordCharacters : `[${wordCharacters}]`;
967
+ } else if (next === "d") {
968
+ result += "\\p{Nd}";
969
+ } else {
970
+ result += `\\${next}`;
971
+ }
972
+ continue;
973
+ }
974
+ if (current === "[" && !inClass) {
975
+ inClass = true;
976
+ } else if (current === "]" && inClass) {
977
+ inClass = false;
978
+ }
979
+ result += current;
980
+ }
981
+ return new RegExp(result, "u");
982
+ }
983
+
984
+ // ../../Compiler/dist/Diagnostics/SourceLocation.js
985
+ var sourceLocation = (line, column2, path) => path === void 0 ? { line, column: column2 } : { line, column: column2, path };
986
+
987
+ // ../../Compiler/dist/Parsing/SourceLine.js
988
+ var isBlank = (line) => line.content.length === 0;
989
+ var locationOf = (line) => sourceLocation(line.number, line.indent + 1, line.path);
990
+ var startOf = (line) => sourceLocation(line.number, 1, line.path);
991
+
992
+ // ../../Compiler/dist/Parsing/AuthorizeParser.js
993
+ var continuationPattern = pattern("^(?:(?:or|and)\\s+)?[A-Za-z_(][\\w\\s()]*$");
994
+ var tokenPattern = new RegExp(pattern("\\(|\\)|[A-Za-z_]\\w*").source, "gu");
995
+ var namePattern = pattern("^[A-Z]\\w*$");
996
+ function parseAuthorize(context, line) {
997
+ let text = line.content.substring("authorize".length);
998
+ for (let child = context.peekChild(line.indent); child !== void 0 && continuationPattern.test(child.content); child = context.peekChild(line.indent)) {
999
+ context.reader.takeSignificant();
1000
+ text += ` ${child.content}`;
1001
+ }
1002
+ const tokens = tokenize(text);
1003
+ const location = locationOf(line);
1004
+ if (tokens.length === 0) {
1005
+ context.error(DiagnosticCodes.AuthorizeWithoutPolicy, "Expected at least one policy after 'authorize'", location);
1006
+ return null;
1007
+ }
1008
+ const parser = new RequirementParser(context, tokens, location);
1009
+ const requirement = parser.parse();
1010
+ return requirement === null ? null : { kind: "AuthorizeSyntax", requirement, location };
1011
+ }
1012
+ function combineAuthorize(first, next) {
1013
+ if (first === null)
1014
+ return next;
1015
+ if (next === null)
1016
+ return first;
1017
+ return {
1018
+ kind: "AuthorizeSyntax",
1019
+ requirement: { kind: "LogicalPolicyRequirementSyntax", left: first.requirement, operator: "And", right: next.requirement, location: first.location },
1020
+ location: first.location
1021
+ };
1022
+ }
1023
+ function tokenize(text) {
1024
+ const tokens = [];
1025
+ for (const token of text.match(tokenPattern) ?? []) {
1026
+ if (tokens.length > 0 && isOperandEnd(tokens[tokens.length - 1]) && isOperandStart(token)) {
1027
+ tokens.push("and");
1028
+ }
1029
+ tokens.push(token);
1030
+ }
1031
+ return tokens;
1032
+ }
1033
+ var isName = (token) => token !== "(" && token !== ")" && token !== "and" && token !== "or";
1034
+ var isOperandEnd = (token) => token === ")" || isName(token);
1035
+ var isOperandStart = (token) => token === "(" || isName(token);
1036
+ var RequirementParser = class {
1037
+ context;
1038
+ tokens;
1039
+ location;
1040
+ #position = 0;
1041
+ constructor(context, tokens, location) {
1042
+ this.context = context;
1043
+ this.tokens = tokens;
1044
+ this.location = location;
1045
+ }
1046
+ parse() {
1047
+ const requirement = this.#or();
1048
+ if (requirement !== null && this.#position < this.tokens.length) {
1049
+ this.context.error(DiagnosticCodes.UnexpectedTokenInAuthorize, `Unexpected '${this.tokens[this.#position]}' in authorize`, this.location);
1050
+ }
1051
+ return requirement;
1052
+ }
1053
+ #or() {
1054
+ return this.#chain("or", "Or", () => this.#and());
1055
+ }
1056
+ #and() {
1057
+ return this.#chain("and", "And", () => this.#groupOrReference());
1058
+ }
1059
+ #chain(token, operator, operand2) {
1060
+ let left = operand2();
1061
+ while (left !== null && this.tokens[this.#position] === token) {
1062
+ this.#position++;
1063
+ const right = operand2();
1064
+ if (right === null) {
1065
+ return null;
1066
+ }
1067
+ left = { kind: "LogicalPolicyRequirementSyntax", left, operator, right, location: this.location };
1068
+ }
1069
+ return left;
1070
+ }
1071
+ #groupOrReference() {
1072
+ if (this.tokens[this.#position] !== "(") {
1073
+ return this.#reference();
1074
+ }
1075
+ this.#position++;
1076
+ const requirement = this.#or();
1077
+ if (this.tokens[this.#position] === ")") {
1078
+ this.#position++;
1079
+ } else {
1080
+ this.context.error(DiagnosticCodes.UnclosedAuthorizeGroup, "Expected ')' in authorize", this.location);
1081
+ }
1082
+ return requirement;
1083
+ }
1084
+ #reference() {
1085
+ if (this.#position >= this.tokens.length) {
1086
+ this.context.error(DiagnosticCodes.AuthorizeWithoutPolicy, "Expected a policy name", this.location);
1087
+ return null;
1088
+ }
1089
+ const token = this.tokens[this.#position++];
1090
+ if (!namePattern.test(token)) {
1091
+ this.context.error(DiagnosticCodes.InvalidPolicyReference, `Invalid policy reference '${token}' - policy names are PascalCase identifiers`, this.location);
1092
+ return null;
1093
+ }
1094
+ return { kind: "PolicyReferenceSyntax", name: token, location: this.location };
1095
+ }
1096
+ };
1097
+
1098
+ // ../../Compiler/dist/Text/StringLiteral.js
1099
+ var stringBodyPattern = '(?:[^"\\\\]|\\\\.)*';
1100
+ var escapes = { "\\": "\\", '"': '"', n: "\n", r: "\r", t: " " };
1101
+ function unescapeString(value) {
1102
+ if (!value.includes("\\")) {
1103
+ return value;
1104
+ }
1105
+ let result = "";
1106
+ for (let index = 0; index < value.length; index++) {
1107
+ const escaped = index + 1 < value.length ? escapes[value[index + 1]] : void 0;
1108
+ if (value[index] === "\\" && escaped !== void 0) {
1109
+ result += escaped;
1110
+ index++;
1111
+ } else {
1112
+ result += value[index];
1113
+ }
1114
+ }
1115
+ return result;
1116
+ }
1117
+
1118
+ // ../../Compiler/dist/Parsing/CodeBlockParser.js
1119
+ function parseFencedText(context, opener, tagLine, allowMarkdown = false) {
1120
+ const onTagLine = tagLine.content.startsWith("```");
1121
+ const open = onTagLine ? tagLine : context.reader.peekSignificant();
1122
+ const expectedFence = opener === "description" ? "```text" : `\`\`\`${opener}`;
1123
+ if (open === void 0 || open !== tagLine && open.indent <= tagLine.indent || open.content !== expectedFence && !(allowMarkdown && opener === "description" && open.content === "```markdown") && !(open.content === "```" && open !== tagLine)) {
1124
+ context.error(DiagnosticCodes.ExpectedCodeFence, `Expected an opening \`\`\`${opener === "description" ? "text" : opener} fence after '${opener}'`, locationOf(tagLine));
1125
+ return null;
1126
+ }
1127
+ if (open !== tagLine) {
1128
+ context.reader.takeSignificant();
1129
+ }
1130
+ if (opener === "description" && open.content === "```") {
1131
+ context.warning(DiagnosticCodes.LegacyInlineCodeFence, "A bare description fence is deprecated - use '```text' instead", locationOf(open));
1132
+ }
1133
+ const code = [];
1134
+ for (; ; ) {
1135
+ const line = context.reader.takeRaw();
1136
+ if (line === void 0) {
1137
+ context.error(DiagnosticCodes.UnclosedCodeBlock, "Unclosed inline code block - expected a closing ``` line", locationOf(open));
1138
+ break;
1139
+ }
1140
+ if (line.raw.trim() === "```") {
1141
+ break;
1142
+ }
1143
+ let strip = 0;
1144
+ while (strip < open.indent && strip < line.raw.length && line.raw[strip] === " ") {
1145
+ strip++;
1146
+ }
1147
+ code.push(line.raw.substring(strip));
1148
+ }
1149
+ return code.join("\n");
1150
+ }
1151
+
1152
+ // ../../Compiler/dist/Parsing/DescriptionParser.js
1153
+ var descriptionPattern = pattern(`^description\\s+"(${stringBodyPattern})"$`);
1154
+ function parseDescription(context, line, existing, owner, allowMarkdown = false) {
1155
+ if (line.content === "description") {
1156
+ const text = parseFencedText(context, "description", line, allowMarkdown);
1157
+ if (text === null) {
1158
+ return existing;
1159
+ }
1160
+ if (text.trim().length === 0) {
1161
+ context.error(DiagnosticCodes.EmptyDescription, `${owner} declares an empty description - the fenced block must contain text`, locationOf(line));
1162
+ return existing;
1163
+ }
1164
+ return keep(context, line, existing, owner, text);
1165
+ }
1166
+ const match = descriptionPattern.exec(line.content);
1167
+ if (match === null) {
1168
+ context.error(DiagnosticCodes.InvalidDescription, `Invalid description '${line.content}' - expected 'description "<text>"'`, locationOf(line));
1169
+ return existing;
1170
+ }
1171
+ return keep(context, line, existing, owner, unescapeString(match[1]));
1172
+ }
1173
+ function keep(context, line, existing, owner, description) {
1174
+ if (existing !== null) {
1175
+ context.error(DiagnosticCodes.DuplicateDescription, `${owner} already declares a description - at most one is allowed`, locationOf(line));
1176
+ return existing;
1177
+ }
1178
+ return description;
1179
+ }
1180
+
1181
+ // ../../Compiler/dist/Parsing/FileImportParser.js
1182
+ var fileImportPattern2 = pattern('^import\\s+"([^"\\\\]+)"$');
1183
+ var quotedPattern = pattern('^import\\s+"');
1184
+ var isFileImport = (content) => quotedPattern.test(content);
1185
+ function tryParseFileImport(line) {
1186
+ const match = fileImportPattern2.exec(line.content);
1187
+ return match === null ? void 0 : { kind: "FileImportSyntax", pattern: match[1], location: locationOf(line) };
1188
+ }
1189
+ function parseFileImport(context, line, imports) {
1190
+ const fileImport = tryParseFileImport(line);
1191
+ if (fileImport !== void 0) {
1192
+ imports.push(fileImport);
1193
+ return;
1194
+ }
1195
+ context.error(DiagnosticCodes.InvalidFileImport, `Invalid import '${line.content}' - inside a module or feature, import names files: 'import "<path or glob>"'`, locationOf(line));
1196
+ context.skipBlock(line.indent);
1197
+ }
1198
+
1199
+ // ../../Compiler/dist/Parsing/LineText.js
1200
+ var firstWord2 = (content) => {
1201
+ const space = content.indexOf(" ");
1202
+ return space === -1 ? content : content.substring(0, space);
1203
+ };
1204
+ var unescapeIdentifier = (identifier) => identifier.replaceAll("@", "");
1205
+ function splitTopLevel(text, separator) {
1206
+ const parts = [];
1207
+ let start = 0;
1208
+ let inString = false;
1209
+ let inTemplate = false;
1210
+ for (let index = 0; index < text.length; index++) {
1211
+ const current = text[index];
1212
+ if (current === "\\" && inString && index + 1 < text.length) {
1213
+ index++;
1214
+ } else if (current === '"' && !inTemplate) {
1215
+ inString = !inString;
1216
+ } else if (current === "`" && !inString) {
1217
+ inTemplate = !inTemplate;
1218
+ } else if (current === separator && !inString && !inTemplate) {
1219
+ parts.push(text.substring(start, index));
1220
+ start = index + 1;
1221
+ }
1222
+ }
1223
+ parts.push(text.substring(start));
1224
+ return parts;
1225
+ }
1226
+
1227
+ // ../../Compiler/dist/Syntax/Structure.js
1228
+ var sliceTypes2 = ["StateChange", "StateView", "Automation", "Translate"];
1229
+
1230
+ // ../../Compiler/dist/Parsing/CaptureParser.js
1231
+ var header = pattern("^capture\\s+([A-Za-z_]\\w*)$");
1232
+ var appendPattern = pattern("^append\\s+([A-Z]\\w*)$");
1233
+ var childrenPattern = pattern("^children\\s+([a-z_]\\w*)\\s+identified\\s+by\\s+([\\w.]+)$");
1234
+ var nestedPattern = pattern("^nested\\s+([\\w.]+)$");
1235
+ function parseCapture(context, line) {
1236
+ const name = header.exec(line.content)?.[1] ?? "";
1237
+ let source = null;
1238
+ let key = null;
1239
+ const appends = [];
1240
+ const children = [];
1241
+ const nested = [];
1242
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
1243
+ context.reader.takeSignificant();
1244
+ switch (firstWord2(child.content)) {
1245
+ case "source":
1246
+ source = parseSource(context, child);
1247
+ break;
1248
+ case "key":
1249
+ key = child.content.substring("key".length).trim();
1250
+ break;
1251
+ case "append":
1252
+ pushAppend(context, child, appends);
1253
+ break;
1254
+ case "children": {
1255
+ const match = childrenPattern.exec(child.content);
1256
+ const blockAppends = appendsOf(context, child);
1257
+ if (match !== null) {
1258
+ children.push({ kind: "CaptureChildrenSyntax", property: match[1], identifiedBy: match[2], appends: blockAppends, location: locationOf(child) });
1259
+ }
1260
+ break;
1261
+ }
1262
+ case "nested": {
1263
+ const match = nestedPattern.exec(child.content);
1264
+ const blockAppends = appendsOf(context, child);
1265
+ if (match !== null) {
1266
+ nested.push({ kind: "CaptureNestedSyntax", property: match[1], appends: blockAppends, location: locationOf(child) });
1267
+ }
1268
+ break;
1269
+ }
1270
+ default:
1271
+ context.skipOpaqueBlock(child.indent);
1272
+ }
1273
+ }
1274
+ return { kind: "CaptureSyntax", name, source, key, appends, children, nested, location: locationOf(line) };
1275
+ }
1276
+ function parseSource(context, line) {
1277
+ const settings = [];
1278
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
1279
+ context.reader.takeSignificant();
1280
+ const settingName = firstWord2(child.content);
1281
+ settings.push({ kind: "CaptureSourceSettingSyntax", name: settingName, value: child.content.substring(settingName.length).trim(), location: locationOf(child) });
1282
+ }
1283
+ return { kind: "CaptureSourceSyntax", syntaxKind: line.content.substring("source".length).trim(), settings, location: locationOf(line) };
1284
+ }
1285
+ function appendsOf(context, line) {
1286
+ const appends = [];
1287
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
1288
+ context.reader.takeSignificant();
1289
+ if (firstWord2(child.content) === "append") {
1290
+ pushAppend(context, child, appends);
1291
+ } else {
1292
+ context.skipOpaqueBlock(child.indent);
1293
+ }
1294
+ }
1295
+ return appends;
1296
+ }
1297
+ function pushAppend(context, line, appends) {
1298
+ const match = appendPattern.exec(line.content);
1299
+ context.skipOpaqueBlock(line.indent);
1300
+ if (match !== null) {
1301
+ appends.push({ kind: "CaptureAppendSyntax", event: match[1], location: locationOf(line) });
1302
+ }
1303
+ }
1304
+
1305
+ // ../../Compiler/dist/Parsing/StructuredValueParser.js
1306
+ var maximumDepth = 64;
1307
+ var InvalidStructuredValue = class extends Error {
1308
+ };
1309
+ var StructuredValueParser = class {
1310
+ text;
1311
+ start;
1312
+ context;
1313
+ #position = 0;
1314
+ constructor(text, start, context) {
1315
+ this.text = text;
1316
+ this.start = start;
1317
+ this.context = context;
1318
+ }
1319
+ parse() {
1320
+ const value = this.#value(0);
1321
+ this.#whitespace();
1322
+ if (this.#position < this.text.length) {
1323
+ throw new InvalidStructuredValue(`'${this.text[this.#position]}' is invalid after a single JSON value.`);
1324
+ }
1325
+ return value;
1326
+ }
1327
+ #value(depth) {
1328
+ this.#whitespace();
1329
+ const location = this.#at();
1330
+ const current = this.text[this.#position];
1331
+ if (current === "[" || current === "{") {
1332
+ if (depth >= maximumDepth) {
1333
+ throw new InvalidStructuredValue(`The value nests deeper than ${maximumDepth} levels.`);
1334
+ }
1335
+ return current === "[" ? this.#list(depth, location) : this.#object(depth, location);
1336
+ }
1337
+ if (current === '"') {
1338
+ return { kind: "LiteralExpressionSyntax", value: this.#string(), location };
1339
+ }
1340
+ for (const [word, value] of [["true", true], ["false", false], ["null", null]]) {
1341
+ if (this.text.startsWith(word, this.#position)) {
1342
+ this.#position += word.length;
1343
+ return { kind: "LiteralExpressionSyntax", value, location };
1344
+ }
1345
+ }
1346
+ return { kind: "LiteralExpressionSyntax", value: this.#number(), location };
1347
+ }
1348
+ #list(depth, location) {
1349
+ this.#position++;
1350
+ const items = [];
1351
+ this.#whitespace();
1352
+ if (this.#take("]")) {
1353
+ return { kind: "ListExpressionSyntax", items, location };
1354
+ }
1355
+ for (; ; ) {
1356
+ items.push(this.#value(depth + 1));
1357
+ this.#whitespace();
1358
+ if (this.#take("]")) {
1359
+ return { kind: "ListExpressionSyntax", items, location };
1360
+ }
1361
+ this.#expect(",");
1362
+ }
1363
+ }
1364
+ #object(depth, location) {
1365
+ this.#position++;
1366
+ const members = [];
1367
+ const names = /* @__PURE__ */ new Set();
1368
+ this.#whitespace();
1369
+ if (this.#take("}")) {
1370
+ return { kind: "ObjectExpressionSyntax", members, location };
1371
+ }
1372
+ for (; ; ) {
1373
+ this.#whitespace();
1374
+ const keyLocation = this.#at();
1375
+ if (this.text[this.#position] !== '"') {
1376
+ throw new InvalidStructuredValue("Expected a property name in double quotes.");
1377
+ }
1378
+ const name = this.#string();
1379
+ this.#whitespace();
1380
+ this.#expect(":");
1381
+ const value = this.#value(depth + 1);
1382
+ if (names.has(name)) {
1383
+ this.context?.error(DiagnosticCodes.DuplicateStructuredValueMember, `Duplicate property '${name}' in structured value`, keyLocation);
1384
+ } else {
1385
+ names.add(name);
1386
+ members.push({ kind: "ObjectMemberSyntax", name, value, location: keyLocation });
1387
+ }
1388
+ this.#whitespace();
1389
+ if (this.#take("}")) {
1390
+ return { kind: "ObjectExpressionSyntax", members, location };
1391
+ }
1392
+ this.#expect(",");
1393
+ }
1394
+ }
1395
+ #string() {
1396
+ const end = this.#stringEnd(this.#position);
1397
+ const raw = this.text.substring(this.#position, end);
1398
+ this.#position = end;
1399
+ try {
1400
+ return JSON.parse(raw);
1401
+ } catch {
1402
+ throw new InvalidStructuredValue(`${raw} is not a valid JSON string.`);
1403
+ }
1404
+ }
1405
+ #stringEnd(from) {
1406
+ for (let index = from + 1; index < this.text.length; index++) {
1407
+ if (this.text[index] === "\\") {
1408
+ index++;
1409
+ } else if (this.text[index] === '"') {
1410
+ return index + 1;
1411
+ }
1412
+ }
1413
+ throw new InvalidStructuredValue("A string is not closed.");
1414
+ }
1415
+ #number() {
1416
+ const match = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/.exec(this.text.substring(this.#position));
1417
+ if (match === null) {
1418
+ throw new InvalidStructuredValue(`'${this.text[this.#position] ?? ""}' is an invalid start of a value.`);
1419
+ }
1420
+ this.#position += match[0].length;
1421
+ const number = Number(match[0]);
1422
+ if (!Number.isFinite(number)) {
1423
+ throw new InvalidStructuredValue("JSON number is outside the finite Double range.");
1424
+ }
1425
+ return number;
1426
+ }
1427
+ #at() {
1428
+ return { ...this.start, column: this.start.column + this.#position };
1429
+ }
1430
+ #whitespace() {
1431
+ while (this.#position < this.text.length && " \n\r".includes(this.text[this.#position])) {
1432
+ this.#position++;
1433
+ }
1434
+ }
1435
+ #take(character) {
1436
+ if (this.text[this.#position] !== character) {
1437
+ return false;
1438
+ }
1439
+ this.#position++;
1440
+ return true;
1441
+ }
1442
+ #expect(character) {
1443
+ if (!this.#take(character)) {
1444
+ throw new InvalidStructuredValue(`Expected '${character}' at position ${this.#position}.`);
1445
+ }
1446
+ }
1447
+ };
1448
+
1449
+ // ../../Compiler/dist/Parsing/ExpressionParser.js
1450
+ var pathPattern = pattern("^@?[A-Za-z_]\\w*(\\.@?[A-Za-z_$]\\w*)*$");
1451
+ var numberPattern = pattern("^-?\\d+(\\.\\d+)?$");
1452
+ var contextRoots2 = ["command", "arguments", "tenant", "causedBy", "causation", "occurred", "identity"];
1453
+ var causedByProperties2 = ["subject", "name", "userName"];
1454
+ var identityProperties2 = ["id", "name", "userName", "isAuthenticated", "roles", "claims"];
1455
+ function parseMappingSource(text, location, context) {
1456
+ text = text.trim();
1457
+ if (text.startsWith("$context.")) {
1458
+ const path = text.substring("$context.".length);
1459
+ warnOnUnknownContextPath(path, location, context);
1460
+ return { kind: "ContextExpressionSyntax", path, location };
1461
+ }
1462
+ if (text.startsWith("$env.")) {
1463
+ return { kind: "EnvironmentExpressionSyntax", name: text.substring("$env.".length), location };
1464
+ }
1465
+ if (text.startsWith("$strings.")) {
1466
+ return { kind: "StringsExpressionSyntax", key: text.substring("$strings.".length), location };
1467
+ }
1468
+ if (text.startsWith("$.")) {
1469
+ return { kind: "SourceItemExpressionSyntax", path: text.substring("$.".length), location };
1470
+ }
1471
+ if (text.startsWith("{") || text.startsWith("[")) {
1472
+ try {
1473
+ return new StructuredValueParser(text, location, context).parse();
1474
+ } catch (error) {
1475
+ if (!(error instanceof InvalidStructuredValue)) {
1476
+ throw error;
1477
+ }
1478
+ context?.error(DiagnosticCodes.InvalidStructuredValue, `Invalid inline structured value: ${error.message}`, location);
1479
+ return { kind: "RawExpressionSyntax", text, location };
1480
+ }
1481
+ }
1482
+ const literal = parseLiteral(text, location);
1483
+ if (literal !== void 0) {
1484
+ return literal;
1485
+ }
1486
+ if (pathPattern.test(text)) {
1487
+ return { kind: "PathExpressionSyntax", path: text, location };
1488
+ }
1489
+ return { kind: "RawExpressionSyntax", text, location };
1490
+ }
1491
+ function warnOnUnknownContextPath(path, location, context) {
1492
+ const [root, member] = path.split(".");
1493
+ if (!contextRoots2.includes(root)) {
1494
+ context?.warning(DiagnosticCodes.UnknownContextPath, `Unknown $context path '${path}' - expected one of ${contextRoots2.join(", ")}`, location);
1495
+ } else if (member !== void 0 && root === "causedBy" && !causedByProperties2.includes(member)) {
1496
+ context?.warning(DiagnosticCodes.UnknownContextCausedByProperty, `Unknown $context.causedBy property '${member}' - expected ${causedByProperties2.join(", ")}`, location);
1497
+ } else if (member !== void 0 && root === "identity" && !identityProperties2.includes(member)) {
1498
+ context?.warning(DiagnosticCodes.UnknownContextIdentityProperty, `Unknown $context.identity property '${member}' - expected ${identityProperties2.join(", ")}`, location);
1499
+ }
1500
+ }
1501
+ function parseLiteral(text, location) {
1502
+ const literal = (value) => ({ kind: "LiteralExpressionSyntax", value, location });
1503
+ switch (text) {
1504
+ case "true":
1505
+ return literal(true);
1506
+ case "false":
1507
+ return literal(false);
1508
+ case "null":
1509
+ return literal(null);
1510
+ }
1511
+ const quoted = text.length >= 2 && (text.startsWith('"') && text.endsWith('"') || text.startsWith("'") && text.endsWith("'"));
1512
+ if (quoted) {
1513
+ return literal(unescapeString(text.substring(1, text.length - 1)));
1514
+ }
1515
+ if (numberPattern.test(text) && !Number.isNaN(Number(text))) {
1516
+ return literal(Number(text));
1517
+ }
1518
+ return void 0;
1519
+ }
1520
+
1521
+ // ../../Compiler/dist/Parsing/EventMetadataParser.js
1522
+ var idPattern = pattern(`^id\\s+"(${stringBodyPattern})"$`);
1523
+ var EventMetadataParser = class {
1524
+ name;
1525
+ value = { id: null, description: null, documentation: null };
1526
+ constructor(name) {
1527
+ this.name = name;
1528
+ }
1529
+ tryParse(context, line) {
1530
+ const location = locationOf(line);
1531
+ switch (firstWord2(line.content)) {
1532
+ case "id": {
1533
+ const match = idPattern.exec(line.content);
1534
+ const id = match === null ? "" : unescapeString(match[1]);
1535
+ if (id.trim().length === 0 || this.value.id !== null) {
1536
+ context.error(DiagnosticCodes.InvalidEventId, `Event '${this.name}' accepts one nonempty 'id "<old-name>"'`, location);
1537
+ } else {
1538
+ this.value.id = id;
1539
+ if (id === this.name) {
1540
+ context.information(DiagnosticCodes.RedundantEventId, `Event '${this.name}' already has this name as its identity - remove the redundant id`, location);
1541
+ }
1542
+ }
1543
+ return true;
1544
+ }
1545
+ case "description":
1546
+ this.value.description = parseDescription(context, line, this.value.description, `Event '${this.name}'`, true);
1547
+ return true;
1548
+ case "documentation": {
1549
+ if (line.content !== "documentation" || context.peekChild(line.indent)?.content !== "```markdown") {
1550
+ context.error(DiagnosticCodes.InvalidEventDocumentation, `Event '${this.name}' documentation requires a fenced markdown block`, location);
1551
+ context.skipOpaqueBlock(line.indent);
1552
+ return true;
1553
+ }
1554
+ const text = parseFencedText(context, "markdown", line);
1555
+ if (text === null || text.trim().length === 0 || this.value.documentation !== null) {
1556
+ context.error(DiagnosticCodes.InvalidEventDocumentation, `Event '${this.name}' accepts one nonempty documentation block`, location);
1557
+ } else {
1558
+ this.value.documentation = text;
1559
+ }
1560
+ return true;
1561
+ }
1562
+ default:
1563
+ return false;
1564
+ }
1565
+ }
1566
+ };
1567
+
1568
+ // ../../Compiler/dist/Parsing/FileReferences.js
1569
+ var typeReferencePattern = pattern("^[A-Za-z_]\\w*(?:\\[\\])?(?:\\?|\\s+optional)?$");
1570
+ var pathOf = (line) => firstWord2(line.content) === "file" ? line.content.substring("file".length).trim() : "";
1571
+ var isFileDirective = (line) => pathOf(line).length > 0;
1572
+ var isFileDirectiveAmongProperties = (line) => isFileDirective(line) && !typeReferencePattern.test(pathOf(line));
1573
+
1574
+ // ../../Compiler/dist/Parsing/PropertyLineParser.js
1575
+ var propertyPattern2 = pattern("^(@?[a-z_]\\w*)\\s+([\\w.]+(?:\\[\\])?(?:\\?|\\s+optional)?)(?:\\s+(identifier))?$");
1576
+ var reversedModifiers = pattern("^@?[a-z_]\\w*\\s+[\\w.]+(?:\\[\\])?\\s+identifier\\s+optional(?:\\s*=.*)?$");
1577
+ function tryParseProperty(line) {
1578
+ const match = propertyPattern2.exec(line.content);
1579
+ if (match === null) {
1580
+ return void 0;
1581
+ }
1582
+ const location = locationOf(line);
1583
+ return {
1584
+ kind: "PropertySyntax",
1585
+ name: unescapeIdentifier(match[1]),
1586
+ type: parseTypeRef(match[2], { ...location, column: location.column + line.content.indexOf(match[2], match[1].length) }),
1587
+ isIdentifier: match[3] !== void 0,
1588
+ location
1589
+ };
1590
+ }
1591
+ function parseTypeRef(text, location) {
1592
+ const legacy = text.endsWith("?");
1593
+ const canonical = /\soptional$/.test(text);
1594
+ const isOptional = legacy || canonical;
1595
+ if (isOptional) {
1596
+ text = text.substring(0, text.length - (legacy ? 1 : "optional".length)).trimEnd();
1597
+ }
1598
+ const isCollection = text.endsWith("[]");
1599
+ if (isCollection) {
1600
+ text = text.substring(0, text.length - 2);
1601
+ }
1602
+ return { kind: "TypeRefSyntax", name: text, isCollection, isOptional, location };
1603
+ }
1604
+ function parseProperty(context, line) {
1605
+ const property = tryParseProperty(line);
1606
+ if (property !== void 0) {
1607
+ reportLegacyOptionalSuffix(context, property.type, line);
1608
+ } else {
1609
+ reportInvalidModifierOrder(context, line);
1610
+ }
1611
+ return property;
1612
+ }
1613
+ function reportLegacyOptionalSuffix(context, type, line) {
1614
+ const length = type.name.length + (type.isCollection ? 2 : 0);
1615
+ const offset = type.location.column - line.indent - 1 + length;
1616
+ if (type.isOptional && line.content[offset] === "?") {
1617
+ const name = type.name + (type.isCollection ? "[]" : "");
1618
+ context.information(DiagnosticCodes.LegacyOptionalSuffix, `Write '${name} optional' instead of '${name}?'.`, type.location);
1619
+ }
1620
+ }
1621
+ function reportInvalidModifierOrder(context, line) {
1622
+ if (reversedModifiers.test(line.content)) {
1623
+ context.error(DiagnosticCodes.InvalidOptionalModifierOrder, "Write 'optional' before 'identifier': '<name> <Type> optional identifier'.", locationOf(line));
1624
+ }
1625
+ }
1626
+
1627
+ // ../../Compiler/dist/Parsing/DeclarationParsers.js
1628
+ var typeHeader = pattern("^type\\s+([A-Za-z_]\\w*)$");
1629
+ var eventHeader = pattern("^event\\s+([A-Za-z_]\\w*)(?:\\s+generation\\s+([0-9]+))?$");
1630
+ var readModelHeader = pattern("^readmodel\\s+([A-Za-z_]\\w*)$");
1631
+ var maximumGeneration = 4294967295;
1632
+ var typeShapedPattern = pattern("^[A-Z]\\w*(?:\\[\\])?(?:\\?|\\s+optional)?$");
1633
+ var tagIdentifierPattern = pattern("^[A-Za-z_]\\w*$");
1634
+ var isDescription = (line) => firstWord2(line.content) === "description" && tryParseProperty(line) === void 0;
1635
+ function withoutIdentifier(context, property, line, code, message) {
1636
+ if (!property.isIdentifier) {
1637
+ return property;
1638
+ }
1639
+ context.error(code, message, locationOf(line));
1640
+ return { ...property, isIdentifier: false };
1641
+ }
1642
+ function parseType(context, header10) {
1643
+ const name = typeHeader.exec(header10.content)?.[1] ?? "";
1644
+ if (name === "") {
1645
+ context.error(DiagnosticCodes.InvalidTypeDeclaration, `Invalid type declaration '${header10.content}' - expected 'type <Name>'`, locationOf(header10));
1646
+ }
1647
+ const properties = [];
1648
+ let description = null;
1649
+ for (let line = context.peekChild(header10.indent); line !== void 0; line = context.peekChild(header10.indent)) {
1650
+ context.reader.takeSignificant();
1651
+ if (isDescription(line)) {
1652
+ description = parseDescription(context, line, description, `Type '${name}'`);
1653
+ continue;
1654
+ }
1655
+ if (isFileDirectiveAmongProperties(line)) {
1656
+ continue;
1657
+ }
1658
+ const property = parseProperty(context, line);
1659
+ if (property === void 0) {
1660
+ context.error(DiagnosticCodes.InvalidPropertyDeclaration, `Invalid property '${line.content}' - expected '<name> <Type>'`, locationOf(line));
1661
+ continue;
1662
+ }
1663
+ properties.push(withoutIdentifier(context, property, line, DiagnosticCodes.IdentifierOutsideCommand, `Property '${property.name}' of type '${name}' cannot be marked identifier - only a command property can be`));
1664
+ }
1665
+ if (properties.length === 0) {
1666
+ context.error(DiagnosticCodes.TypeWithoutProperties, `Type '${name}' must declare at least one property`, locationOf(header10));
1667
+ }
1668
+ return { kind: "TypeSyntax", name, properties, description, location: locationOf(header10) };
1669
+ }
1670
+ function parseEvent(context, header10) {
1671
+ const match = eventHeader.exec(header10.content);
1672
+ const name = match?.[1] ?? "";
1673
+ if (match === null) {
1674
+ context.error(DiagnosticCodes.InvalidEventDeclaration, `Invalid event declaration '${header10.content}' - expected 'event <Name> [generation <N>]'`, locationOf(header10));
1675
+ }
1676
+ const hasGenerationMarker = match?.[2] !== void 0;
1677
+ let generation = 1;
1678
+ if (hasGenerationMarker) {
1679
+ const declared = Number(match[2]);
1680
+ if (!Number.isSafeInteger(declared) || declared === 0 || declared >= maximumGeneration) {
1681
+ context.error(DiagnosticCodes.InvalidEventGeneration, `Event '${name}' must declare a generation between 1 and ${maximumGeneration - 1}`, locationOf(header10));
1682
+ } else {
1683
+ generation = declared;
1684
+ }
1685
+ }
1686
+ const properties = [];
1687
+ const tags = [];
1688
+ const metadata = new EventMetadataParser(name);
1689
+ for (let line = context.peekChild(header10.indent); line !== void 0; line = context.peekChild(header10.indent)) {
1690
+ context.reader.takeSignificant();
1691
+ if (isFileDirectiveAmongProperties(line)) {
1692
+ continue;
1693
+ }
1694
+ if (firstWord2(line.content) === "tag") {
1695
+ const tag = parseTag(context, line);
1696
+ if (tag !== void 0) {
1697
+ tags.push(tag);
1698
+ }
1699
+ continue;
1700
+ }
1701
+ const property = parseProperty(context, line);
1702
+ if (property === void 0) {
1703
+ if (!metadata.tryParse(context, line)) {
1704
+ context.error(DiagnosticCodes.InvalidPropertyDeclaration, `Invalid property '${line.content}' - expected '<name> <Type>'`, locationOf(line));
1705
+ }
1706
+ continue;
1707
+ }
1708
+ properties.push(withoutIdentifier(context, property, line, DiagnosticCodes.IdentifierOnEventProperty, `Property '${property.name}' of event '${name}' cannot be marked identifier - an event never carries its event source id`));
1709
+ }
1710
+ return { kind: "EventSyntax", name, properties, tags, generation, hasGenerationMarker, ...metadata.value, location: locationOf(header10) };
1711
+ }
1712
+ function parseTag(context, line, eventDeclaration = true) {
1713
+ const value = line.content.substring("tag".length).trim();
1714
+ if (eventDeclaration && typeShapedPattern.test(value)) {
1715
+ context.warning(DiagnosticCodes.TagPropertyReadAsTag, `'${line.content}' declares a static tag with the value '${value}', not a property named 'tag' - write 'tag "${value}"' for the tag, or '@${line.content}' for the property`, locationOf(line));
1716
+ }
1717
+ if (value.length === 0) {
1718
+ context.error(DiagnosticCodes.TagWithoutValue, "Expected a value after 'tag' - an identifier, a string literal or a context expression", locationOf(line));
1719
+ return void 0;
1720
+ }
1721
+ if (tagIdentifierPattern.test(value)) {
1722
+ return { kind: "TagSyntax", value: { kind: "LiteralExpressionSyntax", value, location: locationOf(line) }, location: locationOf(line) };
1723
+ }
1724
+ const expression = parseMappingSource(value, locationOf(line), context);
1725
+ if (expression.kind === "RawExpressionSyntax") {
1726
+ context.error(DiagnosticCodes.InvalidTagValue, `Invalid tag value '${value}' - expected an identifier, a string literal or a context expression`, locationOf(line));
1727
+ return void 0;
1728
+ }
1729
+ return { kind: "TagSyntax", value: expression, location: locationOf(line) };
1730
+ }
1731
+ function parseReadModel(context, header10) {
1732
+ const name = readModelHeader.exec(header10.content)?.[1] ?? "";
1733
+ if (name === "") {
1734
+ context.error(DiagnosticCodes.InvalidReadModelDeclaration, `Invalid read model declaration '${header10.content}' - expected 'readmodel <Name>'`, locationOf(header10));
1735
+ }
1736
+ const properties = [];
1737
+ let description = null;
1738
+ for (let line = context.peekChild(header10.indent); line !== void 0; line = context.peekChild(header10.indent)) {
1739
+ context.reader.takeSignificant();
1740
+ if (isDescription(line)) {
1741
+ description = parseDescription(context, line, description, `Read model '${name}'`);
1742
+ } else if (isFileDirectiveAmongProperties(line)) {
1743
+ continue;
1744
+ } else {
1745
+ const property = parseProperty(context, line);
1746
+ if (property === void 0) {
1747
+ context.error(DiagnosticCodes.InvalidPropertyDeclaration, `Invalid property '${line.content}' - expected '<name> <Type>'`, locationOf(line));
1748
+ continue;
1749
+ }
1750
+ properties.push(withoutIdentifier(context, property, line, DiagnosticCodes.IdentifierOutsideCommand, `Property '${property.name}' of read model '${name}' cannot be marked identifier - only a command property can be`));
1751
+ }
1752
+ }
1753
+ return { kind: "ReadModelSyntax", name, properties, description, location: locationOf(header10) };
1754
+ }
1755
+
1756
+ // ../../Compiler/dist/Parsing/ProducesParser.js
1757
+ var inlineHeader = pattern("^produces\\s+event\\s+([A-Za-z_]\\w*)(?:\\s+(generation)(?:\\s+.*)?)?$");
1758
+ var plainHeader = pattern("^produces\\s+([A-Z]\\w*)$");
1759
+ var conditional = pattern("^produces\\s+when\\s+(.+)$");
1760
+ var eventName = pattern("^[A-Z]\\w*$");
1761
+ var targetPattern = pattern("^for\\s+(\\S.*)$");
1762
+ var mappingPattern = pattern("^(@?[\\w.]+)\\s*=(?!=|>)\\s*(.+)$");
1763
+ var typedMappingPattern = pattern("^(.+?)\\s*=(?!=|>)\\s*(.+)$");
1764
+ var reserved = /* @__PURE__ */ new Set(["namespace", "sequence", "correlation", "causation", "causedBy", "occurred"]);
1765
+ function parseProduces(context, header10, inCommand = false) {
1766
+ const inline = inlineHeader.exec(header10.content);
1767
+ let parent = header10;
1768
+ let name;
1769
+ if (inline !== null) {
1770
+ if (!inCommand) {
1771
+ context.error(DiagnosticCodes.InlineEventOutsideCommand, "Inline events can only be declared inside commands", locationOf(header10));
1772
+ context.skipOpaqueBlock(header10.indent);
1773
+ return void 0;
1774
+ }
1775
+ if (inline[2] !== void 0) {
1776
+ context.error(DiagnosticCodes.InlineEventGeneration, "Inline events are generation 1 - extract the event before declaring generations", locationOf(header10));
1777
+ }
1778
+ name = inline[1];
1779
+ } else if (conditional.test(header10.content)) {
1780
+ const child = context.peekChild(header10.indent);
1781
+ if (child === void 0 || !eventName.test(child.content)) {
1782
+ context.error(DiagnosticCodes.ProducesWhenWithoutEvent, "Expected an event name on the line after 'produces when'", locationOf(header10));
1783
+ context.skipOpaqueBlock(header10.indent);
1784
+ return void 0;
1785
+ }
1786
+ context.reader.takeSignificant();
1787
+ parent = child;
1788
+ name = child.content;
1789
+ } else {
1790
+ const plain = plainHeader.exec(header10.content);
1791
+ if (plain === null) {
1792
+ context.error(DiagnosticCodes.InvalidProducesDeclaration, `Invalid produces declaration '${header10.content}' - expected 'produces <EventType>' or 'produces when <condition>'`, locationOf(header10));
1793
+ context.skipOpaqueBlock(header10.indent);
1794
+ return void 0;
1795
+ }
1796
+ name = plain[1];
1797
+ }
1798
+ const properties = [];
1799
+ const propertyNames = /* @__PURE__ */ new Set();
1800
+ const mappings = [];
1801
+ const tags = [];
1802
+ const metadata = new EventMetadataParser(name);
1803
+ let target = null;
1804
+ for (let line = context.peekChild(parent.indent); line !== void 0; line = context.peekChild(parent.indent)) {
1805
+ context.reader.takeSignificant();
1806
+ const keyword = firstWord2(line.content);
1807
+ const location = locationOf(line);
1808
+ if (reserved.has(keyword)) {
1809
+ context.error(DiagnosticCodes.ReservedProductionMetadata, `'${keyword}' is system-assigned production metadata and cannot be supplied here`, location);
1810
+ context.skipOpaqueBlock(line.indent);
1811
+ continue;
1812
+ }
1813
+ if (inline !== null && (keyword === "generation" || keyword === "origin")) {
1814
+ context.error(keyword === "generation" ? DiagnosticCodes.InlineEventGeneration : DiagnosticCodes.ReservedProductionMetadata, keyword === "generation" ? "Inline events are generation 1 - extract the event before declaring generations" : "An inline event is local to its command and cannot declare origin", location);
1815
+ context.skipOpaqueBlock(line.indent);
1816
+ continue;
1817
+ }
1818
+ if (keyword === "tag") {
1819
+ const tag = parseTag(context, line, false);
1820
+ if (tag !== void 0)
1821
+ tags.push(tag);
1822
+ continue;
1823
+ }
1824
+ const forMatch = targetPattern.exec(line.content);
1825
+ if (forMatch !== null) {
1826
+ if (target !== null) {
1827
+ context.error(DiagnosticCodes.DuplicateProducesTarget, `'${parent.content}' already declares where it lands - an event is appended to one event source`, location);
1828
+ } else {
1829
+ target = parseMappingSource(forMatch[1], location, context);
1830
+ }
1831
+ continue;
1832
+ }
1833
+ const match = (inline === null ? mappingPattern : typedMappingPattern).exec(line.content);
1834
+ let property = match === null || inline === null ? void 0 : parseProperty(context, { ...line, content: match[1].trimEnd() });
1835
+ if (match !== null && (inline === null || property !== void 0)) {
1836
+ if (property !== void 0) {
1837
+ if (property.isIdentifier) {
1838
+ context.error(DiagnosticCodes.IdentifierOnEventProperty, `Property '${property.name}' of event '${name}' cannot be marked identifier - an event never carries its event source id`, location);
1839
+ property = { ...property, isIdentifier: false };
1840
+ }
1841
+ const propertyName = property.name;
1842
+ if (propertyNames.has(propertyName)) {
1843
+ context.error(DiagnosticCodes.DuplicateDeclaration, `Event '${name}' already declares property '${property.name}'`, location);
1844
+ }
1845
+ propertyNames.add(propertyName);
1846
+ properties.push(property);
1847
+ }
1848
+ mappings.push({ kind: "PropertyMappingSyntax", property: property?.name ?? unescapeIdentifier(match[1]), source: parseMappingSource(match[2], location, context), location });
1849
+ } else if (inline === null || !metadata.tryParse(context, line)) {
1850
+ context.error(DiagnosticCodes.InvalidPropertyMapping, `Invalid ${inline === null ? "" : "inline "}property mapping '${line.content}' - expected '<property>${inline === null ? "" : " <Type>"} = <source>'`, location);
1851
+ }
1852
+ }
1853
+ if (parent !== header10)
1854
+ context.skipBlock(header10.indent);
1855
+ return {
1856
+ kind: "ProducesSyntax",
1857
+ event: name,
1858
+ mappings,
1859
+ for: target,
1860
+ tags: inline === null ? tags : [],
1861
+ location: locationOf(header10),
1862
+ inlineEvent: inline === null ? null : { kind: "EventSyntax", name, properties, tags, generation: 1, hasGenerationMarker: false, ...metadata.value, location: locationOf(header10) }
1863
+ };
1864
+ }
1865
+
1866
+ // ../../Compiler/dist/Parsing/CommandParser.js
1867
+ var header2 = pattern("^command\\s+([A-Za-z_]\\w*)$");
1868
+ var severityPattern = pattern("\\bseverity\\s+(\\S+)$");
1869
+ var messagePattern = pattern(`\\bmessage\\s+(?:"(${stringBodyPattern})"|(\\$strings\\.\\S*))$`);
1870
+ var rulePattern = pattern("^([\\w.]+)\\s+(.+)$");
1871
+ var operandPattern = pattern("^(not empty|length ==|all >=|all >|matches|max|min|rule|>=|<=|==|!=|>|<)\\s*(.*)$");
1872
+ var ruleNamePattern = pattern("^[A-Za-z_]\\w*$");
1873
+ var optionalReads = pattern("^reads\\s+[A-Z]\\w*\\s+optional(?:\\s|$)");
1874
+ var operandKinds = {
1875
+ max: "Max",
1876
+ min: "Min",
1877
+ ">": "GreaterThan",
1878
+ ">=": "GreaterThanOrEqual",
1879
+ "<": "LessThan",
1880
+ "<=": "LessThanOrEqual",
1881
+ "==": "Equal",
1882
+ "!=": "NotEqual",
1883
+ "length ==": "Length",
1884
+ matches: "Matches",
1885
+ "all >": "AllGreaterThan",
1886
+ "all >=": "AllGreaterThanOrEqual"
1887
+ };
1888
+ var severities = { information: "Information", warning: "Warning", error: "Error" };
1889
+ var opaqueDirectives = /* @__PURE__ */ new Set(["reads", "handler", "concurrency"]);
1890
+ var propertyShapedDirectives = /* @__PURE__ */ new Set(["description", "handler", "concurrency"]);
1891
+ function parseCommand(context, line) {
1892
+ const name = header2.exec(line.content)?.[1] ?? "";
1893
+ if (name === "") {
1894
+ context.error(DiagnosticCodes.InvalidCommandDeclaration, `Invalid command declaration '${line.content}' - expected 'command <Name>'`, locationOf(line));
1895
+ }
1896
+ const properties = [];
1897
+ let identifier;
1898
+ const validations = [];
1899
+ const produces = [];
1900
+ let description = null;
1901
+ let authorize = null;
1902
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
1903
+ context.reader.takeSignificant();
1904
+ const keyword = firstWord2(child.content);
1905
+ const asProperty = tryParseProperty(child);
1906
+ if (asProperty !== void 0 && (propertyShapedDirectives.has(keyword) || keyword === "validate" && child.content !== "validate csharp")) {
1907
+ identifier = addProperty(context, properties, asProperty, name, child, identifier);
1908
+ } else if (keyword === "description") {
1909
+ description = parseDescription(context, child, description, `Command '${name}'`);
1910
+ } else if (keyword === "authorize") {
1911
+ authorize = combineAuthorize(authorize, parseAuthorize(context, child));
1912
+ } else if (keyword === "validate") {
1913
+ const validate = parseValidate(context, child);
1914
+ if (validate !== void 0) {
1915
+ validations.push(validate);
1916
+ }
1917
+ } else if (keyword === "produces") {
1918
+ const production = parseProduces(context, child, true);
1919
+ if (production !== void 0)
1920
+ produces.push(production);
1921
+ } else if (opaqueDirectives.has(keyword)) {
1922
+ if (optionalReads.test(child.content)) {
1923
+ context.error(DiagnosticCodes.OptionalReadsNotSupported, "Optional reads are not yet supported (see #308).", locationOf(child));
1924
+ }
1925
+ context.skipOpaqueBlock(child.indent);
1926
+ } else if (asProperty !== void 0) {
1927
+ identifier = addProperty(context, properties, asProperty, name, child, identifier);
1928
+ } else {
1929
+ reportInvalidModifierOrder(context, child);
1930
+ context.error(DiagnosticCodes.UnknownCommandDirective, `Unexpected '${child.content}' in command body`, locationOf(child));
1931
+ context.skipBlock(child.indent);
1932
+ }
1933
+ }
1934
+ return { kind: "CommandSyntax", name, description, authorize, properties, validations, produces, location: locationOf(line) };
1935
+ }
1936
+ function addProperty(context, properties, property, commandName, line, identifier) {
1937
+ reportLegacyOptionalSuffix(context, property.type, line);
1938
+ if (property.isIdentifier && identifier !== void 0) {
1939
+ context.error(DiagnosticCodes.DuplicateCommandIdentifier, `Command '${commandName}' already marks '${identifier.name}' as identifier - only one property can be the identifier`, property.location);
1940
+ property = { ...property, isIdentifier: false };
1941
+ }
1942
+ properties.push(property);
1943
+ return identifier ?? (property.isIdentifier ? property : void 0);
1944
+ }
1945
+ function parseValidate(context, line) {
1946
+ if (line.content === "validate") {
1947
+ const fence = context.peekChild(line.indent);
1948
+ if (fence !== void 0 && fence.content.startsWith("```")) {
1949
+ context.reader.takeSignificant();
1950
+ context.skipFencedBody();
1951
+ return { kind: "CodeValidateSyntax", location: locationOf(line) };
1952
+ }
1953
+ const rules = [];
1954
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
1955
+ context.reader.takeSignificant();
1956
+ if (firstWord2(child.content) === "require") {
1957
+ context.skipOpaqueBlock(child.indent);
1958
+ continue;
1959
+ }
1960
+ const rule2 = parseValidationRule(context, child);
1961
+ if (rule2 !== void 0) {
1962
+ rules.push(rule2);
1963
+ }
1964
+ }
1965
+ return { kind: "DeclarativeValidateSyntax", rules, location: locationOf(line) };
1966
+ }
1967
+ if (line.content === "validate csharp") {
1968
+ context.skipOpaqueBlock(line.indent);
1969
+ return { kind: "CodeValidateSyntax", location: locationOf(line) };
1970
+ }
1971
+ context.error(DiagnosticCodes.InvalidValidateDeclaration, `Invalid validate declaration '${line.content}' - expected 'validate' or 'validate csharp'`, locationOf(line));
1972
+ context.skipBlock(line.indent);
1973
+ return void 0;
1974
+ }
1975
+ function parseValidationRule(context, line) {
1976
+ const { content: withSeverity, message } = splitMessage(line.content);
1977
+ const severity = splitSeverity(context, line, withSeverity);
1978
+ if (severity === void 0) {
1979
+ return void 0;
1980
+ }
1981
+ const match = rulePattern.exec(severity.content);
1982
+ if (match === null) {
1983
+ context.error(DiagnosticCodes.InvalidValidationRule, `Invalid validation rule '${line.content}'`, locationOf(line));
1984
+ return void 0;
1985
+ }
1986
+ const parsed = parseRule(context, match[2], line);
1987
+ if (parsed === void 0) {
1988
+ return void 0;
1989
+ }
1990
+ if (parsed.kind === "Rule") {
1991
+ context.skipOpaqueBlock(line.indent);
1992
+ }
1993
+ return {
1994
+ kind: "ValidationRuleSyntax",
1995
+ property: match[1],
1996
+ rule: parsed.kind,
1997
+ value: parsed.value,
1998
+ message,
1999
+ severity: severity.severity,
2000
+ location: locationOf(line)
2001
+ };
2002
+ }
2003
+ function splitMessage(content) {
2004
+ const match = messagePattern.exec(content);
2005
+ if (match === null) {
2006
+ return { content, message: null };
2007
+ }
2008
+ const message = match[1] !== void 0 ? unescapeString(match[1]) : match[2];
2009
+ return { content: content.substring(0, match.index).trimEnd(), message };
2010
+ }
2011
+ function splitSeverity(context, line, text) {
2012
+ const match = severityPattern.exec(text);
2013
+ if (match === null) {
2014
+ return { content: text, severity: "Error" };
2015
+ }
2016
+ const severity = severities[match[1]];
2017
+ if (severity === void 0) {
2018
+ context.error(DiagnosticCodes.InvalidValidationSeverity, `Unknown validation severity '${match[1]}' - expected information, warning or error`, locationOf(line));
2019
+ return void 0;
2020
+ }
2021
+ return { content: text.substring(0, match.index).trimEnd(), severity };
2022
+ }
2023
+ function parseRule(context, rule2, line) {
2024
+ if (rule2 === "not empty") {
2025
+ return { kind: "NotEmpty", value: null };
2026
+ }
2027
+ const operand2 = operandPattern.exec(rule2);
2028
+ if (operand2 === null) {
2029
+ context.error(DiagnosticCodes.InvalidValidationRule, `Invalid validation rule '${line.content}'`, locationOf(line));
2030
+ return void 0;
2031
+ }
2032
+ if (operand2[1] === "rule") {
2033
+ const name = operand2[2].trim();
2034
+ if (!ruleNamePattern.test(name)) {
2035
+ context.error(DiagnosticCodes.InvalidRuleName, `Invalid rule name '${name}' in '${line.content}' - expected 'rule <Name>' with an identifier`, locationOf(line));
2036
+ return void 0;
2037
+ }
2038
+ return { kind: "Rule", value: { kind: "PathExpressionSyntax", path: name, location: locationOf(line) } };
2039
+ }
2040
+ return { kind: operandKinds[operand2[1]], value: parseMappingSource(operand2[2], locationOf(line), context) };
2041
+ }
2042
+
2043
+ // ../../Compiler/dist/Parsing/ConstraintParser.js
2044
+ var header3 = pattern("^constraint\\s+([A-Za-z_]\\w*)$");
2045
+ var uniqueEventPattern = pattern("^unique\\s+event\\s+([A-Z]\\w*)$");
2046
+ var uniquePropertyPattern = pattern("^unique\\s+([a-z_][\\w.]*(?:\\s*,\\s*[a-z_][\\w.]*)*)\\s+on\\s+([A-Z]\\w*)$");
2047
+ var releasePattern = pattern("^released\\s+by\\s+([A-Z]\\w*)$");
2048
+ var messagePattern2 = pattern(`^message\\s+"(${stringBodyPattern})"$`);
2049
+ var targetOf = (rule2) => rule2.kind === "FileConstraintSyntax" ? void 0 : rule2.event;
2050
+ function parseConstraint(context, line) {
2051
+ const headerMatch = header3.exec(line.content);
2052
+ if (headerMatch === null) {
2053
+ context.error(DiagnosticCodes.InvalidConstraintDeclaration, `Invalid constraint declaration '${line.content}' - expected 'constraint <Name>'`, locationOf(line));
2054
+ }
2055
+ const name = headerMatch?.[1] ?? firstWord2(line.content);
2056
+ const rules = [];
2057
+ const releases = [];
2058
+ const releasedEvents = /* @__PURE__ */ new Set();
2059
+ const targets = /* @__PURE__ */ new Set();
2060
+ let message = null;
2061
+ let ignoreCasing = false;
2062
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
2063
+ context.reader.takeSignificant();
2064
+ const release = releasePattern.exec(child.content);
2065
+ const text = messagePattern2.exec(child.content);
2066
+ if (release !== null) {
2067
+ if (releasedEvents.has(release[1])) {
2068
+ context.error(DiagnosticCodes.DuplicateConstraintBody, `Constraint '${name}' already releases with event '${release[1]}'`, locationOf(child));
2069
+ } else {
2070
+ releases.push(release[1]);
2071
+ releasedEvents.add(release[1]);
2072
+ }
2073
+ } else if (text !== null) {
2074
+ if (message !== null) {
2075
+ context.error(DiagnosticCodes.DuplicateConstraintBody, `Constraint '${name}' already has a message`, locationOf(child));
2076
+ } else {
2077
+ message = unescapeString(text[1]);
2078
+ }
2079
+ } else if (child.content === "ignore casing") {
2080
+ if (ignoreCasing) {
2081
+ context.error(DiagnosticCodes.DuplicateConstraintBody, `Constraint '${name}' already ignores casing`, locationOf(child));
2082
+ }
2083
+ ignoreCasing = true;
2084
+ } else {
2085
+ addRule(context, name, child, rules, targets);
2086
+ }
2087
+ }
2088
+ for (const release of releases.filter((release2) => targets.has(release2))) {
2089
+ context.error(DiagnosticCodes.DuplicateConstraintBody, `Constraint '${name}' cannot target and release event '${release}'`, locationOf(line));
2090
+ }
2091
+ if (rules.length === 0) {
2092
+ context.error(DiagnosticCodes.ConstraintWithoutRule, `Constraint '${name}' must declare 'unique ... on ...', 'unique event ...' or 'file ...'`, locationOf(line));
2093
+ rules.push(rule(name, locationOf(line), { kind: "UniqueEventConstraintSyntax", event: "" }));
2094
+ }
2095
+ if (rules[0].kind === "FileConstraintSyntax" && (releases.length > 0 || message !== null || ignoreCasing)) {
2096
+ context.error(DiagnosticCodes.InvalidConstraintBody, `File constraint '${name}' cannot have declarative options`, locationOf(line));
2097
+ }
2098
+ return { ...rules[0], additionalRules: rules.slice(1), releasedBy: releases, message, ignoreCasing };
2099
+ }
2100
+ function addRule(context, name, line, rules, targets) {
2101
+ const parsed = parseRule2(context, name, line);
2102
+ if (parsed === void 0) {
2103
+ return;
2104
+ }
2105
+ if (rules.length > 0 && (parsed.kind === "FileConstraintSyntax" || rules[0].kind === "FileConstraintSyntax" || parsed.kind === "UniqueEventConstraintSyntax" !== (rules[0].kind === "UniqueEventConstraintSyntax"))) {
2106
+ context.error(DiagnosticCodes.DuplicateConstraintBody, `Constraint '${name}' cannot mix constraint kinds`, locationOf(line));
2107
+ return;
2108
+ }
2109
+ const target = targetOf(parsed);
2110
+ if (target !== void 0 && targets.has(target)) {
2111
+ context.error(DiagnosticCodes.DuplicateConstraintBody, `Constraint '${name}' already targets event '${target}'`, locationOf(line));
2112
+ return;
2113
+ }
2114
+ if (target !== void 0)
2115
+ targets.add(target);
2116
+ rules.push(parsed);
2117
+ }
2118
+ function parseRule2(context, name, line) {
2119
+ const location = locationOf(line);
2120
+ const uniqueEvent = uniqueEventPattern.exec(line.content);
2121
+ if (uniqueEvent !== null) {
2122
+ return rule(name, location, { kind: "UniqueEventConstraintSyntax", event: uniqueEvent[1] });
2123
+ }
2124
+ const uniqueProperty = uniquePropertyPattern.exec(line.content);
2125
+ if (uniqueProperty !== null) {
2126
+ const properties = uniqueProperty[1].split(",").map((property) => property.trim());
2127
+ if (new Set(properties).size !== properties.length) {
2128
+ context.error(DiagnosticCodes.DuplicateConstraintBody, `Constraint '${name}' repeats a property in its composite key`, location);
2129
+ return void 0;
2130
+ }
2131
+ return rule(name, location, { kind: "UniquePropertyConstraintSyntax", property: properties[0], additionalProperties: properties.slice(1), event: uniqueProperty[2] });
2132
+ }
2133
+ if (isFileDirective(line)) {
2134
+ context.warning(DiagnosticCodes.FileConstraintOnlySupportsUniqueness, "A file constraint can only declare unique constraints in Chronicle - declare them with 'unique ...' so they are portable; a rule that is not uniqueness belongs in command validation or a 'require' condition", location);
2135
+ const path = line.content.substring("file".length).trim();
2136
+ return rule(name, location, { kind: "FileConstraintSyntax", file: { kind: "FileReferenceSyntax", path, location } });
2137
+ }
2138
+ context.error(DiagnosticCodes.InvalidConstraintBody, `Invalid constraint body '${line.content}'`, location);
2139
+ return void 0;
2140
+ }
2141
+ function rule(name, location, shape) {
2142
+ return { ...shape, name, additionalRules: [], releasedBy: [], ignoreCasing: false, message: null, location };
2143
+ }
2144
+
2145
+ // ../../Compiler/dist/Parsing/ProjectionParser.js
2146
+ var header4 = pattern("^projection\\s+(@?[\\w.]+)\\s*(?:=>\\s*([\\w.]+))?$");
2147
+ var eventSpecPattern = pattern("^(@?[\\w.]+)(?:\\s+key\\s+(.+))?$");
2148
+ var joinPattern = pattern("^join\\s+(@?[\\w.]+)\\s+on\\s+(@?[\\w.]+)$");
2149
+ var withPattern = pattern("^with\\s+(@?[\\w.]+)$");
2150
+ var childrenPattern2 = pattern("^children\\s+(@?[\\w.]+)\\s+identified\\s+by\\s+(.+)$");
2151
+ var nestedPattern2 = pattern("^nested\\s+(@?[\\w.]+)$");
2152
+ var removeWithPattern = pattern("^remove\\s+with\\s+(@?[\\w.]+)(?:\\s+key\\s+(.+))?$");
2153
+ var removeViaJoinPattern = pattern("^remove\\s+via\\s+join\\s+on\\s+(@?[\\w.]+)(?:\\s+key\\s+(.+))?$");
2154
+ var clearWithPattern = pattern("^clear\\s+with\\s+(@?[\\w.]+)$");
2155
+ var variantPattern = pattern("^variant\\s+(@?[\\w.]+)\\s*$");
2156
+ var entersOnPattern = pattern("^enters\\s+on\\s+(@?[\\w.]+)(?:\\s+key\\s+(.+))?$");
2157
+ var keywordMappingPattern = pattern("^(increment|decrement|count|clear)\\s+(@?[$\\w.]+)$");
2158
+ var arithmeticPattern = pattern("^(add|subtract)\\s+(@?[$\\w.]+)\\s+by\\s+(.+)$");
2159
+ var setPattern = pattern("^set\\s+(@?[$\\w.]+)\\s+(?:=|to)\\s+(.+)$");
2160
+ var assignmentPattern = pattern("^(@?[$\\w.@]+)\\s*=(?!=|>)\\s*(.+)$");
2161
+ var keywordMappings = {
2162
+ increment: "IncrementMappingSyntax",
2163
+ decrement: "DecrementMappingSyntax",
2164
+ clear: "ClearMappingSyntax",
2165
+ count: "CountMappingSyntax"
2166
+ };
2167
+ function parseProjection(context, line) {
2168
+ const match = header4.exec(line.content);
2169
+ if (match === null) {
2170
+ context.error(DiagnosticCodes.InvalidProjectionDeclaration, `Invalid projection declaration '${line.content}' - expected 'projection <Name> [=> <ReadModel>]'`, locationOf(line));
2171
+ context.skipBlock(line.indent);
2172
+ return { kind: "ProjectionSyntax", name: firstWord2(line.content), readModel: null, sequence: null, autoMap: "Inherit", blocks: [], location: locationOf(line) };
2173
+ }
2174
+ const name = match[1];
2175
+ let sequence = null;
2176
+ let autoMap = "Inherit";
2177
+ const blocks = [];
2178
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
2179
+ context.reader.takeSignificant();
2180
+ if (isFileDirective(child)) {
2181
+ continue;
2182
+ }
2183
+ const keyword = firstWord2(child.content);
2184
+ if (keyword === "sequence") {
2185
+ sequence = child.content.substring("sequence".length).trim();
2186
+ } else if (keyword === "automap") {
2187
+ autoMap = "Enabled";
2188
+ } else if (child.content === "no automap") {
2189
+ autoMap = "Disabled";
2190
+ } else if (keyword === "key") {
2191
+ skipKey(context, child);
2192
+ } else if (keyword === "variant") {
2193
+ blocks.push(parseVariant(context, child));
2194
+ } else {
2195
+ const block = parseBlock(context, child, false);
2196
+ if (block !== void 0) {
2197
+ blocks.push(block);
2198
+ }
2199
+ }
2200
+ }
2201
+ reportVariantConflicts(context, blocks, name);
2202
+ if (blocks.length === 0) {
2203
+ context.error(DiagnosticCodes.EmptyProjection, `Projection '${name}' must contain at least one directive`, locationOf(line));
2204
+ }
2205
+ return { kind: "ProjectionSyntax", name, readModel: match[2] ?? null, sequence, autoMap, blocks, location: locationOf(line) };
2206
+ }
2207
+ function reportVariantConflicts(context, blocks, name) {
2208
+ const variants = blocks.filter((block) => block.kind === "ProjectionVariantSyntax");
2209
+ const byName = /* @__PURE__ */ new Map();
2210
+ variants.forEach((variant) => byName.set(variant.name, [...byName.get(variant.name) ?? [], variant]));
2211
+ for (const duplicate of [...byName.values()].flatMap((group) => group.slice(1))) {
2212
+ context.error(DiagnosticCodes.DuplicateProjectionVariant, `Duplicate variant '${duplicate.name}' - a variant name is declared once`, duplicate.location);
2213
+ }
2214
+ const entering = /* @__PURE__ */ new Set();
2215
+ for (const entry of blocks.flatMap((block) => block.kind === "ProjectionVariantSyntax" ? block.entersOn : [])) {
2216
+ if (entry.event.length > 0 && entering.has(entry.event)) {
2217
+ context.error(DiagnosticCodes.DuplicateVariantEnteringEvent, `Entering event '${entry.event}' is claimed more than once in projection '${name}'`, entry.location);
2218
+ }
2219
+ entering.add(entry.event);
2220
+ }
2221
+ }
2222
+ function parseBlock(context, line, nestedScope) {
2223
+ const location = locationOf(line);
2224
+ switch (firstWord2(line.content)) {
2225
+ case "from":
2226
+ return parseFrom(context, line);
2227
+ case "every": {
2228
+ let includeChildren = true;
2229
+ const { autoMap, mappings } = parseMappingBlock(context, line, (child) => {
2230
+ if (child.content !== "exclude children") {
2231
+ return false;
2232
+ }
2233
+ includeChildren = false;
2234
+ return true;
2235
+ });
2236
+ return { kind: "EverySyntax", includeChildren, autoMap, mappings, location };
2237
+ }
2238
+ case "all": {
2239
+ const { autoMap, mappings } = parseMappingBlock(context, line);
2240
+ return { kind: "AllSyntax", autoMap, mappings, location };
2241
+ }
2242
+ case "join":
2243
+ return parseJoin(context, line);
2244
+ case "children":
2245
+ return parseChildren(context, line);
2246
+ case "nested":
2247
+ return parseNested(context, line);
2248
+ case "remove":
2249
+ return parseRemove(context, line);
2250
+ case "clear":
2251
+ if (!nestedScope) {
2252
+ context.error(DiagnosticCodes.ClearWithOutsideNestedBlock, "'clear with' is only valid inside a nested block", location);
2253
+ }
2254
+ return parseClearWith(context, line);
2255
+ default:
2256
+ context.error(DiagnosticCodes.UnknownProjectionDirective, `Unexpected '${firstWord2(line.content)}' in projection body`, location);
2257
+ context.skipBlock(line.indent);
2258
+ return void 0;
2259
+ }
2260
+ }
2261
+ function parseFrom(context, line) {
2262
+ const events = [];
2263
+ for (const spec of splitTopLevel(line.content.substring("from".length), ",")) {
2264
+ const text = spec.trim();
2265
+ if (text.length === 0) {
2266
+ context.error(DiagnosticCodes.FromWithoutEvent, "Expected an event type after 'from'", locationOf(line));
2267
+ continue;
2268
+ }
2269
+ const match = eventSpecPattern.exec(text);
2270
+ if (match === null) {
2271
+ context.error(DiagnosticCodes.InvalidEventReference, `Invalid event reference '${text}'`, locationOf(line));
2272
+ continue;
2273
+ }
2274
+ events.push({ kind: "EventSpecSyntax", event: unescapeIdentifier(match[1]), location: locationOf(line) });
2275
+ }
2276
+ const mappings = [];
2277
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
2278
+ context.reader.takeSignificant();
2279
+ const keyword = firstWord2(child.content);
2280
+ if (keyword === "key") {
2281
+ skipKey(context, child);
2282
+ } else if (keyword !== "parent") {
2283
+ pushMapping(child, mappings);
2284
+ }
2285
+ }
2286
+ return { kind: "FromSyntax", events, mappings, location: locationOf(line) };
2287
+ }
2288
+ function parseJoin(context, line) {
2289
+ const match = joinPattern.exec(line.content);
2290
+ if (match === null) {
2291
+ context.error(DiagnosticCodes.InvalidJoinDeclaration, `Invalid join declaration '${line.content}' - expected 'join <property> on <key>'`, locationOf(line));
2292
+ context.skipBlock(line.indent);
2293
+ return { kind: "JoinSyntax", property: "", on: "", events: [], location: locationOf(line) };
2294
+ }
2295
+ const events = [];
2296
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
2297
+ context.reader.takeSignificant();
2298
+ const withMatch = withPattern.exec(child.content);
2299
+ if (withMatch === null) {
2300
+ context.error(DiagnosticCodes.JoinWithoutEvent, `Expected 'with <EventType>' in join block, got '${child.content}'`, locationOf(child));
2301
+ context.skipBlock(child.indent);
2302
+ continue;
2303
+ }
2304
+ const { autoMap, mappings } = parseMappingBlock(context, child);
2305
+ events.push({ kind: "JoinEventSyntax", event: unescapeIdentifier(withMatch[1]), autoMap, mappings, location: locationOf(child) });
2306
+ }
2307
+ return { kind: "JoinSyntax", property: unescapeIdentifier(match[1]), on: unescapeIdentifier(match[2]), events, location: locationOf(line) };
2308
+ }
2309
+ function parseChildren(context, line) {
2310
+ const match = childrenPattern2.exec(line.content);
2311
+ if (match === null) {
2312
+ context.error(DiagnosticCodes.InvalidChildrenDeclaration, `Invalid children declaration '${line.content}' - expected 'children <collection> identified by <key>'`, locationOf(line));
2313
+ context.skipBlock(line.indent);
2314
+ return { kind: "ChildrenSyntax", property: "", autoMap: "Inherit", blocks: [], location: locationOf(line) };
2315
+ }
2316
+ const { autoMap, blocks } = parseChildBlocks(context, line);
2317
+ return { kind: "ChildrenSyntax", property: unescapeIdentifier(match[1]), autoMap, blocks, location: locationOf(line) };
2318
+ }
2319
+ function parseNested(context, line) {
2320
+ const match = nestedPattern2.exec(line.content);
2321
+ if (match === null) {
2322
+ context.error(DiagnosticCodes.InvalidNestedDeclaration, `Invalid nested declaration '${line.content}' - expected 'nested <property>'`, locationOf(line));
2323
+ context.skipBlock(line.indent);
2324
+ return { kind: "NestedSyntax", property: "", autoMap: "Inherit", blocks: [], location: locationOf(line) };
2325
+ }
2326
+ const property = unescapeIdentifier(match[1]);
2327
+ const { autoMap, blocks } = parseChildBlocks(context, line);
2328
+ if (!blocks.some((block) => block.kind === "FromSyntax")) {
2329
+ context.error(DiagnosticCodes.NestedBlockWithoutFrom, `Nested block '${property}' must contain at least one 'from' directive`, locationOf(line));
2330
+ }
2331
+ return { kind: "NestedSyntax", property, autoMap, blocks, location: locationOf(line) };
2332
+ }
2333
+ function parseChildBlocks(context, line) {
2334
+ const blocks = [];
2335
+ let autoMap = "Inherit";
2336
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
2337
+ context.reader.takeSignificant();
2338
+ if (child.content === "automap") {
2339
+ autoMap = "Enabled";
2340
+ continue;
2341
+ }
2342
+ if (child.content === "no automap") {
2343
+ autoMap = "Disabled";
2344
+ continue;
2345
+ }
2346
+ const block = parseBlock(context, child, true);
2347
+ if (block !== void 0) {
2348
+ blocks.push(block);
2349
+ }
2350
+ }
2351
+ return { autoMap, blocks };
2352
+ }
2353
+ function parseRemove(context, line) {
2354
+ const viaJoin = removeViaJoinPattern.exec(line.content);
2355
+ if (viaJoin !== null) {
2356
+ return { kind: "RemoveViaJoinSyntax", event: unescapeIdentifier(viaJoin[1]), location: locationOf(line) };
2357
+ }
2358
+ const match = removeWithPattern.exec(line.content);
2359
+ if (match === null) {
2360
+ context.error(DiagnosticCodes.InvalidRemoveDeclaration, `Invalid remove declaration '${line.content}' - expected 'remove with <EventType>' or 'remove via join on <EventType>'`, locationOf(line));
2361
+ context.skipBlock(line.indent);
2362
+ return void 0;
2363
+ }
2364
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
2365
+ context.reader.takeSignificant();
2366
+ if (firstWord2(child.content) !== "parent") {
2367
+ context.error(DiagnosticCodes.UnknownRemoveDirective, `Unexpected '${child.content}' in remove block - only 'parent' is allowed`, locationOf(child));
2368
+ }
2369
+ }
2370
+ return { kind: "RemoveWithSyntax", event: unescapeIdentifier(match[1]), location: locationOf(line) };
2371
+ }
2372
+ function parseClearWith(context, line) {
2373
+ const match = clearWithPattern.exec(line.content);
2374
+ if (match === null) {
2375
+ context.error(DiagnosticCodes.InvalidClearDeclaration, `Invalid clear declaration '${line.content}' - expected 'clear with <EventType>'`, locationOf(line));
2376
+ return { kind: "ClearWithSyntax", event: "", location: locationOf(line) };
2377
+ }
2378
+ return { kind: "ClearWithSyntax", event: unescapeIdentifier(match[1]), location: locationOf(line) };
2379
+ }
2380
+ function parseVariant(context, line) {
2381
+ const match = variantPattern.exec(line.content);
2382
+ if (match === null) {
2383
+ context.error(DiagnosticCodes.InvalidProjectionVariantDeclaration, `Invalid variant declaration '${line.content}' - expected 'variant <Name>'`, locationOf(line));
2384
+ context.skipBlock(line.indent);
2385
+ return { kind: "ProjectionVariantSyntax", name: firstWord2(line.content), entersOn: [], blocks: [], location: locationOf(line) };
2386
+ }
2387
+ const name = unescapeIdentifier(match[1]);
2388
+ const entersOn = [];
2389
+ const blocks = [];
2390
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
2391
+ context.reader.takeSignificant();
2392
+ const keyword = firstWord2(child.content);
2393
+ if (keyword === "enters") {
2394
+ entersOn.push(parseEntersOn(context, child));
2395
+ } else if (keyword === "variant") {
2396
+ context.error(DiagnosticCodes.NestedProjectionVariantNotAllowed, "A variant cannot be declared inside another variant", locationOf(child));
2397
+ context.skipBlock(child.indent);
2398
+ } else {
2399
+ const block = parseBlock(context, child, false);
2400
+ if (block !== void 0) {
2401
+ blocks.push(block);
2402
+ }
2403
+ }
2404
+ }
2405
+ if (entersOn.length === 0) {
2406
+ context.error(DiagnosticCodes.VariantRequiresEnteringEvent, `Variant '${name}' must declare at least one 'enters on' event`, locationOf(line));
2407
+ }
2408
+ return { kind: "ProjectionVariantSyntax", name, entersOn, blocks, location: locationOf(line) };
2409
+ }
2410
+ function parseEntersOn(context, line) {
2411
+ const match = entersOnPattern.exec(line.content);
2412
+ if (match === null) {
2413
+ context.error(DiagnosticCodes.InvalidEntersOnDeclaration, `Invalid 'enters on' declaration '${line.content}' - expected 'enters on <EventType> [key <expression>]'`, locationOf(line));
2414
+ context.skipBlock(line.indent);
2415
+ return { kind: "ProjectionEntersOnSyntax", event: "", location: locationOf(line) };
2416
+ }
2417
+ return { kind: "ProjectionEntersOnSyntax", event: unescapeIdentifier(match[1]), location: locationOf(line) };
2418
+ }
2419
+ function skipKey(context, line) {
2420
+ if (context.peekChild(line.indent) === void 0) {
2421
+ return;
2422
+ }
2423
+ context.skipBlock(line.indent);
2424
+ const closing = context.reader.peekSignificant();
2425
+ if (closing !== void 0 && closing.indent === line.indent && closing.content === "}") {
2426
+ context.reader.takeSignificant();
2427
+ }
2428
+ }
2429
+ function parseMappingBlock(context, line, extra = () => false) {
2430
+ let autoMap = "Inherit";
2431
+ const mappings = [];
2432
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
2433
+ context.reader.takeSignificant();
2434
+ if (child.content === "automap") {
2435
+ autoMap = "Enabled";
2436
+ } else if (child.content === "no automap") {
2437
+ autoMap = "Disabled";
2438
+ } else if (!extra(child)) {
2439
+ pushMapping(child, mappings);
2440
+ }
2441
+ }
2442
+ return { autoMap, mappings };
2443
+ }
2444
+ function pushMapping(line, mappings) {
2445
+ const location = locationOf(line);
2446
+ const keyword = keywordMappingPattern.exec(line.content);
2447
+ if (keyword !== null) {
2448
+ if (keyword[1] !== "clear" || keyword[2] !== "with") {
2449
+ mappings.push({ kind: keywordMappings[keyword[1]], property: unescapeIdentifier(keyword[2]), location });
2450
+ }
2451
+ return;
2452
+ }
2453
+ const arithmetic = arithmeticPattern.exec(line.content);
2454
+ if (arithmetic !== null) {
2455
+ mappings.push({ kind: arithmetic[1] === "add" ? "AddMappingSyntax" : "SubtractMappingSyntax", property: unescapeIdentifier(arithmetic[2]), location });
2456
+ return;
2457
+ }
2458
+ const assigned = setPattern.exec(line.content) ?? assignmentPattern.exec(line.content);
2459
+ if (assigned !== null) {
2460
+ mappings.push({ kind: "SetMappingSyntax", property: unescapeIdentifier(assigned[1]), location });
2461
+ }
2462
+ }
2463
+
2464
+ // ../../Compiler/dist/Parsing/QueryParser.js
2465
+ var header5 = pattern("^query\\s+([A-Za-z_]\\w*)\\s*=>\\s*(observable\\s+)?([\\w.]+(?:\\[\\])?(?:\\?|\\s+optional)?)$");
2466
+ var parameterPattern = pattern("^([a-z_]\\w*)\\s+([\\w.]+(?:\\[\\])?(?:\\?|\\s+optional)?)(?:\\s+from\\s+(.+))?$");
2467
+ var scopePattern = pattern("^scoped\\s+to\\s+([a-z_]\\w*)$");
2468
+ var opaqueDirectives2 = /* @__PURE__ */ new Set(["performer"]);
2469
+ function parseQuery(context, line) {
2470
+ const match = header5.exec(line.content);
2471
+ if (match === null) {
2472
+ context.error(DiagnosticCodes.InvalidQueryDeclaration, `Invalid query declaration '${line.content}' - expected 'query <Name> => [observable] <ReadModel>'`, locationOf(line));
2473
+ context.skipBlock(line.indent);
2474
+ return {
2475
+ kind: "QuerySyntax",
2476
+ name: firstWord2(line.content),
2477
+ returnType: parseTypeRef("", locationOf(line)),
2478
+ by: null,
2479
+ filters: [],
2480
+ description: null,
2481
+ isObservable: false,
2482
+ scope: null,
2483
+ authorize: null,
2484
+ location: locationOf(line)
2485
+ };
2486
+ }
2487
+ const name = match[1];
2488
+ const returnType = parseTypeRef(match[3], { ...locationOf(line), column: line.indent + 1 + match[0].length - match[3].length });
2489
+ if (!(match[2] === void 0 && returnType.name === "observable" && returnType.isOptional && !returnType.isCollection)) {
2490
+ reportLegacyOptionalSuffix(context, returnType, line);
2491
+ }
2492
+ let by = null;
2493
+ const filters = [];
2494
+ let description = null;
2495
+ let scope = null;
2496
+ let authorize = null;
2497
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
2498
+ context.reader.takeSignificant();
2499
+ const keyword = firstWord2(child.content);
2500
+ if (keyword === "description") {
2501
+ description = parseDescription(context, child, description, `Query '${name}'`);
2502
+ } else if (keyword === "by") {
2503
+ const parameter = parseParameter(context, child, "by");
2504
+ if (parameter !== void 0) {
2505
+ if (by !== null) {
2506
+ context.error(DiagnosticCodes.InvalidQueryParameter, `Query '${name}' already declares 'by' - a query can have at most one key parameter`, locationOf(child));
2507
+ }
2508
+ by = parameter;
2509
+ }
2510
+ } else if (keyword === "filter") {
2511
+ const filter = parseParameter(context, child, "filter");
2512
+ if (filter !== void 0) {
2513
+ filters.push(filter);
2514
+ }
2515
+ } else if (keyword === "authorize") {
2516
+ authorize = combineAuthorize(authorize, parseAuthorize(context, child));
2517
+ } else if (keyword === "scoped") {
2518
+ scope = parseScope(context, child, scope, name) ?? scope;
2519
+ } else if (opaqueDirectives2.has(keyword)) {
2520
+ context.skipOpaqueBlock(child.indent);
2521
+ } else {
2522
+ context.error(DiagnosticCodes.UnknownQueryDirective, `Unexpected '${child.content}' in query body - expected description, by, filter, authorize, scoped or performer`, locationOf(child));
2523
+ context.skipBlock(child.indent);
2524
+ }
2525
+ }
2526
+ return {
2527
+ kind: "QuerySyntax",
2528
+ name,
2529
+ returnType,
2530
+ by,
2531
+ filters,
2532
+ description,
2533
+ isObservable: match[2] !== void 0,
2534
+ scope,
2535
+ authorize,
2536
+ location: locationOf(line)
2537
+ };
2538
+ }
2539
+ function parseParameter(context, line, keyword) {
2540
+ const match = parameterPattern.exec(line.content.substring(keyword.length).trim());
2541
+ if (match === null) {
2542
+ context.error(DiagnosticCodes.InvalidQueryParameter, `Invalid '${keyword}' parameter '${line.content}' - expected '${keyword} <name> <Type> [from <source>]'`, locationOf(line));
2543
+ return void 0;
2544
+ }
2545
+ const nameOffset = line.content.indexOf(match[1], keyword.length);
2546
+ const type = parseTypeRef(match[2], { ...locationOf(line), column: line.indent + 1 + line.content.indexOf(match[2], nameOffset + match[1].length) });
2547
+ reportLegacyOptionalSuffix(context, type, line);
2548
+ return { kind: "QueryParameterSyntax", name: match[1], type, location: locationOf(line) };
2549
+ }
2550
+ function parseScope(context, line, existing, queryName) {
2551
+ const match = scopePattern.exec(line.content);
2552
+ if (match === null) {
2553
+ context.error(DiagnosticCodes.InvalidScopeDeclaration, `Invalid scope declaration '${line.content}' - expected 'scoped to <scope>'`, locationOf(line));
2554
+ return void 0;
2555
+ }
2556
+ if (existing !== null) {
2557
+ context.error(DiagnosticCodes.DuplicateScope, `Query '${queryName}' already declares a scope - results are narrowed one way`, locationOf(line));
2558
+ return void 0;
2559
+ }
2560
+ return match[1];
2561
+ }
2562
+
2563
+ // ../../Compiler/dist/Parsing/TriggerDataParser.js
2564
+ var typedValue = pattern("^@?[a-z_]\\w*\\s+[\\w.]+");
2565
+ function parseTriggerData(context, line) {
2566
+ const property = parseProperty(context, line);
2567
+ if (property !== void 0) {
2568
+ context.triggerData.push(property);
2569
+ return;
2570
+ }
2571
+ if (typedValue.test(line.content) && /\?|\boptional\b/.test(line.content)) {
2572
+ context.error(DiagnosticCodes.InvalidTriggerData, `Invalid trigger value '${line.content}' - expected '<name>' or '<name> <Type>'`, locationOf(line));
2573
+ }
2574
+ context.skipOpaqueBlock(line.indent);
2575
+ }
2576
+ function parseTriggerDeclaration(context, header10) {
2577
+ for (let line = context.peekChild(header10.indent); line !== void 0; line = context.peekChild(header10.indent)) {
2578
+ context.reader.takeSignificant();
2579
+ if (firstWord2(line.content) === "description") {
2580
+ parseDescription(context, line, null, `Trigger '${header10.content}'`);
2581
+ } else if (!isFileDirective(line)) {
2582
+ parseTriggerData(context, line);
2583
+ }
2584
+ }
2585
+ }
2586
+
2587
+ // ../../Compiler/dist/Parsing/ReactionParser.js
2588
+ var header6 = pattern("^reaction\\s+([A-Za-z_]\\w*)$");
2589
+ var whenPattern = pattern("^when\\s+([A-Za-z_]\\w*)$");
2590
+ var everyPattern = pattern("^every\\s+(\\d+)\\s+(seconds?|minutes?|hours?|days?)$");
2591
+ var atPattern = pattern("^at\\s+(\\d{2}:\\d{2})(?:\\s+on\\s+(?:(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)|day\\s+(\\d{1,2})))?$");
2592
+ var clauseKeywords2 = /* @__PURE__ */ new Set(["when", "every", "at"]);
2593
+ var invokesPattern = pattern("^invokes\\s+([A-Z]\\w*)$");
2594
+ var optionalReads2 = pattern("^reads\\s+[A-Z]\\w*\\s+optional(?:\\s|$)");
2595
+ function parseReaction(context, line) {
2596
+ const name = header6.exec(line.content)?.[1] ?? "";
2597
+ if (name === "") {
2598
+ context.error(DiagnosticCodes.InvalidReactionDeclaration, `Invalid reaction declaration '${line.content}' - expected 'reaction <Name>'`, locationOf(line));
2599
+ }
2600
+ let description = null;
2601
+ const triggers = [];
2602
+ const sources = /* @__PURE__ */ new Set();
2603
+ let reported = false;
2604
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
2605
+ context.reader.takeSignificant();
2606
+ const keyword = firstWord2(child.content);
2607
+ if (keyword === "description") {
2608
+ description = parseDescription(context, child, description, `Reaction '${name}'`);
2609
+ continue;
2610
+ }
2611
+ if (keyword === "where") {
2612
+ continue;
2613
+ }
2614
+ if (!clauseKeywords2.has(keyword)) {
2615
+ context.error(DiagnosticCodes.InvalidReactionTrigger, `Expected a trigger in reaction body, got '${child.content}' - a reaction is set off by 'when <Name>', 'every <n> <unit>' or 'at <HH:mm>'`, locationOf(child));
2616
+ context.skipBlock(child.indent);
2617
+ reported = true;
2618
+ continue;
2619
+ }
2620
+ const source = parseTriggerSource(context, child);
2621
+ if (source === void 0) {
2622
+ reported = true;
2623
+ continue;
2624
+ }
2625
+ const key = sourceKey(source);
2626
+ if (sources.has(key)) {
2627
+ context.error(DiagnosticCodes.DuplicateReactionTrigger, `Reaction '${name}' already declares '${child.content}' - a second says nothing the first did not`, locationOf(child));
2628
+ context.skipBlock(child.indent);
2629
+ continue;
2630
+ }
2631
+ sources.add(key);
2632
+ triggers.push(parseTrigger(context, child, source));
2633
+ }
2634
+ if (triggers.length === 0 && !reported) {
2635
+ context.error(DiagnosticCodes.ReactionWithoutTrigger, `Reaction '${name}' must declare at least one trigger - nothing sets it off`, locationOf(line));
2636
+ }
2637
+ return { kind: "ReactionSyntax", name, description, triggers, location: locationOf(line) };
2638
+ }
2639
+ function parseTrigger(context, line, source) {
2640
+ let description = null;
2641
+ const produces = [];
2642
+ const invokes = [];
2643
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
2644
+ context.reader.takeSignificant();
2645
+ const keyword = firstWord2(child.content);
2646
+ if (keyword === "description") {
2647
+ description = parseDescription(context, child, description, `Trigger '${child.content}'`);
2648
+ } else if (keyword === "produces") {
2649
+ const produced = parseProduces(context, child);
2650
+ if (produced !== void 0) {
2651
+ produces.push(produced);
2652
+ }
2653
+ } else if (keyword === "invokes") {
2654
+ const match = invokesPattern.exec(child.content);
2655
+ if (match === null) {
2656
+ context.error(DiagnosticCodes.InvalidInvokesDeclaration, `Invalid invokes declaration '${child.content}' - expected 'invokes <Command>'`, locationOf(child));
2657
+ context.skipBlock(child.indent);
2658
+ } else {
2659
+ invokes.push({ kind: "InvokesSyntax", command: match[1], location: locationOf(child) });
2660
+ context.skipOpaqueBlock(child.indent);
2661
+ }
2662
+ } else if (keyword === "reads" || keyword === "file" || child.content === "csharp" || child.content.startsWith("```")) {
2663
+ if (optionalReads2.test(child.content)) {
2664
+ context.error(DiagnosticCodes.OptionalReadsNotSupported, "Optional reads are not yet supported (see #308).", locationOf(child));
2665
+ }
2666
+ if (child.content.startsWith("```")) {
2667
+ context.skipFencedBody();
2668
+ }
2669
+ context.skipOpaqueBlock(child.indent);
2670
+ } else {
2671
+ parseTriggerData(context, child);
2672
+ }
2673
+ }
2674
+ return { kind: "ReactionTriggerSyntax", source, description, produces, invokes, location: locationOf(line) };
2675
+ }
2676
+ function sourceKey(source) {
2677
+ switch (source.kind) {
2678
+ case "NamedTriggerSourceSyntax":
2679
+ return JSON.stringify([source.kind, source.name]);
2680
+ case "IntervalTriggerSourceSyntax":
2681
+ return JSON.stringify([source.kind, source.amount, source.unit]);
2682
+ case "ScheduleTriggerSourceSyntax":
2683
+ return JSON.stringify([source.kind, source.time, source.dayOfWeek, source.dayOfMonth]);
2684
+ }
2685
+ }
2686
+ function parseTriggerSource(context, line) {
2687
+ const location = locationOf(line);
2688
+ switch (firstWord2(line.content)) {
2689
+ case "when": {
2690
+ const match = whenPattern.exec(line.content);
2691
+ if (match === null) {
2692
+ context.error(DiagnosticCodes.InvalidReactionTrigger, `Invalid trigger '${line.content}' - expected 'when <Name>'`, location);
2693
+ context.skipBlock(line.indent);
2694
+ return void 0;
2695
+ }
2696
+ return { kind: "NamedTriggerSourceSyntax", name: match[1], location };
2697
+ }
2698
+ case "every": {
2699
+ const match = everyPattern.exec(line.content);
2700
+ const amount = match === null ? NaN : Number(match[1]);
2701
+ if (match === null || !Number.isInteger(amount) || amount < 1 || amount > 2147483647) {
2702
+ context.error(DiagnosticCodes.InvalidIntervalTrigger, `Invalid interval '${line.content}' - expected 'every <n> <seconds|minutes|hours|days>'`, location);
2703
+ context.skipBlock(line.indent);
2704
+ return void 0;
2705
+ }
2706
+ return { kind: "IntervalTriggerSourceSyntax", amount, unit: unitOf(match[2]), location };
2707
+ }
2708
+ default:
2709
+ return parseSchedule(context, line);
2710
+ }
2711
+ }
2712
+ function parseSchedule(context, line) {
2713
+ const location = locationOf(line);
2714
+ const match = atPattern.exec(line.content);
2715
+ const time = match === null ? void 0 : timeOf(match[1]);
2716
+ if (match === null || time === void 0) {
2717
+ context.error(DiagnosticCodes.InvalidScheduleTrigger, `Invalid schedule '${line.content}' - expected 'at <HH:mm>', optionally followed by 'on <Weekday>' or 'on day <n>'`, location);
2718
+ context.skipBlock(line.indent);
2719
+ return void 0;
2720
+ }
2721
+ if (match[3] !== void 0) {
2722
+ const day = Number(match[3]);
2723
+ if (day < 1 || day > 31) {
2724
+ context.error(DiagnosticCodes.InvalidScheduleTrigger, `Invalid day of month '${day}' in '${line.content}' - a day of the month is between 1 and 31`, location);
2725
+ context.skipBlock(line.indent);
2726
+ return void 0;
2727
+ }
2728
+ return { kind: "ScheduleTriggerSourceSyntax", time, dayOfWeek: null, dayOfMonth: day, location };
2729
+ }
2730
+ return { kind: "ScheduleTriggerSourceSyntax", time, dayOfWeek: match[2] ?? null, dayOfMonth: null, location };
2731
+ }
2732
+ function timeOf(text) {
2733
+ const [hours, minutes] = text.split(":").map(Number);
2734
+ if (!(hours >= 0 && hours <= 23 && minutes >= 0 && minutes <= 59)) {
2735
+ return void 0;
2736
+ }
2737
+ return `${text}:00.0000000`;
2738
+ }
2739
+ function unitOf(text) {
2740
+ switch (text.replace(/s+$/, "")) {
2741
+ case "second":
2742
+ return "Seconds";
2743
+ case "minute":
2744
+ return "Minutes";
2745
+ case "hour":
2746
+ return "Hours";
2747
+ default:
2748
+ return "Days";
2749
+ }
2750
+ }
2751
+
2752
+ // ../../Compiler/dist/Parsing/ScreenParser.js
2753
+ var operand = `(?:"(${stringBodyPattern})"|(\\$strings\\.\\w+(?:\\.\\w+)*))`;
2754
+ var header7 = pattern("^screen\\s+([A-Za-z_]\\w*)$");
2755
+ var data = pattern("^data\\s+([\\w.]+(?:\\[\\])?)\\s+via\\s+query\\s+(\\w+(?:\\.\\w+)*)(?:\\s+by\\s+(\\w+))?$");
2756
+ var action = pattern("^action\\s+([A-Za-z_]\\w*(?:\\.\\w+)*)$");
2757
+ var label = pattern(`^label\\s+${operand}$`);
2758
+ var navigate = pattern("^navigate\\s+to\\s+(\\w+(?:\\.\\w+)*)(?:\\s+by\\s+(\\w+))?$");
2759
+ var slot = pattern("^[a-z_]\\w*$");
2760
+ var title = pattern(`^title\\s+${operand}$`);
2761
+ var column = pattern(`^column\\s+([\\w.]+)(?:\\s+label\\s+${operand})?$`);
2762
+ var rowClick = pattern("^on\\s+row-click\\s+(navigate\\s+to\\s+.+)$");
2763
+ var field = pattern(`^field\\s+([\\w.]+)\\s+label\\s+${operand}$`);
2764
+ var inlineLanguages = /* @__PURE__ */ new Set(["csharp", "typescript", "react", "html", "sql"]);
2765
+ var operandText = (match, quotedGroup) => match[quotedGroup] !== void 0 ? unescapeString(match[quotedGroup]) : match[quotedGroup + 1];
2766
+ var isInteraction = (line) => ["on", "uses"].includes(firstWord2(line.content));
2767
+ var isCodeLine = (line) => line.content.startsWith("```") || inlineLanguages.has(line.content);
2768
+ function parseScreen(context, line) {
2769
+ const match = header7.exec(line.content);
2770
+ if (match === null) {
2771
+ context.error(DiagnosticCodes.InvalidScreenDeclaration, `Invalid screen declaration '${line.content}' - expected 'screen <Name>'`, locationOf(line));
2772
+ }
2773
+ const directives = [];
2774
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
2775
+ context.reader.takeSignificant();
2776
+ if (!isFileDirective(child)) {
2777
+ pushDirective(context, child, directives);
2778
+ }
2779
+ }
2780
+ return { kind: "ScreenSyntax", name: match?.[1] ?? "", directives, location: locationOf(line) };
2781
+ }
2782
+ function pushDirective(context, line, directives) {
2783
+ const directive = parseDirective(context, line);
2784
+ if (directive !== void 0) {
2785
+ directives.push(directive);
2786
+ }
2787
+ }
2788
+ function parseDirectives(context, parent) {
2789
+ const directives = [];
2790
+ for (let child = context.peekChild(parent.indent); child !== void 0; child = context.peekChild(parent.indent)) {
2791
+ context.reader.takeSignificant();
2792
+ pushDirective(context, child, directives);
2793
+ }
2794
+ return directives;
2795
+ }
2796
+ function parseDirective(context, line) {
2797
+ switch (firstWord2(line.content)) {
2798
+ case "data":
2799
+ return parseData(context, line);
2800
+ case "action":
2801
+ return parseAction(context, line);
2802
+ case "template":
2803
+ return parseTemplateReference(context, line);
2804
+ case "section":
2805
+ return parseSection(context, line);
2806
+ case "title":
2807
+ return parseTitle(context, line);
2808
+ case "table":
2809
+ return parseTable(context, line);
2810
+ case "summary":
2811
+ return parseSummary(context, line);
2812
+ case "navigate":
2813
+ return parseNavigate(context, line.content, line);
2814
+ case "on":
2815
+ context.skipOpaqueBlock(line.indent);
2816
+ return { kind: "ScreenBehaviorSyntax", location: locationOf(line) };
2817
+ case "uses":
2818
+ context.skipOpaqueBlock(line.indent);
2819
+ return { kind: "ScreenUsesBehaviorSyntax", location: locationOf(line) };
2820
+ default:
2821
+ if (isCodeLine(line)) {
2822
+ return parseCode(context, line);
2823
+ }
2824
+ context.error(DiagnosticCodes.UnknownScreenDirective, `Unexpected '${line.content}' in screen body`, locationOf(line));
2825
+ context.skipBlock(line.indent);
2826
+ return void 0;
2827
+ }
2828
+ }
2829
+ function parseData(context, line) {
2830
+ const match = data.exec(line.content);
2831
+ if (match === null) {
2832
+ context.error(DiagnosticCodes.InvalidDataDirective, `Invalid data directive '${line.content}' - expected 'data <ReadModel> via query <Query> [by <param>]'`, locationOf(line));
2833
+ return void 0;
2834
+ }
2835
+ return { kind: "ScreenDataSyntax", type: parseTypeRef(match[1], locationOf(line)), query: match[2], by: match[3] ?? null, location: locationOf(line) };
2836
+ }
2837
+ function parseAction(context, line) {
2838
+ const match = action.exec(line.content);
2839
+ if (match === null) {
2840
+ context.error(DiagnosticCodes.InvalidActionDirective, `Invalid action directive '${line.content}' - expected 'action <Command>'`, locationOf(line));
2841
+ context.skipBlock(line.indent);
2842
+ return void 0;
2843
+ }
2844
+ let text = null;
2845
+ let target = null;
2846
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
2847
+ context.reader.takeSignificant();
2848
+ const labelMatch = label.exec(child.content);
2849
+ if (labelMatch !== null) {
2850
+ text = operandText(labelMatch, 1);
2851
+ } else if (firstWord2(child.content) === "navigate") {
2852
+ target = parseNavigate(context, child.content, child) ?? null;
2853
+ } else {
2854
+ context.error(DiagnosticCodes.UnknownActionDirective, `Unexpected '${child.content}' in action - expected 'label "..."' or 'navigate to ...'`, locationOf(child));
2855
+ }
2856
+ }
2857
+ return { kind: "ScreenActionSyntax", command: match[1], label: text, navigate: target, location: locationOf(line) };
2858
+ }
2859
+ function parseNavigate(context, text, line) {
2860
+ const match = navigate.exec(text);
2861
+ if (match === null) {
2862
+ context.error(DiagnosticCodes.InvalidNavigation, `Invalid navigation '${text}' - expected 'navigate to <Screen> [by <param>]'`, locationOf(line));
2863
+ return void 0;
2864
+ }
2865
+ return { kind: "ScreenNavigateSyntax", screen: match[1], by: match[2] ?? null, location: locationOf(line) };
2866
+ }
2867
+ function parseTemplateReference(context, line) {
2868
+ const name = line.content.substring("template".length).trim();
2869
+ const slots = [];
2870
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
2871
+ context.reader.takeSignificant();
2872
+ if (!slot.test(child.content)) {
2873
+ context.error(DiagnosticCodes.InvalidScreenLayoutSlot, `Expected a slot name in template '${name}', got '${child.content}'`, locationOf(child));
2874
+ context.skipBlock(child.indent);
2875
+ continue;
2876
+ }
2877
+ slots.push({ kind: "ScreenSlotSyntax", name: child.content, directives: parseDirectives(context, child), location: locationOf(child) });
2878
+ }
2879
+ return { kind: "ScreenTemplateReferenceSyntax", name, slots, location: locationOf(line) };
2880
+ }
2881
+ function parseSection(context, line) {
2882
+ const name = line.content.substring("section".length).trim();
2883
+ return { kind: "ScreenSectionSyntax", name, directives: parseDirectives(context, line), location: locationOf(line) };
2884
+ }
2885
+ function parseTitle(context, line) {
2886
+ const match = title.exec(line.content);
2887
+ if (match === null) {
2888
+ context.error(DiagnosticCodes.InvalidTitleDirective, `Invalid title directive '${line.content}' - expected 'title "..."'`, locationOf(line));
2889
+ return { kind: "ScreenTitleSyntax", text: "", location: locationOf(line) };
2890
+ }
2891
+ return { kind: "ScreenTitleSyntax", text: operandText(match, 1), location: locationOf(line) };
2892
+ }
2893
+ function parseTable(context, line) {
2894
+ const target = line.content.substring("table".length).trim();
2895
+ const columns = [];
2896
+ let click = null;
2897
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
2898
+ context.reader.takeSignificant();
2899
+ const columnMatch = column.exec(child.content);
2900
+ const clickMatch = rowClick.exec(child.content);
2901
+ if (columnMatch !== null) {
2902
+ const labelled = columnMatch[2] !== void 0 || columnMatch[3] !== void 0;
2903
+ columns.push({ kind: "ScreenColumnSyntax", property: columnMatch[1], label: labelled ? operandText(columnMatch, 2) : null, location: locationOf(child) });
2904
+ } else if (clickMatch !== null) {
2905
+ click = parseNavigate(context, clickMatch[1], child) ?? null;
2906
+ } else if (isInteraction(child)) {
2907
+ context.skipOpaqueBlock(child.indent);
2908
+ } else {
2909
+ context.error(DiagnosticCodes.UnknownTableDirective, `Unexpected '${child.content}' in table - expected 'column ...', 'on row-click navigate to ...', 'on <trigger>' or 'uses <Behavior>'`, locationOf(child));
2910
+ }
2911
+ }
2912
+ return { kind: "ScreenTableSyntax", target, columns, rowClick: click, location: locationOf(line) };
2913
+ }
2914
+ function parseSummary(context, line) {
2915
+ const target = line.content.substring("summary".length).trim();
2916
+ const fields = [];
2917
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
2918
+ context.reader.takeSignificant();
2919
+ const match = field.exec(child.content);
2920
+ if (match === null) {
2921
+ context.error(DiagnosticCodes.UnknownSummaryDirective, `Unexpected '${child.content}' in summary - expected 'field <property> label "..."'`, locationOf(child));
2922
+ continue;
2923
+ }
2924
+ fields.push({ kind: "ScreenFieldSyntax", property: match[1], label: operandText(match, 2), location: locationOf(child) });
2925
+ }
2926
+ return { kind: "ScreenSummarySyntax", target, fields, location: locationOf(line) };
2927
+ }
2928
+ function parseCode(context, line) {
2929
+ const language = line.content.startsWith("```") ? line.content.substring(3) : line.content;
2930
+ if (!inlineLanguages.has(language)) {
2931
+ context.error(DiagnosticCodes.ExpectedCodeFence, `Expected a registered language on the opening fence, not '${line.content}'`, locationOf(line));
2932
+ return void 0;
2933
+ }
2934
+ if (!line.content.startsWith("```")) {
2935
+ context.warning(DiagnosticCodes.LegacyInlineCodeFence, `'${language}' on its own line is deprecated - use '\`\`\`${language}' instead`, locationOf(line));
2936
+ }
2937
+ const code = parseFencedText(context, language, line);
2938
+ return code === null ? void 0 : {
2939
+ kind: "ScreenCodeSyntax",
2940
+ code: { kind: "CodeBlockSyntax", language, code, location: locationOf(line) },
2941
+ location: locationOf(line)
2942
+ };
2943
+ }
2944
+
2945
+ // ../../Compiler/dist/Parsing/SpecificationParser.js
2946
+ var header8 = pattern("^specification\\s+([A-Za-z_]\\w*)$");
2947
+ var givenPattern = pattern("^given\\s+([A-Z]\\w*)$");
2948
+ var whenAppendPattern = pattern("^when\\s+append\\s+([A-Z]\\w*)$");
2949
+ var whenPattern2 = pattern("^when\\s+([A-Z]\\w*)$");
2950
+ var thenEventPattern = pattern("^then\\s+([A-Z]\\w*)$");
2951
+ var thenQueryPrefix = pattern("^then\\s+query\\b");
2952
+ var readModelPrefix = pattern("^(?:given|then)\\s+readmodel\\b");
2953
+ var givenReadModelPattern = pattern("^given\\s+readmodel\\s+([A-Z]\\w*)$");
2954
+ var thenReadModelPattern = pattern("^then\\s+readmodel\\s+([A-Z]\\w*)(\\s+exactly)?$");
2955
+ var thenNoPrefix = pattern("^then\\s+no\\b");
2956
+ var thenErrorPattern = pattern(`^then\\s+error\\s+"(${stringBodyPattern})"$`);
2957
+ var mappingPattern2 = pattern("^([\\w.]+)\\s*=(?!=|>)\\s*(.+)$");
2958
+ var givenClockPrefix = pattern("^given\\s+clock\\b");
2959
+ var givenCapturePrefix = pattern("^given\\s+capture\\b");
2960
+ var whenClockPrefix = pattern("^when\\s+clock\\b");
2961
+ var whenTriggerPrefix = pattern("^when\\s+trigger\\b");
2962
+ var whenCapturePrefix = pattern("^when\\s+capture\\b");
2963
+ var whenQueryPrefix = pattern("^when\\s+query\\b");
2964
+ var thenResultPrefix = pattern("^then\\s+result\\b");
2965
+ var noResultPrefix = pattern("^then\\s+no\\s+result\\b");
2966
+ var clockPattern = pattern('^(given|when)\\s+clock\\s+"(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d+)?)?(?:Z|[+-]\\d{2}:\\d{2}))"$');
2967
+ var whenTriggerPattern = pattern("^when\\s+trigger\\s+([A-Za-z_]\\w*)$");
2968
+ var capturePattern = pattern("^(?:given|when)\\s+capture\\s+([A-Za-z_]\\w*)$");
2969
+ var whenQueryPattern = pattern("^when\\s+query\\s+([A-Za-z_]\\w*(?:\\.\\w+)*)$");
2970
+ var thenResultPattern = pattern("^then\\s+result(\\s+exactly)?$");
2971
+ function parseSpecification(context, line) {
2972
+ const name = header8.exec(line.content)?.[1] ?? "";
2973
+ if (name === "") {
2974
+ context.error(DiagnosticCodes.InvalidSpecificationDeclaration, `Invalid specification declaration '${line.content}' - expected 'specification <Name>'`, locationOf(line));
2975
+ }
2976
+ const body = {
2977
+ given: [],
2978
+ givenReadModels: [],
2979
+ when: null,
2980
+ whenAppended: null,
2981
+ whenDeclared: false,
2982
+ thenEvents: [],
2983
+ thenEventsInAnyOrder: false,
2984
+ thenReadModels: [],
2985
+ thenErrors: [],
2986
+ givenClock: null,
2987
+ givenCaptures: [],
2988
+ whenClock: null,
2989
+ whenTrigger: null,
2990
+ whenCapture: null,
2991
+ whenQuery: null,
2992
+ thenResults: [],
2993
+ thenNoResult: null
2994
+ };
2995
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
2996
+ context.reader.takeSignificant();
2997
+ if (isFileDirective(child)) {
2998
+ continue;
2999
+ }
3000
+ const keyword = thenNoPrefix.test(child.content) ? "then" : firstWord2(child.content);
3001
+ if (keyword === "given") {
3002
+ parseGiven(context, child, body);
3003
+ } else if (keyword === "when") {
3004
+ parseWhen(context, child, body, name);
3005
+ } else if (keyword === "then") {
3006
+ parseThen(context, child, body);
3007
+ } else {
3008
+ context.error(DiagnosticCodes.UnknownSpecificationDirective, `Unexpected '${firstWord2(child.content)}' in specification body`, locationOf(child));
3009
+ context.skipBlock(child.indent);
3010
+ }
3011
+ }
3012
+ const { whenDeclared: _, ...members } = body;
3013
+ return { kind: "SpecificationSyntax", name, ...members, location: locationOf(line) };
3014
+ }
3015
+ function parseGiven(context, line, body) {
3016
+ if (givenClockPrefix.test(line.content)) {
3017
+ if (body.givenClock !== null) {
3018
+ context.error(DiagnosticCodes.InvalidSpecificationClock, "A specification states its clock at most once.", locationOf(line));
3019
+ context.skipBlock(line.indent);
3020
+ } else {
3021
+ body.givenClock = parseClock(context, line, "given");
3022
+ }
3023
+ } else if (givenCapturePrefix.test(line.content)) {
3024
+ const capture = parseCapture2(context, line, "given");
3025
+ if (capture !== null) {
3026
+ body.givenCaptures.push(capture);
3027
+ }
3028
+ } else if (line.content.startsWith("given caller")) {
3029
+ context.skipOpaqueBlock(line.indent);
3030
+ } else if (readModelPrefix.test(line.content)) {
3031
+ const readModel = parseReadModelStep(context, line, givenReadModelPattern, "given");
3032
+ if (readModel !== void 0) {
3033
+ body.givenReadModels.push(readModel);
3034
+ }
3035
+ } else {
3036
+ const event = parseEventStep(context, line, givenPattern, "given");
3037
+ if (event !== void 0) {
3038
+ body.given.push(event);
3039
+ }
3040
+ }
3041
+ }
3042
+ function parseWhen(context, line, body, name) {
3043
+ const appends = line.content.startsWith("when append");
3044
+ if (body.whenDeclared) {
3045
+ const code = body.whenAppended !== null || appends ? DiagnosticCodes.ConflictingSpecificationActions : DiagnosticCodes.DuplicateSpecificationWhen;
3046
+ context.error(code, `Specification '${name}' already declares a 'when' - a specification can have at most one`, locationOf(line));
3047
+ context.skipBlock(line.indent);
3048
+ return;
3049
+ }
3050
+ body.whenDeclared = true;
3051
+ if (appends) {
3052
+ body.whenAppended = parseEventStep(context, line, whenAppendPattern, "when append") ?? null;
3053
+ return;
3054
+ }
3055
+ if (whenClockPrefix.test(line.content)) {
3056
+ body.whenClock = parseClock(context, line, "when");
3057
+ return;
3058
+ }
3059
+ if (whenTriggerPrefix.test(line.content)) {
3060
+ body.whenTrigger = parseNamedStep(context, line, whenTriggerPattern, DiagnosticCodes.InvalidSpecificationTrigger, "when trigger", "when trigger <Trigger>", (trigger, values2) => ({ kind: "SpecificationTriggerSyntax", trigger, values: values2, location: locationOf(line) }));
3061
+ return;
3062
+ }
3063
+ if (whenCapturePrefix.test(line.content)) {
3064
+ body.whenCapture = parseCapture2(context, line, "when");
3065
+ return;
3066
+ }
3067
+ if (whenQueryPrefix.test(line.content)) {
3068
+ body.whenQuery = parseNamedStep(context, line, whenQueryPattern, DiagnosticCodes.InvalidSpecificationQueryAction, "when query", "when query <Query>", (query, values2) => ({ kind: "SpecificationWhenQuerySyntax", query, arguments: values2, location: locationOf(line) }));
3069
+ return;
3070
+ }
3071
+ const match = whenPattern2.exec(line.content);
3072
+ if (match === null) {
3073
+ context.error(DiagnosticCodes.InvalidSpecificationWhen, `Invalid 'when' declaration '${line.content}' - expected 'when <CommandType>' or 'when append <EventType>'`, locationOf(line));
3074
+ context.skipBlock(line.indent);
3075
+ return;
3076
+ }
3077
+ const values = parseValuesWithEventSource(context, line);
3078
+ body.when = { kind: "SpecificationCommandSyntax", commandType: match[1], ...values, location: locationOf(line) };
3079
+ }
3080
+ function parseThen(context, line, body) {
3081
+ if (line.content.startsWith("then events")) {
3082
+ if (line.content !== "then events in any order" || body.thenEventsInAnyOrder) {
3083
+ context.error(DiagnosticCodes.InvalidSpecificationEventOrder, "Expected one 'then events in any order' directive.", locationOf(line));
3084
+ } else {
3085
+ body.thenEventsInAnyOrder = true;
3086
+ }
3087
+ context.skipBlock(line.indent);
3088
+ return;
3089
+ }
3090
+ if (thenResultPrefix.test(line.content)) {
3091
+ parseResult(context, line, body);
3092
+ return;
3093
+ }
3094
+ if (noResultPrefix.test(line.content)) {
3095
+ if (line.content !== "then no result" || body.thenNoResult !== null) {
3096
+ context.error(DiagnosticCodes.InvalidSpecificationQueryAction, "Expected one 'then no result' directive.", locationOf(line));
3097
+ } else {
3098
+ body.thenNoResult = { kind: "SpecificationNoResultSyntax", location: locationOf(line) };
3099
+ }
3100
+ context.skipBlock(line.indent);
3101
+ return;
3102
+ }
3103
+ if (line.content.startsWith("then denied")) {
3104
+ if (line.content !== "then denied") {
3105
+ context.error(DiagnosticCodes.InvalidSpecificationDenied, "Expected exactly 'then denied'.", locationOf(line));
3106
+ context.skipBlock(line.indent);
3107
+ }
3108
+ return;
3109
+ }
3110
+ if (line.content === "then error") {
3111
+ body.thenErrors.push({ kind: "SpecificationErrorSyntax", name: null, location: locationOf(line) });
3112
+ return;
3113
+ }
3114
+ const error = thenErrorPattern.exec(line.content);
3115
+ if (error !== null) {
3116
+ body.thenErrors.push({ kind: "SpecificationErrorSyntax", name: unescapeString(error[1]), location: locationOf(line) });
3117
+ return;
3118
+ }
3119
+ if (firstWord2(line.content.substring("then".length).trim()) === "error") {
3120
+ context.error(DiagnosticCodes.InvalidThenError, `Invalid 'then error' declaration '${line.content}' - expected 'then error' or 'then error "<reason>"'`, locationOf(line));
3121
+ context.skipBlock(line.indent);
3122
+ return;
3123
+ }
3124
+ if (thenNoPrefix.test(line.content) || thenQueryPrefix.test(line.content)) {
3125
+ context.skipOpaqueBlock(line.indent);
3126
+ return;
3127
+ }
3128
+ if (readModelPrefix.test(line.content)) {
3129
+ const readModel = parseReadModelStep(context, line, thenReadModelPattern, "then");
3130
+ if (readModel !== void 0) {
3131
+ body.thenReadModels.push(readModel);
3132
+ }
3133
+ return;
3134
+ }
3135
+ const event = parseEventStep(context, line, thenEventPattern, "then");
3136
+ if (event !== void 0) {
3137
+ body.thenEvents.push(event);
3138
+ }
3139
+ }
3140
+ function parseClock(context, line, keyword) {
3141
+ const match = clockPattern.exec(line.content);
3142
+ context.skipBlock(line.indent);
3143
+ if (match === null || match[1] !== keyword) {
3144
+ context.error(DiagnosticCodes.InvalidSpecificationClock, `Invalid '${keyword} clock' - expected '${keyword} clock "<ISO 8601 instant>"', such as '${keyword} clock "2026-10-05T08:00:00Z"'`, locationOf(line));
3145
+ return null;
3146
+ }
3147
+ return { kind: "SpecificationClockSyntax", instant: match[2], location: locationOf(line) };
3148
+ }
3149
+ function parseCapture2(context, line, keyword) {
3150
+ return parseNamedStep(context, line, capturePattern, DiagnosticCodes.InvalidSpecificationCapture, `${keyword} capture`, `${keyword} capture <Capture>`, (capture, record) => ({ kind: "SpecificationCaptureSyntax", capture, record, location: locationOf(line) }));
3151
+ }
3152
+ function parseNamedStep(context, line, regex, code, keyword, expected, create) {
3153
+ const match = regex.exec(line.content);
3154
+ if (match === null) {
3155
+ context.error(code, `Invalid '${keyword}' declaration '${line.content}' - expected '${expected}'`, locationOf(line));
3156
+ context.skipBlock(line.indent);
3157
+ return null;
3158
+ }
3159
+ return create(match[1], parseValues(context, line));
3160
+ }
3161
+ function parseResult(context, line, body) {
3162
+ const match = thenResultPattern.exec(line.content);
3163
+ if (match === null) {
3164
+ context.error(DiagnosticCodes.InvalidSpecificationQueryAction, `Invalid 'then result' declaration '${line.content}' - expected 'then result [exactly]'`, locationOf(line));
3165
+ context.skipBlock(line.indent);
3166
+ return;
3167
+ }
3168
+ body.thenResults.push({ kind: "SpecificationQueryResultSyntax", properties: parseValues(context, line), exactly: match[1] !== void 0, location: locationOf(line) });
3169
+ }
3170
+ function parseReadModelStep(context, line, regex, keyword) {
3171
+ const match = regex.exec(line.content);
3172
+ if (match === null) {
3173
+ context.error(DiagnosticCodes.InvalidReadModelStep, `Invalid '${keyword} readmodel' declaration '${line.content}' - expected '${keyword} readmodel <ReadModelType>'`, locationOf(line));
3174
+ context.skipBlock(line.indent);
3175
+ return void 0;
3176
+ }
3177
+ return {
3178
+ kind: "SpecificationReadModelSyntax",
3179
+ name: match[1],
3180
+ properties: parseValues(context, line),
3181
+ exactly: keyword === "then" && match[2] !== void 0,
3182
+ location: locationOf(line)
3183
+ };
3184
+ }
3185
+ function parseEventStep(context, line, regex, keyword) {
3186
+ const match = regex.exec(line.content);
3187
+ if (match === null) {
3188
+ context.error(DiagnosticCodes.InvalidEventStep, `Invalid '${keyword}' declaration '${line.content}' - expected '${keyword} <EventType>'`, locationOf(line));
3189
+ context.skipBlock(line.indent);
3190
+ return void 0;
3191
+ }
3192
+ return { kind: "SpecificationEventSyntax", eventType: match[1], ...parseValuesWithEventSource(context, line), location: locationOf(line) };
3193
+ }
3194
+ function parseValuesWithEventSource(context, parent) {
3195
+ const values = [];
3196
+ let eventSource = null;
3197
+ for (let child = context.peekChild(parent.indent); child !== void 0; child = context.peekChild(parent.indent)) {
3198
+ context.reader.takeSignificant();
3199
+ const mapping = mappingPattern2.exec(child.content);
3200
+ if (mapping !== null) {
3201
+ values.push(mappingOf(context, child, mapping));
3202
+ } else if (firstWord2(child.content) === "for") {
3203
+ const source = child.content.substring("for".length).trim();
3204
+ if (source.length === 0) {
3205
+ context.error(DiagnosticCodes.InvalidSpecificationEventSource, "Invalid event-source assertion 'for' - expected 'for <value>'", locationOf(child));
3206
+ } else if (eventSource !== null) {
3207
+ context.error(DiagnosticCodes.DuplicateSpecificationEventSource, "A specification step can declare its event-source assertion only once", locationOf(child));
3208
+ } else {
3209
+ eventSource = parseMappingSource(source, locationOf(child), context);
3210
+ }
3211
+ } else {
3212
+ context.error(DiagnosticCodes.InvalidSpecificationValue, `Invalid property mapping '${child.content}' - expected '<property> = <value>'`, locationOf(child));
3213
+ }
3214
+ }
3215
+ return { values, for: eventSource };
3216
+ }
3217
+ function parseValues(context, parent) {
3218
+ const values = [];
3219
+ for (let child = context.peekChild(parent.indent); child !== void 0; child = context.peekChild(parent.indent)) {
3220
+ context.reader.takeSignificant();
3221
+ const mapping = mappingPattern2.exec(child.content);
3222
+ if (mapping === null) {
3223
+ context.error(DiagnosticCodes.InvalidSpecificationValue, `Invalid property mapping '${child.content}' - expected '<property> = <value>'`, locationOf(child));
3224
+ continue;
3225
+ }
3226
+ values.push(mappingOf(context, child, mapping));
3227
+ }
3228
+ return values;
3229
+ }
3230
+ function mappingOf(context, line, match) {
3231
+ return { kind: "PropertyMappingSyntax", property: match[1], source: parseMappingSource(match[2], locationOf(line), context), location: locationOf(line) };
3232
+ }
3233
+
3234
+ // ../../Compiler/dist/Parsing/SliceParser.js
3235
+ var header9 = pattern("^slice\\s+([A-Za-z]\\w*)\\s+([A-Za-z_]\\w*)$");
3236
+ var opaqueMembers = /* @__PURE__ */ new Set(["reducer"]);
3237
+ function parseSlice(context, line) {
3238
+ const match = header9.exec(line.content);
3239
+ let type = "StateChange";
3240
+ let name = "";
3241
+ if (match === null) {
3242
+ context.error(DiagnosticCodes.InvalidSliceDeclaration, `Invalid slice declaration '${line.content}' - expected 'slice <Type> <Name>'`, locationOf(line));
3243
+ } else {
3244
+ name = match[2];
3245
+ if (sliceTypes2.includes(match[1])) {
3246
+ type = match[1];
3247
+ } else {
3248
+ context.error(DiagnosticCodes.UnknownSliceType, `Unknown slice type '${match[1]}' - expected StateChange, StateView, Automation or Translate`, locationOf(line));
3249
+ }
3250
+ }
3251
+ let description = null;
3252
+ const events = [];
3253
+ const commands = [];
3254
+ const queries = [];
3255
+ const projections = [];
3256
+ const reactions = [];
3257
+ const captures = [];
3258
+ const constraints = [];
3259
+ const specifications = [];
3260
+ const readModels = [];
3261
+ const screens = [];
3262
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
3263
+ context.reader.takeSignificant();
3264
+ if (isFileDirective(child)) {
3265
+ continue;
3266
+ }
3267
+ const keyword = firstWord2(child.content);
3268
+ if (keyword === "description") {
3269
+ description = parseDescription(context, child, description, `Slice '${name}'`);
3270
+ } else if (keyword === "event") {
3271
+ events.push(parseEvent(context, child));
3272
+ } else if (keyword === "command") {
3273
+ commands.push(parseCommand(context, child));
3274
+ } else if (keyword === "query") {
3275
+ queries.push(parseQuery(context, child));
3276
+ } else if (keyword === "projection") {
3277
+ projections.push(parseProjection(context, child));
3278
+ } else if (keyword === "capture") {
3279
+ captures.push(parseCapture(context, child));
3280
+ } else if (keyword === "reaction") {
3281
+ reactions.push(parseReaction(context, child));
3282
+ } else if (keyword === "constraint") {
3283
+ constraints.push(parseConstraint(context, child));
3284
+ } else if (keyword === "specification") {
3285
+ specifications.push(parseSpecification(context, child));
3286
+ } else if (keyword === "readmodel") {
3287
+ readModels.push(parseReadModel(context, child));
3288
+ } else if (keyword === "screen") {
3289
+ screens.push(parseScreen(context, child));
3290
+ } else if (opaqueMembers.has(keyword)) {
3291
+ context.skipOpaqueBlock(child.indent);
3292
+ } else {
3293
+ context.warning(DiagnosticCodes.UnknownSliceDirective, `Unknown construct '${keyword}' in slice '${name}'`, locationOf(child));
3294
+ context.skipBlock(child.indent);
3295
+ }
3296
+ }
3297
+ return {
3298
+ kind: "SliceSyntax",
3299
+ type,
3300
+ name,
3301
+ description,
3302
+ events,
3303
+ commands,
3304
+ queries,
3305
+ projections,
3306
+ captures,
3307
+ reactions,
3308
+ constraints,
3309
+ specifications,
3310
+ readModels,
3311
+ screens,
3312
+ location: locationOf(line)
3313
+ };
3314
+ }
3315
+
3316
+ // ../../Compiler/dist/Parsing/FeatureBody.js
3317
+ var featurePattern = pattern("^feature\\s+([A-Za-z_]\\w*)$");
3318
+ var opaqueFeatureMembers = /* @__PURE__ */ new Set(["on", "uses", "contribute"]);
3319
+ var featureBodyExpected = "description, authorize, import, feature, slice, contribute, 'on <trigger>' or 'uses <Behavior>'";
3320
+ var FeatureBody = class {
3321
+ name;
3322
+ #features = [];
3323
+ #slices = [];
3324
+ #fileImports = [];
3325
+ #description = null;
3326
+ #authorize = null;
3327
+ constructor(name) {
3328
+ this.name = name;
3329
+ }
3330
+ // Parses one already consumed line of the body; false when the line does not belong to a feature body,
3331
+ // and nothing was reported.
3332
+ tryParse(context, line) {
3333
+ const keyword = firstWord2(line.content);
3334
+ switch (keyword) {
3335
+ case "description":
3336
+ this.#description = parseDescription(context, line, this.#description, `Feature '${this.name}'`);
3337
+ return true;
3338
+ case "authorize":
3339
+ this.#authorize = combineAuthorize(this.#authorize, parseAuthorize(context, line));
3340
+ return true;
3341
+ case "import":
3342
+ parseFileImport(context, line, this.#fileImports);
3343
+ return true;
3344
+ case "feature":
3345
+ this.#features.push(parseFeature(context, line));
3346
+ return true;
3347
+ case "slice":
3348
+ this.#slices.push(parseSlice(context, line));
3349
+ return true;
3350
+ default:
3351
+ if (opaqueFeatureMembers.has(keyword)) {
3352
+ context.skipOpaqueBlock(line.indent);
3353
+ return true;
3354
+ }
3355
+ return false;
3356
+ }
3357
+ }
3358
+ // Builds the feature, located at its header or, when it only places an imported file, at that file.
3359
+ build(location, isPlacement = false) {
3360
+ return {
3361
+ kind: "FeatureSyntax",
3362
+ name: this.name,
3363
+ description: this.#description,
3364
+ authorize: this.#authorize,
3365
+ features: this.#features,
3366
+ slices: this.#slices,
3367
+ fileImports: this.#fileImports,
3368
+ isPlacement,
3369
+ location
3370
+ };
3371
+ }
3372
+ };
3373
+ function parseFeature(context, line) {
3374
+ const name = featurePattern.exec(line.content)?.[1] ?? "";
3375
+ if (name === "") {
3376
+ context.error(DiagnosticCodes.InvalidFeatureDeclaration, `Invalid feature declaration '${line.content}' - expected 'feature <Name>'`, locationOf(line));
3377
+ }
3378
+ const body = new FeatureBody(name);
3379
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
3380
+ context.reader.takeSignificant();
3381
+ if (!body.tryParse(context, child)) {
3382
+ context.error(DiagnosticCodes.UnknownFeatureDirective, `Unexpected '${firstWord2(child.content)}' in feature body - expected ${featureBodyExpected}`, locationOf(child));
3383
+ context.skipBlock(child.indent);
3384
+ }
3385
+ }
3386
+ return body.build(locationOf(line));
3387
+ }
3388
+
3389
+ // ../../Compiler/dist/Parsing/ModuleBody.js
3390
+ var modulePattern = pattern("^module\\s+([A-Za-z_]\\w*)$");
3391
+ var opaqueModuleMembers = /* @__PURE__ */ new Set(["on", "uses", "screen", "dialog", "form", "contribute"]);
3392
+ var moduleBodyExpected = "description, authorize, import, screen template, dialog template, form, contribute, feature, 'on <trigger>' or 'uses <Behavior>'";
3393
+ var ModuleBody = class {
3394
+ name;
3395
+ #features = [];
3396
+ #fileImports = [];
3397
+ #description = null;
3398
+ #authorize = null;
3399
+ constructor(name) {
3400
+ this.name = name;
3401
+ }
3402
+ // Parses one already consumed line of the body; false when the line does not belong to a module body,
3403
+ // and nothing was reported.
3404
+ tryParse(context, line) {
3405
+ const keyword = firstWord2(line.content);
3406
+ switch (keyword) {
3407
+ case "description":
3408
+ this.#description = parseDescription(context, line, this.#description, `Module '${this.name}'`);
3409
+ return true;
3410
+ case "authorize":
3411
+ this.#authorize = combineAuthorize(this.#authorize, parseAuthorize(context, line));
3412
+ return true;
3413
+ case "import":
3414
+ parseFileImport(context, line, this.#fileImports);
3415
+ return true;
3416
+ case "feature":
3417
+ this.#features.push(parseFeature(context, line));
3418
+ return true;
3419
+ default:
3420
+ if (opaqueModuleMembers.has(keyword)) {
3421
+ context.skipOpaqueBlock(line.indent);
3422
+ return true;
3423
+ }
3424
+ return false;
3425
+ }
3426
+ }
3427
+ // Parses the children of a header line into this body, reporting what does not belong in a module.
3428
+ parseChildren(context, line) {
3429
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
3430
+ context.reader.takeSignificant();
3431
+ if (!this.tryParse(context, child)) {
3432
+ context.error(DiagnosticCodes.UnknownModuleDirective, `Unexpected '${firstWord2(child.content)}' in module body - expected ${moduleBodyExpected}`, locationOf(child));
3433
+ context.skipBlock(child.indent);
3434
+ }
3435
+ }
3436
+ }
3437
+ // Builds the module, located at its header or, when it only places an imported file, at that file.
3438
+ build(location, isPlacement = false) {
3439
+ return {
3440
+ kind: "ModuleSyntax",
3441
+ name: this.name,
3442
+ description: this.#description,
3443
+ authorize: this.#authorize,
3444
+ features: this.#features,
3445
+ fileImports: this.#fileImports,
3446
+ isPlacement,
3447
+ location
3448
+ };
3449
+ }
3450
+ };
3451
+ function parseModule(context, line) {
3452
+ const name = modulePattern.exec(line.content)?.[1] ?? "";
3453
+ if (name === "") {
3454
+ context.error(DiagnosticCodes.InvalidModuleDeclaration, `Invalid module declaration '${line.content}' - expected 'module <Name>'`, locationOf(line));
3455
+ }
3456
+ const body = new ModuleBody(name);
3457
+ body.parseChildren(context, line);
3458
+ return body.build(locationOf(line));
3459
+ }
3460
+
3461
+ // ../../Compiler/dist/Parsing/LineReader.js
3462
+ var LineReader = class {
3463
+ lines;
3464
+ #index = 0;
3465
+ constructor(lines) {
3466
+ this.lines = lines;
3467
+ }
3468
+ peekSignificant() {
3469
+ while (this.#index < this.lines.length && isBlank(this.lines[this.#index])) {
3470
+ this.#index++;
3471
+ }
3472
+ return this.#index < this.lines.length ? this.lines[this.#index] : void 0;
3473
+ }
3474
+ takeSignificant() {
3475
+ const line = this.peekSignificant();
3476
+ if (line === void 0) {
3477
+ throw new Error("There is no significant line left to take");
3478
+ }
3479
+ this.#index++;
3480
+ return line;
3481
+ }
3482
+ takeRaw() {
3483
+ return this.#index < this.lines.length ? this.lines[this.#index++] : void 0;
3484
+ }
3485
+ };
3486
+
3487
+ // ../../Compiler/dist/Syntax/EventDeclarations.js
3488
+ function eventDeclarations(slice) {
3489
+ return [...slice.events, ...slice.commands.flatMap((command) => command.produces).flatMap((produced) => produced.inlineEvent === null ? [] : [produced.inlineEvent])];
3490
+ }
3491
+
3492
+ // ../../Compiler/dist/Syntax/ProductionDestinations.js
3493
+ function requiresExplicitDestinations(command) {
3494
+ const identifier = command.properties.find((property) => property.isIdentifier)?.name;
3495
+ return command.produces.some((produced) => produced.for !== null && (produced.for.kind !== "PathExpressionSyntax" || produced.for.path !== identifier)) || command.produces.some((produced) => produced.inlineEvent !== null && produced.for === null) && command.produces.some((produced) => produced.inlineEvent === null && produced.for === null);
3496
+ }
3497
+
3498
+ // ../../Compiler/dist/Parsing/InlineEventValidator.js
3499
+ function validateInlineEvents(application, context) {
3500
+ const slices = [];
3501
+ const inFeature = (feature) => {
3502
+ slices.push(...feature.slices);
3503
+ feature.features.forEach(inFeature);
3504
+ };
3505
+ application.modules.forEach((module) => module.features.forEach(inFeature));
3506
+ const eventCounts = /* @__PURE__ */ new Map();
3507
+ for (const event of slices.flatMap(eventDeclarations))
3508
+ eventCounts.set(event.name, (eventCounts.get(event.name) ?? 0) + 1);
3509
+ const importedNames = new Set(application.imports.map((value) => value.qualifiedName.split(".").at(-1)));
3510
+ for (const command of slices.flatMap((slice) => slice.commands)) {
3511
+ const identifier = command.properties.find((property) => property.isIdentifier)?.name;
3512
+ const mixed = requiresExplicitDestinations(command);
3513
+ for (const production of command.produces) {
3514
+ const inline = production.inlineEvent;
3515
+ if (inline !== null && ((eventCounts.get(inline.name) ?? 0) > 1 || importedNames.has(inline.name))) {
3516
+ context.error(DiagnosticCodes.InlineEventCollision, `Inline event '${inline.name}' collides with another event declaration or import`, production.location);
3517
+ }
3518
+ if (mixed && production.for === null) {
3519
+ context.error(DiagnosticCodes.ExplicitProducesTargetsRequired, `Production '${production.event}' in command '${command.name}' must state 'for' explicitly - every production must state 'for' when destinations differ`, production.location);
3520
+ }
3521
+ const destination = production.for?.kind === "PathExpressionSyntax" ? production.for.path : production.for === null && inline !== null ? identifier : void 0;
3522
+ if (identifier === void 0 || destination !== identifier)
3523
+ continue;
3524
+ for (const mapping of production.mappings.filter((mapping2) => mapping2.source.kind === "PathExpressionSyntax" && mapping2.source.path === identifier)) {
3525
+ const message = `Event '${production.event}' copies command identifier '${identifier}' into payload property '${mapping.property}' although it already identifies the event source`;
3526
+ if (inline === null)
3527
+ context.information(DiagnosticCodes.EventSourceIdInPayload, message, mapping.location);
3528
+ else
3529
+ context.warning(DiagnosticCodes.EventSourceIdInPayload, message, mapping.location);
3530
+ }
3531
+ }
3532
+ }
3533
+ }
3534
+
3535
+ // ../../Compiler/dist/Parsing/ParserContext.js
3536
+ var ParserContext = class {
3537
+ reader;
3538
+ path;
3539
+ #diagnostics = [];
3540
+ // Authoring verification needs these committed values even though SyntaxJson omits them.
3541
+ triggerData = [];
3542
+ constructor(reader, path) {
3543
+ this.reader = reader;
3544
+ this.path = path;
3545
+ }
3546
+ get start() {
3547
+ return sourceLocation(1, 1, this.path);
3548
+ }
3549
+ get diagnostics() {
3550
+ return this.#diagnostics;
3551
+ }
3552
+ information(code, message, location) {
3553
+ this.#diagnostics.push({ severity: "information", code, message, location });
3554
+ }
3555
+ error(code, message, location) {
3556
+ this.#diagnostics.push({ severity: "error", code, message, location });
3557
+ }
3558
+ warning(code, message, location) {
3559
+ this.#diagnostics.push({ severity: "warning", code, message, location });
3560
+ }
3561
+ // The next significant line when it is indented deeper than its parent - that is, when it belongs to
3562
+ // the parent's body under the offside rule.
3563
+ peekChild(parentIndent) {
3564
+ const line = this.reader.peekSignificant();
3565
+ return line !== void 0 && line.indent > parentIndent ? line : void 0;
3566
+ }
3567
+ // Skips the body of a construct, the way the C# parser does after reporting it.
3568
+ skipBlock(parentIndent) {
3569
+ while (this.peekChild(parentIndent) !== void 0) {
3570
+ this.reader.takeSignificant();
3571
+ }
3572
+ }
3573
+ // Skips the body of a construct this compiler deliberately does not model. Unlike skipBlock it steps
3574
+ // over fenced code blocks whole, because a fenced line may be indented less than the block it is in -
3575
+ // reading it as significant would end the skip early and misread the code as Screenplay.
3576
+ skipOpaqueBlock(parentIndent) {
3577
+ let child = this.peekChild(parentIndent);
3578
+ while (child !== void 0) {
3579
+ this.reader.takeSignificant();
3580
+ if (child.content.startsWith("```")) {
3581
+ this.skipFencedBody();
3582
+ }
3583
+ child = this.peekChild(parentIndent);
3584
+ }
3585
+ }
3586
+ // Takes the raw lines of a fenced block up to and including its closing fence.
3587
+ skipFencedBody() {
3588
+ for (let line = this.reader.takeRaw(); line !== void 0; line = this.reader.takeRaw()) {
3589
+ if (line.raw.trim() === "```") {
3590
+ return;
3591
+ }
3592
+ }
3593
+ }
3594
+ };
3595
+
3596
+ // ../../Compiler/dist/Parsing/ScreenplayParser.js
3597
+ var domainPattern = pattern("^domain\\s+([A-Za-z_]\\w*(?:\\.[A-Za-z_]\\w*)*)$");
3598
+ var importPattern = pattern("^import\\s+([\\w.]+)$");
3599
+ var conceptPattern2 = pattern("^concept\\s+(\\w+)\\s*:\\s*(\\w+)((?:\\s+@\\w+)*)$");
3600
+ var enumValuePattern = pattern("^@?[a-z_]\\w*$");
3601
+ var attributeReasonPattern2 = pattern(`^([a-z_]\\w*)\\s+reason\\s+"(${stringBodyPattern})"$`);
3602
+ var personaPattern = pattern("^persona\\s+([A-Za-z_]\\w*)$");
3603
+ var personaPolicyPattern = pattern("^policy\\s+([A-Za-z_]\\w*)$");
3604
+ var tabIndentPattern = /^[ ]*\t/;
3605
+ var primitiveTypes2 = ["Uuid", "String", "Int", "Decimal", "Bool", "Date", "DateTime"];
3606
+ var opaqueTopLevel = /* @__PURE__ */ new Set(["policy", "authentication", "seed", "ui", "theme", "trigger", "layout", "behavior"]);
3607
+ var bodyKeywords = /* @__PURE__ */ new Set(["slice", "feature", "description", "authorize", "screen", "dialog", "form", "contribute", "on", "uses"]);
3608
+ function parseApplication(context, lines, placement = documentPlacement) {
3609
+ warnOnTabIndentation(context, lines);
3610
+ const moduleBody = placement.length === 1 ? new ModuleBody(placement[0]) : void 0;
3611
+ const featureBody = placement.length > 1 ? new FeatureBody(placement[placement.length - 1]) : void 0;
3612
+ const placedBody = moduleBody ?? featureBody;
3613
+ let domain = null;
3614
+ const imports = [];
3615
+ const fileImports2 = [];
3616
+ const concepts = [];
3617
+ const types = [];
3618
+ const modules = [];
3619
+ const personas = [];
3620
+ let sawOtherConstruct = false;
3621
+ for (let line = context.reader.peekSignificant(); line !== void 0; line = context.reader.peekSignificant()) {
3622
+ context.reader.takeSignificant();
3623
+ const keyword = firstWord2(line.content);
3624
+ if (keyword === "domain") {
3625
+ domain = parseDomain(context, line, domain, sawOtherConstruct);
3626
+ continue;
3627
+ }
3628
+ sawOtherConstruct ||= declaresConstruct(keyword, line, placement);
3629
+ if (keyword === "import" && isFileImport(line.content)) {
3630
+ if (placedBody !== void 0) {
3631
+ placedBody.tryParse(context, line);
3632
+ } else {
3633
+ parseFileImport(context, line, fileImports2);
3634
+ }
3635
+ } else if (keyword === "import") {
3636
+ const match = importPattern.exec(line.content);
3637
+ if (match === null) {
3638
+ context.error(DiagnosticCodes.InvalidImportDeclaration, `Invalid import '${line.content}' - expected 'import <Qualified.Name>'`, locationOf(line));
3639
+ } else {
3640
+ imports.push({ kind: "ImportSyntax", qualifiedName: match[1], location: locationOf(line) });
3641
+ }
3642
+ } else if (keyword === "concept") {
3643
+ concepts.push(parseConcept(context, line));
3644
+ } else if (keyword === "type") {
3645
+ types.push(parseType(context, line));
3646
+ } else if (keyword === "module" && !isDocumentPlacement(placement)) {
3647
+ parseModuleInPlacedFile(context, line, placement, moduleBody);
3648
+ } else if (keyword === "module") {
3649
+ modules.push(parseModule(context, line));
3650
+ } else if (keyword === "persona") {
3651
+ personas.push(parsePersona(context, line));
3652
+ } else if (keyword === "trigger") {
3653
+ parseTriggerDeclaration(context, line);
3654
+ } else if (opaqueTopLevel.has(keyword)) {
3655
+ context.skipOpaqueBlock(line.indent);
3656
+ } else if (placedBody?.tryParse(context, line) !== true) {
3657
+ reportUnexpectedTopLevel(context, line, placement);
3658
+ }
3659
+ }
3660
+ if (moduleBody !== void 0) {
3661
+ modules.unshift(moduleBody.build(context.start, true));
3662
+ } else if (featureBody !== void 0) {
3663
+ modules.unshift(place(placement, featureBody.build(context.start, true), context.start));
3664
+ }
3665
+ return { kind: "ApplicationSyntax", domain, imports, concepts, types, modules, personas, fileImports: fileImports2, location: context.start };
3666
+ }
3667
+ function declaresConstruct(keyword, line, placement) {
3668
+ if (keyword === "import") {
3669
+ return importPattern.test(line.content);
3670
+ }
3671
+ if (keyword === "module") {
3672
+ return isDocumentPlacement(placement);
3673
+ }
3674
+ return keyword === "concept" || keyword === "type" || keyword === "persona" || opaqueTopLevel.has(keyword);
3675
+ }
3676
+ function parseModuleInPlacedFile(context, line, placement, moduleBody) {
3677
+ const name = modulePattern.exec(line.content)?.[1] ?? "";
3678
+ if (moduleBody !== void 0 && name === placement[0]) {
3679
+ moduleBody.parseChildren(context, line);
3680
+ return;
3681
+ }
3682
+ context.error(DiagnosticCodes.ModuleInPlacedFile, `This file is imported into ${describePlacement(placement)}, so it cannot declare module '${name}' - import it at the top level of a document instead`, locationOf(line));
3683
+ context.skipBlock(line.indent);
3684
+ }
3685
+ function reportUnexpectedTopLevel(context, line, placement) {
3686
+ const word = firstWord2(line.content);
3687
+ if (!isDocumentPlacement(placement)) {
3688
+ const expected = placement.length === 1 ? moduleBodyExpected : featureBodyExpected;
3689
+ context.error(DiagnosticCodes.UnexpectedInPlacedFile, `Unexpected '${word}' in a file imported into ${describePlacement(placement)} - expected an application declaration or ${expected}`, locationOf(line));
3690
+ } else {
3691
+ const hint = bodyKeywords.has(word) ? ` - '${word}' belongs in a module or feature; wrap it in one, or import this file from inside one` : " - expected domain, import, concept, type, policy, persona, authentication, module, seed, trigger, behavior, ui profile, theme or layout";
3692
+ context.error(DiagnosticCodes.UnknownTopLevelConstruct, `Unexpected '${word}' at the top level${hint}`, locationOf(line));
3693
+ }
3694
+ context.skipBlock(line.indent);
3695
+ }
3696
+ function place(placement, innermost, start) {
3697
+ let feature = innermost;
3698
+ for (let index = placement.length - 2; index >= 1; index--) {
3699
+ feature = {
3700
+ kind: "FeatureSyntax",
3701
+ name: placement[index],
3702
+ description: null,
3703
+ authorize: null,
3704
+ features: [feature],
3705
+ slices: [],
3706
+ fileImports: [],
3707
+ isPlacement: true,
3708
+ location: start
3709
+ };
3710
+ }
3711
+ return {
3712
+ kind: "ModuleSyntax",
3713
+ name: placement[0],
3714
+ description: null,
3715
+ authorize: null,
3716
+ features: [feature],
3717
+ fileImports: [],
3718
+ isPlacement: true,
3719
+ location: start
3720
+ };
3721
+ }
3722
+ function parseDomain(context, line, existing, sawOtherConstruct) {
3723
+ const match = domainPattern.exec(line.content);
3724
+ if (match === null) {
3725
+ context.error(DiagnosticCodes.InvalidDomainDeclaration, `Invalid domain declaration '${line.content}' - expected 'domain <Qualified.Name>'`, locationOf(line));
3726
+ return existing;
3727
+ }
3728
+ if (existing !== null) {
3729
+ context.error(DiagnosticCodes.DuplicateDomain, "The document already declares a domain - a document can have at most one", locationOf(line));
3730
+ return existing;
3731
+ }
3732
+ if (sawOtherConstruct) {
3733
+ context.error(DiagnosticCodes.DomainNotFirst, "'domain' must be declared before any other construct", locationOf(line));
3734
+ }
3735
+ return { kind: "DomainSyntax", name: match[1], location: locationOf(line) };
3736
+ }
3737
+ function warnOnTabIndentation(context, lines) {
3738
+ let inFence = false;
3739
+ for (const line of lines) {
3740
+ if (line.raw.trimStart().startsWith("```")) {
3741
+ inFence = !inFence;
3742
+ continue;
3743
+ }
3744
+ if (!inFence && tabIndentPattern.test(line.raw)) {
3745
+ context.warning(DiagnosticCodes.TabIndentation, "Screenplay is indentation based - use spaces, not tabs", startOf(line));
3746
+ }
3747
+ }
3748
+ }
3749
+ function parseConcept(context, line) {
3750
+ const match = conceptPattern2.exec(line.content);
3751
+ if (match === null) {
3752
+ context.error(DiagnosticCodes.InvalidConceptDeclaration, `Invalid concept declaration '${line.content}' - expected 'concept <Name> : <Type>'`, locationOf(line));
3753
+ context.skipBlock(line.indent);
3754
+ return { kind: "ConceptSyntax", name: firstWord2(line.content), type: "", attributes: [], values: [], location: locationOf(line) };
3755
+ }
3756
+ const [, name, type, attributeText] = match;
3757
+ const attributes = attributeText.split(" ").filter((attribute) => attribute.length > 0).map((attribute) => ({ kind: "ConceptAttributeSyntax", name: attribute.replace(/^@+/, ""), reason: null, location: locationOf(line) }));
3758
+ if (type !== "Enum" && !primitiveTypes2.includes(type)) {
3759
+ context.error(DiagnosticCodes.UnknownPrimitiveType, `Unknown primitive type '${type}' - expected ${primitiveTypes2.join(", ")} or Enum`, locationOf(line));
3760
+ }
3761
+ const attributeIndices = /* @__PURE__ */ new Map();
3762
+ attributes.forEach((attribute, index) => {
3763
+ if (!attributeIndices.has(attribute.name))
3764
+ attributeIndices.set(attribute.name, index);
3765
+ });
3766
+ const values = [];
3767
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
3768
+ context.reader.takeSignificant();
3769
+ const reason = attributeReasonPattern2.exec(child.content);
3770
+ if (isFileDirective(child)) {
3771
+ continue;
3772
+ } else if (firstWord2(child.content) === "validate") {
3773
+ if (type === "Enum" && child.content === "validate" && context.peekChild(child.indent) === void 0) {
3774
+ context.warning(DiagnosticCodes.ValidateReadAsEnumerationBlock, `'validate' in enumeration concept '${name}' declares an empty validate block, not a value named 'validate' - write '@validate' for the value`, locationOf(child));
3775
+ }
3776
+ context.skipOpaqueBlock(child.indent);
3777
+ } else if (reason !== null) {
3778
+ applyAttributeReason(context, child, name, attributes, attributeIndices, reason[1], unescapeString(reason[2]));
3779
+ } else if (type === "Enum" && enumValuePattern.test(child.content)) {
3780
+ values.push(unescapeIdentifier(child.content));
3781
+ } else if (type === "Enum") {
3782
+ context.error(DiagnosticCodes.InvalidEnumerationValue, `Invalid enum value '${child.content}' - expected an identifier`, locationOf(child));
3783
+ } else {
3784
+ context.error(DiagnosticCodes.UnknownConceptDirective, `Unexpected '${child.content}' in concept body - expected validate, 'file <path>' or '<attribute> reason "<text>"'`, locationOf(child));
3785
+ context.skipBlock(child.indent);
3786
+ }
3787
+ }
3788
+ return { kind: "ConceptSyntax", name, type, attributes, values, location: locationOf(line) };
3789
+ }
3790
+ function applyAttributeReason(context, line, concept, attributes, indices, attribute, reason) {
3791
+ const index = indices.get(attribute);
3792
+ if (index === void 0) {
3793
+ context.error(DiagnosticCodes.AttributeReasonWithoutAttribute, `Concept '${concept}' declares a reason for '${attribute}' without the attribute - write 'concept ${concept} : <Type> @${attribute}'`, locationOf(line));
3794
+ } else if (attributes[index].reason !== null) {
3795
+ context.error(DiagnosticCodes.DuplicateAttributeReason, `Concept '${concept}' already declares a reason for '${attribute}' - at most one is allowed`, locationOf(line));
3796
+ } else {
3797
+ attributes[index] = { ...attributes[index], reason };
3798
+ }
3799
+ }
3800
+ function parsePersona(context, line) {
3801
+ const name = personaPattern.exec(line.content)?.[1] ?? "";
3802
+ if (name === "") {
3803
+ context.error(DiagnosticCodes.InvalidPersonaDeclaration, `Invalid persona declaration '${line.content}' - expected 'persona <Name>'`, locationOf(line));
3804
+ }
3805
+ let description = null;
3806
+ const policies = [];
3807
+ for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
3808
+ context.reader.takeSignificant();
3809
+ const keyword = firstWord2(child.content);
3810
+ if (keyword === "description") {
3811
+ description = parseDescription(context, child, description, `Persona '${name}'`);
3812
+ } else if (keyword === "policy") {
3813
+ const policy = personaPolicyPattern.exec(child.content);
3814
+ if (policy === null) {
3815
+ context.error(DiagnosticCodes.InvalidPersonaPolicyReference, `Invalid policy reference '${child.content}' - expected 'policy <Name>'`, locationOf(child));
3816
+ } else {
3817
+ policies.push(policy[1]);
3818
+ }
3819
+ } else {
3820
+ context.error(DiagnosticCodes.UnknownPersonaDirective, `Unexpected '${keyword}' in persona body - expected description or policy`, locationOf(child));
3821
+ context.skipBlock(child.indent);
3822
+ }
3823
+ }
3824
+ return { kind: "PersonaSyntax", name, description, policies, location: locationOf(line) };
3825
+ }
3826
+
3827
+ // ../../Compiler/dist/Parsing/SourceLineSplitter.js
3828
+ function splitLines(source, hashComments = false, path) {
3829
+ const result = [];
3830
+ let number = 0;
3831
+ let offset = 0;
3832
+ for (const raw of source.split("\n")) {
3833
+ number++;
3834
+ const line = raw.endsWith("\r") ? raw.replace(/\r+$/, "") : raw;
3835
+ const indent = line.length - line.trimStart().length;
3836
+ const content = stripComment(line.substring(indent), hashComments).trimEnd();
3837
+ result.push(path === void 0 ? { number, raw: line, indent, content, startOffset: offset } : { number, raw: line, indent, content, path, startOffset: offset });
3838
+ offset += raw.length + 1;
3839
+ }
3840
+ return result;
3841
+ }
3842
+ function commentStart(text, hashComments = false) {
3843
+ let inString = false;
3844
+ let inTemplate = false;
3845
+ for (let index = 0; index < text.length; index++) {
3846
+ const current = text[index];
3847
+ if (current === "\\" && inString && index + 1 < text.length) {
3848
+ index++;
3849
+ } else if (current === '"' && !inTemplate) {
3850
+ inString = !inString;
3851
+ } else if (current === "`" && !inString) {
3852
+ inTemplate = !inTemplate;
3853
+ } else if (!inString && !inTemplate) {
3854
+ if (current === "/" && index + 1 < text.length && text[index + 1] === "/") {
3855
+ return index;
3856
+ }
3857
+ if (hashComments && current === "#") {
3858
+ return index;
3859
+ }
3860
+ }
3861
+ }
3862
+ return -1;
3863
+ }
3864
+ function stripComment(text, hashComments) {
3865
+ const comment = commentStart(text, hashComments);
3866
+ return comment < 0 ? text : text.substring(0, comment);
3867
+ }
3868
+
3869
+ // ../../Compiler/dist/ScreenplayCompiler.js
3870
+ function parse(source, path, placement = documentPlacement) {
3871
+ const { value, diagnostics, success } = parseForAuthoring(source, path, placement);
3872
+ return { value, diagnostics, success };
3873
+ }
3874
+ function parseForAuthoring(source, path, placement = documentPlacement) {
3875
+ const lines = splitLines(source, false, path);
3876
+ const context = new ParserContext(new LineReader(lines), path);
3877
+ const value = parseApplication(context, lines, placement);
3878
+ validateInlineEvents(value, context);
3879
+ return {
3880
+ value,
3881
+ diagnostics: context.diagnostics,
3882
+ triggerData: context.triggerData,
3883
+ success: !context.diagnostics.some((diagnostic) => diagnostic.severity === "error")
3884
+ };
3885
+ }
3886
+
3887
+ // ../../Compiler/dist/Syntax/SyntaxJson.js
3888
+ var isNode = (value) => typeof value === "object" && value !== null && typeof value.kind === "string";
3889
+ function toSyntaxJson(node) {
3890
+ return write(node);
3891
+ }
3892
+ function write(value) {
3893
+ if (Array.isArray(value)) {
3894
+ return value.map(write);
3895
+ }
3896
+ if (isNode(value)) {
3897
+ const result = { kind: value.kind };
3898
+ const members = Object.keys(value).filter((member) => member !== "kind" && member !== "location").sort(ordinal);
3899
+ for (const member of members) {
3900
+ result[member] = write(value[member]);
3901
+ }
3902
+ return result;
3903
+ }
3904
+ if (value === void 0) {
3905
+ return null;
3906
+ }
3907
+ return value;
3908
+ }
3909
+ function ordinal(left, right) {
3910
+ return left < right ? -1 : left > right ? 1 : 0;
3911
+ }
3912
+
3913
+ // ../../Compiler/dist/Authoring/QuickFixes.js
3914
+ function legacyOptionalTypeLength(line, diagnostic) {
3915
+ if (diagnostic.code !== DiagnosticCodes.LegacyOptionalSuffix)
3916
+ return 0;
3917
+ return /^[\p{L}\p{Mn}\p{Nd}\p{Pc}.]+(?:\[\])?\?/u.exec(line.slice(diagnostic.location.column - 1))?.[0].length ?? 0;
3918
+ }
3919
+ function prepareQuickFixes(source, options = {}) {
3920
+ const original = parseForAuthoring(source, void 0, options.placement);
3921
+ if (!original.success)
3922
+ return () => [];
3923
+ const lines = source.split(/\r\n|\r|\n/);
3924
+ const starts = [0];
3925
+ for (const match of source.matchAll(/\r\n|\r|\n/g))
3926
+ starts.push(match.index + match[0].length);
3927
+ const occurrences = original.diagnostics.filter((diagnostic) => diagnostic.code === DiagnosticCodes.LegacyOptionalSuffix).flatMap((diagnostic) => {
3928
+ const length = legacyOptionalTypeLength(lines[diagnostic.location.line - 1], diagnostic);
3929
+ return length === 0 ? [] : [{ diagnostic, edit: { start: starts[diagnostic.location.line - 1] + diagnostic.location.column + length - 2, length: 1, text: " optional" } }];
3930
+ });
3931
+ if (occurrences.length === 0)
3932
+ return () => [];
3933
+ const syntax = verificationShape(original);
3934
+ const byLine = new Map(occurrences.map((occurrence) => [occurrence.diagnostic.location.line, occurrence]));
3935
+ const verifiedOccurrences = /* @__PURE__ */ new Map();
3936
+ let documentChecked = false;
3937
+ let documentFix;
3938
+ const verify = (fix, line) => {
3939
+ const candidate = applyQuickFixEdits(source, fix.edits);
3940
+ if (candidate === void 0)
3941
+ return void 0;
3942
+ const parsed = parseForAuthoring(candidate, void 0, options.placement);
3943
+ return parsed.success && verificationShape(parsed) === syntax && !parsed.diagnostics.some((diagnostic) => diagnostic.code === fix.diagnosticCode && (line === void 0 || line === diagnostic.location.line)) ? fix : void 0;
3944
+ };
3945
+ return (line) => {
3946
+ if (!documentChecked) {
3947
+ documentFix = verify({ diagnosticCode: DiagnosticCodes.LegacyOptionalSuffix, title: "Use 'optional' throughout this document", scope: "document", edits: occurrences.map((occurrence) => occurrence.edit) });
3948
+ documentChecked = true;
3949
+ }
3950
+ const selected = line === void 0 ? void 0 : byLine.get(line);
3951
+ let occurrenceFix;
3952
+ if (selected !== void 0 && line !== void 0) {
3953
+ if (!verifiedOccurrences.has(line)) {
3954
+ if (verifiedOccurrences.size === 32)
3955
+ verifiedOccurrences.delete(verifiedOccurrences.keys().next().value);
3956
+ verifiedOccurrences.set(line, verify({ diagnosticCode: DiagnosticCodes.LegacyOptionalSuffix, title: "Use 'optional' instead of '?'", scope: "occurrence", edits: [selected.edit] }, line));
3957
+ }
3958
+ occurrenceFix = verifiedOccurrences.get(line);
3959
+ }
3960
+ return [occurrenceFix, documentFix].filter((fix) => fix !== void 0);
3961
+ };
3962
+ }
3963
+ function verificationShape(parsed) {
3964
+ return JSON.stringify([toSyntaxJson(parsed.value), parsed.triggerData.map((value) => toSyntaxJson(value))]);
3965
+ }
3966
+ function applyQuickFixEdits(source, edits) {
3967
+ const parts = [];
3968
+ let end = 0;
3969
+ for (const edit of edits) {
3970
+ if (edit.start < end || edit.start < 0 || edit.length < 0 || edit.start + edit.length > source.length)
3971
+ return void 0;
3972
+ parts.push(source.slice(end, edit.start), edit.text);
3973
+ end = edit.start + edit.length;
3974
+ }
3975
+ parts.push(source.slice(end));
3976
+ return parts.join("");
3977
+ }
3978
+
3979
+ // inline-event-validation.ts
3980
+ var reserved2 = /* @__PURE__ */ new Set(["namespace", "sequence", "correlation", "causation", "causedBy", "occurred"]);
3981
+ var quotedId = /^id\s+"((?:[^"\\]|\\.)*)"$/;
3982
+ function validateInlineEvents2(lines, symbols, application) {
3983
+ lines = eventAnalysisSource(lines);
3984
+ const issues = [];
3985
+ const fences = fenceMap(lines);
3986
+ const documentationBlocks = nonemptyMarkdownBlocks(lines, fences);
3987
+ const commandProductions = new Set(symbols.commands.flatMap((command) => command.productionHeaders ?? []));
3988
+ const eventCounts = /* @__PURE__ */ new Map();
3989
+ const importedNames = /* @__PURE__ */ new Set();
3990
+ for (const document of [symbols, application]) {
3991
+ for (const event of document.events) eventCounts.set(event.name, (eventCounts.get(event.name) ?? 0) + 1);
3992
+ for (const imported of document.imports) importedNames.add(imported.shortName);
3993
+ }
3994
+ const report = (line, code, message, severity = "error") => {
3995
+ issues.push({ line, startColumn: indentOf(lines[line]) + 1, endColumn: lines[line].length + 1, code, message, severity });
3996
+ };
3997
+ for (const event of symbols.events) {
3998
+ const body = directBody(lines, fences, event.line, indentOf(lines[event.line]));
3999
+ if (event.inline) {
4000
+ const properties = /* @__PURE__ */ new Set();
4001
+ for (const property of event.properties) {
4002
+ if (properties.has(property.name)) report(property.line, diagnosticCodes.duplicateDeclaration, `Event '${event.name}' already declares property '${property.name}'.`);
4003
+ properties.add(property.name);
4004
+ }
4005
+ if (!commandProductions.has(event.line)) report(event.line, diagnosticCodes.inlineEventOutsideCommand, "Inline events can only be declared inside commands.");
4006
+ if (event.generation !== void 0) report(event.line, diagnosticCodes.inlineEventGeneration, "Inline events are generation 1; extract the event before declaring generations.");
4007
+ if ((eventCounts.get(event.name) ?? 0) > 1 || importedNames.has(event.name)) {
4008
+ report(event.line, diagnosticCodes.inlineEventCollision, `Inline event '${event.name}' collides with another declaration or import.`);
4009
+ }
4010
+ }
4011
+ let hasId = false;
4012
+ let hasDocumentation = false;
4013
+ for (const index of body) {
4014
+ const text = lines[index].trim();
4015
+ const keyword = text.split(/\s+/)[0];
4016
+ if (event.inline && keyword === "generation") report(index, diagnosticCodes.inlineEventGeneration, "Inline events are generation 1; extract the event before declaring generations.");
4017
+ if (event.inline && keyword === "origin") report(index, diagnosticCodes.reservedProductionMetadata, "An inline event is local to its command and cannot declare origin.");
4018
+ if (/^(?:id|description|documentation)\s+[\w.]+(?:\[\])?(?:\?|\s+optional)?(?:\s*=.*)?$/.test(text)) continue;
4019
+ if (keyword === "id") {
4020
+ const match = text.match(quotedId);
4021
+ if (hasId || match === null || match[1].trim().length === 0) report(index, diagnosticCodes.invalidEventId, 'Expected one nonempty id "<old-name>".');
4022
+ else if (match[1] === event.name) report(index, diagnosticCodes.redundantEventId, "This id repeats the event name; remove it.", "information");
4023
+ hasId = true;
4024
+ }
4025
+ if (keyword === "documentation") {
4026
+ let next = index + 1;
4027
+ while (next < lines.length && lines[next].trim().length === 0) next++;
4028
+ if (hasDocumentation || text !== "documentation" || lines[next]?.trim() !== "```markdown" || indentOf(lines[next]) <= indentOf(lines[index]) || !documentationBlocks.has(next)) {
4029
+ report(index, diagnosticCodes.invalidEventDocumentation, "Expected one nonempty fenced markdown documentation block.");
4030
+ }
4031
+ hasDocumentation = true;
4032
+ }
4033
+ }
4034
+ }
4035
+ const productionIndents = [];
4036
+ for (let index = 0; index < lines.length; index++) {
4037
+ if (fences[index] || lines[index].trim().length === 0) continue;
4038
+ const indent = indentOf(lines[index]);
4039
+ while (productionIndents.length > 0 && productionIndents[productionIndents.length - 1] >= indent) productionIndents.pop();
4040
+ const keyword = lines[index].trim().split(/\s+/)[0];
4041
+ if (reserved2.has(keyword) && productionIndents.length > 0) {
4042
+ report(index, diagnosticCodes.reservedProductionMetadata, `'${keyword}' is system-assigned production metadata.`);
4043
+ }
4044
+ if (keyword === "produces") productionIndents.push(indent);
4045
+ }
4046
+ for (const command of symbols.commands) {
4047
+ const { identifier, mixed } = productionDestinations(command);
4048
+ for (const production of command.produces ?? []) {
4049
+ if (mixed && production.target === void 0) report(production.line, diagnosticCodes.explicitProducesTargetsRequired, `Production '${production.name}' must state for explicitly when destinations differ.`);
4050
+ const destination = production.target ?? (production.inline ? identifier : void 0);
4051
+ if (identifier === void 0 || destination !== identifier) continue;
4052
+ for (const mapping of production.mappings.filter((mapping2) => mapping2.source === identifier)) {
4053
+ report(mapping.line, diagnosticCodes.eventSourceIdInPayload, `The payload copies '${identifier}', which already identifies the event source.`, production.inline ? "warning" : "information");
4054
+ }
4055
+ }
4056
+ }
4057
+ return issues;
4058
+ }
4059
+ function nonemptyMarkdownBlocks(lines, fences) {
4060
+ const blocks = /* @__PURE__ */ new Set();
4061
+ let opening;
4062
+ let content = false;
4063
+ for (let index = 0; index < lines.length; index++) {
4064
+ if (!fences[index]) continue;
4065
+ const text = lines[index].trim();
4066
+ if (opening === void 0) {
4067
+ opening = index;
4068
+ content = false;
4069
+ } else if (text === "```") {
4070
+ if (content && lines[opening].trim() === "```markdown") blocks.add(opening);
4071
+ opening = void 0;
4072
+ } else if (text.length > 0) {
4073
+ content = true;
4074
+ }
4075
+ }
4076
+ return blocks;
4077
+ }
4078
+
4079
+ // validation.ts
4080
+ function issue(severity, line, startColumn, length, message, code) {
4081
+ return { severity, message, line, startColumn, endColumn: startColumn + length, code };
4082
+ }
4083
+ function tokenIssue(severity, line, text, token, message, code) {
4084
+ const column2 = text.indexOf(token) + 1;
4085
+ return issue(severity, line, column2, token.length, message, code);
4086
+ }
4087
+ function validateDeclarations(lines, symbols, application) {
4088
+ const issues = [];
4089
+ const types = /* @__PURE__ */ new Set([...knownTypeNames(symbols, primitiveTypes), ...knownTypeNames(application, [])]);
4090
+ const checkProperties = (properties, owner) => {
4091
+ for (const property of properties.filter(
4092
+ (candidate) => !types.has(propertyTypeReference(candidate).name)
4093
+ )) {
4094
+ const bare = propertyTypeReference(property).name;
4095
+ issues.push(
4096
+ tokenIssue(
4097
+ "warning",
4098
+ property.line,
4099
+ lines[property.line],
4100
+ property.type,
4101
+ bare === "optional" ? `Unknown type 'optional' on '${property.name}' of ${owner} \u2014 did you forget the type before 'optional'?` : `Unknown type '${bare}' on '${property.name}' of ${owner} \u2014 declare it with 'concept ${bare} : <Primitive>' or 'type ${bare}'.`,
4102
+ diagnosticCodes.unknownType
4103
+ )
4104
+ );
4105
+ }
4106
+ };
4107
+ for (const type of symbols.types) checkProperties(type.properties, `type '${type.name}'`);
4108
+ for (const event of symbols.events) checkProperties(event.properties, `event '${event.name}'`);
4109
+ for (const query of symbols.queries) checkProperties(query.parameters, `query '${query.name}'`);
4110
+ for (const command of symbols.commands) {
4111
+ checkProperties(command.properties, `command '${command.name}'`);
4112
+ const identifiers = command.properties.filter((property) => property.isIdentifier);
4113
+ for (const extra of identifiers.slice(1)) {
4114
+ issues.push(
4115
+ tokenIssue(
4116
+ "error",
4117
+ extra.line,
4118
+ lines[extra.line],
4119
+ "identifier",
4120
+ `Command '${command.name}' already marks '${identifiers[0].name}' as identifier \u2014 only one property can be the identifier.`,
4121
+ diagnosticCodes.duplicateCommandIdentifier
4122
+ )
4123
+ );
4124
+ }
4125
+ }
4126
+ const declared = /* @__PURE__ */ new Map();
4127
+ for (const declaration of [...symbols.concepts, ...symbols.types]) {
4128
+ const first = declared.get(declaration.name);
4129
+ if (first === void 0) {
4130
+ declared.set(declaration.name, declaration.line);
4131
+ continue;
4132
+ }
4133
+ issues.push(
4134
+ tokenIssue(
4135
+ "error",
4136
+ declaration.line,
4137
+ lines[declaration.line],
4138
+ declaration.name,
4139
+ `Duplicate declaration of '${declaration.name}' \u2014 concept and type names must be unique.`,
4140
+ diagnosticCodes.duplicateDeclaration
4141
+ )
4142
+ );
4143
+ }
4144
+ return issues;
4145
+ }
4146
+ function validateLines(lines, context = {}) {
4147
+ const fences = fenceMap(lines);
4148
+ const symbols = scanDocument(lines);
4149
+ const application = context.application ?? mergeSymbols();
4150
+ const events = /* @__PURE__ */ new Set([...knownEventNames(symbols), ...knownEventNames(application)]);
4151
+ const policies = new Set([...symbols.policies, ...application.policies].map((policy) => policy.name));
4152
+ const issues = validateDeclarations(lines, symbols, application);
4153
+ issues.push(...validateProductionDestinations(lines, symbols));
4154
+ const optionalCodes = /* @__PURE__ */ new Set([DiagnosticCodes.LegacyOptionalSuffix, DiagnosticCodes.InvalidOptionalModifierOrder, DiagnosticCodes.OptionalReadsNotSupported]);
4155
+ for (const diagnostic of parse(lines.join("\n"), void 0, context.placement).diagnostics) {
4156
+ if (!optionalCodes.has(diagnostic.code)) continue;
4157
+ const line = diagnostic.location.line - 1;
4158
+ const length = legacyOptionalTypeLength(lines[line], diagnostic) || lines[line].length - diagnostic.location.column + 1;
4159
+ issues.push(issue(diagnostic.severity, line, diagnostic.location.column, length, diagnostic.message, diagnostic.code));
4160
+ }
4161
+ const checkEvent = (line, text, name) => {
4162
+ if (!events.has(name)) {
4163
+ issues.push(
4164
+ tokenIssue(
4165
+ "warning",
4166
+ line,
4167
+ text,
4168
+ name,
4169
+ `Unknown event type '${name}' \u2014 declare it in a slice or import it.`,
4170
+ diagnosticCodes.unknownEvent
4171
+ )
4172
+ );
4173
+ }
4174
+ };
4175
+ let authorizeIndent = -1;
4176
+ for (let index = 0; index < lines.length; index++) {
4177
+ const line = lines[index];
4178
+ const trimmed = line.trim();
4179
+ if (fences[index] || trimmed.length === 0) continue;
4180
+ const leading = line.match(/^[ ]*(\t+)/);
4181
+ if (leading) {
4182
+ issues.push(
4183
+ issue(
4184
+ "warning",
4185
+ index,
4186
+ leading[0].length - leading[1].length + 1,
4187
+ leading[1].length,
4188
+ "Screenplay is indentation-based \u2014 use spaces, not tabs.",
4189
+ diagnosticCodes.tabIndentation
4190
+ )
4191
+ );
4192
+ }
4193
+ if (authorizeIndent >= 0) {
4194
+ if (indentOf(line) > authorizeIndent && /^(?:or\s+)?[A-Z]\w*(?:\s+or\s+[A-Z]\w*)*$/.test(trimmed)) {
4195
+ for (const name of trimmed.split(/\s+/).filter((token) => token !== "or")) {
4196
+ if (!policies.has(name)) {
4197
+ issues.push(
4198
+ tokenIssue(
4199
+ "warning",
4200
+ index,
4201
+ line,
4202
+ name,
4203
+ `Unknown policy '${name}' \u2014 declare it with 'policy ${name}'.`,
4204
+ diagnosticCodes.unknownPolicy
4205
+ )
4206
+ );
4207
+ }
4208
+ }
4209
+ continue;
4210
+ }
4211
+ authorizeIndent = -1;
4212
+ }
4213
+ const fileImportIssue = validateImport(lines, fences, index);
4214
+ if (fileImportIssue) issues.push(fileImportIssue);
4215
+ const slice = trimmed.match(/^slice\s+(\w+)/);
4216
+ if (slice && !sliceTypes.includes(slice[1])) {
4217
+ issues.push(
4218
+ tokenIssue(
4219
+ "error",
4220
+ index,
4221
+ line,
4222
+ slice[1],
4223
+ `Unknown slice type '${slice[1]}' \u2014 expected ${sliceTypes.join(", ")}.`,
4224
+ diagnosticCodes.unknownSliceType
4225
+ )
4226
+ );
4227
+ }
4228
+ const concept = trimmed.match(/^concept\s+\w+\s*:\s*(\w+)/);
4229
+ if (concept && concept[1] !== "Enum" && !primitiveTypes.includes(concept[1])) {
4230
+ issues.push(
4231
+ tokenIssue(
4232
+ "error",
4233
+ index,
4234
+ line,
4235
+ concept[1],
4236
+ `Unknown primitive type '${concept[1]}' \u2014 expected ${primitiveTypes.join(", ")} or Enum.`,
4237
+ diagnosticCodes.unknownPrimitiveType
4238
+ )
4239
+ );
4240
+ }
4241
+ const authorize = trimmed.match(/^authorize\s+(.*)$/);
4242
+ if (authorize) {
4243
+ authorizeIndent = indentOf(line);
4244
+ for (const name of authorize[1].split(/\s+/).filter((token) => token !== "or" && token.length > 0)) {
4245
+ if (!policies.has(name)) {
4246
+ issues.push(
4247
+ tokenIssue(
4248
+ "warning",
4249
+ index,
4250
+ line,
4251
+ name,
4252
+ `Unknown policy '${name}' \u2014 declare it with 'policy ${name}'.`,
4253
+ diagnosticCodes.unknownPolicy
4254
+ )
4255
+ );
4256
+ }
4257
+ }
4258
+ }
4259
+ const reactsOn = trimmed.match(/^on\s+([A-Z]\w*)\s*$/);
4260
+ if (reactsOn) checkEvent(index, line, reactsOn[1]);
4261
+ const produces = trimmed.match(/^produces\s+([A-Z]\w*)\s*$/);
4262
+ if (produces) checkEvent(index, line, produces[1]);
4263
+ if (/^produces\s+when\b/.test(trimmed)) {
4264
+ for (let next = index + 1; next < lines.length; next++) {
4265
+ const candidate = lines[next];
4266
+ if (fences[next] || candidate.trim().length === 0) continue;
4267
+ if (indentOf(candidate) > indentOf(line)) {
4268
+ const name = candidate.trim().match(/^([A-Z]\w*)\s*$/);
4269
+ if (name) checkEvent(next, candidate, name[1]);
4270
+ }
4271
+ break;
4272
+ }
4273
+ }
4274
+ const uniqueEvent = trimmed.match(/^unique\s+event\s+([A-Z]\w*)/);
4275
+ if (uniqueEvent) checkEvent(index, line, uniqueEvent[1]);
4276
+ const uniqueProperty = trimmed.match(/^unique\s+[a-z_]\w*\s+on\s+([A-Z]\w*)/);
4277
+ if (uniqueProperty) checkEvent(index, line, uniqueProperty[1]);
4278
+ for (const path of line.match(/\$context\.[\w.]+/g) ?? []) {
4279
+ const segments = path.substring("$context.".length).split(".");
4280
+ if (!contextRoots.includes(segments[0])) {
4281
+ issues.push(
4282
+ tokenIssue(
4283
+ "warning",
4284
+ index,
4285
+ line,
4286
+ path,
4287
+ `Unknown $context path '${segments.join(".")}' \u2014 expected one of ${contextRoots.join(", ")}.`,
4288
+ diagnosticCodes.unknownContextPath
4289
+ )
4290
+ );
4291
+ } else if (segments[0] === "causedBy" && segments.length > 1 && !causedByProperties.includes(segments[1])) {
4292
+ issues.push(
4293
+ tokenIssue(
4294
+ "warning",
4295
+ index,
4296
+ line,
4297
+ path,
4298
+ `Unknown $context.causedBy property '${segments[1]}' \u2014 expected ${causedByProperties.join(", ")}.`,
4299
+ diagnosticCodes.unknownContextCausedByProperty
4300
+ )
4301
+ );
4302
+ } else if (segments[0] === "identity" && segments.length > 1 && !identityProperties.includes(segments[1])) {
4303
+ issues.push(
4304
+ tokenIssue(
4305
+ "warning",
4306
+ index,
4307
+ line,
4308
+ path,
4309
+ `Unknown $context.identity property '${segments[1]}' \u2014 expected ${identityProperties.join(", ")}.`,
4310
+ diagnosticCodes.unknownContextIdentityProperty
4311
+ )
4312
+ );
4313
+ }
4314
+ }
4315
+ }
4316
+ issues.push(...validateEventContextPaths(lines, fences));
4317
+ issues.push(...validateInlineEvents2(lines, symbols, application));
4318
+ const fenceLines = lines.map((line, index) => ({ line, index })).filter(({ line }) => /^\s*```(?:[a-z]+)?\s*$/.test(line));
4319
+ if (fenceLines.length % 2 === 1) {
4320
+ const last = fenceLines[fenceLines.length - 1];
4321
+ issues.push(
4322
+ issue(
4323
+ "error",
4324
+ last.index,
4325
+ 1,
4326
+ last.line.length + 1,
4327
+ "Unclosed inline code block \u2014 expected a closing ``` line.",
4328
+ diagnosticCodes.unclosedCodeBlock
4329
+ )
4330
+ );
4331
+ }
4332
+ return issues;
4333
+ }
4334
+ function validateProductionDestinations(lines, symbols) {
4335
+ const issues = [];
4336
+ lines = eventAnalysisSource(lines);
4337
+ for (const command of symbols.commands) {
4338
+ const identifiers = command.properties.filter((property) => property.isIdentifier && !propertyTypeReference(property).isOptional && !propertyTypeReference(property).isCollection);
4339
+ if (identifiers.length !== 1) continue;
4340
+ for (const production of command.produces ?? []) {
4341
+ if (production.inline || production.conditional || production.target !== void 0) continue;
4342
+ const line = production.line;
4343
+ issues.push(issue(
4344
+ "information",
4345
+ line,
4346
+ indentOf(lines[line]) + 1,
4347
+ lines[line].trim().length,
4348
+ `Plain 'produces ${production.name}' omits its destination \u2014 use 'for ${identifiers[0].name}' to explicitly select the command's identifier.`,
4349
+ diagnosticCodes.omittedProductionDestination
4350
+ ));
4351
+ }
4352
+ }
4353
+ return issues;
4354
+ }
4355
+ function validateImport(lines, fences, index) {
4356
+ const line = lines[index];
4357
+ const trimmed = line.trim().replace(/\s*\/\/.*$/, "");
4358
+ if (!/^import\b/.test(trimmed) || fileImportOn(line, index)) return void 0;
4359
+ const indent = indentOf(line);
4360
+ const inBody = indent > 0 && ["module", "feature"].includes(enclosingChain(lines, fences, index, indent)[0]);
4361
+ if (!inBody && !isFileImportLine(line)) return void 0;
4362
+ return issue(
4363
+ "error",
4364
+ index,
4365
+ indent + 1,
4366
+ trimmed.length,
4367
+ `Invalid import '${trimmed}' \u2014 inside a module or feature, import names files: 'import "<path or glob>"'.`,
4368
+ diagnosticCodes.invalidFileImport
4369
+ );
4370
+ }
4371
+ var mappingTarget = /^(?:(?:increment|decrement|count|clear|add|subtract|set)\s+)?@?([$\w.]+)(?=\s|=|$)/;
4372
+ function validateEventContextPaths(lines, fences) {
4373
+ const issues = [];
4374
+ const names = (members) => members.map((member) => member.name).join(", ");
4375
+ for (let index = 0; index < lines.length; index++) {
4376
+ const line = lines[index];
4377
+ if (fences[index]) continue;
4378
+ for (const match of line.matchAll(/(\.)?\$eventContext((?:\.(?:\w+(?:\(\))?)?)*)/g)) {
4379
+ const token = match[0].substring(match[1]?.length ?? 0);
4380
+ const written = match[2];
4381
+ if (written.length === 0) {
4382
+ if (match[1]) {
4383
+ issues.push(issue("error", index, (match.index ?? 0) + 2, token.length, `'$eventContext' names no member - expected one of ${names(resolveEventContextPath("").expected)}.`, diagnosticCodes.missingEventContextPath));
4384
+ }
4385
+ continue;
4386
+ }
4387
+ const path = written.substring(1);
4388
+ const resolution = resolveEventContextPath(path);
4389
+ const column2 = (match.index ?? 0) + (match[1]?.length ?? 0) + 1;
4390
+ switch (resolution.status) {
4391
+ case "missing":
4392
+ issues.push(issue("error", index, column2, token.length, `'$eventContext.${path}' names no member - expected one of ${names(resolution.expected)}.`, diagnosticCodes.missingEventContextPath));
4393
+ break;
4394
+ case "unknownMember":
4395
+ issues.push(issue("warning", index, column2, token.length, `Unknown event context member '${resolution.segment}' in '$eventContext.${path}' - expected one of ${names(resolution.expected)}.`, diagnosticCodes.unknownEventContextMember));
4396
+ break;
4397
+ case "unknownSubPath": {
4398
+ const has = resolution.expected.length === 0 ? "no members to address" : `members ${names(resolution.expected)}`;
4399
+ issues.push(issue("warning", index, column2, token.length, `Unknown event context path '$eventContext.${path}' - '${resolution.member?.name}' (${resolution.member?.type}) has ${has}.`, diagnosticCodes.unknownEventContextPath));
4400
+ break;
4401
+ }
4402
+ case "belowCollection":
4403
+ issues.push(issue("error", index, column2, token.length, `'$eventContext.${path}' cannot resolve - '${resolution.member?.name}' is a collection (${resolution.member?.type}) and cannot be addressed below.`, diagnosticCodes.eventContextPathBelowCollection));
4404
+ break;
4405
+ }
4406
+ }
4407
+ const target = line.trim().match(mappingTarget)?.[1];
4408
+ const source = target?.match(/\.\$(\w+)/)?.[1];
4409
+ if (target && source && source !== "eventContext") {
4410
+ issues.push(tokenIssue("warning", index, line, target, `Dynamic dictionary key '$${source}' in '${target}' is never resolved - only '$eventContext.<path>' is, so the literal text '$${source}' becomes the key.`, diagnosticCodes.unresolvedDynamicKeySource));
4411
+ }
4412
+ }
4413
+ return issues;
4414
+ }
4415
+
4416
+ export {
4417
+ languageId,
4418
+ languageExtensionPoint,
4419
+ constructKeywords,
4420
+ clauseKeywords,
4421
+ codeBlockTags,
4422
+ contextRoots,
4423
+ causedByProperties,
4424
+ sliceTypes,
4425
+ primitiveTypes,
4426
+ conceptAttributes,
4427
+ languageConfiguration,
4428
+ typeReferenceSymbol,
4429
+ typeReferenceText,
4430
+ indentOf,
4431
+ firstWord,
4432
+ fenceMap,
4433
+ enclosingChain,
4434
+ nearestEnclosingLine,
4435
+ eventAnalysisSource,
4436
+ propertyTypeReference,
4437
+ directBody,
4438
+ scanDocument,
4439
+ mergeSymbols,
4440
+ knownEventNames,
4441
+ builtInTriggerNames,
4442
+ knownTriggerNames,
4443
+ knownTypeNames,
4444
+ eventContextPaths,
4445
+ namesEventContextMember,
4446
+ eventContextMembers,
4447
+ eventContextMembersAfter,
4448
+ eventContextMemberAt,
4449
+ describeEventContext,
4450
+ describeEventContextMember,
4451
+ productionDestinations,
4452
+ destinationHints,
4453
+ DiagnosticCodes,
4454
+ prepareQuickFixes,
4455
+ diagnosticCodes,
4456
+ isFileImportLine,
4457
+ fileImportOn,
4458
+ fileImports,
4459
+ importablePaths,
4460
+ validateLines,
4461
+ validateEventContextPaths
4462
+ };
4463
+ //# sourceMappingURL=chunk-7WJEZ72S.js.map