@cratis/screenplay-language 4.255.0 → 4.257.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundles/compiler/Authoring/QuickFixes.js +2 -2
- package/dist/bundles/compiler/Authoring/QuickFixes.js.map +1 -1
- package/dist/bundles/compiler/Diagnostics/DiagnosticCodes.js +1 -1
- package/dist/bundles/compiler/Diagnostics/DiagnosticCodes.js.map +1 -1
- package/dist/bundles/compiler/Files/PlayApplicationAssembly.js +1 -1
- package/dist/bundles/compiler/Files/PlayApplicationAssembly.js.map +1 -1
- package/dist/bundles/compiler/Files/PlayFolderMerge.js +1 -1
- package/dist/bundles/compiler/Parsing/AuthorizeParser.js +1 -1
- package/dist/bundles/compiler/Parsing/AuthorizeParser.js.map +1 -1
- package/dist/bundles/compiler/Parsing/CaptureParser.js +1 -1
- package/dist/bundles/compiler/Parsing/CommandHandlerValidator.js +1 -1
- package/dist/bundles/compiler/Parsing/CommandHandlerValidator.js.map +1 -1
- package/dist/bundles/compiler/Parsing/CommandParser.js +1 -1
- package/dist/bundles/compiler/Parsing/CommandParser.js.map +1 -1
- package/dist/bundles/compiler/Parsing/FeatureBody.js +1 -1
- package/dist/bundles/compiler/Parsing/ImplementationParser.js +2 -2
- package/dist/bundles/compiler/Parsing/ImplementationParser.js.map +1 -1
- package/dist/bundles/compiler/Parsing/ModuleBody.js +1 -1
- package/dist/bundles/compiler/Parsing/PossibleEventsParser.js +2 -0
- package/dist/bundles/compiler/Parsing/PossibleEventsParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ProducesParser.js +1 -1
- package/dist/bundles/compiler/Parsing/ProjectionParser.js +1 -1
- package/dist/bundles/compiler/Parsing/ProjectionParser.js.map +1 -1
- package/dist/bundles/compiler/Parsing/QueryParser.js +1 -1
- package/dist/bundles/compiler/Parsing/ReadModelMemberTypeValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/ReadModelMemberTypeValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ScreenParser.js +1 -1
- package/dist/bundles/compiler/Parsing/ScreenplayParser.js +1 -1
- package/dist/bundles/compiler/Parsing/ScreenplayParser.js.map +1 -1
- package/dist/bundles/compiler/Parsing/SliceParser.js +1 -1
- package/dist/bundles/compiler/ScreenplayCompiler.js +1 -1
- package/dist/bundles/compiler/ScreenplayCompiler.js.map +1 -1
- package/dist/bundles/compiler/Syntax/ScreenplaySyntaxWalker.js +1 -1
- package/dist/bundles/compiler/Syntax/ScreenplaySyntaxWalker.js.map +1 -1
- package/dist/bundles/compiler/Syntax/SyntaxCollections.js +1 -1
- package/dist/bundles/compiler/Syntax/SyntaxCollections.js.map +1 -1
- package/dist/bundles/compiler/Syntax/SyntaxJson.js +1 -1
- package/dist/bundles/compiler/Syntax/SyntaxJson.js.map +1 -1
- package/dist/bundles/compiler/index.js +1 -1
- package/dist/bundles/diagnostic-codes.js +1 -1
- package/dist/bundles/diagnostic-codes.js.map +1 -1
- package/dist/bundles/keyword-docs.js +1 -1
- package/dist/bundles/keyword-docs.js.map +1 -1
- package/dist/bundles/validation.js +1 -1
- package/dist/bundles/validation.js.map +1 -1
- package/dist/diagnostic-codes.d.ts +1 -0
- package/dist/diagnostic-codes.d.ts.map +1 -1
- package/dist/validation.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{unescapeString as t}from"../Text/StringLiteral.js";import{locationOf as n}from"./SourceLine.js";import{firstWord as r}from"./LineText.js";import{isBlankImplementationHint as i}from"../Text/ImplementationHintText.js";const
|
|
2
|
-
`),location:n(r)}}function parseHandler(t,i){let a=t.peekChild(i.indent);if(a===void 0)return t.error(e.HandlerWithoutImplementation,`Expected a 'file' directive or an inline code block in the handler`,n(i)),null;if(t.reader.takeSignificant(),r(a.content)===`implementation`)return parseImplementation(t,i,a);let o=isFile(a)?parseFile(t,a):null,s=o===null&&isCode(t,a)?parseCode(t,a):null;if(o!==null||s!==null){let a=t.peekChild(i.indent);return a!==void 0&&r(a.content)===`implementation`&&(t.error(e.ConflictingImplementationSources,`A handler cannot mix wrapped and direct sources.`,n(a)),t.skipBlock(i.indent)),{kind:`HandlerSyntax`,file:o,code:s,implementation:null,location:n(i)}}return t.error(e.UnknownHandlerDirective,`Unexpected '${a.content}' in handler - expected 'file <path>' or an inline code block`,n(a)),t.skipBlock(i.indent),null}function parseImplementation(t,i,a){let o=parseImplementationWrapper(t,a);for(let a=t.peekChild(i.indent);a!==void 0;a=t.peekChild(i.indent))t.reader.takeSignificant(),t.error(r(a.content)===`implementation`?e.InvalidImplementationBlock:e.ConflictingImplementationSources,`A handler has one implementation wrapper and cannot mix wrapped and direct sources.`,n(a)),isCode(t,a)?parseCode(t,a):t.skipBlock(a.indent);return{kind:`HandlerSyntax`,...o,location:n(i)}}function parseImplementationWrapper(
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{unescapeString as t}from"../Text/StringLiteral.js";import{locationOf as n}from"./SourceLine.js";import{firstWord as r}from"./LineText.js";import{isBlankImplementationHint as i}from"../Text/ImplementationHintText.js";import{parsePossibleEvents as a}from"./PossibleEventsParser.js";const o=/* @__PURE__ */ RegExp(`^hint[\\u0009-\\u000d\\u0020\\u0085\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000]+"((?:[^"\\\\\\r\\n]|\\\\[^\\r\\n])*)"$`),isFile=e=>r(e.content)===`file`&&e.content.substring(4).trim().length>0,isCode=(e,t)=>t.content.startsWith("```")||e.languages.has(t.content);function parseFile(t,r){let i=r.content.substring(4).trim();return/^(?:[/\\]|[A-Za-z]:[/\\]|~[/\\])/.test(i)&&t.warning(e.AbsoluteFileReference,`'${i}' is an absolute path - a file reference is relative to the repository root, so it means the same thing on every machine`,n(r)),{kind:`FileReferenceSyntax`,path:i,location:n(r)}}const isClosingCodeFence=e=>e.raw.trim()==="```";function parseCode(t,r){let i=r.content.startsWith("```")?r.content.substring(3):r.content;if(!t.languages.has(i))return t.error(e.ExpectedCodeFence,`Expected a registered language on the opening fence, not '${r.content}'`,n(r)),null;let a=r;if(!r.content.startsWith("```")){t.warning(e.LegacyInlineCodeFence,`'${i}' on its own line is deprecated - use '\`\`\`${i}' instead`,n(r));let o=t.reader.peekSignificant();if(o===void 0||o.indent<=r.indent||o.content!=="```"&&o.content!==`\`\`\`${i}`)return t.error(e.ExpectedCodeFence,`Expected an opening \`\`\`${i} fence after '${i}'`,n(r)),null;a=t.reader.takeSignificant()}let o=[];for(;;){let r=t.reader.takeRaw();if(r===void 0){t.error(e.UnclosedCodeBlock,"Unclosed inline code block - expected a closing ``` line",n(a));break}if(isClosingCodeFence(r))break;let i=0;for(;i<a.indent&&r.raw[i]===` `;)i++;o.push(r.raw.substring(i))}return{kind:`CodeBlockSyntax`,language:i,code:o.join(`
|
|
2
|
+
`),location:n(r)}}function parseHandler(e,t){let n=e.peekChild(t.indent)?.content===`may produce`?a(e,e.reader.takeSignificant()):null,r=parseHandlerBody(e,t);return r===null||n===null?r:{...r,possibleEvents:n}}function parseHandlerBody(t,i){let a=t.peekChild(i.indent);if(a===void 0)return t.error(e.HandlerWithoutImplementation,`Expected a 'file' directive or an inline code block in the handler`,n(i)),null;if(t.reader.takeSignificant(),r(a.content)===`implementation`)return parseImplementation(t,i,a);let o=isFile(a)?parseFile(t,a):null,s=o===null&&isCode(t,a)?parseCode(t,a):null;if(o!==null||s!==null){let a=t.peekChild(i.indent);return a!==void 0&&r(a.content)===`implementation`&&(t.error(e.ConflictingImplementationSources,`A handler cannot mix wrapped and direct sources.`,n(a)),t.skipBlock(i.indent)),{kind:`HandlerSyntax`,file:o,code:s,implementation:null,location:n(i)}}return t.error(e.UnknownHandlerDirective,`Unexpected '${a.content}' in handler - expected 'file <path>' or an inline code block`,n(a)),t.skipBlock(i.indent),null}function parseImplementation(t,i,a){let o=parseImplementationWrapper(t,a);for(let a=t.peekChild(i.indent);a!==void 0;a=t.peekChild(i.indent))t.reader.takeSignificant(),t.error(r(a.content)===`implementation`?e.InvalidImplementationBlock:e.ConflictingImplementationSources,`A handler has one implementation wrapper and cannot mix wrapped and direct sources.`,n(a)),isCode(t,a)?parseCode(t,a):t.skipBlock(a.indent);return{kind:`HandlerSyntax`,...o,location:n(i)}}function parseImplementationWrapper(a,s){let c=[],l=null,u=null,d=!1;s.content!==`implementation`&&a.error(e.InvalidImplementationBlock,`Expected 'implementation' with no operand.`,n(s));for(let f=a.peekChild(s.indent);f!==void 0;f=a.peekChild(s.indent))if(a.reader.takeSignificant(),r(f.content)===`hint`||o.test(f.content)){let r=o.exec(f.content),s=r===null?null:t(r[1]);i(s)?a.error(e.InvalidImplementationHint,`Expected 'hint' followed by one nonblank quoted string.`,n(f)):c.push({kind:`ImplementationHintSyntax`,text:s,location:n(f)});let l=a.peekChild(f.indent);l!==void 0&&(a.error(e.InvalidImplementationHint,`A hint cannot have children.`,n(l)),a.skipBlock(f.indent))}else if(isFile(f)||f.content.startsWith("```")){d&&a.error(e.ConflictingImplementationSources,`An implementation has at most one file or inline payload.`,n(f));let t=isFile(f)?parseFile(a,f):null,r=t===null?parseCode(a,f):null;d||(l=t,u=r),d=!0;let i=a.peekChild(f.indent);t!==null&&i!==void 0&&(a.error(e.InvalidImplementationBlock,`A file directive cannot have children.`,n(i)),a.skipBlock(f.indent))}else a.error(e.InvalidImplementationBlock,`Unexpected '${f.content}' in implementation - expected hint, file or a tagged fence.`,n(f)),a.skipBlock(f.indent);return{file:l,code:u,implementation:{kind:`ImplementationSyntax`,hints:c,location:n(s)}}}export{isClosingCodeFence,isCode,isFile,parseCode,parseFile,parseHandler,parseImplementationWrapper};
|
|
3
3
|
//# sourceMappingURL=ImplementationParser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImplementationParser.js","names":["hintPattern","firstWord","line","context","path","DiagnosticCodes","locationOf","language","tag","open","next","lines","strip","body","handler","file","code","extra","source","wrapper","hints","hasPayload","child","match","text","unescapeString","isBlankImplementationHint","nested","parsedFile","parsedCode"],"sources":["../../../../../../Compiler/Parsing/ImplementationParser.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { DiagnosticCodes } from '../Diagnostics/DiagnosticCodes';\nimport { CodeBlockSyntax, FileReferenceSyntax, HandlerSyntax, ImplementationHintSyntax, ImplementationSyntax } from '../Syntax/Implementations';\nimport { isBlankImplementationHint } from '../Text/ImplementationHintText';\nimport { unescapeString } from '../Text/StringLiteral';\nimport { firstWord } from './LineText';\nimport { ParserContext } from './ParserContext';\nimport { locationOf, SourceLine } from './SourceLine';\n\n// Match ImplementationHintText's White_Space set, not ECMAScript \\s. A hint stays on one CR/LF-delimited source line.\n// eslint-disable-next-line no-control-regex -- The shared whitespace set deliberately includes U+0009 through U+000D.\nconst hintPattern = new RegExp('^hint[\\\\u0009-\\\\u000d\\\\u0020\\\\u0085\\\\u00a0\\\\u1680\\\\u2000-\\\\u200a\\\\u2028\\\\u2029\\\\u202f\\\\u205f\\\\u3000]+\"((?:[^\"\\\\\\\\\\\\r\\\\n]|\\\\\\\\[^\\\\r\\\\n])*)\"$');\nexport const isFile = (line: SourceLine): boolean => firstWord(line.content) === 'file' && line.content.substring(4).trim().length > 0;\nexport const isCode = (context: ParserContext, line: SourceLine): boolean => line.content.startsWith('```') || context.languages.has(line.content);\n\nexport function parseFile(context: ParserContext, line: SourceLine): FileReferenceSyntax {\n const path = line.content.substring(4).trim();\n if (/^(?:[/\\\\]|[A-Za-z]:[/\\\\]|~[/\\\\])/.test(path)) {\n context.warning(DiagnosticCodes.AbsoluteFileReference, `'${path}' is an absolute path - a file reference is relative to the repository root, so it means the same thing on every machine`, locationOf(line));\n }\n return { kind: 'FileReferenceSyntax', path, location: locationOf(line) };\n}\n\nexport const isClosingCodeFence = (line: SourceLine): boolean => line.raw.trim() === '```';\n\nexport function parseCode(context: ParserContext, tag: SourceLine): CodeBlockSyntax | null {\n const language = tag.content.startsWith('```') ? tag.content.substring(3) : tag.content;\n if (!context.languages.has(language)) {\n context.error(DiagnosticCodes.ExpectedCodeFence, `Expected a registered language on the opening fence, not '${tag.content}'`, locationOf(tag));\n return null;\n }\n let open = tag;\n if (!tag.content.startsWith('```')) {\n context.warning(DiagnosticCodes.LegacyInlineCodeFence, `'${language}' on its own line is deprecated - use '\\`\\`\\`${language}' instead`, locationOf(tag));\n const next = context.reader.peekSignificant();\n if (next === undefined || next.indent <= tag.indent || (next.content !== '```' && next.content !== `\\`\\`\\`${language}`)) {\n context.error(DiagnosticCodes.ExpectedCodeFence, `Expected an opening \\`\\`\\`${language} fence after '${language}'`, locationOf(tag));\n return null;\n }\n open = context.reader.takeSignificant();\n }\n const lines: string[] = [];\n for (;;) {\n const line = context.reader.takeRaw();\n if (line === undefined) {\n context.error(DiagnosticCodes.UnclosedCodeBlock, 'Unclosed inline code block - expected a closing ``` line', locationOf(open));\n break;\n }\n if (isClosingCodeFence(line)) break;\n let strip = 0;\n while (strip < open.indent && line.raw[strip] === ' ') strip++;\n lines.push(line.raw.substring(strip));\n }\n return { kind: 'CodeBlockSyntax', language, code: lines.join('\\n'), location: locationOf(tag) };\n}\n\nexport function parseHandler(context: ParserContext, handler: SourceLine): HandlerSyntax | null {\n const body = context.peekChild(handler.indent);\n if (body === undefined) {\n context.error(DiagnosticCodes.HandlerWithoutImplementation, \"Expected a 'file' directive or an inline code block in the handler\", locationOf(handler));\n return null;\n }\n context.reader.takeSignificant();\n if (firstWord(body.content) === 'implementation') return parseImplementation(context, handler, body);\n const file = isFile(body) ? parseFile(context, body) : null;\n const code = file === null && isCode(context, body) ? parseCode(context, body) : null;\n if (file !== null || code !== null) {\n const extra = context.peekChild(handler.indent);\n if (extra !== undefined && firstWord(extra.content) === 'implementation') {\n context.error(DiagnosticCodes.ConflictingImplementationSources, 'A handler cannot mix wrapped and direct sources.', locationOf(extra));\n context.skipBlock(handler.indent);\n }\n return { kind: 'HandlerSyntax', file, code, implementation: null, location: locationOf(handler) };\n }\n context.error(DiagnosticCodes.UnknownHandlerDirective, `Unexpected '${body.content}' in handler - expected 'file <path>' or an inline code block`, locationOf(body));\n context.skipBlock(handler.indent);\n return null;\n}\n\nfunction parseImplementation(context: ParserContext, handler: SourceLine, wrapper: SourceLine): HandlerSyntax {\n const source = parseImplementationWrapper(context, wrapper);\n for (let extra = context.peekChild(handler.indent); extra !== undefined; extra = context.peekChild(handler.indent)) {\n context.reader.takeSignificant();\n context.error(firstWord(extra.content) === 'implementation' ? DiagnosticCodes.InvalidImplementationBlock : DiagnosticCodes.ConflictingImplementationSources,\n 'A handler has one implementation wrapper and cannot mix wrapped and direct sources.', locationOf(extra));\n if (isCode(context, extra)) parseCode(context, extra);\n else context.skipBlock(extra.indent);\n }\n return { kind: 'HandlerSyntax', ...source, location: locationOf(handler) };\n}\n\nexport function parseImplementationWrapper(context: ParserContext, wrapper: SourceLine): { file: FileReferenceSyntax | null; code: CodeBlockSyntax | null; implementation: ImplementationSyntax } {\n const hints: ImplementationHintSyntax[] = [];\n let file: FileReferenceSyntax | null = null;\n let code: CodeBlockSyntax | null = null;\n let hasPayload = false;\n if (wrapper.content !== 'implementation') context.error(DiagnosticCodes.InvalidImplementationBlock, \"Expected 'implementation' with no operand.\", locationOf(wrapper));\n for (let child = context.peekChild(wrapper.indent); child !== undefined; child = context.peekChild(wrapper.indent)) {\n context.reader.takeSignificant();\n if (firstWord(child.content) === 'hint' || hintPattern.test(child.content)) {\n const match = hintPattern.exec(child.content);\n const text = match === null ? null : unescapeString(match[1]);\n if (isBlankImplementationHint(text)) context.error(DiagnosticCodes.InvalidImplementationHint, \"Expected 'hint' followed by one nonblank quoted string.\", locationOf(child));\n else hints.push({ kind: 'ImplementationHintSyntax', text: text!, location: locationOf(child) });\n const nested = context.peekChild(child.indent);\n if (nested !== undefined) {\n context.error(DiagnosticCodes.InvalidImplementationHint, 'A hint cannot have children.', locationOf(nested));\n context.skipBlock(child.indent);\n }\n } else if (isFile(child) || child.content.startsWith('```')) {\n if (hasPayload) context.error(DiagnosticCodes.ConflictingImplementationSources, 'An implementation has at most one file or inline payload.', locationOf(child));\n const parsedFile = isFile(child) ? parseFile(context, child) : null;\n const parsedCode = parsedFile === null ? parseCode(context, child) : null;\n if (!hasPayload) { file = parsedFile; code = parsedCode; }\n hasPayload = true;\n const nested = context.peekChild(child.indent);\n if (parsedFile !== null && nested !== undefined) {\n context.error(DiagnosticCodes.InvalidImplementationBlock, 'A file directive cannot have children.', locationOf(nested));\n context.skipBlock(child.indent);\n }\n } else {\n context.error(DiagnosticCodes.InvalidImplementationBlock, `Unexpected '${child.content}' in implementation - expected hint, file or a tagged fence.`, locationOf(child));\n context.skipBlock(child.indent);\n }\n }\n return { file, code, implementation: { kind: 'ImplementationSyntax', hints, location: locationOf(wrapper) } };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ImplementationParser.js","names":["hintPattern","firstWord","line","context","path","DiagnosticCodes","locationOf","language","tag","open","next","lines","strip","possibleEvents","handler","parsePossibleEvents","parsed","body","file","code","extra","source","wrapper","hints","hasPayload","child","match","text","unescapeString","isBlankImplementationHint","nested","parsedFile","parsedCode"],"sources":["../../../../../../Compiler/Parsing/ImplementationParser.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { DiagnosticCodes } from '../Diagnostics/DiagnosticCodes';\nimport { CodeBlockSyntax, FileReferenceSyntax, HandlerSyntax, ImplementationHintSyntax, ImplementationSyntax } from '../Syntax/Implementations';\nimport { isBlankImplementationHint } from '../Text/ImplementationHintText';\nimport { unescapeString } from '../Text/StringLiteral';\nimport { firstWord } from './LineText';\nimport { ParserContext } from './ParserContext';\nimport { parsePossibleEvents } from './PossibleEventsParser';\nimport { locationOf, SourceLine } from './SourceLine';\n\n// Match ImplementationHintText's White_Space set, not ECMAScript \\s. A hint stays on one CR/LF-delimited source line.\n// eslint-disable-next-line no-control-regex -- The shared whitespace set deliberately includes U+0009 through U+000D.\nconst hintPattern = new RegExp('^hint[\\\\u0009-\\\\u000d\\\\u0020\\\\u0085\\\\u00a0\\\\u1680\\\\u2000-\\\\u200a\\\\u2028\\\\u2029\\\\u202f\\\\u205f\\\\u3000]+\"((?:[^\"\\\\\\\\\\\\r\\\\n]|\\\\\\\\[^\\\\r\\\\n])*)\"$');\nexport const isFile = (line: SourceLine): boolean => firstWord(line.content) === 'file' && line.content.substring(4).trim().length > 0;\nexport const isCode = (context: ParserContext, line: SourceLine): boolean => line.content.startsWith('```') || context.languages.has(line.content);\n\nexport function parseFile(context: ParserContext, line: SourceLine): FileReferenceSyntax {\n const path = line.content.substring(4).trim();\n if (/^(?:[/\\\\]|[A-Za-z]:[/\\\\]|~[/\\\\])/.test(path)) {\n context.warning(DiagnosticCodes.AbsoluteFileReference, `'${path}' is an absolute path - a file reference is relative to the repository root, so it means the same thing on every machine`, locationOf(line));\n }\n return { kind: 'FileReferenceSyntax', path, location: locationOf(line) };\n}\n\nexport const isClosingCodeFence = (line: SourceLine): boolean => line.raw.trim() === '```';\n\nexport function parseCode(context: ParserContext, tag: SourceLine): CodeBlockSyntax | null {\n const language = tag.content.startsWith('```') ? tag.content.substring(3) : tag.content;\n if (!context.languages.has(language)) {\n context.error(DiagnosticCodes.ExpectedCodeFence, `Expected a registered language on the opening fence, not '${tag.content}'`, locationOf(tag));\n return null;\n }\n let open = tag;\n if (!tag.content.startsWith('```')) {\n context.warning(DiagnosticCodes.LegacyInlineCodeFence, `'${language}' on its own line is deprecated - use '\\`\\`\\`${language}' instead`, locationOf(tag));\n const next = context.reader.peekSignificant();\n if (next === undefined || next.indent <= tag.indent || (next.content !== '```' && next.content !== `\\`\\`\\`${language}`)) {\n context.error(DiagnosticCodes.ExpectedCodeFence, `Expected an opening \\`\\`\\`${language} fence after '${language}'`, locationOf(tag));\n return null;\n }\n open = context.reader.takeSignificant();\n }\n const lines: string[] = [];\n for (;;) {\n const line = context.reader.takeRaw();\n if (line === undefined) {\n context.error(DiagnosticCodes.UnclosedCodeBlock, 'Unclosed inline code block - expected a closing ``` line', locationOf(open));\n break;\n }\n if (isClosingCodeFence(line)) break;\n let strip = 0;\n while (strip < open.indent && line.raw[strip] === ' ') strip++;\n lines.push(line.raw.substring(strip));\n }\n return { kind: 'CodeBlockSyntax', language, code: lines.join('\\n'), location: locationOf(tag) };\n}\n\nexport function parseHandler(context: ParserContext, handler: SourceLine): HandlerSyntax | null {\n const first = context.peekChild(handler.indent);\n const possibleEvents = first?.content === 'may produce' ? parsePossibleEvents(context, context.reader.takeSignificant()!) : null;\n const parsed = parseHandlerBody(context, handler);\n return parsed === null || possibleEvents === null ? parsed : { ...parsed, possibleEvents };\n}\n\nfunction parseHandlerBody(context: ParserContext, handler: SourceLine): HandlerSyntax | null {\n const body = context.peekChild(handler.indent);\n if (body === undefined) {\n context.error(DiagnosticCodes.HandlerWithoutImplementation, \"Expected a 'file' directive or an inline code block in the handler\", locationOf(handler));\n return null;\n }\n context.reader.takeSignificant();\n if (firstWord(body.content) === 'implementation') return parseImplementation(context, handler, body);\n const file = isFile(body) ? parseFile(context, body) : null;\n const code = file === null && isCode(context, body) ? parseCode(context, body) : null;\n if (file !== null || code !== null) {\n const extra = context.peekChild(handler.indent);\n if (extra !== undefined && firstWord(extra.content) === 'implementation') {\n context.error(DiagnosticCodes.ConflictingImplementationSources, 'A handler cannot mix wrapped and direct sources.', locationOf(extra));\n context.skipBlock(handler.indent);\n }\n return { kind: 'HandlerSyntax', file, code, implementation: null, location: locationOf(handler) };\n }\n context.error(DiagnosticCodes.UnknownHandlerDirective, `Unexpected '${body.content}' in handler - expected 'file <path>' or an inline code block`, locationOf(body));\n context.skipBlock(handler.indent);\n return null;\n}\n\nfunction parseImplementation(context: ParserContext, handler: SourceLine, wrapper: SourceLine): HandlerSyntax {\n const source = parseImplementationWrapper(context, wrapper);\n for (let extra = context.peekChild(handler.indent); extra !== undefined; extra = context.peekChild(handler.indent)) {\n context.reader.takeSignificant();\n context.error(firstWord(extra.content) === 'implementation' ? DiagnosticCodes.InvalidImplementationBlock : DiagnosticCodes.ConflictingImplementationSources,\n 'A handler has one implementation wrapper and cannot mix wrapped and direct sources.', locationOf(extra));\n if (isCode(context, extra)) parseCode(context, extra);\n else context.skipBlock(extra.indent);\n }\n return { kind: 'HandlerSyntax', ...source, location: locationOf(handler) };\n}\n\nexport function parseImplementationWrapper(context: ParserContext, wrapper: SourceLine): { file: FileReferenceSyntax | null; code: CodeBlockSyntax | null; implementation: ImplementationSyntax } {\n const hints: ImplementationHintSyntax[] = [];\n let file: FileReferenceSyntax | null = null;\n let code: CodeBlockSyntax | null = null;\n let hasPayload = false;\n if (wrapper.content !== 'implementation') context.error(DiagnosticCodes.InvalidImplementationBlock, \"Expected 'implementation' with no operand.\", locationOf(wrapper));\n for (let child = context.peekChild(wrapper.indent); child !== undefined; child = context.peekChild(wrapper.indent)) {\n context.reader.takeSignificant();\n if (firstWord(child.content) === 'hint' || hintPattern.test(child.content)) {\n const match = hintPattern.exec(child.content);\n const text = match === null ? null : unescapeString(match[1]);\n if (isBlankImplementationHint(text)) context.error(DiagnosticCodes.InvalidImplementationHint, \"Expected 'hint' followed by one nonblank quoted string.\", locationOf(child));\n else hints.push({ kind: 'ImplementationHintSyntax', text: text!, location: locationOf(child) });\n const nested = context.peekChild(child.indent);\n if (nested !== undefined) {\n context.error(DiagnosticCodes.InvalidImplementationHint, 'A hint cannot have children.', locationOf(nested));\n context.skipBlock(child.indent);\n }\n } else if (isFile(child) || child.content.startsWith('```')) {\n if (hasPayload) context.error(DiagnosticCodes.ConflictingImplementationSources, 'An implementation has at most one file or inline payload.', locationOf(child));\n const parsedFile = isFile(child) ? parseFile(context, child) : null;\n const parsedCode = parsedFile === null ? parseCode(context, child) : null;\n if (!hasPayload) { file = parsedFile; code = parsedCode; }\n hasPayload = true;\n const nested = context.peekChild(child.indent);\n if (parsedFile !== null && nested !== undefined) {\n context.error(DiagnosticCodes.InvalidImplementationBlock, 'A file directive cannot have children.', locationOf(nested));\n context.skipBlock(child.indent);\n }\n } else {\n context.error(DiagnosticCodes.InvalidImplementationBlock, `Unexpected '${child.content}' in implementation - expected hint, file or a tagged fence.`, locationOf(child));\n context.skipBlock(child.indent);\n }\n }\n return { file, code, implementation: { kind: 'ImplementationSyntax', hints, location: locationOf(wrapper) } };\n}\n"],"mappings":"wZAcA,MAAMA,EAAc,gBAAI,OAAO,6IAA6I,EAC/J,OAAU,GAA8BC,EAAUC,EAAK,OAAO,IAAM,QAAUA,EAAK,QAAQ,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAS,EACxH,QAAU,EAAwB,IAA8BA,EAAK,QAAQ,WAAW,KAAK,GAAKC,EAAQ,UAAU,IAAID,EAAK,OAAO,EAEjJ,SAAgB,UAAU,EAAwB,EAAuC,CACrF,IAAME,EAAOF,EAAK,QAAQ,UAAU,CAAC,CAAC,CAAC,KAAK,EAI5C,MAHI,mCAAmC,KAAKE,CAAI,GAC5CD,EAAQ,QAAQE,EAAgB,sBAAuB,IAAID,EAAK,0HAA2HE,EAAWJ,CAAI,CAAC,EAExM,CAAE,KAAM,sBAAuB,OAAM,SAAUI,EAAWJ,CAAI,CAAE,CAC3E,CAEA,MAAa,mBAAsB,GAA8BA,EAAK,IAAI,KAAK,IAAM,MAErF,SAAgB,UAAU,EAAwB,EAAyC,CACvF,IAAMK,EAAWC,EAAI,QAAQ,WAAW,KAAK,EAAIA,EAAI,QAAQ,UAAU,CAAC,EAAIA,EAAI,QAChF,GAAI,CAACL,EAAQ,UAAU,IAAII,CAAQ,EAE/B,OADAJ,EAAQ,MAAME,EAAgB,kBAAmB,6DAA6DG,EAAI,QAAQ,GAAIF,EAAWE,CAAG,CAAC,EACtI,KAEX,IAAIC,EAAOD,EACX,GAAI,CAACA,EAAI,QAAQ,WAAW,KAAK,EAAG,CAChCL,EAAQ,QAAQE,EAAgB,sBAAuB,IAAIE,EAAS,+CAA+CA,EAAS,WAAYD,EAAWE,CAAG,CAAC,EACvJ,IAAME,EAAOP,EAAQ,OAAO,gBAAgB,EAC5C,GAAIO,IAAS,IAAA,IAAaA,EAAK,QAAUF,EAAI,QAAWE,EAAK,UAAY,OAASA,EAAK,UAAY,SAASH,IAExG,OADAJ,EAAQ,MAAME,EAAgB,kBAAmB,6BAA6BE,EAAS,gBAAgBA,EAAS,GAAID,EAAWE,CAAG,CAAC,EAC5H,KAEX,EAAOL,EAAQ,OAAO,gBAAgB,CAC1C,CACA,IAAMQ,EAAkB,CAAC,EACzB,OAAS,CACL,IAAMT,EAAOC,EAAQ,OAAO,QAAQ,EACpC,GAAID,IAAS,IAAA,GAAW,CACpBC,EAAQ,MAAME,EAAgB,kBAAmB,2DAA4DC,EAAWG,CAAI,CAAC,EAC7H,KACJ,CACA,GAAI,mBAAmBP,CAAI,EAAG,MAC9B,IAAIU,EAAQ,EACZ,KAAOA,EAAQH,EAAK,QAAUP,EAAK,IAAIU,KAAW,KAAK,IACvDD,EAAM,KAAKT,EAAK,IAAI,UAAUU,CAAK,CAAC,CACxC,CACA,MAAO,CAAE,KAAM,kBAAmB,WAAU,KAAMD,EAAM,KAAK;CAAI,EAAG,SAAUL,EAAWE,CAAG,CAAE,CAClG,CAEA,SAAgB,aAAa,EAAwB,EAA2C,CAE5F,IAAMK,EADQV,EAAQ,UAAUW,EAAQ,MACb,CAAC,EAAE,UAAY,cAAgBC,EAAoBZ,EAASA,EAAQ,OAAO,gBAAgB,CAAE,EAAI,KACtHa,EAAS,iBAAiBb,EAASW,CAAO,EAChD,OAAOE,IAAW,MAAQH,IAAmB,KAAOG,EAAS,CAAE,GAAGA,EAAQ,gBAAe,CAC7F,CAEA,SAAS,iBAAiB,EAAwB,EAA2C,CACzF,IAAMC,EAAOd,EAAQ,UAAUW,EAAQ,MAAM,EAC7C,GAAIG,IAAS,IAAA,GAET,OADAd,EAAQ,MAAME,EAAgB,6BAA8B,qEAAsEC,EAAWQ,CAAO,CAAC,EAC9I,KAGX,GADAX,EAAQ,OAAO,gBAAgB,EAC3BF,EAAUgB,EAAK,OAAO,IAAM,iBAAkB,OAAO,oBAAoBd,EAASW,EAASG,CAAI,EACnG,IAAMC,EAAO,OAAOD,CAAI,EAAI,UAAUd,EAASc,CAAI,EAAI,KACjDE,EAAOD,IAAS,MAAQ,OAAOf,EAASc,CAAI,EAAI,UAAUd,EAASc,CAAI,EAAI,KACjF,GAAIC,IAAS,MAAQC,IAAS,KAAM,CAChC,IAAMC,EAAQjB,EAAQ,UAAUW,EAAQ,MAAM,EAK9C,OAJIM,IAAU,IAAA,IAAanB,EAAUmB,EAAM,OAAO,IAAM,mBACpDjB,EAAQ,MAAME,EAAgB,iCAAkC,mDAAoDC,EAAWc,CAAK,CAAC,EACrIjB,EAAQ,UAAUW,EAAQ,MAAM,GAE7B,CAAE,KAAM,gBAAiB,OAAM,OAAM,eAAgB,KAAM,SAAUR,EAAWQ,CAAO,CAAE,CACpG,CAGA,OAFAX,EAAQ,MAAME,EAAgB,wBAAyB,eAAeY,EAAK,QAAQ,+DAAgEX,EAAWW,CAAI,CAAC,EACnKd,EAAQ,UAAUW,EAAQ,MAAM,EACzB,IACX,CAEA,SAAS,oBAAoB,EAAwB,EAAqB,EAAoC,CAC1G,IAAMO,EAAS,2BAA2BlB,EAASmB,CAAO,EAC1D,IAAK,IAAIF,EAAQjB,EAAQ,UAAUW,EAAQ,MAAM,EAAGM,IAAU,IAAA,GAAW,EAAQjB,EAAQ,UAAUW,EAAQ,MAAM,EAC7GX,EAAQ,OAAO,gBAAgB,EAC/BA,EAAQ,MAAMF,EAAUmB,EAAM,OAAO,IAAM,iBAAmBf,EAAgB,2BAA6BA,EAAgB,iCACvH,sFAAuFC,EAAWc,CAAK,CAAC,EACxG,OAAOjB,EAASiB,CAAK,EAAG,UAAUjB,EAASiB,CAAK,EAC/CjB,EAAQ,UAAUiB,EAAM,MAAM,EAEvC,MAAO,CAAE,KAAM,gBAAiB,GAAGC,EAAQ,SAAUf,EAAWQ,CAAO,CAAE,CAC7E,CAEA,SAAgB,2BAA2B,EAAwB,EAA+H,CAC9L,IAAMS,EAAoC,CAAC,EACvCL,EAAmC,KACnCC,EAA+B,KAC/BK,EAAa,GACbF,EAAQ,UAAY,kBAAkBnB,EAAQ,MAAME,EAAgB,2BAA4B,6CAA8CC,EAAWgB,CAAO,CAAC,EACrK,IAAK,IAAIG,EAAQtB,EAAQ,UAAUmB,EAAQ,MAAM,EAAGG,IAAU,IAAA,GAAW,EAAQtB,EAAQ,UAAUmB,EAAQ,MAAM,EAE7G,GADAnB,EAAQ,OAAO,gBAAgB,EAC3BF,EAAUwB,EAAM,OAAO,IAAM,QAAUzB,EAAY,KAAKyB,EAAM,OAAO,EAAG,CACxE,IAAMC,EAAQ1B,EAAY,KAAKyB,EAAM,OAAO,EACtCE,EAAOD,IAAU,KAAO,KAAOE,EAAeF,EAAM,EAAE,EACxDG,EAA0BF,CAAI,EAAGxB,EAAQ,MAAME,EAAgB,0BAA2B,0DAA2DC,EAAWmB,CAAK,CAAC,EACrKF,EAAM,KAAK,CAAE,KAAM,2BAAkC,OAAO,SAAUjB,EAAWmB,CAAK,CAAE,CAAC,EAC9F,IAAMK,EAAS3B,EAAQ,UAAUsB,EAAM,MAAM,EACzCK,IAAW,IAAA,KACX3B,EAAQ,MAAME,EAAgB,0BAA2B,+BAAgCC,EAAWwB,CAAM,CAAC,EAC3G3B,EAAQ,UAAUsB,EAAM,MAAM,EAEtC,MAAO,GAAI,OAAOA,CAAK,GAAKA,EAAM,QAAQ,WAAW,KAAK,EAAG,CACrDD,GAAYrB,EAAQ,MAAME,EAAgB,iCAAkC,4DAA6DC,EAAWmB,CAAK,CAAC,EAC9J,IAAMM,EAAa,OAAON,CAAK,EAAI,UAAUtB,EAASsB,CAAK,EAAI,KACzDO,EAAaD,IAAe,KAAO,UAAU5B,EAASsB,CAAK,EAAI,KAChED,IAAc,EAAOO,EAAY,EAAOC,GAC7C,EAAa,GACb,IAAMF,EAAS3B,EAAQ,UAAUsB,EAAM,MAAM,EACzCM,IAAe,MAAQD,IAAW,IAAA,KAClC3B,EAAQ,MAAME,EAAgB,2BAA4B,yCAA0CC,EAAWwB,CAAM,CAAC,EACtH3B,EAAQ,UAAUsB,EAAM,MAAM,EAEtC,MACItB,EAAQ,MAAME,EAAgB,2BAA4B,eAAeoB,EAAM,QAAQ,8DAA+DnB,EAAWmB,CAAK,CAAC,EACvKtB,EAAQ,UAAUsB,EAAM,MAAM,EAGtC,MAAO,CAAE,OAAM,OAAM,eAAgB,CAAE,KAAM,uBAAwB,QAAO,SAAUnB,EAAWgB,CAAO,CAAE,CAAE,CAChH"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{pattern as t}from"../Text/patterns.js";import{locationOf as n}from"./SourceLine.js";import{
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{pattern as t}from"../Text/patterns.js";import{locationOf as n}from"./SourceLine.js";import{combineAuthorize as r,parseAuthorize as i}from"./AuthorizeParser.js";import{firstWord as a}from"./LineText.js";import{parseDescription as o}from"./DescriptionParser.js";import{parsePurposeReference as s}from"./PurposeParser.js";import{parseDocumentation as c}from"./DocumentationParser.js";import{parseDependsOn as l}from"./DependsOnParser.js";import{parseFileImport as u}from"./FileImportParser.js";import{collectInputUses as d}from"./InputUses.js";import{misplacedReactionIdentity as f}from"./ReactionIdentityParser.js";import{parseExample as p}from"./SpecificationExampleParser.js";import{parseToolbar as m}from"./ScreenParser.js";import{parseFeature as h}from"./FeatureBody.js";const g=t(`^module\\s+([A-Za-z_]\\w*)$`),_=/* @__PURE__ */ new Set([`on`,`uses`,`screen`,`dialog`,`form`,`contribute`,`navigation`,`template`]),v=`description, documentation, depends on <Name>, authorize, import, screen template, dialog template, form, contribute, toolbar, navigation, feature, example, 'on <trigger>' or 'uses <Behavior>'`;var ModuleBody=class{name;#e=[];#t=[];#n=[];#r=[];#i=[];#a=[];#o=null;#s=null;#c=null;constructor(e){this.name=e}tryParse(t,n){let g=a(n.content);switch(g){case`runs`:return f(t,n),!0;case`description`:return this.#o=o(t,n,this.#o,`Module '${this.name}'`),!0;case`documentation`:return this.#s=c(t,n,this.#s,`Module '${this.name}'`),!0;case`depends`:return l(t,n,this.#r,e.UnknownModuleDirective),!0;case`purpose`:return s(t,n,this.#i),!0;case`authorize`:return this.#c=r(this.#c,i(t,n)),!0;case`import`:return u(t,n,this.#n),!0;case`example`:return this.#t.push(p(t,n)),!0;case`toolbar`:return this.#a.push(m(t,n)),!0;case`feature`:return this.#e.push(h(t,n)),!0;default:return _.has(g)?(d(t,n),!0):!1}}parseChildren(t,r){for(let i=t.peekChild(r.indent);i!==void 0;i=t.peekChild(r.indent))t.reader.takeSignificant(),this.tryParse(t,i)||(t.error(e.UnknownModuleDirective,`Unexpected '${a(i.content)}' in module body - expected ${v}`,n(i)),t.skipBlock(i.indent))}build(e,t=!1){return{kind:`ModuleSyntax`,name:this.name,description:this.#o,documentation:this.#s,authorize:this.#c,dependsOn:this.#r,purposes:this.#i,...this.#a.length>0?{toolbars:this.#a}:{},features:this.#e,examples:this.#t,fileImports:this.#n,isPlacement:t,location:e}}};function parseModule(t,r){let i=g.exec(r.content)?.[1]??``;i===``&&t.error(e.InvalidModuleDeclaration,`Invalid module declaration '${r.content}' - expected 'module <Name>'`,n(r));let a=new ModuleBody(i),o=t.scope;return t.scope=[i],a.parseChildren(t,r),t.scope=o,a.build(n(r))}export{ModuleBody,v as moduleBodyExpected,g as modulePattern,parseModule};
|
|
2
2
|
//# sourceMappingURL=ModuleBody.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{locationOf as t}from"./SourceLine.js";import{firstWord as n}from"./LineText.js";import{parseCommandStream as r}from"./EventSourceParser.js";import{parseTag as i}from"./DeclarationParsers.js";function parsePossibleEvents(n,r){let i=[],a=/* @__PURE__ */ new Set;for(;n.peekChild(r.indent)!==void 0;){let r=n.reader.takeSignificant(),o=/^([A-Z]\w*(?:\.[A-Za-z_]\w*)*)(?:\s+for\s+(?:(one\s+of)\s+)?([A-Za-z_]\w*))?$/.exec(r.content);if(o===null){invalid(n,r);continue}if(a.has(o[1])){n.error(e.InvalidPossibleEventsDeclaration,`Possible event '${o[1]}' is declared more than once; one destination rule is allowed per event type.`,t(r)),n.skipBlock(r.indent);continue}a.add(o[1]);let[s,c]=parseMetadata(n,r);i.push({kind:`PossibleEventSyntax`,event:o[1],property:o[3]??null,oneOf:o[2]!==void 0,stream:s,tags:c,location:t(r)})}return{kind:`PossibleEventsSyntax`,events:i,location:t(r)}}function parseMetadata(e,t){let r=null,i=[];for(;e.peekChild(t.indent)!==void 0;){let t=e.reader.takeSignificant();n(t.content)===`stream`?r=parseRoute(e,t,r):n(t.content)===`tag`?collectTag(e,t,i):invalid(e,t)}return[r,i]}function collectTag(e,t,n){let r=i(e,t,!1);r!==void 0&&n.push(r)}function parseRoute(n,i,a){let o=/^stream\s+([A-Za-z_]\w*\.[A-Za-z_]\w*)$/.exec(i.content);if(a!==null||o===null)return n.error(e.InvalidCommandStream,a===null?`Expected 'stream <Source>.<Stream>'.`:`A production can declare at most one stream route.`,t(i)),n.skipBlock(i.indent),a;let s=t(i),c={kind:`PropertySyntax`,name:`stream`,type:{kind:`TypeRefSyntax`,name:o[1],isCollection:!1,isOptional:!1,location:{...s,column:i.indent+i.content.indexOf(o[1])+1}},isIdentifier:!1,location:s};return r(n,i,c,!1)}function invalid(n,r){n.error(e.InvalidPossibleEventsDeclaration,`Expected an event name, optionally followed by 'for <property>' or 'for one of <collection property>'; entries accept only stream and tag children.`,t(r)),n.skipBlock(r.indent)}export{parsePossibleEvents};
|
|
2
|
+
//# sourceMappingURL=PossibleEventsParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PossibleEventsParser.js","names":["events","names","context","header","line","match","DiagnosticCodes","locationOf","stream","tags","child","firstWord","tag","parseTag","previous","location","candidate","parseCommandStream"],"sources":["../../../../../../Compiler/Parsing/PossibleEventsParser.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { DiagnosticCodes } from '../Diagnostics/DiagnosticCodes';\nimport { CommandStreamSyntax } from '../Syntax/CommandStreamSyntax';\nimport { PropertySyntax, TagSyntax } from '../Syntax/Declarations';\nimport { PossibleEventSyntax } from '../Syntax/PossibleEventSyntax';\nimport { PossibleEventsSyntax } from '../Syntax/PossibleEventsSyntax';\nimport { parseCommandStream } from './EventSourceParser';\nimport { ParserContext } from './ParserContext';\nimport { firstWord } from './LineText';\nimport { locationOf, SourceLine } from './SourceLine';\nimport { parseTag } from './DeclarationParsers';\n\nexport function parsePossibleEvents(context: ParserContext, header: SourceLine): PossibleEventsSyntax {\n const events: PossibleEventSyntax[] = [];\n const names = new Set<string>();\n while (context.peekChild(header.indent) !== undefined) {\n const line = context.reader.takeSignificant()!;\n const match = /^([A-Z]\\w*(?:\\.[A-Za-z_]\\w*)*)(?:\\s+for\\s+(?:(one\\s+of)\\s+)?([A-Za-z_]\\w*))?$/.exec(line.content);\n if (match === null) {\n invalid(context, line);\n continue;\n }\n if (names.has(match[1])) {\n context.error(DiagnosticCodes.InvalidPossibleEventsDeclaration, `Possible event '${match[1]}' is declared more than once; one destination rule is allowed per event type.`, locationOf(line));\n context.skipBlock(line.indent);\n continue;\n }\n names.add(match[1]);\n const [stream, tags] = parseMetadata(context, line);\n events.push({ kind: 'PossibleEventSyntax', event: match[1], property: match[3] ?? null, oneOf: match[2] !== undefined, stream, tags, location: locationOf(line) });\n }\n return { kind: 'PossibleEventsSyntax', events, location: locationOf(header) };\n}\n\nfunction parseMetadata(context: ParserContext, line: SourceLine): [CommandStreamSyntax | null, TagSyntax[]] {\n let stream: CommandStreamSyntax | null = null;\n const tags: TagSyntax[] = [];\n while (context.peekChild(line.indent) !== undefined) {\n const child = context.reader.takeSignificant()!;\n if (firstWord(child.content) === 'stream') {\n stream = parseRoute(context, child, stream);\n } else if (firstWord(child.content) === 'tag') {\n collectTag(context, child, tags);\n } else {\n invalid(context, child);\n }\n }\n return [stream, tags];\n}\n\nfunction collectTag(context: ParserContext, line: SourceLine, tags: TagSyntax[]): void {\n const tag = parseTag(context, line, false);\n if (tag !== undefined) tags.push(tag);\n}\n\nfunction parseRoute(context: ParserContext, line: SourceLine, previous: CommandStreamSyntax | null): CommandStreamSyntax | null {\n const match = /^stream\\s+([A-Za-z_]\\w*\\.[A-Za-z_]\\w*)$/.exec(line.content);\n if (previous !== null || match === null) {\n context.error(DiagnosticCodes.InvalidCommandStream, previous !== null ? 'A production can declare at most one stream route.' : \"Expected 'stream <Source>.<Stream>'.\", locationOf(line));\n context.skipBlock(line.indent);\n return previous;\n }\n const location = locationOf(line);\n const candidate: PropertySyntax = { kind: 'PropertySyntax', name: 'stream', type: { kind: 'TypeRefSyntax', name: match[1], isCollection: false, isOptional: false, location: { ...location, column: line.indent + line.content.indexOf(match[1]) + 1 } }, isIdentifier: false, location };\n return parseCommandStream(context, line, candidate, false);\n}\n\nfunction invalid(context: ParserContext, line: SourceLine): void {\n context.error(DiagnosticCodes.InvalidPossibleEventsDeclaration, \"Expected an event name, optionally followed by 'for <property>' or 'for one of <collection property>'; entries accept only stream and tag children.\", locationOf(line));\n context.skipBlock(line.indent);\n}\n"],"mappings":"+TAcA,SAAgB,oBAAoB,EAAwB,EAA0C,CAClG,IAAMA,EAAgC,CAAC,EACjCC,kBAAQ,IAAI,IAClB,KAAOC,EAAQ,UAAUC,EAAO,MAAM,IAAM,IAAA,IAAW,CACnD,IAAMC,EAAOF,EAAQ,OAAO,gBAAgB,EACtCG,EAAQ,gFAAgF,KAAKD,EAAK,OAAO,EAC/G,GAAIC,IAAU,KAAM,CAChB,QAAQH,EAASE,CAAI,EACrB,QACJ,CACA,GAAIH,EAAM,IAAII,EAAM,EAAE,EAAG,CACrBH,EAAQ,MAAMI,EAAgB,iCAAkC,mBAAmBD,EAAM,GAAG,+EAAgFE,EAAWH,CAAI,CAAC,EAC5LF,EAAQ,UAAUE,EAAK,MAAM,EAC7B,QACJ,CACAH,EAAM,IAAII,EAAM,EAAE,EAClB,GAAM,CAACG,EAAQC,GAAQ,cAAcP,EAASE,CAAI,EAClDJ,EAAO,KAAK,CAAE,KAAM,sBAAuB,MAAOK,EAAM,GAAI,SAAUA,EAAM,IAAM,KAAM,MAAOA,EAAM,KAAO,IAAA,GAAW,SAAQ,OAAM,SAAUE,EAAWH,CAAI,CAAE,CAAC,CACrK,CACA,MAAO,CAAE,KAAM,uBAAwB,SAAQ,SAAUG,EAAWJ,CAAM,CAAE,CAChF,CAEA,SAAS,cAAc,EAAwB,EAA6D,CACxG,IAAIK,EAAqC,KACnCC,EAAoB,CAAC,EAC3B,KAAOP,EAAQ,UAAUE,EAAK,MAAM,IAAM,IAAA,IAAW,CACjD,IAAMM,EAAQR,EAAQ,OAAO,gBAAgB,EACzCS,EAAUD,EAAM,OAAO,IAAM,SAC7B,EAAS,WAAWR,EAASQ,EAAOF,CAAM,EACnCG,EAAUD,EAAM,OAAO,IAAM,MACpC,WAAWR,EAASQ,EAAOD,CAAI,EAE/B,QAAQP,EAASQ,CAAK,CAE9B,CACA,MAAO,CAACF,EAAQC,CAAI,CACxB,CAEA,SAAS,WAAW,EAAwB,EAAkB,EAAyB,CACnF,IAAMG,EAAMC,EAASX,EAASE,EAAM,EAAK,EACrCQ,IAAQ,IAAA,IAAWH,EAAK,KAAKG,CAAG,CACxC,CAEA,SAAS,WAAW,EAAwB,EAAkB,EAAkE,CAC5H,IAAMP,EAAQ,0CAA0C,KAAKD,EAAK,OAAO,EACzE,GAAIU,IAAa,MAAQT,IAAU,KAG/B,OAFAH,EAAQ,MAAMI,EAAgB,qBAAsBQ,IAAa,KAA8D,uCAAvD,qDAA+FP,EAAWH,CAAI,CAAC,EACvLF,EAAQ,UAAUE,EAAK,MAAM,EACtBU,EAEX,IAAMC,EAAWR,EAAWH,CAAI,EAC1BY,EAA4B,CAAE,KAAM,iBAAkB,KAAM,SAAU,KAAM,CAAE,KAAM,gBAAiB,KAAMX,EAAM,GAAI,aAAc,GAAO,WAAY,GAAO,SAAU,CAAE,GAAGU,EAAU,OAAQX,EAAK,OAASA,EAAK,QAAQ,QAAQC,EAAM,EAAE,EAAI,CAAE,CAAE,EAAG,aAAc,GAAO,UAAS,EACxR,OAAOY,EAAmBf,EAASE,EAAMY,EAAW,EAAK,CAC7D,CAEA,SAAS,QAAQ,EAAwB,EAAwB,CAC7Dd,EAAQ,MAAMI,EAAgB,iCAAkC,sJAAuJC,EAAWH,CAAI,CAAC,EACvOF,EAAQ,UAAUE,EAAK,MAAM,CACjC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{pattern as t}from"../Text/patterns.js";import{locationOf as n}from"./SourceLine.js";import{parseMappingSource as r}from"./ExpressionParser.js";import{diagnosticText as i}from"../Diagnostics/DiagnosticArgument.js";import{firstWord as a,unescapeIdentifier as o}from"./LineText.js";import{parseProperty as s}from"./PropertyLineParser.js";import{parseCondition as c}from"./ConditionParser.js";import{sourceStreamPattern as l}from"../Text/SourceStreamNames.js";import{parseCommandStream as u}from"./EventSourceParser.js";import{
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{pattern as t}from"../Text/patterns.js";import{locationOf as n}from"./SourceLine.js";import{parseMappingSource as r}from"./ExpressionParser.js";import{diagnosticText as i}from"../Diagnostics/DiagnosticArgument.js";import{firstWord as a,unescapeIdentifier as o}from"./LineText.js";import{parseProperty as s}from"./PropertyLineParser.js";import{parseCondition as c}from"./ConditionParser.js";import{sourceStreamPattern as l}from"../Text/SourceStreamNames.js";import{parseCommandStream as u}from"./EventSourceParser.js";import{EventMetadataParser as d}from"./EventMetadataParser.js";import{parseTag as f}from"./DeclarationParsers.js";import{parseOperation as p}from"./OperationParser.js";const m=t(`^produces\\s+operation(?:\\s|$)`),h=t(`^produces\\s+event\\s+([A-Za-z_]\\w*)(?:\\s+(generation)(?:\\s+.*)?)?$`),g=t(`^produces\\s+([A-Z]\\w*(?:\\.[A-Za-z_]\\w*)*)$`),_=t(`^produces\\s+when\\s+(.+)$`),v=t(`^[A-Z]\\w*(?:\\.[A-Za-z_]\\w*)*$`),y=t(`^for\\s+(\\S.*)$`),b=t(`^(@?[\\w.]+)\\s*=(?!=|>)\\s*(.+)$`),x=t(`^(.+?)\\s*=(?!=|>)\\s*(.+)$`),S=/* @__PURE__ */ new Set([`namespace`,`sequence`,`correlation`,`causation`,`causedBy`,`occurred`]);function parseProduces(t,C,w=!1){if(m.test(C.content)){if(!w){t.error(e.OperationOutsideCommand,`Operations can only be produced by commands.`,n(C)),t.skipOpaqueBlock(C.indent);return}let r=p(t,C,!0);return{kind:`ProducesSyntax`,when:null,event:r.operation.name,targetLocation:{...n(C),column:C.indent+C.content.match(/^produces\s+operation(?:\s+|$)/)[0].length+1},inlineEvent:null,inlineOperation:r.operation,mappings:r.mappings,for:null,tags:[],location:n(C)}}let T=h.exec(C.content),E=C,D=null,O,k;if(T!==null){if(!w){t.error(e.InlineEventOutsideCommand,`Inline events can only be declared inside commands`,n(C)),t.skipOpaqueBlock(C.indent);return}T[2]!==void 0&&t.error(e.InlineEventGeneration,`Inline events are generation 1 - extract the event before declaring generations`,n(C)),O=T[1],k=C.indent+C.content.match(/^produces\s+event\s+/)[0].length+1}else if(_.test(C.content)){D=c(t,_.exec(C.content)[1],n(C));let r=t.peekChild(C.indent);if(r===void 0||!v.test(r.content)){t.error(e.ProducesWhenWithoutEvent,`Expected an event name on the line after 'produces when'`,n(C)),t.skipOpaqueBlock(C.indent);return}t.reader.takeSignificant(),E=r,O=r.content,k=r.indent+1}else{let r=g.exec(C.content);if(r===null){t.error(e.InvalidProducesDeclaration,`Invalid produces declaration '${C.content}' - expected 'produces <EventType>' or 'produces when <condition>'`,n(C)),t.skipOpaqueBlock(C.indent);return}O=r[1],k=C.indent+C.content.match(/^produces\s+/)[0].length+1}let A=[],j=/* @__PURE__ */ new Set,M=[],N=[],P=new d(O),F=null,I=null;for(let c=t.peekChild(E.indent);c!==void 0;c=t.peekChild(E.indent)){t.reader.takeSignificant();let d=a(c.content),p=n(c);if(S.has(d)){t.error(e.ReservedProductionMetadata,`'${d}' is system-assigned production metadata and cannot be supplied here`,p),t.skipOpaqueBlock(c.indent);continue}if(T!==null&&(d===`generation`||d===`origin`)){t.error(d===`generation`?e.InlineEventGeneration:e.ReservedProductionMetadata,d===`generation`?`Inline events are generation 1 - extract the event before declaring generations`:`An inline event is local to its command and cannot declare origin`,p),t.skipOpaqueBlock(c.indent);continue}if(d===`stream`&&!c.content.includes(`=`)){let n=l(`^stream\\s+([A-Za-z_]\\w*\\.[A-Za-z_]\\w*)$`).exec(c.content);if(!w)t.error(e.ProductionRouteOutsideCommand,`Only command event productions can declare a stream route.`,p),t.skipBlock(c.indent);else if(I!==null)t.error(e.InvalidCommandStream,`A production can declare at most one stream route.`,p),t.skipBlock(c.indent);else if(n===null)t.error(e.InvalidCommandStream,`Expected 'stream <Source>.<Stream>'.`,p),t.skipBlock(c.indent);else{let e={...p,column:c.indent+c.content.indexOf(n[1])+1},r={kind:`PropertySyntax`,name:`stream`,type:{kind:`TypeRefSyntax`,name:n[1],isCollection:!1,isOptional:!1,location:e},isIdentifier:!1,location:p};I=u(t,c,r,!1)}continue}if(d===`tag`){let e=f(t,c,!1);e!==void 0&&N.push(e);continue}let m=y.exec(c.content);if(m!==null){F===null?F=r(m[1],p,t):t.error(e.DuplicateProducesTarget,`'${E.content}' already declares where it lands - an event is appended to one event source`,p);continue}let h=(T===null?b:x).exec(c.content),g=h===null||T===null?void 0:s(t,{...c,content:h[1].trimEnd()});if(h!==null&&(T===null||g!==void 0)){if(g!==void 0){g.isIdentifier&&(t.error(e.IdentifierOnEventProperty,`Property '${g.name}' of event '${O}' cannot be marked identifier - an event never carries its event source id`,p),g={...g,isIdentifier:!1});let n=g.name;j.has(n)&&t.error(e.DuplicateDeclaration,`Event '${O}' already declares property '${g.name}'`,p),j.add(n),A.push(g)}M.push({kind:`PropertyMappingSyntax`,property:g?.name??o(h[1]),source:r(h[2],{...p,column:c.indent+c.content.length-h[2].length+1},t),location:p})}else(T===null||!P.tryParse(t,c))&&t.error(e.InvalidPropertyMapping,`Invalid ${T===null?``:`inline `}property mapping '${c.content}' - expected '<property>${T===null?``:` <Type>`} = <source>'`,p,i(`text`,c.content))}return E!==C&&t.skipBlock(C.indent),{kind:`ProducesSyntax`,when:D,event:O,stream:I,targetLocation:{...n(E),column:k},inlineOperation:null,mappings:M,for:F,tags:T===null?N:[],location:n(C),inlineEvent:T===null?null:{kind:`EventSyntax`,name:O,properties:A,tags:N,generation:1,hasGenerationMarker:!1,...P.value,location:n(C)}}}export{parseProduces};
|
|
2
2
|
//# sourceMappingURL=ProducesParser.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{pattern as t}from"../Text/patterns.js";import{locationOf as n}from"./SourceLine.js";import{diagnosticText as r}from"../Diagnostics/DiagnosticArgument.js";import{firstWord as i,splitTopLevel as a,unescapeIdentifier as o}from"./LineText.js";import{parseDescription as s}from"./DescriptionParser.js";import{isFileDirective as c}from"./FileReferences.js";import{parseProjectionExpression as l}from"./ProjectionExpressionParser.js";import{validateProjectionEventScopes as u}from"./ProjectionEventScopeValidator.js";const d=t(`^projection\\s+(@?[\\w.]+)\\s*(?:=>\\s*([\\w.]+))?$`),f=t(`^(@?[\\w.]+)(?:\\s+key\\s+(.+))?$`),p=t(`^join\\s+(@?[\\w.]+)\\s+on\\s+(@?[\\w.]+)$`),m=t(`^with\\s+(@?[\\w.]+)$`),h=t(`^children\\s+(@?[\\w.]+)\\s+identified\\s+by\\s+(.+)$`),g=t(`^nested\\s+(@?[\\w.]+)$`),_=t(`^remove\\s+with\\s+(@?[\\w.]+)(?:\\s+key\\s+(.+))?$`),v=t(`^remove\\s+via\\s+join\\s+on\\s+(@?[\\w.]+)(?:\\s+key\\s+(.+))?$`),y=t(`^clear\\s+with\\s+(@?[\\w.]+)$`),b=t(`^variant\\s+(@?[\\w.]+)\\s*$`),x=t(`^enters\\s+on\\s+(@?[\\w.]+)(?:\\s+key\\s+(.+))?$`),S=t(`^(increment|decrement|count|clear)\\s+(@?[$\\w.]+)$`),C=t(`^(add|subtract)\\s+(@?[$\\w.]+)\\s+by\\s+(.+?)(?:\\s+\\*\\s+(.+))?$`),w=t(`^set\\s+(@?[$\\w.]+)\\s+(?:=|to)\\s+(.+)$`),T=t(`^(@?[$\\w.@]+)\\s*=(?!=|>)\\s*(.+)$`),E={increment:`IncrementMappingSyntax`,decrement:`DecrementMappingSyntax`,clear:`ClearMappingSyntax`,count:`CountMappingSyntax`};function parseProjection(t,r){let a=d.exec(r.content);if(a===null)return t.error(e.InvalidProjectionDeclaration,`Invalid projection declaration '${r.content}' - expected 'projection <Name> [=> <ReadModel>]'`,n(r)),t.skipBlock(r.indent),{kind:`ProjectionSyntax`,sourceOptions:t.sourceOptions,name:i(r.content),readModel:null,sequence:null,autoMap:`Inherit`,blocks:[],location:n(r)};let o=a[1],l=null,f=null,p=`Inherit`,m=null,h=[];for(let e=t.peekChild(r.indent);e!==void 0;e=t.peekChild(r.indent)){if(t.reader.takeSignificant(),c(e))continue;let n=i(e.content);if(n===`description`)f=s(t,e,f,`Projection '${o}'`);else if(n===`sequence`)l=e.content.substring(8).trim();else if(n===`automap`)p=`Enabled`;else if(e.content===`no automap`)p=`Disabled`;else if(n===`key`)m=parseKey(t,e);else if(n===`variant`)h.push(parseVariant(t,e));else{let n=parseBlock(t,e,!1);n!==void 0&&h.push(n)}}return reportVariantConflicts(t,h,o),u(t,o,h),h.length===0&&t.error(e.EmptyProjection,`Projection '${o}' must contain at least one directive`,n(r)),{kind:`ProjectionSyntax`,sourceOptions:t.sourceOptions,name:o,readModel:a[2]??null,sequence:l,autoMap:p,key:m,blocks:h,description:f,location:n(r)}}function reportVariantConflicts(t,n,r){let i=n.filter(e=>e.kind===`ProjectionVariantSyntax`),a=/* @__PURE__ */ new Map;i.forEach(e=>a.set(e.name,[...a.get(e.name)??[],e]));for(let n of[...a.values()].flatMap(e=>e.slice(1)))t.error(e.DuplicateProjectionVariant,`Duplicate variant '${n.name}' - a variant name is declared once`,n.location);let o=/* @__PURE__ */ new Set;for(let i of n.flatMap(e=>e.kind===`ProjectionVariantSyntax`?e.entersOn:[]))i.event.length>0&&o.has(i.event)&&t.error(e.DuplicateVariantEnteringEvent,`Entering event '${i.event}' is claimed more than once in projection '${r}'`,i.location),o.add(i.event)}function parseBlock(t,r,a){let o=n(r);switch(i(r.content)){case`from`:return parseFrom(t,r);case`every`:{let e=!0,{autoMap:n,mappings:i}=parseMappingBlock(t,r,t=>t.content===`exclude children`&&(e=!1,!0));return{kind:`EverySyntax`,includeChildren:e,autoMap:n,mappings:i,location:o}}case`all`:{let{autoMap:e,mappings:n}=parseMappingBlock(t,r);return{kind:`AllSyntax`,autoMap:e,mappings:n,location:o}}case`join`:return parseJoin(t,r);case`children`:return parseChildren(t,r);case`nested`:return parseNested(t,r);case`remove`:return parseRemove(t,r);case`clear`:return a||t.error(e.ClearWithOutsideNestedBlock,`'clear with' is only valid inside a nested block`,o),parseClearWith(t,r);default:t.error(e.UnknownProjectionDirective,`Unexpected '${i(r.content)}' in projection body`,o),t.skipBlock(r.indent);return}}function parseFrom(t,r){let s=[];for(let i of a(r.content.substring(4),`,`)){let a=i.trim();if(a.length===0){t.error(e.FromWithoutEvent,`Expected an event type after 'from'`,n(r));continue}let c=f.exec(a);c===null?t.error(e.InvalidEventReference,`Invalid event reference '${a}'`,n(r)):s.push({kind:`EventSpecSyntax`,event:o(c[1]),key:c[2]===void 0?null:l(c[2],n(r),t),location:n(r)})}let c=[],u=null,d=null;for(let e=t.peekChild(r.indent);e!==void 0;e=t.peekChild(r.indent)){t.reader.takeSignificant();let r=i(e.content);r===`key`?u=parseKey(t,e):r===`parent`?d=l(e.content.substring(6),n(e),t):pushMapping(t,e,c)}return{kind:`FromSyntax`,events:s,key:u,parentKey:d,mappings:c,location:n(r)}}function parseJoin(t,r){let i=p.exec(r.content);if(i===null)return t.error(e.InvalidJoinDeclaration,`Invalid join declaration '${r.content}' - expected 'join <property> on <key>'`,n(r)),t.skipBlock(r.indent),{kind:`JoinSyntax`,property:``,on:``,events:[],location:n(r)};let a=[];for(let i=t.peekChild(r.indent);i!==void 0;i=t.peekChild(r.indent)){t.reader.takeSignificant();let r=m.exec(i.content);if(r===null){t.error(e.JoinWithoutEvent,`Expected 'with <EventType>' in join block, got '${i.content}'`,n(i)),t.skipBlock(i.indent);continue}let{autoMap:s,mappings:c}=parseMappingBlock(t,i);a.push({kind:`JoinEventSyntax`,event:o(r[1]),autoMap:s,mappings:c,location:n(i)})}return{kind:`JoinSyntax`,property:o(i[1]),on:o(i[2]),events:a,location:n(r)}}function parseChildren(t,r){let i=h.exec(r.content);if(i===null)return t.error(e.InvalidChildrenDeclaration,`Invalid children declaration '${r.content}' - expected 'children <collection> identified by <key>'`,n(r)),t.skipBlock(r.indent),{kind:`ChildrenSyntax`,property:``,autoMap:`Inherit`,blocks:[],location:n(r)};let{autoMap:a,blocks:s}=parseChildBlocks(t,r);return{kind:`ChildrenSyntax`,property:o(i[1]),identifiedBy:l(i[2],n(r),t),autoMap:a,blocks:s,location:n(r)}}function parseNested(t,r){let i=g.exec(r.content);if(i===null)return t.error(e.InvalidNestedDeclaration,`Invalid nested declaration '${r.content}' - expected 'nested <property>'`,n(r)),t.skipBlock(r.indent),{kind:`NestedSyntax`,property:``,autoMap:`Inherit`,blocks:[],location:n(r)};let a=o(i[1]),{autoMap:s,blocks:c}=parseChildBlocks(t,r);return c.some(e=>e.kind===`FromSyntax`)||t.error(e.NestedBlockWithoutFrom,`Nested block '${a}' must contain at least one 'from' directive`,n(r)),{kind:`NestedSyntax`,property:a,autoMap:s,blocks:c,location:n(r)}}function parseChildBlocks(e,t){let n=[],r=`Inherit`;for(let i=e.peekChild(t.indent);i!==void 0;i=e.peekChild(t.indent)){if(e.reader.takeSignificant(),i.content===`automap`){r=`Enabled`;continue}if(i.content===`no automap`){r=`Disabled`;continue}let t=parseBlock(e,i,!0);t!==void 0&&n.push(t)}return{autoMap:r,blocks:n}}function parseRemove(t,r){let a=v.exec(r.content);if(a!==null)return{kind:`RemoveViaJoinSyntax`,event:o(a[1]),key:a[2]===void 0?null:l(a[2],n(r),t),location:n(r)};let s=_.exec(r.content);if(s===null){t.error(e.InvalidRemoveDeclaration,`Invalid remove declaration '${r.content}' - expected 'remove with <EventType>' or 'remove via join on <EventType>'`,n(r)),t.skipBlock(r.indent);return}let c=s[2]===void 0?null:l(s[2],n(r),t),u=null,d=null;for(let a=t.peekChild(r.indent);a!==void 0;a=t.peekChild(r.indent))if(t.reader.takeSignificant(),i(a.content)===`parent`)d=l(a.content.substring(6),n(a),t);else if(i(a.content)===`key`){(c!==null||u!==null)&&t.error(e.InvalidReadModelKeyLookup,`A removal can only declare one key.`,n(a));let r=parseKey(t,a);r.kind===`CompositeKeySyntax`?u=r:c=r.expression}else t.error(e.UnknownRemoveDirective,`Unexpected '${a.content}' in remove block - only 'parent' or 'key' is allowed`,n(a));return{kind:`RemoveWithSyntax`,event:o(s[1]),key:c,...u===null?{}:{partsKey:u},parentKey:d,location:n(r)}}function parseClearWith(t,r){let i=y.exec(r.content);return i===null?(t.error(e.InvalidClearDeclaration,`Invalid clear declaration '${r.content}' - expected 'clear with <EventType>'`,n(r)),{kind:`ClearWithSyntax`,event:``,location:n(r)}):{kind:`ClearWithSyntax`,event:o(i[1]),location:n(r)}}function parseVariant(t,r){let a=b.exec(r.content);if(a===null)return t.error(e.InvalidProjectionVariantDeclaration,`Invalid variant declaration '${r.content}' - expected 'variant <Name>'`,n(r)),t.skipBlock(r.indent),{kind:`ProjectionVariantSyntax`,name:i(r.content),entersOn:[],blocks:[],location:n(r)};let s=o(a[1]),c=[],l=[];for(let a=t.peekChild(r.indent);a!==void 0;a=t.peekChild(r.indent)){t.reader.takeSignificant();let r=i(a.content);if(r===`enters`)c.push(parseEntersOn(t,a));else if(r===`variant`)t.error(e.NestedProjectionVariantNotAllowed,`A variant cannot be declared inside another variant`,n(a)),t.skipBlock(a.indent);else{let e=parseBlock(t,a,!1);e!==void 0&&l.push(e)}}return c.length===0&&t.error(e.VariantRequiresEnteringEvent,`Variant '${s}' must declare at least one 'enters on' event`,n(r)),{kind:`ProjectionVariantSyntax`,name:s,entersOn:c,blocks:l,location:n(r)}}function parseEntersOn(t,r){let i=x.exec(r.content);return i===null?(t.error(e.InvalidEntersOnDeclaration,`Invalid 'enters on' declaration '${r.content}' - expected 'enters on <EventType> [key <expression>]'`,n(r)),t.skipBlock(r.indent),{kind:`ProjectionEntersOnSyntax`,event:``,key:null,location:n(r)}):{kind:`ProjectionEntersOnSyntax`,event:o(i[1]),key:i[2]===void 0?null:l(i[2],n(r),t),location:n(r)}}function parseKey(t,r){let i=r.content.substring(3).trim();if(t.peekChild(r.indent)===void 0)return{kind:`ExpressionKeySyntax`,expression:l(i,n(r),t),location:n(r)};let a=[];for(let s=t.peekChild(r.indent);s!==void 0;s=t.peekChild(r.indent)){if(t.reader.takeSignificant(),s.content===`}`)continue;let r=T.exec(s.content);if(r===null){t.sourceOptions.numericMode===`exact`&&t.error(e.InvalidCompositeKeyPart,`Invalid composite key part '${s.content}' - expected '<property> = <expression>'`,n(s));continue}let c=l(r[2],n(s),t);t.sourceOptions.numericMode===`exact`&&i.replace(/\{$/,``).trim().length>0&&c.kind===`TemplateExpressionSyntax`&&t.error(e.TemplateInCompositeKey,`Template expressions are not allowed in composite keys`,n(s)),a.push({kind:`KeyPartSyntax`,property:o(r[1]),expression:c,location:n(s)})}let s=t.reader.peekSignificant();return s!==void 0&&s.indent===r.indent&&s.content===`}`&&t.reader.takeSignificant(),t.sourceOptions.numericMode===`exact`&&a.length===0&&t.error(e.EmptyCompositeKey,`Composite keys must contain at least one part`,n(r)),{kind:`CompositeKeySyntax`,type:i.replace(/\{$/,``).trim(),parts:a,location:n(r)}}function parseMappingBlock(e,t,n=()=>!1){let r=`Inherit`,i=[];for(let a=e.peekChild(t.indent);a!==void 0;a=e.peekChild(t.indent))e.reader.takeSignificant(),a.content===`automap`?r=`Enabled`:a.content===`no automap`?r=`Disabled`:n(a)||pushMapping(e,a,i);return{autoMap:r,mappings:i}}function pushMapping(t,i,a){let s=n(i),c=S.exec(i.content);if(c!==null){c[1]!==`clear`||c[2]!==`with`?a.push({kind:E[c[1]],property:o(c[2]),location:s}):t.sourceOptions.numericMode===`exact`&&t.error(e.InvalidProjectionMapping,`Invalid mapping '${i.content}' - 'clear with' is a block directive and needs an event type; to clear a property named 'with', write 'clear @with'`,s,r(`text`,i.content));return}let u=C.exec(i.content);if(u!==null){a.push({kind:u[1]===`add`?`AddMappingSyntax`:`SubtractMappingSyntax`,property:o(u[2]),value:l(u[3],s,t),...u[4]===void 0?{}:{factor:l(u[4],s,t)},location:s});return}let d=w.exec(i.content)??T.exec(i.content);d===null?t.sourceOptions.numericMode===`exact`&&t.error(e.InvalidProjectionMapping,`Invalid mapping '${i.content}'`,s,r(`text`,i.content)):a.push({kind:`SetMappingSyntax`,property:o(d[1]),source:l(d[2],s,t),location:s})}export{parseProjection};
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{pattern as t}from"../Text/patterns.js";import{locationOf as n}from"./SourceLine.js";import{diagnosticText as r}from"../Diagnostics/DiagnosticArgument.js";import{firstWord as i,splitTopLevel as a,unescapeIdentifier as o}from"./LineText.js";import{parseDescription as s}from"./DescriptionParser.js";import{isFileDirective as c}from"./FileReferences.js";import{parseProjectionExpression as l}from"./ProjectionExpressionParser.js";import{validateProjectionEventScopes as u}from"./ProjectionEventScopeValidator.js";const d=t(`^projection\\s+(@?[\\w.]+)\\s*(?:=>\\s*([\\w.]+))?$`),f=t(`^(@?[\\w.]+)(?:\\s+key\\s+(.+))?$`),p=t(`^join\\s+(@?[\\w.]+)\\s+on\\s+(@?[\\w.]+)$`),m=t(`^with\\s+(@?[\\w.]+)$`),h=t(`^children\\s+(@?[\\w.]+)\\s+identified\\s+by\\s+(.+)$`),g=t(`^nested\\s+(@?[\\w.]+)$`),_=t(`^remove\\s+with\\s+(@?[\\w.]+)(?:\\s+key\\s+(.+))?$`),v=t(`^remove\\s+via\\s+join\\s+on\\s+(@?[\\w.]+)(?:\\s+key\\s+(.+))?$`),y=t(`^clear\\s+with\\s+(@?[\\w.]+)$`),b=t(`^variant\\s+(@?[\\w.]+)\\s*$`),x=t(`^enters\\s+on\\s+(@?[\\w.]+)(?:\\s+key\\s+(.+))?$`),S=t(`^(increment|decrement|count|clear)\\s+(@?[$\\w.]+)$`),C=t(`^(add|subtract)\\s+(@?[$\\w.]+)\\s+by\\s+(.+?)(?:\\s+\\*\\s+(.+))?$`),w=t(`^set\\s+(@?[$\\w.]+)\\s+(?:=|to)\\s+(.+)$`),T=t(`^(@?[$\\w.@]+)\\s*=(?!=|>)\\s*(.+)$`),E={increment:`IncrementMappingSyntax`,decrement:`DecrementMappingSyntax`,clear:`ClearMappingSyntax`,count:`CountMappingSyntax`};function parseProjection(t,r){let a=d.exec(r.content);if(a===null)return t.error(e.InvalidProjectionDeclaration,`Invalid projection declaration '${r.content}' - expected 'projection <Name> [=> <ReadModel>]'`,n(r)),t.skipBlock(r.indent),{kind:`ProjectionSyntax`,sourceOptions:t.sourceOptions,name:i(r.content),readModel:null,sequence:null,autoMap:`Inherit`,blocks:[],location:n(r)};let o=a[1],l=null,f=null,p=`Inherit`,m=null,h=[];for(let e=t.peekChild(r.indent);e!==void 0;e=t.peekChild(r.indent)){if(t.reader.takeSignificant(),c(e))continue;let n=i(e.content);if(n===`description`)f=s(t,e,f,`Projection '${o}'`);else if(n===`sequence`)l=e.content.substring(8).trim();else if(n===`automap`)p=`Enabled`;else if(e.content===`no automap`)p=`Disabled`;else if(n===`key`)m=parseKey(t,e);else if(n===`variant`)h.push(parseVariant(t,e));else{let n=parseBlock(t,e,!1);n!==void 0&&h.push(n)}}return reportVariantConflicts(t,h,o),u(t,o,h),h.length===0&&t.error(e.EmptyProjection,`Projection '${o}' must contain at least one directive`,n(r)),{kind:`ProjectionSyntax`,sourceOptions:t.sourceOptions,name:o,readModel:a[2]??null,sequence:l,autoMap:p,key:m,blocks:h,description:f,location:n(r)}}function reportVariantConflicts(t,n,r){let i=n.filter(e=>e.kind===`ProjectionVariantSyntax`),a=/* @__PURE__ */ new Map;i.forEach(e=>a.set(e.name,[...a.get(e.name)??[],e]));for(let n of[...a.values()].flatMap(e=>e.slice(1)))t.error(e.DuplicateProjectionVariant,`Duplicate variant '${n.name}' - a variant name is declared once`,n.location);let o=/* @__PURE__ */ new Set;for(let i of n.flatMap(e=>e.kind===`ProjectionVariantSyntax`?e.entersOn:[]))i.event.length>0&&o.has(i.event)&&t.error(e.DuplicateVariantEnteringEvent,`Entering event '${i.event}' is claimed more than once in projection '${r}'`,i.location),o.add(i.event)}function parseBlock(t,r,a){let o=n(r);switch(i(r.content)){case`from`:return parseFrom(t,r);case`every`:{let e=!0,{autoMap:n,mappings:i}=parseMappingBlock(t,r,t=>t.content===`exclude children`&&(e=!1,!0));return{kind:`EverySyntax`,includeChildren:e,autoMap:n,mappings:i,location:o}}case`all`:{let{autoMap:e,mappings:n}=parseMappingBlock(t,r);return{kind:`AllSyntax`,autoMap:e,mappings:n,location:o}}case`join`:return parseJoin(t,r);case`children`:return parseChildren(t,r);case`nested`:return parseNested(t,r);case`remove`:return parseRemove(t,r);case`clear`:return a||t.error(e.ClearWithOutsideNestedBlock,`'clear with' is only valid inside a nested block`,o),parseClearWith(t,r);default:t.error(e.UnknownProjectionDirective,`Unexpected '${i(r.content)}' in projection body`,o),t.skipBlock(r.indent);return}}function parseFrom(t,r){let s=[];for(let i of a(r.content.substring(4),`,`)){let a=i.trim();if(a.length===0){t.error(e.FromWithoutEvent,`Expected an event type after 'from'`,n(r));continue}let c=f.exec(a);c===null?t.error(e.InvalidEventReference,`Invalid event reference '${a}'`,n(r)):s.push({kind:`EventSpecSyntax`,event:o(c[1]),key:c[2]===void 0?null:l(c[2],n(r),t),location:n(r)})}let c=[],u=null,d=null;for(let e=t.peekChild(r.indent);e!==void 0;e=t.peekChild(r.indent)){t.reader.takeSignificant();let r=i(e.content);r===`key`?u=parseKey(t,e):r===`parent`?d=l(e.content.substring(6),n(e),t):pushMapping(t,e,c)}return{kind:`FromSyntax`,events:s,key:u,parentKey:d,mappings:c,location:n(r)}}function parseJoin(t,r){let i=p.exec(r.content);if(i===null)return t.error(e.InvalidJoinDeclaration,`Invalid join declaration '${r.content}' - expected 'join <property> on <key>'`,n(r)),t.skipBlock(r.indent),{kind:`JoinSyntax`,property:``,on:``,events:[],location:n(r)};let a=[];for(let i=t.peekChild(r.indent);i!==void 0;i=t.peekChild(r.indent)){t.reader.takeSignificant();let r=m.exec(i.content);if(r===null){t.error(e.JoinWithoutEvent,`Expected 'with <EventType>' in join block, got '${i.content}'`,n(i)),t.skipBlock(i.indent);continue}let{autoMap:s,mappings:c}=parseMappingBlock(t,i);a.push({kind:`JoinEventSyntax`,event:o(r[1]),autoMap:s,mappings:c,location:n(i)})}return{kind:`JoinSyntax`,property:o(i[1]),on:o(i[2]),events:a,location:n(r)}}function parseChildren(t,r){let i=h.exec(r.content);if(i===null)return t.error(e.InvalidChildrenDeclaration,`Invalid children declaration '${r.content}' - expected 'children <collection> identified by <key>'`,n(r)),t.skipBlock(r.indent),{kind:`ChildrenSyntax`,property:``,autoMap:`Inherit`,blocks:[],location:n(r)};let{autoMap:a,blocks:s}=parseChildBlocks(t,r);return{kind:`ChildrenSyntax`,property:o(i[1]),identifiedBy:l(i[2],n(r),t),autoMap:a,blocks:s,location:n(r)}}function parseNested(t,r){let i=g.exec(r.content);if(i===null)return t.error(e.InvalidNestedDeclaration,`Invalid nested declaration '${r.content}' - expected 'nested <property>'`,n(r)),t.skipBlock(r.indent),{kind:`NestedSyntax`,property:``,autoMap:`Inherit`,blocks:[],location:n(r)};let a=o(i[1]),{autoMap:s,blocks:c}=parseChildBlocks(t,r);return c.some(e=>e.kind===`FromSyntax`)||t.error(e.NestedBlockWithoutFrom,`Nested block '${a}' must contain at least one 'from' directive`,n(r)),{kind:`NestedSyntax`,property:a,autoMap:s,blocks:c,location:n(r)}}function parseChildBlocks(e,t){let n=[],r=`Inherit`;for(let i=e.peekChild(t.indent);i!==void 0;i=e.peekChild(t.indent)){if(e.reader.takeSignificant(),i.content===`automap`){r=`Enabled`;continue}if(i.content===`no automap`){r=`Disabled`;continue}let t=parseBlock(e,i,!0);t!==void 0&&n.push(t)}return{autoMap:r,blocks:n}}function parseRemove(t,r){let a=v.exec(r.content);if(a!==null)return{kind:`RemoveViaJoinSyntax`,event:o(a[1]),key:a[2]===void 0?null:l(a[2],n(r),t),location:n(r)};let s=_.exec(r.content);if(s===null){t.error(e.InvalidRemoveDeclaration,`Invalid remove declaration '${r.content}' - expected 'remove with <EventType>' or 'remove via join on <EventType>'`,n(r)),t.skipBlock(r.indent);return}let c=s[2]===void 0?null:l(s[2],n(r),t),u=null,d=null;for(let a=t.peekChild(r.indent);a!==void 0;a=t.peekChild(r.indent))if(t.reader.takeSignificant(),i(a.content)===`parent`)d=l(a.content.substring(6),n(a),t);else if(i(a.content)===`key`){(c!==null||u!==null)&&t.error(e.InvalidReadModelKeyLookup,`A removal can only declare one key.`,n(a));let r=parseKey(t,a);r.kind===`CompositeKeySyntax`?u=r:c=r.expression}else t.error(e.UnknownRemoveDirective,`Unexpected '${a.content}' in remove block - only 'parent' or 'key' is allowed`,n(a));return{kind:`RemoveWithSyntax`,event:o(s[1]),key:c,...u===null?{}:{partsKey:u},parentKey:d,location:n(r)}}function parseClearWith(t,r){let i=y.exec(r.content);return i===null?(t.error(e.InvalidClearDeclaration,`Invalid clear declaration '${r.content}' - expected 'clear with <EventType>'`,n(r)),{kind:`ClearWithSyntax`,event:``,location:n(r)}):{kind:`ClearWithSyntax`,event:o(i[1]),location:n(r)}}function parseVariant(t,r){let a=b.exec(r.content);if(a===null)return t.error(e.InvalidProjectionVariantDeclaration,`Invalid variant declaration '${r.content}' - expected 'variant <Name>'`,n(r)),t.skipBlock(r.indent),{kind:`ProjectionVariantSyntax`,name:i(r.content),entersOn:[],blocks:[],location:n(r)};let s=o(a[1]),c=[],l=[];for(let a=t.peekChild(r.indent);a!==void 0;a=t.peekChild(r.indent)){t.reader.takeSignificant();let r=i(a.content);if(r===`enters`)c.push(parseEntersOn(t,a));else if(r===`variant`)t.error(e.NestedProjectionVariantNotAllowed,`A variant cannot be declared inside another variant`,n(a)),t.skipBlock(a.indent);else{let e=parseBlock(t,a,!1);e!==void 0&&l.push(e)}}return c.length===0&&t.error(e.VariantRequiresEnteringEvent,`Variant '${s}' must declare at least one 'enters on' event`,n(r)),{kind:`ProjectionVariantSyntax`,name:s,entersOn:c,blocks:l,location:n(r)}}function parseEntersOn(t,r){let i=x.exec(r.content);return i===null?(t.error(e.InvalidEntersOnDeclaration,`Invalid 'enters on' declaration '${r.content}' - expected 'enters on <EventType> [key <expression>]'`,n(r)),t.skipBlock(r.indent),{kind:`ProjectionEntersOnSyntax`,event:``,key:null,location:n(r)}):{kind:`ProjectionEntersOnSyntax`,event:o(i[1]),key:i[2]===void 0?null:l(i[2],n(r),t),location:n(r)}}function parseKey(t,r){let i=r.content.substring(3).trim();if(t.peekChild(r.indent)===void 0)return{kind:`ExpressionKeySyntax`,expression:l(i,n(r),t),location:n(r)};i.endsWith(`{`)&&t.information(e.RedundantCompositeKeyBraces,`Write the composite key without braces; the indented parts already belong to the key.`,n(r));let a=[];for(let s=t.peekChild(r.indent);s!==void 0;s=t.peekChild(r.indent)){if(t.reader.takeSignificant(),s.content===`}`)continue;let r=T.exec(s.content);if(r===null){t.sourceOptions.numericMode===`exact`&&t.error(e.InvalidCompositeKeyPart,`Invalid composite key part '${s.content}' - expected '<property> = <expression>'`,n(s));continue}let c=l(r[2],n(s),t);t.sourceOptions.numericMode===`exact`&&i.replace(/\{$/,``).trim().length>0&&c.kind===`TemplateExpressionSyntax`&&t.error(e.TemplateInCompositeKey,`Template expressions are not allowed in composite keys`,n(s)),a.push({kind:`KeyPartSyntax`,property:o(r[1]),expression:c,location:n(s)})}let s=t.reader.peekSignificant();return s!==void 0&&s.indent===r.indent&&s.content===`}`&&t.reader.takeSignificant(),t.sourceOptions.numericMode===`exact`&&a.length===0&&t.error(e.EmptyCompositeKey,`Composite keys must contain at least one part`,n(r)),{kind:`CompositeKeySyntax`,type:i.replace(/\{$/,``).trim(),parts:a,location:n(r)}}function parseMappingBlock(e,t,n=()=>!1){let r=`Inherit`,i=[];for(let a=e.peekChild(t.indent);a!==void 0;a=e.peekChild(t.indent))e.reader.takeSignificant(),a.content===`automap`?r=`Enabled`:a.content===`no automap`?r=`Disabled`:n(a)||pushMapping(e,a,i);return{autoMap:r,mappings:i}}function pushMapping(t,i,a){let s=n(i),c=S.exec(i.content);if(c!==null){c[1]!==`clear`||c[2]!==`with`?a.push({kind:E[c[1]],property:o(c[2]),location:s}):t.sourceOptions.numericMode===`exact`&&t.error(e.InvalidProjectionMapping,`Invalid mapping '${i.content}' - 'clear with' is a block directive and needs an event type; to clear a property named 'with', write 'clear @with'`,s,r(`text`,i.content));return}let u=C.exec(i.content);if(u!==null){a.push({kind:u[1]===`add`?`AddMappingSyntax`:`SubtractMappingSyntax`,property:o(u[2]),value:l(u[3],s,t),...u[4]===void 0?{}:{factor:l(u[4],s,t)},location:s});return}let d=w.exec(i.content)??T.exec(i.content);d===null?t.sourceOptions.numericMode===`exact`&&t.error(e.InvalidProjectionMapping,`Invalid mapping '${i.content}'`,s,r(`text`,i.content)):a.push({kind:`SetMappingSyntax`,property:o(d[1]),source:l(d[2],s,t),location:s})}export{parseProjection};
|
|
2
2
|
//# sourceMappingURL=ProjectionParser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectionParser.js","names":["header","pattern","eventSpecPattern","joinPattern","withPattern","childrenPattern","nestedPattern","removeWithPattern","removeViaJoinPattern","clearWithPattern","variantPattern","entersOnPattern","keywordMappingPattern","arithmeticPattern","setPattern","assignmentPattern","keywordMappings","match","line","context","DiagnosticCodes","locationOf","firstWord","name","sequence","description","autoMap","key","blocks","child","isFileDirective","keyword","parseDescription","block","validateProjectionEventScopes","variants","byName","variant","duplicate","group","entering","entry","location","includeChildren","nestedScope","events","spec","splitTopLevel","text","unescapeIdentifier","parseProjectionExpression","mappings","parentKey","withMatch","property","viaJoin","partsKey","parsed","entersOn","parts","expression","closing","extra","diagnosticText","arithmetic","assigned"],"sources":["../../../../../../Compiler/Parsing/ProjectionParser.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { diagnosticText } from '../Diagnostics/DiagnosticArgument';\nimport { DiagnosticCodes } from '../Diagnostics/DiagnosticCodes';\nimport {\n AutoMapMode, ChildrenSyntax, ClearWithSyntax, CompositeKeySyntax, EventSpecSyntax, FromSyntax, JoinEventSyntax, JoinSyntax, MappingKind, MappingSyntax, NestedSyntax,\n KeyPartSyntax, KeySyntax, ProjectionBlockSyntax, ProjectionEntersOnSyntax, ProjectionSyntax, ProjectionVariantSyntax,\n} from '../Syntax/Projections';\nimport { ExpressionSyntax } from '../Syntax/Expressions';\nimport { pattern } from '../Text/patterns';\nimport { parseProjectionExpression } from './ProjectionExpressionParser';\nimport { validateProjectionEventScopes } from './ProjectionEventScopeValidator';\nimport { isFileDirective } from './FileReferences';\nimport { parseDescription } from './DescriptionParser';\nimport { firstWord, splitTopLevel, unescapeIdentifier } from './LineText';\nimport { ParserContext } from './ParserContext';\nimport { locationOf, SourceLine } from './SourceLine';\n\nconst header = pattern('^projection\\\\s+(@?[\\\\w.]+)\\\\s*(?:=>\\\\s*([\\\\w.]+))?$');\nconst eventSpecPattern = pattern('^(@?[\\\\w.]+)(?:\\\\s+key\\\\s+(.+))?$');\nconst joinPattern = pattern('^join\\\\s+(@?[\\\\w.]+)\\\\s+on\\\\s+(@?[\\\\w.]+)$');\nconst withPattern = pattern('^with\\\\s+(@?[\\\\w.]+)$');\nconst childrenPattern = pattern('^children\\\\s+(@?[\\\\w.]+)\\\\s+identified\\\\s+by\\\\s+(.+)$');\nconst nestedPattern = pattern('^nested\\\\s+(@?[\\\\w.]+)$');\nconst removeWithPattern = pattern('^remove\\\\s+with\\\\s+(@?[\\\\w.]+)(?:\\\\s+key\\\\s+(.+))?$');\nconst removeViaJoinPattern = pattern('^remove\\\\s+via\\\\s+join\\\\s+on\\\\s+(@?[\\\\w.]+)(?:\\\\s+key\\\\s+(.+))?$');\nconst clearWithPattern = pattern('^clear\\\\s+with\\\\s+(@?[\\\\w.]+)$');\nconst variantPattern = pattern('^variant\\\\s+(@?[\\\\w.]+)\\\\s*$');\nconst entersOnPattern = pattern('^enters\\\\s+on\\\\s+(@?[\\\\w.]+)(?:\\\\s+key\\\\s+(.+))?$');\nconst keywordMappingPattern = pattern('^(increment|decrement|count|clear)\\\\s+(@?[$\\\\w.]+)$');\nconst arithmeticPattern = pattern('^(add|subtract)\\\\s+(@?[$\\\\w.]+)\\\\s+by\\\\s+(.+?)(?:\\\\s+\\\\*\\\\s+(.+))?$');\nconst setPattern = pattern('^set\\\\s+(@?[$\\\\w.]+)\\\\s+(?:=|to)\\\\s+(.+)$');\nconst assignmentPattern = pattern('^(@?[$\\\\w.@]+)\\\\s*=(?!=|>)\\\\s*(.+)$');\nconst keywordMappings: Record<string, MappingKind> = {\n increment: 'IncrementMappingSyntax',\n decrement: 'DecrementMappingSyntax',\n clear: 'ClearMappingSyntax',\n count: 'CountMappingSyntax',\n};\n\n// Reads a projection's structure: its name, the read model it builds, the events each block consumes, the\n// properties each mapping sets and where automap is turned on or off. Keys, and where a mapping takes its\n// value from, are recognized and skipped.\nexport function parseProjection(context: ParserContext, line: SourceLine): ProjectionSyntax {\n const match = header.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidProjectionDeclaration, `Invalid projection declaration '${line.content}' - expected 'projection <Name> [=> <ReadModel>]'`, locationOf(line));\n context.skipBlock(line.indent);\n return { kind: 'ProjectionSyntax', sourceOptions: context.sourceOptions, name: firstWord(line.content), readModel: null, sequence: null, autoMap: 'Inherit', blocks: [], location: locationOf(line) };\n }\n const name = match[1];\n let sequence: string | null = null;\n let description: string | null = null;\n let autoMap: AutoMapMode = 'Inherit';\n let key: KeySyntax | null = null;\n const blocks: ProjectionBlockSyntax[] = [];\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n if (isFileDirective(child)) {\n continue;\n }\n const keyword = firstWord(child.content);\n if (keyword === 'description') {\n description = parseDescription(context, child, description, `Projection '${name}'`);\n } else if (keyword === 'sequence') {\n sequence = child.content.substring('sequence'.length).trim();\n } else if (keyword === 'automap') {\n autoMap = 'Enabled';\n } else if (child.content === 'no automap') {\n autoMap = 'Disabled';\n } else if (keyword === 'key') {\n key = parseKey(context, child);\n } else if (keyword === 'variant') {\n blocks.push(parseVariant(context, child));\n } else {\n const block = parseBlock(context, child, false);\n if (block !== undefined) {\n blocks.push(block);\n }\n }\n }\n reportVariantConflicts(context, blocks, name);\n validateProjectionEventScopes(context, name, blocks);\n if (blocks.length === 0) {\n context.error(DiagnosticCodes.EmptyProjection, `Projection '${name}' must contain at least one directive`, locationOf(line));\n }\n return { kind: 'ProjectionSyntax', sourceOptions: context.sourceOptions, name, readModel: match[2] ?? null, sequence, autoMap, key, blocks, description, location: locationOf(line) };\n}\n\nfunction reportVariantConflicts(context: ParserContext, blocks: readonly ProjectionBlockSyntax[], name: string): void {\n // Grouped by name in the order each name first appears, as the C# parser reports them.\n const variants = blocks.filter((block): block is ProjectionVariantSyntax => block.kind === 'ProjectionVariantSyntax');\n const byName = new Map<string, ProjectionVariantSyntax[]>();\n variants.forEach(variant => byName.set(variant.name, [...(byName.get(variant.name) ?? []), variant]));\n for (const duplicate of [...byName.values()].flatMap(group => group.slice(1))) {\n context.error(DiagnosticCodes.DuplicateProjectionVariant, `Duplicate variant '${duplicate.name}' - a variant name is declared once`, duplicate.location);\n }\n const entering = new Set<string>();\n for (const entry of blocks.flatMap(block => block.kind === 'ProjectionVariantSyntax' ? block.entersOn : [])) {\n if (entry.event.length > 0 && entering.has(entry.event)) {\n context.error(DiagnosticCodes.DuplicateVariantEnteringEvent, `Entering event '${entry.event}' is claimed more than once in projection '${name}'`, entry.location);\n }\n entering.add(entry.event);\n }\n}\n\nfunction parseBlock(context: ParserContext, line: SourceLine, nestedScope: boolean): ProjectionBlockSyntax | undefined {\n const location = locationOf(line);\n switch (firstWord(line.content)) {\n case 'from':\n return parseFrom(context, line);\n case 'every': {\n let includeChildren = true;\n const { autoMap, mappings } = parseMappingBlock(context, line, child => {\n if (child.content !== 'exclude children') {\n return false;\n }\n includeChildren = false;\n return true;\n });\n return { kind: 'EverySyntax', includeChildren, autoMap, mappings, location };\n }\n case 'all': {\n const { autoMap, mappings } = parseMappingBlock(context, line);\n return { kind: 'AllSyntax', autoMap, mappings, location };\n }\n case 'join':\n return parseJoin(context, line);\n case 'children':\n return parseChildren(context, line);\n case 'nested':\n return parseNested(context, line);\n case 'remove':\n return parseRemove(context, line);\n case 'clear':\n if (!nestedScope) {\n context.error(DiagnosticCodes.ClearWithOutsideNestedBlock, '\\'clear with\\' is only valid inside a nested block', location);\n }\n return parseClearWith(context, line);\n default:\n context.error(DiagnosticCodes.UnknownProjectionDirective, `Unexpected '${firstWord(line.content)}' in projection body`, location);\n context.skipBlock(line.indent);\n return undefined;\n }\n}\n\nfunction parseFrom(context: ParserContext, line: SourceLine): FromSyntax {\n const events: EventSpecSyntax[] = [];\n for (const spec of splitTopLevel(line.content.substring('from'.length), ',')) {\n const text = spec.trim();\n if (text.length === 0) {\n context.error(DiagnosticCodes.FromWithoutEvent, 'Expected an event type after \\'from\\'', locationOf(line));\n continue;\n }\n const match = eventSpecPattern.exec(text);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidEventReference, `Invalid event reference '${text}'`, locationOf(line));\n continue;\n }\n events.push({ kind: 'EventSpecSyntax', event: unescapeIdentifier(match[1]), key: match[2] === undefined ? null : parseProjectionExpression(match[2], locationOf(line), context), location: locationOf(line) });\n }\n const mappings: MappingSyntax[] = [];\n let key: KeySyntax | null = null;\n let parentKey: ExpressionSyntax | null = null;\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n const keyword = firstWord(child.content);\n if (keyword === 'key') key = parseKey(context, child);\n else if (keyword === 'parent') parentKey = parseProjectionExpression(child.content.substring('parent'.length), locationOf(child), context);\n else pushMapping(context, child, mappings);\n }\n return { kind: 'FromSyntax', events, key, parentKey, mappings, location: locationOf(line) };\n}\n\nfunction parseJoin(context: ParserContext, line: SourceLine): JoinSyntax {\n const match = joinPattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidJoinDeclaration, `Invalid join declaration '${line.content}' - expected 'join <property> on <key>'`, locationOf(line));\n context.skipBlock(line.indent);\n return { kind: 'JoinSyntax', property: '', on: '', events: [], location: locationOf(line) };\n }\n const events: JoinEventSyntax[] = [];\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n const withMatch = withPattern.exec(child.content);\n if (withMatch === null) {\n context.error(DiagnosticCodes.JoinWithoutEvent, `Expected 'with <EventType>' in join block, got '${child.content}'`, locationOf(child));\n context.skipBlock(child.indent);\n continue;\n }\n const { autoMap, mappings } = parseMappingBlock(context, child);\n events.push({ kind: 'JoinEventSyntax', event: unescapeIdentifier(withMatch[1]), autoMap, mappings, location: locationOf(child) });\n }\n return { kind: 'JoinSyntax', property: unescapeIdentifier(match[1]), on: unescapeIdentifier(match[2]), events, location: locationOf(line) };\n}\n\nfunction parseChildren(context: ParserContext, line: SourceLine): ChildrenSyntax {\n const match = childrenPattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidChildrenDeclaration, `Invalid children declaration '${line.content}' - expected 'children <collection> identified by <key>'`, locationOf(line));\n context.skipBlock(line.indent);\n return { kind: 'ChildrenSyntax', property: '', autoMap: 'Inherit', blocks: [], location: locationOf(line) };\n }\n const { autoMap, blocks } = parseChildBlocks(context, line);\n return { kind: 'ChildrenSyntax', property: unescapeIdentifier(match[1]), identifiedBy: parseProjectionExpression(match[2], locationOf(line), context), autoMap, blocks, location: locationOf(line) };\n}\n\nfunction parseNested(context: ParserContext, line: SourceLine): NestedSyntax {\n const match = nestedPattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidNestedDeclaration, `Invalid nested declaration '${line.content}' - expected 'nested <property>'`, locationOf(line));\n context.skipBlock(line.indent);\n return { kind: 'NestedSyntax', property: '', autoMap: 'Inherit', blocks: [], location: locationOf(line) };\n }\n const property = unescapeIdentifier(match[1]);\n const { autoMap, blocks } = parseChildBlocks(context, line);\n if (!blocks.some(block => block.kind === 'FromSyntax')) {\n context.error(DiagnosticCodes.NestedBlockWithoutFrom, `Nested block '${property}' must contain at least one 'from' directive`, locationOf(line));\n }\n return { kind: 'NestedSyntax', property, autoMap, blocks, location: locationOf(line) };\n}\n\nfunction parseChildBlocks(context: ParserContext, line: SourceLine): { autoMap: AutoMapMode; blocks: ProjectionBlockSyntax[] } {\n const blocks: ProjectionBlockSyntax[] = [];\n let autoMap: AutoMapMode = 'Inherit';\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n if (child.content === 'automap') {\n autoMap = 'Enabled';\n continue;\n }\n if (child.content === 'no automap') {\n autoMap = 'Disabled';\n continue;\n }\n const block = parseBlock(context, child, true);\n if (block !== undefined) {\n blocks.push(block);\n }\n }\n return { autoMap, blocks };\n}\n\nfunction parseRemove(context: ParserContext, line: SourceLine): ProjectionBlockSyntax | undefined {\n const viaJoin = removeViaJoinPattern.exec(line.content);\n if (viaJoin !== null) {\n return { kind: 'RemoveViaJoinSyntax', event: unescapeIdentifier(viaJoin[1]), key: viaJoin[2] === undefined ? null : parseProjectionExpression(viaJoin[2], locationOf(line), context), location: locationOf(line) };\n }\n const match = removeWithPattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidRemoveDeclaration, `Invalid remove declaration '${line.content}' - expected 'remove with <EventType>' or 'remove via join on <EventType>'`, locationOf(line));\n context.skipBlock(line.indent);\n return undefined;\n }\n let key = match[2] === undefined ? null : parseProjectionExpression(match[2], locationOf(line), context);\n let partsKey: CompositeKeySyntax | null = null;\n let parentKey: ExpressionSyntax | null = null;\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n if (firstWord(child.content) === 'parent') {\n parentKey = parseProjectionExpression(child.content.substring('parent'.length), locationOf(child), context);\n } else if (firstWord(child.content) === 'key') {\n if (key !== null || partsKey !== null) context.error(DiagnosticCodes.InvalidReadModelKeyLookup, 'A removal can only declare one key.', locationOf(child));\n const parsed = parseKey(context, child);\n if (parsed.kind === 'CompositeKeySyntax') partsKey = parsed;\n else key = parsed.expression;\n } else {\n context.error(DiagnosticCodes.UnknownRemoveDirective, `Unexpected '${child.content}' in remove block - only 'parent' or 'key' is allowed`, locationOf(child));\n }\n }\n return { kind: 'RemoveWithSyntax', event: unescapeIdentifier(match[1]), key, ...(partsKey === null ? {} : { partsKey }), parentKey, location: locationOf(line) };\n}\n\nfunction parseClearWith(context: ParserContext, line: SourceLine): ClearWithSyntax {\n const match = clearWithPattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidClearDeclaration, `Invalid clear declaration '${line.content}' - expected 'clear with <EventType>'`, locationOf(line));\n return { kind: 'ClearWithSyntax', event: '', location: locationOf(line) };\n }\n return { kind: 'ClearWithSyntax', event: unescapeIdentifier(match[1]), location: locationOf(line) };\n}\n\nfunction parseVariant(context: ParserContext, line: SourceLine): ProjectionVariantSyntax {\n const match = variantPattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidProjectionVariantDeclaration, `Invalid variant declaration '${line.content}' - expected 'variant <Name>'`, locationOf(line));\n context.skipBlock(line.indent);\n return { kind: 'ProjectionVariantSyntax', name: firstWord(line.content), entersOn: [], blocks: [], location: locationOf(line) };\n }\n const name = unescapeIdentifier(match[1]);\n const entersOn: ProjectionEntersOnSyntax[] = [];\n const blocks: ProjectionBlockSyntax[] = [];\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n const keyword = firstWord(child.content);\n if (keyword === 'enters') {\n entersOn.push(parseEntersOn(context, child));\n } else if (keyword === 'variant') {\n context.error(DiagnosticCodes.NestedProjectionVariantNotAllowed, 'A variant cannot be declared inside another variant', locationOf(child));\n context.skipBlock(child.indent);\n } else {\n const block = parseBlock(context, child, false);\n if (block !== undefined) {\n blocks.push(block);\n }\n }\n }\n if (entersOn.length === 0) {\n context.error(DiagnosticCodes.VariantRequiresEnteringEvent, `Variant '${name}' must declare at least one 'enters on' event`, locationOf(line));\n }\n return { kind: 'ProjectionVariantSyntax', name, entersOn, blocks, location: locationOf(line) };\n}\n\nfunction parseEntersOn(context: ParserContext, line: SourceLine): ProjectionEntersOnSyntax {\n const match = entersOnPattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidEntersOnDeclaration, `Invalid 'enters on' declaration '${line.content}' - expected 'enters on <EventType> [key <expression>]'`, locationOf(line));\n context.skipBlock(line.indent);\n return { kind: 'ProjectionEntersOnSyntax', event: '', key: null, location: locationOf(line) };\n }\n return { kind: 'ProjectionEntersOnSyntax', event: unescapeIdentifier(match[1]), key: match[2] === undefined ? null : parseProjectionExpression(match[2], locationOf(line), context), location: locationOf(line) };\n}\n\n// A key with a body is a composite key: its parts, then a closing '}' at the key's own indent.\nfunction parseKey(context: ParserContext, line: SourceLine): KeySyntax {\n const text = line.content.substring('key'.length).trim();\n if (context.peekChild(line.indent) === undefined) return { kind: 'ExpressionKeySyntax', expression: parseProjectionExpression(text, locationOf(line), context), location: locationOf(line) };\n const parts: KeyPartSyntax[] = [];\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n if (child.content === '}') continue;\n const match = assignmentPattern.exec(child.content);\n if (match === null) {\n if (context.sourceOptions.numericMode === 'exact') context.error(DiagnosticCodes.InvalidCompositeKeyPart, `Invalid composite key part '${child.content}' - expected '<property> = <expression>'`, locationOf(child));\n continue;\n }\n const expression = parseProjectionExpression(match[2], locationOf(child), context);\n if (context.sourceOptions.numericMode === 'exact' && text.replace(/\\{$/, '').trim().length > 0 && expression.kind === 'TemplateExpressionSyntax') context.error(DiagnosticCodes.TemplateInCompositeKey, 'Template expressions are not allowed in composite keys', locationOf(child));\n parts.push({ kind: 'KeyPartSyntax', property: unescapeIdentifier(match[1]), expression, location: locationOf(child) });\n }\n const closing = context.reader.peekSignificant();\n if (closing !== undefined && closing.indent === line.indent && closing.content === '}') context.reader.takeSignificant();\n if (context.sourceOptions.numericMode === 'exact' && parts.length === 0) context.error(DiagnosticCodes.EmptyCompositeKey, 'Composite keys must contain at least one part', locationOf(line));\n return { kind: 'CompositeKeySyntax', type: text.replace(/\\{$/, '').trim(), parts, location: locationOf(line) };\n}\n\n// Mapping lines carry no body, so a mapping block is its direct children. The last automap setting wins;\n// a line 'extra' claims is not a mapping.\nfunction parseMappingBlock(context: ParserContext, line: SourceLine, extra: (child: SourceLine) => boolean = () => false): { autoMap: AutoMapMode; mappings: MappingSyntax[] } {\n let autoMap: AutoMapMode = 'Inherit';\n const mappings: MappingSyntax[] = [];\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n if (child.content === 'automap') {\n autoMap = 'Enabled';\n } else if (child.content === 'no automap') {\n autoMap = 'Disabled';\n } else if (!extra(child)) {\n pushMapping(context, child, mappings);\n }\n }\n return { autoMap, mappings };\n}\n\n// The property one mapping line sets, and how - the port of the C# ParseMappingLine. Exact reports\n// malformed mappings; Legacy keeps the existing skip behavior.\nfunction pushMapping(context: ParserContext, line: SourceLine, mappings: MappingSyntax[]): void {\n const location = locationOf(line);\n const keyword = keywordMappingPattern.exec(line.content);\n if (keyword !== null) {\n if (keyword[1] !== 'clear' || keyword[2] !== 'with') {\n mappings.push({ kind: keywordMappings[keyword[1]], property: unescapeIdentifier(keyword[2]), location });\n } else if (context.sourceOptions.numericMode === 'exact') {\n context.error(DiagnosticCodes.InvalidProjectionMapping, `Invalid mapping '${line.content}' - 'clear with' is a block directive and needs an event type; to clear a property named 'with', write 'clear @with'`, location, diagnosticText('text', line.content));\n }\n return;\n }\n const arithmetic = arithmeticPattern.exec(line.content);\n if (arithmetic !== null) {\n mappings.push({ kind: arithmetic[1] === 'add' ? 'AddMappingSyntax' : 'SubtractMappingSyntax', property: unescapeIdentifier(arithmetic[2]), value: parseProjectionExpression(arithmetic[3], location, context), ...(arithmetic[4] === undefined ? {} : { factor: parseProjectionExpression(arithmetic[4], location, context) }), location });\n return;\n }\n const assigned = setPattern.exec(line.content) ?? assignmentPattern.exec(line.content);\n if (assigned !== null) {\n mappings.push({ kind: 'SetMappingSyntax', property: unescapeIdentifier(assigned[1]), source: parseProjectionExpression(assigned[2], location, context), location });\n } else if (context.sourceOptions.numericMode === 'exact') {\n context.error(DiagnosticCodes.InvalidProjectionMapping, `Invalid mapping '${line.content}'`, location, diagnosticText('text', line.content));\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ProjectionParser.js","names":["header","pattern","eventSpecPattern","joinPattern","withPattern","childrenPattern","nestedPattern","removeWithPattern","removeViaJoinPattern","clearWithPattern","variantPattern","entersOnPattern","keywordMappingPattern","arithmeticPattern","setPattern","assignmentPattern","keywordMappings","match","line","context","DiagnosticCodes","locationOf","firstWord","name","sequence","description","autoMap","key","blocks","child","isFileDirective","keyword","parseDescription","block","validateProjectionEventScopes","variants","byName","variant","duplicate","group","entering","entry","location","includeChildren","nestedScope","events","spec","splitTopLevel","text","unescapeIdentifier","parseProjectionExpression","mappings","parentKey","withMatch","property","viaJoin","partsKey","parsed","entersOn","parts","expression","closing","extra","diagnosticText","arithmetic","assigned"],"sources":["../../../../../../Compiler/Parsing/ProjectionParser.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { diagnosticText } from '../Diagnostics/DiagnosticArgument';\nimport { DiagnosticCodes } from '../Diagnostics/DiagnosticCodes';\nimport {\n AutoMapMode, ChildrenSyntax, ClearWithSyntax, CompositeKeySyntax, EventSpecSyntax, FromSyntax, JoinEventSyntax, JoinSyntax, MappingKind, MappingSyntax, NestedSyntax,\n KeyPartSyntax, KeySyntax, ProjectionBlockSyntax, ProjectionEntersOnSyntax, ProjectionSyntax, ProjectionVariantSyntax,\n} from '../Syntax/Projections';\nimport { ExpressionSyntax } from '../Syntax/Expressions';\nimport { pattern } from '../Text/patterns';\nimport { parseProjectionExpression } from './ProjectionExpressionParser';\nimport { validateProjectionEventScopes } from './ProjectionEventScopeValidator';\nimport { isFileDirective } from './FileReferences';\nimport { parseDescription } from './DescriptionParser';\nimport { firstWord, splitTopLevel, unescapeIdentifier } from './LineText';\nimport { ParserContext } from './ParserContext';\nimport { locationOf, SourceLine } from './SourceLine';\n\nconst header = pattern('^projection\\\\s+(@?[\\\\w.]+)\\\\s*(?:=>\\\\s*([\\\\w.]+))?$');\nconst eventSpecPattern = pattern('^(@?[\\\\w.]+)(?:\\\\s+key\\\\s+(.+))?$');\nconst joinPattern = pattern('^join\\\\s+(@?[\\\\w.]+)\\\\s+on\\\\s+(@?[\\\\w.]+)$');\nconst withPattern = pattern('^with\\\\s+(@?[\\\\w.]+)$');\nconst childrenPattern = pattern('^children\\\\s+(@?[\\\\w.]+)\\\\s+identified\\\\s+by\\\\s+(.+)$');\nconst nestedPattern = pattern('^nested\\\\s+(@?[\\\\w.]+)$');\nconst removeWithPattern = pattern('^remove\\\\s+with\\\\s+(@?[\\\\w.]+)(?:\\\\s+key\\\\s+(.+))?$');\nconst removeViaJoinPattern = pattern('^remove\\\\s+via\\\\s+join\\\\s+on\\\\s+(@?[\\\\w.]+)(?:\\\\s+key\\\\s+(.+))?$');\nconst clearWithPattern = pattern('^clear\\\\s+with\\\\s+(@?[\\\\w.]+)$');\nconst variantPattern = pattern('^variant\\\\s+(@?[\\\\w.]+)\\\\s*$');\nconst entersOnPattern = pattern('^enters\\\\s+on\\\\s+(@?[\\\\w.]+)(?:\\\\s+key\\\\s+(.+))?$');\nconst keywordMappingPattern = pattern('^(increment|decrement|count|clear)\\\\s+(@?[$\\\\w.]+)$');\nconst arithmeticPattern = pattern('^(add|subtract)\\\\s+(@?[$\\\\w.]+)\\\\s+by\\\\s+(.+?)(?:\\\\s+\\\\*\\\\s+(.+))?$');\nconst setPattern = pattern('^set\\\\s+(@?[$\\\\w.]+)\\\\s+(?:=|to)\\\\s+(.+)$');\nconst assignmentPattern = pattern('^(@?[$\\\\w.@]+)\\\\s*=(?!=|>)\\\\s*(.+)$');\nconst keywordMappings: Record<string, MappingKind> = {\n increment: 'IncrementMappingSyntax',\n decrement: 'DecrementMappingSyntax',\n clear: 'ClearMappingSyntax',\n count: 'CountMappingSyntax',\n};\n\n// Reads a projection's structure: its name, the read model it builds, the events each block consumes, the\n// properties each mapping sets and where automap is turned on or off. Keys, and where a mapping takes its\n// value from, are recognized and skipped.\nexport function parseProjection(context: ParserContext, line: SourceLine): ProjectionSyntax {\n const match = header.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidProjectionDeclaration, `Invalid projection declaration '${line.content}' - expected 'projection <Name> [=> <ReadModel>]'`, locationOf(line));\n context.skipBlock(line.indent);\n return { kind: 'ProjectionSyntax', sourceOptions: context.sourceOptions, name: firstWord(line.content), readModel: null, sequence: null, autoMap: 'Inherit', blocks: [], location: locationOf(line) };\n }\n const name = match[1];\n let sequence: string | null = null;\n let description: string | null = null;\n let autoMap: AutoMapMode = 'Inherit';\n let key: KeySyntax | null = null;\n const blocks: ProjectionBlockSyntax[] = [];\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n if (isFileDirective(child)) {\n continue;\n }\n const keyword = firstWord(child.content);\n if (keyword === 'description') {\n description = parseDescription(context, child, description, `Projection '${name}'`);\n } else if (keyword === 'sequence') {\n sequence = child.content.substring('sequence'.length).trim();\n } else if (keyword === 'automap') {\n autoMap = 'Enabled';\n } else if (child.content === 'no automap') {\n autoMap = 'Disabled';\n } else if (keyword === 'key') {\n key = parseKey(context, child);\n } else if (keyword === 'variant') {\n blocks.push(parseVariant(context, child));\n } else {\n const block = parseBlock(context, child, false);\n if (block !== undefined) {\n blocks.push(block);\n }\n }\n }\n reportVariantConflicts(context, blocks, name);\n validateProjectionEventScopes(context, name, blocks);\n if (blocks.length === 0) {\n context.error(DiagnosticCodes.EmptyProjection, `Projection '${name}' must contain at least one directive`, locationOf(line));\n }\n return { kind: 'ProjectionSyntax', sourceOptions: context.sourceOptions, name, readModel: match[2] ?? null, sequence, autoMap, key, blocks, description, location: locationOf(line) };\n}\n\nfunction reportVariantConflicts(context: ParserContext, blocks: readonly ProjectionBlockSyntax[], name: string): void {\n // Grouped by name in the order each name first appears, as the C# parser reports them.\n const variants = blocks.filter((block): block is ProjectionVariantSyntax => block.kind === 'ProjectionVariantSyntax');\n const byName = new Map<string, ProjectionVariantSyntax[]>();\n variants.forEach(variant => byName.set(variant.name, [...(byName.get(variant.name) ?? []), variant]));\n for (const duplicate of [...byName.values()].flatMap(group => group.slice(1))) {\n context.error(DiagnosticCodes.DuplicateProjectionVariant, `Duplicate variant '${duplicate.name}' - a variant name is declared once`, duplicate.location);\n }\n const entering = new Set<string>();\n for (const entry of blocks.flatMap(block => block.kind === 'ProjectionVariantSyntax' ? block.entersOn : [])) {\n if (entry.event.length > 0 && entering.has(entry.event)) {\n context.error(DiagnosticCodes.DuplicateVariantEnteringEvent, `Entering event '${entry.event}' is claimed more than once in projection '${name}'`, entry.location);\n }\n entering.add(entry.event);\n }\n}\n\nfunction parseBlock(context: ParserContext, line: SourceLine, nestedScope: boolean): ProjectionBlockSyntax | undefined {\n const location = locationOf(line);\n switch (firstWord(line.content)) {\n case 'from':\n return parseFrom(context, line);\n case 'every': {\n let includeChildren = true;\n const { autoMap, mappings } = parseMappingBlock(context, line, child => {\n if (child.content !== 'exclude children') {\n return false;\n }\n includeChildren = false;\n return true;\n });\n return { kind: 'EverySyntax', includeChildren, autoMap, mappings, location };\n }\n case 'all': {\n const { autoMap, mappings } = parseMappingBlock(context, line);\n return { kind: 'AllSyntax', autoMap, mappings, location };\n }\n case 'join':\n return parseJoin(context, line);\n case 'children':\n return parseChildren(context, line);\n case 'nested':\n return parseNested(context, line);\n case 'remove':\n return parseRemove(context, line);\n case 'clear':\n if (!nestedScope) {\n context.error(DiagnosticCodes.ClearWithOutsideNestedBlock, '\\'clear with\\' is only valid inside a nested block', location);\n }\n return parseClearWith(context, line);\n default:\n context.error(DiagnosticCodes.UnknownProjectionDirective, `Unexpected '${firstWord(line.content)}' in projection body`, location);\n context.skipBlock(line.indent);\n return undefined;\n }\n}\n\nfunction parseFrom(context: ParserContext, line: SourceLine): FromSyntax {\n const events: EventSpecSyntax[] = [];\n for (const spec of splitTopLevel(line.content.substring('from'.length), ',')) {\n const text = spec.trim();\n if (text.length === 0) {\n context.error(DiagnosticCodes.FromWithoutEvent, 'Expected an event type after \\'from\\'', locationOf(line));\n continue;\n }\n const match = eventSpecPattern.exec(text);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidEventReference, `Invalid event reference '${text}'`, locationOf(line));\n continue;\n }\n events.push({ kind: 'EventSpecSyntax', event: unescapeIdentifier(match[1]), key: match[2] === undefined ? null : parseProjectionExpression(match[2], locationOf(line), context), location: locationOf(line) });\n }\n const mappings: MappingSyntax[] = [];\n let key: KeySyntax | null = null;\n let parentKey: ExpressionSyntax | null = null;\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n const keyword = firstWord(child.content);\n if (keyword === 'key') key = parseKey(context, child);\n else if (keyword === 'parent') parentKey = parseProjectionExpression(child.content.substring('parent'.length), locationOf(child), context);\n else pushMapping(context, child, mappings);\n }\n return { kind: 'FromSyntax', events, key, parentKey, mappings, location: locationOf(line) };\n}\n\nfunction parseJoin(context: ParserContext, line: SourceLine): JoinSyntax {\n const match = joinPattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidJoinDeclaration, `Invalid join declaration '${line.content}' - expected 'join <property> on <key>'`, locationOf(line));\n context.skipBlock(line.indent);\n return { kind: 'JoinSyntax', property: '', on: '', events: [], location: locationOf(line) };\n }\n const events: JoinEventSyntax[] = [];\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n const withMatch = withPattern.exec(child.content);\n if (withMatch === null) {\n context.error(DiagnosticCodes.JoinWithoutEvent, `Expected 'with <EventType>' in join block, got '${child.content}'`, locationOf(child));\n context.skipBlock(child.indent);\n continue;\n }\n const { autoMap, mappings } = parseMappingBlock(context, child);\n events.push({ kind: 'JoinEventSyntax', event: unescapeIdentifier(withMatch[1]), autoMap, mappings, location: locationOf(child) });\n }\n return { kind: 'JoinSyntax', property: unescapeIdentifier(match[1]), on: unescapeIdentifier(match[2]), events, location: locationOf(line) };\n}\n\nfunction parseChildren(context: ParserContext, line: SourceLine): ChildrenSyntax {\n const match = childrenPattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidChildrenDeclaration, `Invalid children declaration '${line.content}' - expected 'children <collection> identified by <key>'`, locationOf(line));\n context.skipBlock(line.indent);\n return { kind: 'ChildrenSyntax', property: '', autoMap: 'Inherit', blocks: [], location: locationOf(line) };\n }\n const { autoMap, blocks } = parseChildBlocks(context, line);\n return { kind: 'ChildrenSyntax', property: unescapeIdentifier(match[1]), identifiedBy: parseProjectionExpression(match[2], locationOf(line), context), autoMap, blocks, location: locationOf(line) };\n}\n\nfunction parseNested(context: ParserContext, line: SourceLine): NestedSyntax {\n const match = nestedPattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidNestedDeclaration, `Invalid nested declaration '${line.content}' - expected 'nested <property>'`, locationOf(line));\n context.skipBlock(line.indent);\n return { kind: 'NestedSyntax', property: '', autoMap: 'Inherit', blocks: [], location: locationOf(line) };\n }\n const property = unescapeIdentifier(match[1]);\n const { autoMap, blocks } = parseChildBlocks(context, line);\n if (!blocks.some(block => block.kind === 'FromSyntax')) {\n context.error(DiagnosticCodes.NestedBlockWithoutFrom, `Nested block '${property}' must contain at least one 'from' directive`, locationOf(line));\n }\n return { kind: 'NestedSyntax', property, autoMap, blocks, location: locationOf(line) };\n}\n\nfunction parseChildBlocks(context: ParserContext, line: SourceLine): { autoMap: AutoMapMode; blocks: ProjectionBlockSyntax[] } {\n const blocks: ProjectionBlockSyntax[] = [];\n let autoMap: AutoMapMode = 'Inherit';\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n if (child.content === 'automap') {\n autoMap = 'Enabled';\n continue;\n }\n if (child.content === 'no automap') {\n autoMap = 'Disabled';\n continue;\n }\n const block = parseBlock(context, child, true);\n if (block !== undefined) {\n blocks.push(block);\n }\n }\n return { autoMap, blocks };\n}\n\nfunction parseRemove(context: ParserContext, line: SourceLine): ProjectionBlockSyntax | undefined {\n const viaJoin = removeViaJoinPattern.exec(line.content);\n if (viaJoin !== null) {\n return { kind: 'RemoveViaJoinSyntax', event: unescapeIdentifier(viaJoin[1]), key: viaJoin[2] === undefined ? null : parseProjectionExpression(viaJoin[2], locationOf(line), context), location: locationOf(line) };\n }\n const match = removeWithPattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidRemoveDeclaration, `Invalid remove declaration '${line.content}' - expected 'remove with <EventType>' or 'remove via join on <EventType>'`, locationOf(line));\n context.skipBlock(line.indent);\n return undefined;\n }\n let key = match[2] === undefined ? null : parseProjectionExpression(match[2], locationOf(line), context);\n let partsKey: CompositeKeySyntax | null = null;\n let parentKey: ExpressionSyntax | null = null;\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n if (firstWord(child.content) === 'parent') {\n parentKey = parseProjectionExpression(child.content.substring('parent'.length), locationOf(child), context);\n } else if (firstWord(child.content) === 'key') {\n if (key !== null || partsKey !== null) context.error(DiagnosticCodes.InvalidReadModelKeyLookup, 'A removal can only declare one key.', locationOf(child));\n const parsed = parseKey(context, child);\n if (parsed.kind === 'CompositeKeySyntax') partsKey = parsed;\n else key = parsed.expression;\n } else {\n context.error(DiagnosticCodes.UnknownRemoveDirective, `Unexpected '${child.content}' in remove block - only 'parent' or 'key' is allowed`, locationOf(child));\n }\n }\n return { kind: 'RemoveWithSyntax', event: unescapeIdentifier(match[1]), key, ...(partsKey === null ? {} : { partsKey }), parentKey, location: locationOf(line) };\n}\n\nfunction parseClearWith(context: ParserContext, line: SourceLine): ClearWithSyntax {\n const match = clearWithPattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidClearDeclaration, `Invalid clear declaration '${line.content}' - expected 'clear with <EventType>'`, locationOf(line));\n return { kind: 'ClearWithSyntax', event: '', location: locationOf(line) };\n }\n return { kind: 'ClearWithSyntax', event: unescapeIdentifier(match[1]), location: locationOf(line) };\n}\n\nfunction parseVariant(context: ParserContext, line: SourceLine): ProjectionVariantSyntax {\n const match = variantPattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidProjectionVariantDeclaration, `Invalid variant declaration '${line.content}' - expected 'variant <Name>'`, locationOf(line));\n context.skipBlock(line.indent);\n return { kind: 'ProjectionVariantSyntax', name: firstWord(line.content), entersOn: [], blocks: [], location: locationOf(line) };\n }\n const name = unescapeIdentifier(match[1]);\n const entersOn: ProjectionEntersOnSyntax[] = [];\n const blocks: ProjectionBlockSyntax[] = [];\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n const keyword = firstWord(child.content);\n if (keyword === 'enters') {\n entersOn.push(parseEntersOn(context, child));\n } else if (keyword === 'variant') {\n context.error(DiagnosticCodes.NestedProjectionVariantNotAllowed, 'A variant cannot be declared inside another variant', locationOf(child));\n context.skipBlock(child.indent);\n } else {\n const block = parseBlock(context, child, false);\n if (block !== undefined) {\n blocks.push(block);\n }\n }\n }\n if (entersOn.length === 0) {\n context.error(DiagnosticCodes.VariantRequiresEnteringEvent, `Variant '${name}' must declare at least one 'enters on' event`, locationOf(line));\n }\n return { kind: 'ProjectionVariantSyntax', name, entersOn, blocks, location: locationOf(line) };\n}\n\nfunction parseEntersOn(context: ParserContext, line: SourceLine): ProjectionEntersOnSyntax {\n const match = entersOnPattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidEntersOnDeclaration, `Invalid 'enters on' declaration '${line.content}' - expected 'enters on <EventType> [key <expression>]'`, locationOf(line));\n context.skipBlock(line.indent);\n return { kind: 'ProjectionEntersOnSyntax', event: '', key: null, location: locationOf(line) };\n }\n return { kind: 'ProjectionEntersOnSyntax', event: unescapeIdentifier(match[1]), key: match[2] === undefined ? null : parseProjectionExpression(match[2], locationOf(line), context), location: locationOf(line) };\n}\n\n// A key with a body is a composite key: its parts, then a closing '}' at the key's own indent.\nfunction parseKey(context: ParserContext, line: SourceLine): KeySyntax {\n const text = line.content.substring('key'.length).trim();\n if (context.peekChild(line.indent) === undefined) return { kind: 'ExpressionKeySyntax', expression: parseProjectionExpression(text, locationOf(line), context), location: locationOf(line) };\n if (text.endsWith('{')) context.information(DiagnosticCodes.RedundantCompositeKeyBraces, 'Write the composite key without braces; the indented parts already belong to the key.', locationOf(line));\n const parts: KeyPartSyntax[] = [];\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n if (child.content === '}') continue;\n const match = assignmentPattern.exec(child.content);\n if (match === null) {\n if (context.sourceOptions.numericMode === 'exact') context.error(DiagnosticCodes.InvalidCompositeKeyPart, `Invalid composite key part '${child.content}' - expected '<property> = <expression>'`, locationOf(child));\n continue;\n }\n const expression = parseProjectionExpression(match[2], locationOf(child), context);\n if (context.sourceOptions.numericMode === 'exact' && text.replace(/\\{$/, '').trim().length > 0 && expression.kind === 'TemplateExpressionSyntax') context.error(DiagnosticCodes.TemplateInCompositeKey, 'Template expressions are not allowed in composite keys', locationOf(child));\n parts.push({ kind: 'KeyPartSyntax', property: unescapeIdentifier(match[1]), expression, location: locationOf(child) });\n }\n const closing = context.reader.peekSignificant();\n if (closing !== undefined && closing.indent === line.indent && closing.content === '}') context.reader.takeSignificant();\n if (context.sourceOptions.numericMode === 'exact' && parts.length === 0) context.error(DiagnosticCodes.EmptyCompositeKey, 'Composite keys must contain at least one part', locationOf(line));\n return { kind: 'CompositeKeySyntax', type: text.replace(/\\{$/, '').trim(), parts, location: locationOf(line) };\n}\n\n// Mapping lines carry no body, so a mapping block is its direct children. The last automap setting wins;\n// a line 'extra' claims is not a mapping.\nfunction parseMappingBlock(context: ParserContext, line: SourceLine, extra: (child: SourceLine) => boolean = () => false): { autoMap: AutoMapMode; mappings: MappingSyntax[] } {\n let autoMap: AutoMapMode = 'Inherit';\n const mappings: MappingSyntax[] = [];\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n if (child.content === 'automap') {\n autoMap = 'Enabled';\n } else if (child.content === 'no automap') {\n autoMap = 'Disabled';\n } else if (!extra(child)) {\n pushMapping(context, child, mappings);\n }\n }\n return { autoMap, mappings };\n}\n\n// The property one mapping line sets, and how - the port of the C# ParseMappingLine. Exact reports\n// malformed mappings; Legacy keeps the existing skip behavior.\nfunction pushMapping(context: ParserContext, line: SourceLine, mappings: MappingSyntax[]): void {\n const location = locationOf(line);\n const keyword = keywordMappingPattern.exec(line.content);\n if (keyword !== null) {\n if (keyword[1] !== 'clear' || keyword[2] !== 'with') {\n mappings.push({ kind: keywordMappings[keyword[1]], property: unescapeIdentifier(keyword[2]), location });\n } else if (context.sourceOptions.numericMode === 'exact') {\n context.error(DiagnosticCodes.InvalidProjectionMapping, `Invalid mapping '${line.content}' - 'clear with' is a block directive and needs an event type; to clear a property named 'with', write 'clear @with'`, location, diagnosticText('text', line.content));\n }\n return;\n }\n const arithmetic = arithmeticPattern.exec(line.content);\n if (arithmetic !== null) {\n mappings.push({ kind: arithmetic[1] === 'add' ? 'AddMappingSyntax' : 'SubtractMappingSyntax', property: unescapeIdentifier(arithmetic[2]), value: parseProjectionExpression(arithmetic[3], location, context), ...(arithmetic[4] === undefined ? {} : { factor: parseProjectionExpression(arithmetic[4], location, context) }), location });\n return;\n }\n const assigned = setPattern.exec(line.content) ?? assignmentPattern.exec(line.content);\n if (assigned !== null) {\n mappings.push({ kind: 'SetMappingSyntax', property: unescapeIdentifier(assigned[1]), source: parseProjectionExpression(assigned[2], location, context), location });\n } else if (context.sourceOptions.numericMode === 'exact') {\n context.error(DiagnosticCodes.InvalidProjectionMapping, `Invalid mapping '${line.content}'`, location, diagnosticText('text', line.content));\n }\n}\n"],"mappings":"8nBAmBA,MAAMA,EAASC,EAAQ,qDAAqD,EACtEC,EAAmBD,EAAQ,mCAAmC,EAC9DE,EAAcF,EAAQ,4CAA4C,EAClEG,EAAcH,EAAQ,uBAAuB,EAC7CI,EAAkBJ,EAAQ,uDAAuD,EACjFK,EAAgBL,EAAQ,yBAAyB,EACjDM,EAAoBN,EAAQ,qDAAqD,EACjFO,EAAuBP,EAAQ,kEAAkE,EACjGQ,EAAmBR,EAAQ,gCAAgC,EAC3DS,EAAiBT,EAAQ,8BAA8B,EACvDU,EAAkBV,EAAQ,mDAAmD,EAC7EW,EAAwBX,EAAQ,qDAAqD,EACrFY,EAAoBZ,EAAQ,qEAAqE,EACjGa,EAAab,EAAQ,2CAA2C,EAChEc,EAAoBd,EAAQ,qCAAqC,EACjEe,EAA+C,CACjD,UAAW,yBACX,UAAW,yBACX,MAAO,qBACP,MAAO,oBACX,EAKA,SAAgB,gBAAgB,EAAwB,EAAoC,CACxF,IAAMC,EAAQjB,EAAO,KAAKkB,EAAK,OAAO,EACtC,GAAID,IAAU,KAGV,OAFAE,EAAQ,MAAMC,EAAgB,6BAA8B,mCAAmCF,EAAK,QAAQ,mDAAoDG,EAAWH,CAAI,CAAC,EAChLC,EAAQ,UAAUD,EAAK,MAAM,EACtB,CAAE,KAAM,mBAAoB,cAAeC,EAAQ,cAAe,KAAMG,EAAUJ,EAAK,OAAO,EAAG,UAAW,KAAM,SAAU,KAAM,QAAS,UAAW,OAAQ,CAAC,EAAG,SAAUG,EAAWH,CAAI,CAAE,EAExM,IAAMK,EAAON,EAAM,GACfO,EAA0B,KAC1BC,EAA6B,KAC7BC,EAAuB,UACvBC,EAAwB,KACtBC,EAAkC,CAAC,EACzC,IAAK,IAAIC,EAAQV,EAAQ,UAAUD,EAAK,MAAM,EAAGW,IAAU,IAAA,GAAW,EAAQV,EAAQ,UAAUD,EAAK,MAAM,EAAG,CAE1G,GADAC,EAAQ,OAAO,gBAAgB,EAC3BW,EAAgBD,CAAK,EACrB,SAEJ,IAAME,EAAUT,EAAUO,EAAM,OAAO,EACvC,GAAIE,IAAY,cACZ,EAAcC,EAAiBb,EAASU,EAAOJ,EAAa,eAAeF,EAAK,EAAE,OAC/E,GAAIQ,IAAY,WACnB,EAAWF,EAAM,QAAQ,UAAU,CAAiB,CAAC,CAAC,KAAK,OACxD,GAAIE,IAAY,UACnB,EAAU,eACP,GAAIF,EAAM,UAAY,aACzB,EAAU,gBACP,GAAIE,IAAY,MACnB,EAAM,SAASZ,EAASU,CAAK,OAC1B,GAAIE,IAAY,UACnBH,EAAO,KAAK,aAAaT,EAASU,CAAK,CAAC,MACrC,CACH,IAAMI,EAAQ,WAAWd,EAASU,EAAO,EAAK,EAC1CI,IAAU,IAAA,IACVL,EAAO,KAAKK,CAAK,CAEzB,CACJ,CAMA,OALA,uBAAuBd,EAASS,EAAQL,CAAI,EAC5CW,EAA8Bf,EAASI,EAAMK,CAAM,EAC/CA,EAAO,SAAW,GAClBT,EAAQ,MAAMC,EAAgB,gBAAiB,eAAeG,EAAK,uCAAwCF,EAAWH,CAAI,CAAC,EAExH,CAAE,KAAM,mBAAoB,cAAeC,EAAQ,cAAe,OAAM,UAAWF,EAAM,IAAM,KAAM,WAAU,UAAS,MAAK,SAAQ,cAAa,SAAUI,EAAWH,CAAI,CAAE,CACxL,CAEA,SAAS,uBAAuB,EAAwB,EAA0C,EAAoB,CAElH,IAAMiB,EAAWP,EAAO,OAAQ,GAA4CK,EAAM,OAAS,yBAAyB,EAC9GG,kBAAS,IAAI,IACnBD,EAAS,QAAQ,GAAWC,EAAO,IAAIC,EAAQ,KAAM,CAAC,GAAID,EAAO,IAAIC,EAAQ,IAAI,GAAK,CAAC,EAAIA,CAAO,CAAC,CAAC,EACpG,IAAK,IAAMC,IAAa,CAAC,GAAGF,EAAO,OAAO,CAAC,CAAC,CAAC,QAAQ,GAASG,EAAM,MAAM,CAAC,CAAC,EACxEpB,EAAQ,MAAMC,EAAgB,2BAA4B,sBAAsBkB,EAAU,KAAK,qCAAsCA,EAAU,QAAQ,EAE3J,IAAME,kBAAW,IAAI,IACrB,IAAK,IAAMC,KAASb,EAAO,QAAQ,GAASK,EAAM,OAAS,0BAA4BA,EAAM,SAAW,CAAC,CAAC,EAClGQ,EAAM,MAAM,OAAS,GAAKD,EAAS,IAAIC,EAAM,KAAK,GAClDtB,EAAQ,MAAMC,EAAgB,8BAA+B,mBAAmBqB,EAAM,MAAM,6CAA6ClB,EAAK,GAAIkB,EAAM,QAAQ,EAEpKD,EAAS,IAAIC,EAAM,KAAK,CAEhC,CAEA,SAAS,WAAW,EAAwB,EAAkB,EAAyD,CACnH,IAAMC,EAAWrB,EAAWH,CAAI,EAChC,OAAQI,EAAUJ,EAAK,OAAO,EAA9B,CACI,IAAK,OACD,OAAO,UAAUC,EAASD,CAAI,EAClC,IAAK,QAAS,CACV,IAAIyB,EAAkB,GAChB,CAAE,UAAS,YAAa,kBAAkBxB,EAASD,EAAM,GACvDW,EAAM,UAAY,qBAGtB,EAAkB,GACX,GACV,EACD,MAAO,CAAE,KAAM,cAAe,kBAAiB,UAAS,WAAU,UAAS,CAC/E,CACA,IAAK,MAAO,CACR,GAAM,CAAE,UAAS,YAAa,kBAAkBV,EAASD,CAAI,EAC7D,MAAO,CAAE,KAAM,YAAa,UAAS,WAAU,UAAS,CAC5D,CACA,IAAK,OACD,OAAO,UAAUC,EAASD,CAAI,EAClC,IAAK,WACD,OAAO,cAAcC,EAASD,CAAI,EACtC,IAAK,SACD,OAAO,YAAYC,EAASD,CAAI,EACpC,IAAK,SACD,OAAO,YAAYC,EAASD,CAAI,EACpC,IAAK,QAID,OAHK0B,GACDzB,EAAQ,MAAMC,EAAgB,4BAA6B,mDAAsDsB,CAAQ,EAEtH,eAAevB,EAASD,CAAI,EACvC,QACIC,EAAQ,MAAMC,EAAgB,2BAA4B,eAAeE,EAAUJ,EAAK,OAAO,EAAE,sBAAuBwB,CAAQ,EAChIvB,EAAQ,UAAUD,EAAK,MAAM,EAC7B,MACR,CACJ,CAEA,SAAS,UAAU,EAAwB,EAA8B,CACrE,IAAM2B,EAA4B,CAAC,EACnC,IAAK,IAAMC,KAAQC,EAAc7B,EAAK,QAAQ,UAAU,CAAa,EAAG,GAAG,EAAG,CAC1E,IAAM8B,EAAOF,EAAK,KAAK,EACvB,GAAIE,EAAK,SAAW,EAAG,CACnB7B,EAAQ,MAAMC,EAAgB,iBAAkB,sCAAyCC,EAAWH,CAAI,CAAC,EACzG,QACJ,CACA,IAAMD,EAAQf,EAAiB,KAAK8C,CAAI,EACpC/B,IAAU,KACVE,EAAQ,MAAMC,EAAgB,sBAAuB,4BAA4B4B,EAAK,GAAI3B,EAAWH,CAAI,CAAC,EAG9G2B,EAAO,KAAK,CAAE,KAAM,kBAAmB,MAAOI,EAAmBhC,EAAM,EAAE,EAAG,IAAKA,EAAM,KAAO,IAAA,GAAY,KAAOiC,EAA0BjC,EAAM,GAAII,EAAWH,CAAI,EAAGC,CAAO,EAAG,SAAUE,EAAWH,CAAI,CAAE,CAAC,CACjN,CACA,IAAMiC,EAA4B,CAAC,EAC/BxB,EAAwB,KACxByB,EAAqC,KACzC,IAAK,IAAIvB,EAAQV,EAAQ,UAAUD,EAAK,MAAM,EAAGW,IAAU,IAAA,GAAW,EAAQV,EAAQ,UAAUD,EAAK,MAAM,EAAG,CAC1GC,EAAQ,OAAO,gBAAgB,EAC/B,IAAMY,EAAUT,EAAUO,EAAM,OAAO,EACnCE,IAAY,MAAO,EAAM,SAASZ,EAASU,CAAK,EAC3CE,IAAY,SAAU,EAAYmB,EAA0BrB,EAAM,QAAQ,UAAU,CAAe,EAAGR,EAAWQ,CAAK,EAAGV,CAAO,EACpI,YAAYA,EAASU,EAAOsB,CAAQ,CAC7C,CACA,MAAO,CAAE,KAAM,aAAc,SAAQ,MAAK,YAAW,WAAU,SAAU9B,EAAWH,CAAI,CAAE,CAC9F,CAEA,SAAS,UAAU,EAAwB,EAA8B,CACrE,IAAMD,EAAQd,EAAY,KAAKe,EAAK,OAAO,EAC3C,GAAID,IAAU,KAGV,OAFAE,EAAQ,MAAMC,EAAgB,uBAAwB,6BAA6BF,EAAK,QAAQ,yCAA0CG,EAAWH,CAAI,CAAC,EAC1JC,EAAQ,UAAUD,EAAK,MAAM,EACtB,CAAE,KAAM,aAAc,SAAU,GAAI,GAAI,GAAI,OAAQ,CAAC,EAAG,SAAUG,EAAWH,CAAI,CAAE,EAE9F,IAAM2B,EAA4B,CAAC,EACnC,IAAK,IAAIhB,EAAQV,EAAQ,UAAUD,EAAK,MAAM,EAAGW,IAAU,IAAA,GAAW,EAAQV,EAAQ,UAAUD,EAAK,MAAM,EAAG,CAC1GC,EAAQ,OAAO,gBAAgB,EAC/B,IAAMkC,EAAYjD,EAAY,KAAKyB,EAAM,OAAO,EAChD,GAAIwB,IAAc,KAAM,CACpBlC,EAAQ,MAAMC,EAAgB,iBAAkB,mDAAmDS,EAAM,QAAQ,GAAIR,EAAWQ,CAAK,CAAC,EACtIV,EAAQ,UAAUU,EAAM,MAAM,EAC9B,QACJ,CACA,GAAM,CAAE,UAAS,YAAa,kBAAkBV,EAASU,CAAK,EAC9DgB,EAAO,KAAK,CAAE,KAAM,kBAAmB,MAAOI,EAAmBI,EAAU,EAAE,EAAG,UAAS,WAAU,SAAUhC,EAAWQ,CAAK,CAAE,CAAC,CACpI,CACA,MAAO,CAAE,KAAM,aAAc,SAAUoB,EAAmBhC,EAAM,EAAE,EAAG,GAAIgC,EAAmBhC,EAAM,EAAE,EAAG,SAAQ,SAAUI,EAAWH,CAAI,CAAE,CAC9I,CAEA,SAAS,cAAc,EAAwB,EAAkC,CAC7E,IAAMD,EAAQZ,EAAgB,KAAKa,EAAK,OAAO,EAC/C,GAAID,IAAU,KAGV,OAFAE,EAAQ,MAAMC,EAAgB,2BAA4B,iCAAiCF,EAAK,QAAQ,0DAA2DG,EAAWH,CAAI,CAAC,EACnLC,EAAQ,UAAUD,EAAK,MAAM,EACtB,CAAE,KAAM,iBAAkB,SAAU,GAAI,QAAS,UAAW,OAAQ,CAAC,EAAG,SAAUG,EAAWH,CAAI,CAAE,EAE9G,GAAM,CAAE,UAAS,UAAW,iBAAiBC,EAASD,CAAI,EAC1D,MAAO,CAAE,KAAM,iBAAkB,SAAU+B,EAAmBhC,EAAM,EAAE,EAAG,aAAciC,EAA0BjC,EAAM,GAAII,EAAWH,CAAI,EAAGC,CAAO,EAAG,UAAS,SAAQ,SAAUE,EAAWH,CAAI,CAAE,CACvM,CAEA,SAAS,YAAY,EAAwB,EAAgC,CACzE,IAAMD,EAAQX,EAAc,KAAKY,EAAK,OAAO,EAC7C,GAAID,IAAU,KAGV,OAFAE,EAAQ,MAAMC,EAAgB,yBAA0B,+BAA+BF,EAAK,QAAQ,kCAAmCG,EAAWH,CAAI,CAAC,EACvJC,EAAQ,UAAUD,EAAK,MAAM,EACtB,CAAE,KAAM,eAAgB,SAAU,GAAI,QAAS,UAAW,OAAQ,CAAC,EAAG,SAAUG,EAAWH,CAAI,CAAE,EAE5G,IAAMoC,EAAWL,EAAmBhC,EAAM,EAAE,EACtC,CAAE,UAAS,UAAW,iBAAiBE,EAASD,CAAI,EAI1D,OAHKU,EAAO,KAAK,GAASK,EAAM,OAAS,YAAY,GACjDd,EAAQ,MAAMC,EAAgB,uBAAwB,iBAAiBkC,EAAS,8CAA+CjC,EAAWH,CAAI,CAAC,EAE5I,CAAE,KAAM,eAAgB,WAAU,UAAS,SAAQ,SAAUG,EAAWH,CAAI,CAAE,CACzF,CAEA,SAAS,iBAAiB,EAAwB,EAA6E,CAC3H,IAAMU,EAAkC,CAAC,EACrCF,EAAuB,UAC3B,IAAK,IAAIG,EAAQV,EAAQ,UAAUD,EAAK,MAAM,EAAGW,IAAU,IAAA,GAAW,EAAQV,EAAQ,UAAUD,EAAK,MAAM,EAAG,CAE1G,GADAC,EAAQ,OAAO,gBAAgB,EAC3BU,EAAM,UAAY,UAAW,CAC7B,EAAU,UACV,QACJ,CACA,GAAIA,EAAM,UAAY,aAAc,CAChC,EAAU,WACV,QACJ,CACA,IAAMI,EAAQ,WAAWd,EAASU,EAAO,EAAI,EACzCI,IAAU,IAAA,IACVL,EAAO,KAAKK,CAAK,CAEzB,CACA,MAAO,CAAE,UAAS,QAAO,CAC7B,CAEA,SAAS,YAAY,EAAwB,EAAqD,CAC9F,IAAMsB,EAAU/C,EAAqB,KAAKU,EAAK,OAAO,EACtD,GAAIqC,IAAY,KACZ,MAAO,CAAE,KAAM,sBAAuB,MAAON,EAAmBM,EAAQ,EAAE,EAAG,IAAKA,EAAQ,KAAO,IAAA,GAAY,KAAOL,EAA0BK,EAAQ,GAAIlC,EAAWH,CAAI,EAAGC,CAAO,EAAG,SAAUE,EAAWH,CAAI,CAAE,EAErN,IAAMD,EAAQV,EAAkB,KAAKW,EAAK,OAAO,EACjD,GAAID,IAAU,KAAM,CAChBE,EAAQ,MAAMC,EAAgB,yBAA0B,+BAA+BF,EAAK,QAAQ,4EAA6EG,EAAWH,CAAI,CAAC,EACjMC,EAAQ,UAAUD,EAAK,MAAM,EAC7B,MACJ,CACA,IAAIS,EAAMV,EAAM,KAAO,IAAA,GAAY,KAAOiC,EAA0BjC,EAAM,GAAII,EAAWH,CAAI,EAAGC,CAAO,EACnGqC,EAAsC,KACtCJ,EAAqC,KACzC,IAAK,IAAIvB,EAAQV,EAAQ,UAAUD,EAAK,MAAM,EAAGW,IAAU,IAAA,GAAW,EAAQV,EAAQ,UAAUD,EAAK,MAAM,EAEvG,GADAC,EAAQ,OAAO,gBAAgB,EAC3BG,EAAUO,EAAM,OAAO,IAAM,SAC7B,EAAYqB,EAA0BrB,EAAM,QAAQ,UAAU,CAAe,EAAGR,EAAWQ,CAAK,EAAGV,CAAO,OACvG,GAAIG,EAAUO,EAAM,OAAO,IAAM,MAAO,EACvCF,IAAQ,MAAQ6B,IAAa,OAAMrC,EAAQ,MAAMC,EAAgB,0BAA2B,sCAAuCC,EAAWQ,CAAK,CAAC,EACxJ,IAAM4B,EAAS,SAAStC,EAASU,CAAK,EAClC4B,EAAO,OAAS,qBAAsB,EAAWA,EAChD,EAAMA,EAAO,UACtB,MACItC,EAAQ,MAAMC,EAAgB,uBAAwB,eAAeS,EAAM,QAAQ,uDAAwDR,EAAWQ,CAAK,CAAC,EAGpK,MAAO,CAAE,KAAM,mBAAoB,MAAOoB,EAAmBhC,EAAM,EAAE,EAAG,MAAK,GAAIuC,IAAa,KAAO,CAAC,EAAI,CAAE,UAAS,EAAI,YAAW,SAAUnC,EAAWH,CAAI,CAAE,CACnK,CAEA,SAAS,eAAe,EAAwB,EAAmC,CAC/E,IAAMD,EAAQR,EAAiB,KAAKS,EAAK,OAAO,EAKhD,OAJID,IAAU,MACVE,EAAQ,MAAMC,EAAgB,wBAAyB,8BAA8BF,EAAK,QAAQ,uCAAwCG,EAAWH,CAAI,CAAC,EACnJ,CAAE,KAAM,kBAAmB,MAAO,GAAI,SAAUG,EAAWH,CAAI,CAAE,GAErE,CAAE,KAAM,kBAAmB,MAAO+B,EAAmBhC,EAAM,EAAE,EAAG,SAAUI,EAAWH,CAAI,CAAE,CACtG,CAEA,SAAS,aAAa,EAAwB,EAA2C,CACrF,IAAMD,EAAQP,EAAe,KAAKQ,EAAK,OAAO,EAC9C,GAAID,IAAU,KAGV,OAFAE,EAAQ,MAAMC,EAAgB,oCAAqC,gCAAgCF,EAAK,QAAQ,+BAAgCG,EAAWH,CAAI,CAAC,EAChKC,EAAQ,UAAUD,EAAK,MAAM,EACtB,CAAE,KAAM,0BAA2B,KAAMI,EAAUJ,EAAK,OAAO,EAAG,SAAU,CAAC,EAAG,OAAQ,CAAC,EAAG,SAAUG,EAAWH,CAAI,CAAE,EAElI,IAAMK,EAAO0B,EAAmBhC,EAAM,EAAE,EAClCyC,EAAuC,CAAC,EACxC9B,EAAkC,CAAC,EACzC,IAAK,IAAIC,EAAQV,EAAQ,UAAUD,EAAK,MAAM,EAAGW,IAAU,IAAA,GAAW,EAAQV,EAAQ,UAAUD,EAAK,MAAM,EAAG,CAC1GC,EAAQ,OAAO,gBAAgB,EAC/B,IAAMY,EAAUT,EAAUO,EAAM,OAAO,EACvC,GAAIE,IAAY,SACZ2B,EAAS,KAAK,cAAcvC,EAASU,CAAK,CAAC,OACxC,GAAIE,IAAY,UACnBZ,EAAQ,MAAMC,EAAgB,kCAAmC,sDAAuDC,EAAWQ,CAAK,CAAC,EACzIV,EAAQ,UAAUU,EAAM,MAAM,MAC3B,CACH,IAAMI,EAAQ,WAAWd,EAASU,EAAO,EAAK,EAC1CI,IAAU,IAAA,IACVL,EAAO,KAAKK,CAAK,CAEzB,CACJ,CAIA,OAHIyB,EAAS,SAAW,GACpBvC,EAAQ,MAAMC,EAAgB,6BAA8B,YAAYG,EAAK,+CAAgDF,EAAWH,CAAI,CAAC,EAE1I,CAAE,KAAM,0BAA2B,OAAM,WAAU,SAAQ,SAAUG,EAAWH,CAAI,CAAE,CACjG,CAEA,SAAS,cAAc,EAAwB,EAA4C,CACvF,IAAMD,EAAQN,EAAgB,KAAKO,EAAK,OAAO,EAM/C,OALID,IAAU,MACVE,EAAQ,MAAMC,EAAgB,2BAA4B,oCAAoCF,EAAK,QAAQ,yDAA0DG,EAAWH,CAAI,CAAC,EACrLC,EAAQ,UAAUD,EAAK,MAAM,EACtB,CAAE,KAAM,2BAA4B,MAAO,GAAI,IAAK,KAAM,SAAUG,EAAWH,CAAI,CAAE,GAEzF,CAAE,KAAM,2BAA4B,MAAO+B,EAAmBhC,EAAM,EAAE,EAAG,IAAKA,EAAM,KAAO,IAAA,GAAY,KAAOiC,EAA0BjC,EAAM,GAAII,EAAWH,CAAI,EAAGC,CAAO,EAAG,SAAUE,EAAWH,CAAI,CAAE,CACpN,CAGA,SAAS,SAAS,EAAwB,EAA6B,CACnE,IAAM8B,EAAO9B,EAAK,QAAQ,UAAU,CAAY,CAAC,CAAC,KAAK,EACvD,GAAIC,EAAQ,UAAUD,EAAK,MAAM,IAAM,IAAA,GAAW,MAAO,CAAE,KAAM,sBAAuB,WAAYgC,EAA0BF,EAAM3B,EAAWH,CAAI,EAAGC,CAAO,EAAG,SAAUE,EAAWH,CAAI,CAAE,EACvL8B,EAAK,SAAS,GAAG,GAAG7B,EAAQ,YAAYC,EAAgB,4BAA6B,wFAAyFC,EAAWH,CAAI,CAAC,EAClM,IAAMyC,EAAyB,CAAC,EAChC,IAAK,IAAI9B,EAAQV,EAAQ,UAAUD,EAAK,MAAM,EAAGW,IAAU,IAAA,GAAW,EAAQV,EAAQ,UAAUD,EAAK,MAAM,EAAG,CAE1G,GADAC,EAAQ,OAAO,gBAAgB,EAC3BU,EAAM,UAAY,IAAK,SAC3B,IAAMZ,EAAQF,EAAkB,KAAKc,EAAM,OAAO,EAClD,GAAIZ,IAAU,KAAM,CACZE,EAAQ,cAAc,cAAgB,SAASA,EAAQ,MAAMC,EAAgB,wBAAyB,+BAA+BS,EAAM,QAAQ,0CAA2CR,EAAWQ,CAAK,CAAC,EACnN,QACJ,CACA,IAAM+B,EAAaV,EAA0BjC,EAAM,GAAII,EAAWQ,CAAK,EAAGV,CAAO,EAC7EA,EAAQ,cAAc,cAAgB,SAAW6B,EAAK,QAAQ,MAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,OAAS,GAAKY,EAAW,OAAS,4BAA4BzC,EAAQ,MAAMC,EAAgB,uBAAwB,yDAA0DC,EAAWQ,CAAK,CAAC,EACnR8B,EAAM,KAAK,CAAE,KAAM,gBAAiB,SAAUV,EAAmBhC,EAAM,EAAE,EAAG,aAAY,SAAUI,EAAWQ,CAAK,CAAE,CAAC,CACzH,CACA,IAAMgC,EAAU1C,EAAQ,OAAO,gBAAgB,EAG/C,OAFI0C,IAAY,IAAA,IAAaA,EAAQ,SAAW3C,EAAK,QAAU2C,EAAQ,UAAY,KAAK1C,EAAQ,OAAO,gBAAgB,EACnHA,EAAQ,cAAc,cAAgB,SAAWwC,EAAM,SAAW,GAAGxC,EAAQ,MAAMC,EAAgB,kBAAmB,gDAAiDC,EAAWH,CAAI,CAAC,EACpL,CAAE,KAAM,qBAAsB,KAAM8B,EAAK,QAAQ,MAAO,EAAE,CAAC,CAAC,KAAK,EAAG,QAAO,SAAU3B,EAAWH,CAAI,CAAE,CACjH,CAIA,SAAS,kBAAkB,EAAwB,EAAkB,MAA8C,GAA4D,CAC3K,IAAIQ,EAAuB,UACrByB,EAA4B,CAAC,EACnC,IAAK,IAAItB,EAAQV,EAAQ,UAAUD,EAAK,MAAM,EAAGW,IAAU,IAAA,GAAW,EAAQV,EAAQ,UAAUD,EAAK,MAAM,EACvGC,EAAQ,OAAO,gBAAgB,EAC3BU,EAAM,UAAY,UAClB,EAAU,UACHA,EAAM,UAAY,aACzB,EAAU,WACFiC,EAAMjC,CAAK,GACnB,YAAYV,EAASU,EAAOsB,CAAQ,EAG5C,MAAO,CAAE,UAAS,UAAS,CAC/B,CAIA,SAAS,YAAY,EAAwB,EAAkB,EAAiC,CAC5F,IAAMT,EAAWrB,EAAWH,CAAI,EAC1Ba,EAAUnB,EAAsB,KAAKM,EAAK,OAAO,EACvD,GAAIa,IAAY,KAAM,CACdA,EAAQ,KAAO,SAAWA,EAAQ,KAAO,OACzCoB,EAAS,KAAK,CAAE,KAAMnC,EAAgBe,EAAQ,IAAK,SAAUkB,EAAmBlB,EAAQ,EAAE,EAAG,UAAS,CAAC,EAChGZ,EAAQ,cAAc,cAAgB,SAC7CA,EAAQ,MAAMC,EAAgB,yBAA0B,oBAAoBF,EAAK,QAAQ,sHAAuHwB,EAAUqB,EAAe,OAAQ7C,EAAK,OAAO,CAAC,EAElQ,MACJ,CACA,IAAM8C,EAAanD,EAAkB,KAAKK,EAAK,OAAO,EACtD,GAAI8C,IAAe,KAAM,CACrBb,EAAS,KAAK,CAAE,KAAMa,EAAW,KAAO,MAAQ,mBAAqB,wBAAyB,SAAUf,EAAmBe,EAAW,EAAE,EAAG,MAAOd,EAA0Bc,EAAW,GAAItB,EAAUvB,CAAO,EAAG,GAAI6C,EAAW,KAAO,IAAA,GAAY,CAAC,EAAI,CAAE,OAAQd,EAA0Bc,EAAW,GAAItB,EAAUvB,CAAO,CAAE,EAAI,UAAS,CAAC,EAC1U,MACJ,CACA,IAAM8C,EAAWnD,EAAW,KAAKI,EAAK,OAAO,GAAKH,EAAkB,KAAKG,EAAK,OAAO,EACjF+C,IAAa,KAEN9C,EAAQ,cAAc,cAAgB,SAC7CA,EAAQ,MAAMC,EAAgB,yBAA0B,oBAAoBF,EAAK,QAAQ,GAAIwB,EAAUqB,EAAe,OAAQ7C,EAAK,OAAO,CAAC,EAF3IiC,EAAS,KAAK,CAAE,KAAM,mBAAoB,SAAUF,EAAmBgB,EAAS,EAAE,EAAG,OAAQf,EAA0Be,EAAS,GAAIvB,EAAUvB,CAAO,EAAG,UAAS,CAAC,CAI1K"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{pattern as t}from"../Text/patterns.js";import{locationOf as n}from"./SourceLine.js";import{
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{pattern as t}from"../Text/patterns.js";import{locationOf as n}from"./SourceLine.js";import{combineAuthorize as r,parseAuthorize as i}from"./AuthorizeParser.js";import{parseMappingSource as a}from"./ExpressionParser.js";import{firstWord as o}from"./LineText.js";import{parseTypeRef as s,reportLegacyOptionalSuffix as c}from"./PropertyLineParser.js";import{parseDescription as l}from"./DescriptionParser.js";const u=t(`^query\\s+([A-Za-z_]\\w*)\\s*=>\\s*(observable\\s+)?([\\w.]+(?:\\[\\])?(?:\\?|\\s+optional)?)$`),d=t(`^([a-z_]\\w*)\\s+([\\w.]+(?:\\[\\])?(?:\\?|\\s+optional)?)(?:\\s+from\\s+(.+))?$`),f=t(`^scoped\\s+to\\s+([a-z_]\\w*)$`),p=/* @__PURE__ */ new Set([`performer`]);function parseQuery(t,a){let d=u.exec(a.content);if(d===null)return t.error(e.InvalidQueryDeclaration,`Invalid query declaration '${a.content}' - expected 'query <Name> => [observable] <ReadModel>'`,n(a)),t.skipBlock(a.indent),{kind:`QuerySyntax`,name:o(a.content),returnType:s(``,n(a)),by:null,filters:[],description:null,isObservable:!1,scope:null,authorize:null,location:n(a)};let f=d[1],m=s(d[3],{...n(a),column:a.indent+1+d[0].length-d[3].length});(d[2]!==void 0||m.name!==`observable`||!m.isOptional||m.isCollection)&&c(t,m,a);let h=null,g=[],_=!1,v=[],y=null,b=null,x=null;for(let s=t.peekChild(a.indent);s!==void 0;s=t.peekChild(a.indent)){t.reader.takeSignificant();let a=o(s.content);if(a===`description`)y=l(t,s,y,`Query '${f}'`);else if(a===`by`){if(s.content===`by`){_&&t.error(e.InvalidReadModelKeyLookup,`A query cannot combine a by block with another by declaration.`,n(s)),h=null,g.length=0;for(let e=t.peekChild(s.indent);e!==void 0;e=t.peekChild(s.indent)){t.reader.takeSignificant();let n=parseParameter(t,e,``);n!==void 0&&g.push(n)}(g.length<2||new Set(g.map(e=>e.name)).size!==g.length)&&t.error(e.InvalidReadModelKeyLookup,`A query by block requires at least two distinct named key parts.`,n(s)),_=!0}else{let r=parseParameter(t,s,`by`);r!==void 0&&(_&&t.error(e.InvalidQueryParameter,`Query '${f}' already declares 'by' - a query can have at most one key parameter`,n(s)),g.length>0&&t.error(e.InvalidReadModelKeyLookup,`A query cannot combine a by block with a single by line.`,n(s)),g.length=0,h=r,_=!0)}}else if(a===`filter`){let e=parseParameter(t,s,`filter`);e!==void 0&&v.push(e)}else a===`authorize`?x=r(x,i(t,s)):a===`scoped`?b=parseScope(t,s,b,f)??b:p.has(a)?t.skipOpaqueBlock(s.indent):(t.error(e.UnknownQueryDirective,`Unexpected '${s.content}' in query body - expected description, by, filter, authorize, scoped or performer`,n(s)),t.skipBlock(s.indent))}return{kind:`QuerySyntax`,name:f,returnType:m,by:h,...g.length>0?{byParts:g}:{},filters:v,description:y,isObservable:d[2]!==void 0,scope:b,authorize:x,location:n(a)}}function parseParameter(t,r,i){let o=d.exec(r.content.substring(i.length).trim());if(o===null){t.error(e.InvalidQueryParameter,`Invalid '${i}' parameter '${r.content}' - expected '${i} <name> <Type> [from <source>]'`,n(r));return}let l=r.content.indexOf(o[1],i.length),u=s(o[2],{...n(r),column:r.indent+1+r.content.indexOf(o[2],l+o[1].length)});return c(t,u,r),{kind:`QueryParameterSyntax`,name:o[1],type:u,source:o[3]===void 0?null:a(o[3],n(r),t.valueContext),location:n(r)}}function parseScope(t,r,i,a){let o=f.exec(r.content);if(o===null)t.error(e.InvalidScopeDeclaration,`Invalid scope declaration '${r.content}' - expected 'scoped to <scope>'`,n(r));else if(i!==null)t.error(e.DuplicateScope,`Query '${a}' already declares a scope - results are narrowed one way`,n(r));else return o[1]}export{parseQuery};
|
|
2
2
|
//# sourceMappingURL=QueryParser.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{AuthoringProductionResolver as t}from"../Syntax/AuthoringProductionResolver.js";import{dependencySourcesOf as n}from"../Syntax/DependencySources.js";function validateReadModelMemberTypes(r,i){let a=/* @__PURE__ */ new Set([`Uuid`,`String`,`Int`,`Decimal`,`Bool`,`Date`,`DateTime`,...r.concepts.map(e=>e.name),...r.types.map(e=>e.name),...r.imports.map(e=>e.qualifiedName.split(`.`).at(-1))]),o=new t(r).slices.map(({slice:e})=>e),s=o.flatMap(e=>e.readModels),c=/* @__PURE__ */ new Set([...s.map(e=>e.name),...o.flatMap(e=>(n(e).reducers??[]).map(e=>e.readModel)),...o.flatMap(e=>e.projections.flatMap(e=>{let t=e.blocks.filter(e=>e.kind===`ProjectionVariantSyntax`);return t.length>0?t.map(e=>e.name):[e.readModel??e.name]}))]);for(let t of s)for(let n of t.properties.filter(e=>!a.has(e.type.name)&&c.has(e.type.name)))i.error(e.InvalidSemanticBinding,`Read model '${t.name}' member '${n.name}' references unsupported type '${n.type.name}'. Use a primitive, concept or top-level 'type'; read-model shapes and slice-local 'type' declarations are not member types.`,n.type.location)}export{validateReadModelMemberTypes};
|
|
2
|
+
//# sourceMappingURL=ReadModelMemberTypeValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReadModelMemberTypeValidator.js","names":["types","application","concept","type","imported","slices","AuthoringProductionResolver","slice","models","readModels","model","dependencySourcesOf","reducer","variants","projection","block","variant","property","context","DiagnosticCodes"],"sources":["../../../../../../Compiler/Parsing/ReadModelMemberTypeValidator.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { DiagnosticCodes } from '../Diagnostics/DiagnosticCodes';\nimport { AuthoringProductionResolver } from '../Syntax/AuthoringProductionResolver';\nimport { dependencySourcesOf } from '../Syntax/DependencySources';\nimport { ApplicationSyntax } from '../Syntax/Structure';\nimport { ParserContext } from './ParserContext';\n\n// A read model has an identity; only primitives, concepts, top-level types and imported names\n// belong to the reusable value-type namespace. Validate after file composition.\nexport function validateReadModelMemberTypes(application: ApplicationSyntax, context: ParserContext): void {\n const types = new Set([\n 'Uuid', 'String', 'Int', 'Decimal', 'Bool', 'Date', 'DateTime',\n ...application.concepts.map(concept => concept.name),\n ...application.types.map(type => type.name),\n ...application.imports.map(imported => imported.qualifiedName.split('.').at(-1)!),\n ]);\n const slices = new AuthoringProductionResolver(application).slices.map(({ slice }) => slice);\n const models = slices.flatMap(slice => slice.readModels);\n const readModels = new Set([\n ...models.map(model => model.name),\n ...slices.flatMap(slice => (dependencySourcesOf(slice).reducers ?? []).map(reducer => reducer.readModel)),\n ...slices.flatMap(slice => slice.projections.flatMap(projection => {\n const variants = projection.blocks.filter(block => block.kind === 'ProjectionVariantSyntax');\n return variants.length > 0 ? variants.map(variant => variant.name) : [projection.readModel ?? projection.name];\n })),\n ]);\n for (const model of models) {\n for (const property of model.properties.filter(property => !types.has(property.type.name) && readModels.has(property.type.name))) {\n context.error(DiagnosticCodes.InvalidSemanticBinding,\n `Read model '${model.name}' member '${property.name}' references unsupported type '${property.type.name}'. Use a primitive, concept or top-level 'type'; read-model shapes and slice-local 'type' declarations are not member types.`,\n property.type.location);\n }\n }\n}\n"],"mappings":"qRAWA,SAAgB,6BAA6B,EAAgC,EAA8B,CACvG,IAAMA,kBAAQ,IAAI,IAAI,CAClB,OAAQ,SAAU,MAAO,UAAW,OAAQ,OAAQ,WACpD,GAAGC,EAAY,SAAS,IAAI,GAAWC,EAAQ,IAAI,EACnD,GAAGD,EAAY,MAAM,IAAI,GAAQE,EAAK,IAAI,EAC1C,GAAGF,EAAY,QAAQ,IAAI,GAAYG,EAAS,cAAc,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,CAAE,CACpF,CAAC,EACKC,EAAS,IAAIC,EAA4BL,CAAW,CAAC,CAAC,OAAO,KAAK,CAAE,WAAYM,CAAK,EACrFC,EAASH,EAAO,QAAQ,GAASE,EAAM,UAAU,EACjDE,kBAAa,IAAI,IAAI,CACvB,GAAGD,EAAO,IAAI,GAASE,EAAM,IAAI,EACjC,GAAGL,EAAO,QAAQ,IAAUM,EAAoBJ,CAAK,CAAC,CAAC,UAAY,CAAC,EAAA,CAAG,IAAI,GAAWK,EAAQ,SAAS,CAAC,EACxG,GAAGP,EAAO,QAAQ,GAASE,EAAM,YAAY,QAAQ,GAAc,CAC/D,IAAMM,EAAWC,EAAW,OAAO,OAAO,GAASC,EAAM,OAAS,yBAAyB,EAC3F,OAAOF,EAAS,OAAS,EAAIA,EAAS,IAAI,GAAWG,EAAQ,IAAI,EAAI,CAACF,EAAW,WAAaA,EAAW,IAAI,CACjH,CAAC,CAAC,CACN,CAAC,EACD,IAAK,IAAMJ,KAASF,EAChB,IAAK,IAAMS,KAAYP,EAAM,WAAW,OAAO,GAAY,CAACV,EAAM,IAAIiB,EAAS,KAAK,IAAI,GAAKR,EAAW,IAAIQ,EAAS,KAAK,IAAI,CAAC,EAC3HC,EAAQ,MAAMC,EAAgB,uBAC1B,eAAeT,EAAM,KAAK,YAAYO,EAAS,KAAK,iCAAiCA,EAAS,KAAK,KAAK,8HACxGA,EAAS,KAAK,QAAQ,CAGtC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{stringBodyPattern as t,unescapeString as n}from"../Text/StringLiteral.js";import{pattern as r}from"../Text/patterns.js";import{locationOf as i}from"./SourceLine.js";import{parseMappingSource as a}from"./ExpressionParser.js";import{firstWord as o}from"./LineText.js";import{parseTypeRef as s}from"./PropertyLineParser.js";import{parseAuthorize as c}from"./AuthorizeParser.js";import{parseFencedText as l}from"./CodeBlockParser.js";import{parseDescription as u}from"./DescriptionParser.js";import{parseGuardedAction as d}from"./GuardedActionParser.js";import{collectInputUses as f}from"./InputUses.js";import{isFileDirective as p}from"./FileReferences.js";import{parsePlainActionInput as m,parseSubjectClause as h}from"./ActionSubjectClause.js";import{isValidTemplateVersionRange as g,parseBlueprintReference as _,startsBlueprintReference as v}from"./TemplateReferenceText.js";import{parseFromClause as y}from"./UiBindingParser.js";const b=`(?:"(${t})"|(\\$strings\\.\\w+(?:\\.\\w+)*))`,x=r(`^screen\\s+([A-Za-z_]\\w*)$`),S=r(`^data\\s+([\\w.]+(?:\\[\\])?)\\s+via\\s+query\\s+(\\w+(?:\\.\\w+)*)(?:\\s+by\\s+(\\w+))?$`),C=r(`^action\\s+([A-Za-z_]\\w*(?:\\.\\w+)*)$`),w=r(`^label\\s+${b}$`),T=r(`^action\\s+${b}$`),E=r(`^navigate\\s+to\\s+(\\w+(?:\\.\\w+)*)(?:\\s+by\\s+(\\w+))?$`),D=r(`^route\\s+${b}$`),O=r(`^outlet\\s+([A-Za-z_]\\w*)$`),k=r(`^contribute\\s+to\\s+([A-Za-z_]\\w*)(?:\\s+order\\s+(-?\\d+))?$`),A=r(`^parameter\\s+([A-Za-z_]\\w*)\\s+from\\s+(.+)$`),j=r(`^component\\s+([A-Za-z_]\\w*(?:\\.[A-Za-z_]\\w*)*)\\s+([A-Za-z_]\\w*)$`),M=r(`^id\\s+(?:"(${t})"|(\\S+))$`),N=r(`^property\\s+([\\w.]+)\\s+from\\s+(.+)$`),P=r(`^property\\s+([\\w.]+)\\s*=\\s+(.+)$`),F=r(`^exposes\\s+([A-Za-z_]\\w*)\\s+from\\s+(.+)$`),I=r(`^presentation\\s+([A-Za-z_]\\w*)\\s+${b}$`),L=r(`^confirm\\s+${b}$`),R=r(`^item\\s+([A-Za-z_]\\w*)\\s+(action|navigate|dialog)(?:\\s+to)?\\s+([A-Za-z_]\\w*(?:\\.\\w+)*)$`),z=r(`^button\\s+(?:"(${t})"|([A-Za-z_][\\w-]*))(?:\\s+(.*))?$`),B=new RegExp(r(`\\s*(title|slice|emphasis|icon)\\s+(?:"(${t})"|(\\$strings\\.\\w+(?:\\.\\w+)*)|([A-Za-z_][\\w.-]*))(?=\\s|$)`).source,`uy`),V=r(`^[A-Za-z_]\\w*(?:\\.[A-Za-z_]\\w*)*$`),H=r(`^[a-z_]\\w*$`),U=r(`^title\\s+${b}$`),W=r(`^column\\s+([\\w.]+)(?:\\s+label\\s+${b})?$`),G=r(`^on\\s+row-click\\s+(navigate\\s+to\\s+.+)$`),K=r(`^field\\s+([\\w.]+)\\s+label\\s+${b}$`),operandText=(e,t)=>e[t]===void 0?e[t+1]:n(e[t]),isInteraction=e=>[`on`,`uses`].includes(o(e.content)),isCodeLine=(e,t)=>t.content.startsWith("```")||e.languages.has(t.content);function parseScreen(t,n){let r=x.exec(n.content);r===null&&t.error(e.InvalidScreenDeclaration,`Invalid screen declaration '${n.content}' - expected 'screen <Name>'`,i(n));let a=[],s=[],c=null;for(let e=t.peekChild(n.indent);e!==void 0;e=t.peekChild(n.indent))if(t.reader.takeSignificant(),o(e.content)===`contribute`){let n=parseScreenContribution(t,e);n!==void 0&&s.push(n)}else o(e.content)===`description`?c=u(t,e,c,`Screen '${r?.[1]??``}'`):p(e)||pushDirective(t,e,a);return{kind:`ScreenSyntax`,name:r?.[1]??``,directives:a,description:c,...s.length>0?{contributions:s}:{},location:i(n)}}function parseScreenContribution(t,n){let r=k.exec(n.content);if(r===null)t.error(e.UnknownScreenDirective,`Invalid screen contribution '${n.content}' - expected 'contribute to <Point> [order <n>]'`,i(n)),t.skipBlock(n.indent);else return{kind:`ScreenContributionSyntax`,contributionPoint:r[1],order:r[2]===void 0?null:Number(r[2]),directives:parseDirectives(t,n),location:i(n)}}function pushDirective(e,t,n){let r=parseDirective(e,t);r!==void 0&&n.push(r)}function parseDirectives(e,t){let n=[];for(let r=e.peekChild(t.indent);r!==void 0;r=e.peekChild(t.indent))e.reader.takeSignificant(),pushDirective(e,r,n);return n}function parseDirective(t,n){switch(validateNonActionSubjectClause(t,n),o(n.content)){case`data`:return parseData(t,n);case`action`:return parseAction(t,n);case`template`:return parseTemplateReference(t,n);case`section`:return parseSection(t,n);case`title`:return parseTitle(t,n);case`table`:return parseTable(t,n);case`summary`:return parseSummary(t,n);case`component`:return parseComponent(t,n);case`toolbar`:return parseToolbar(t,n);case`navigate`:return parseNavigate(t,n.content,n);case`on`:return f(t,n),{kind:`ScreenBehaviorSyntax`,location:i(n)};case`uses`:return f(t,n),{kind:`ScreenUsesBehaviorSyntax`,location:i(n)};default:if(isCodeLine(t,n))return parseCode(t,n);t.error(e.UnknownScreenDirective,`Unexpected '${n.content}' in screen body`,i(n)),t.skipBlock(n.indent);return}}function parseData(t,n){let r=S.exec(n.content);if(r===null)t.error(e.InvalidDataDirective,`Invalid data directive '${n.content}' - expected 'data <ReadModel> via query <Query> [by <param>]'`,i(n));else return{kind:`ScreenDataSyntax`,type:s(r[1],i(n)),query:r[2],by:r[3]??null,location:i(n)}}function validateNonActionSubjectClause(e,t){let n=(/* @__PURE__ */ new Map([[`data`,S],[`navigate`,E],[`component`,j],[`title`,U]])).get(o(t.content));n!==void 0&&h(e,t,!1,e=>n.test(e))}function parseAction(e,t){let n=h(e,t,!0,e=>C.test(e)||T.test(e)),r=parseActionHeader(e,t,n);return r===void 0||n.subject===void 0?r:{...r,subject:n.subject}}function parseActionHeader(t,n,r){let a=T.exec(r.header);if(a!==null)return d(t,n,operandText(a,1),parseNavigate);let s=C.exec(r.header);if(s===null){t.error(e.InvalidActionDirective,`Invalid action directive '${n.content}' - expected 'action <Command>'`,i(n)),t.skipBlock(n.indent);return}let c=r.label??null,l=null,u=[];for(let r=t.peekChild(n.indent);r!==void 0;r=t.peekChild(n.indent)){t.reader.takeSignificant();let n=w.exec(r.content);n===null?o(r.content)===`navigate`?l=parseNavigate(t,r.content,r)??null:o(r.content)===`with`?addPlainActionInput(t,r,u):t.error(e.UnknownActionDirective,`Unexpected '${r.content}' in action - expected 'label "..."' or 'navigate to ...'`,i(r)):c=operandText(n,1)}return{kind:`ScreenActionSyntax`,command:s[1],label:c,navigate:l,...u.length===0?{}:{inputs:u},location:i(n)}}function addPlainActionInput(e,t,n){let r=m(e,t,n);r!==void 0&&n.push(r)}function parseNavigate(t,n,r){let a=E.exec(n);if(a===null){t.error(e.InvalidNavigation,`Invalid navigation '${n}' - expected 'navigate to <Screen> [by <param>]'`,i(r));return}let o=[],s=null,c=null;for(let n=t.peekChild(r.indent);n!==void 0;n=t.peekChild(r.indent)){t.reader.takeSignificant();let r=A.exec(n.content);if(r!==null){o.push({kind:`ScreenNavigationParameterSyntax`,name:r[1],binding:y(t,r[2],i(n)),location:i(n)});continue}let a=D.exec(n.content);if(a!==null){s=operandText(a,1);continue}let l=O.exec(n.content);l===null?t.error(e.InvalidNavigation,`Unexpected '${n.content}' in navigation - expected 'route "..."', 'outlet <name>' or 'parameter <name> from <binding>'`,i(n)):c=l[1]}return{kind:`ScreenNavigateSyntax`,screen:a[1],by:a[2]??null,route:s,...c===null?{}:{outlet:c},parameters:o,location:i(r)}}function parseTemplateReference(t,n){let r=n.content.substring(8).trim(),a=null,o=null;if(v(r)){let s=_(r);s===void 0?t.error(e.UnknownLayoutDirective,`Invalid template reference '${n.content}' - expected 'template <Name>' or 'template blueprint <Blueprint> <Name> [version "<range>"]'`,i(n)):({blueprint:a,name:r,version:o}=s,o!==null&&!g(o)&&t.error(e.InvalidTemplateVersionRange,`The template version range '${o}' is not one Scene understands - use '*', an exact version or a ^, ~, >=, >, <= or < range such as "^1.2"`,i(n)))}let s=[];for(let a=t.peekChild(n.indent);a!==void 0;a=t.peekChild(n.indent))t.reader.takeSignificant(),H.test(a.content)?s.push({kind:`ScreenSlotSyntax`,name:a.content,directives:parseDirectives(t,a),location:i(a)}):(t.error(e.InvalidScreenLayoutSlot,`Expected a slot name in template '${r}', got '${a.content}'`,i(a)),t.skipBlock(a.indent));return{kind:`ScreenTemplateReferenceSyntax`,name:r,slots:s,...a===null?{}:{blueprint:a},...o===null?{}:{version:o},location:i(n)}}function parseSection(e,t){return{kind:`ScreenSectionSyntax`,name:t.content.substring(7).trim(),directives:parseDirectives(e,t),location:i(t)}}function parseTitle(t,n){let r=U.exec(n.content);return r===null?(t.error(e.InvalidTitleDirective,`Invalid title directive '${n.content}' - expected 'title "..."'`,i(n)),{kind:`ScreenTitleSyntax`,text:``,location:i(n)}):{kind:`ScreenTitleSyntax`,text:operandText(r,1),location:i(n)}}function parseTable(t,n){let r=n.content.substring(5).trim(),a=[],s=null;for(let r=t.peekChild(n.indent);r!==void 0;r=t.peekChild(n.indent)){t.reader.takeSignificant();let n=W.exec(r.content),c=G.exec(r.content);if(n!==null){let e=n[2]!==void 0||n[3]!==void 0;a.push({kind:`ScreenColumnSyntax`,property:n[1],label:e?operandText(n,2):null,location:i(r)})}else c===null?o(r.content)===`on`||isInteraction(r)?f(t,r):t.error(e.UnknownTableDirective,`Unexpected '${r.content}' in table - expected 'column ...', 'on row-click navigate to ...', 'on <trigger>' or 'uses <Behavior>'`,i(r)):s=parseNavigate(t,c[1],r)??null}return{kind:`ScreenTableSyntax`,target:r,columns:a,rowClick:s,location:i(n)}}function parseSummary(t,n){let r=n.content.substring(7).trim(),a=[];for(let r=t.peekChild(n.indent);r!==void 0;r=t.peekChild(n.indent)){t.reader.takeSignificant();let n=K.exec(r.content);n===null?t.error(e.UnknownSummaryDirective,`Unexpected '${r.content}' in summary - expected 'field <property> label "..."'`,i(r)):a.push({kind:`ScreenFieldSyntax`,property:n[1],label:operandText(n,2),location:i(r)})}return{kind:`ScreenSummarySyntax`,target:r,fields:a,location:i(n)}}function parseComponent(t,n){let r=j.exec(n.content);if(r===null){t.error(e.UnknownScreenDirective,`Invalid component directive '${n.content}' - expected 'component <Package.Component> <name>'`,i(n)),t.skipBlock(n.indent);return}let a=null,s=null,c=null,l=[],u=[],d=[],p=[];for(let r=t.peekChild(n.indent);r!==void 0;r=t.peekChild(n.indent))switch(t.reader.takeSignificant(),o(r.content)){case`context`:a=parseUiContext(t,r);break;case`id`:s=parseStableId(t,r);break;case`property`:parseComponentProperty(t,r,l);break;case`icon`:c=r.content.substring(4).trim();break;case`presentation`:parsePresentationValue(t,r,d);break;case`exposes`:parseExposedValue(t,r,u);break;case`outlet`:p.push({kind:`ComponentOutletSyntax`,name:r.content.substring(6).trim(),directives:parseDirectives(t,r),location:i(r)});break;case`on`:f(t,r);break;case`uses`:f(t,r);break;default:t.error(e.UnknownScreenDirective,`Unexpected '${r.content}' in component - expected context, id, property, icon, presentation, exposes, outlet, on or uses`,i(r)),t.skipBlock(r.indent)}return{kind:`ScreenComponentSyntax`,component:r[1],name:r[2],stableId:s,context:a,properties:l,exposes:u,presentation:d,icon:c,outlets:p,location:i(n)}}function parseUiContext(e,t){return parseUiBindingValue(e,t.content.substring(7).trim(),t)}function parseComponentProperty(t,n,r){let o=N.exec(n.content);if(o!==null){r.push({kind:`ComponentPropertySyntax`,property:o[1],binding:y(t,o[2],i(n)),value:null,location:i(n)});return}let s=P.exec(n.content);s===null?t.error(e.UnknownScreenDirective,`Invalid component property '${n.content}' - expected 'property <path> from <binding>' or 'property <path> = <literal|object|array|null>'`,i(n)):r.push({kind:`ComponentPropertySyntax`,property:s[1],binding:null,value:a(s[2],i(n),t),location:i(n)})}function parseStableId(t,n){let r=M.exec(n.content);return r===null?(t.error(e.UnknownScreenDirective,`Invalid component id '${n.content}' - expected 'id "stable-id"'`,i(n)),null):operandText(r,1)}function parseExposedValue(t,n,r){let a=F.exec(n.content);a===null?t.error(e.UnknownScreenDirective,`Invalid exposed value '${n.content}' - expected 'exposes <name> from <binding>'`,i(n)):r.push({kind:`ComponentExposedValueSyntax`,name:a[1],binding:y(t,a[2],i(n)),location:i(n)})}function parsePresentationValue(t,n,r){let a=I.exec(n.content);a===null?t.error(e.UnknownScreenDirective,`Invalid presentation value '${n.content}' - expected 'presentation <key> "value"'`,i(n)):r.push({kind:`PresentationValueSyntax`,name:a[1],value:operandText(a,2),location:i(n)})}function parseToolbar(e,t){let n=t.content.substring(7).trim(),r=[],a=[];for(let n=e.peekChild(t.indent);n!==void 0;n=e.peekChild(t.indent)){if(e.reader.takeSignificant(),o(n.content)===`button`){let t=parseToolbarButton(e,n);t!==void 0&&a.push(t);continue}let t=parseToolbarItem(e,n);t!==void 0&&r.push(t)}return{kind:`ScreenToolbarSyntax`,name:n,items:r,...a.length>0?{buttons:a}:{},location:i(t)}}const q=`button <id> title "<text>" [slice <Module>.<Feature>.<Slice>] [emphasis primary|secondary|quiet] [icon <name>]`;function parseToolbarButton(t,r){let a=z.exec(r.content);if(a===null){t.error(e.InvalidToolbarButton,`Invalid toolbar button '${r.content}' - expected ${q}`,i(r)),t.skipBlock(r.indent);return}let s=a[1]===void 0?a[2]:n(a[1]),l=a[3]??``,u,d,f,p,m=!0,h=0;for(;h<l.length;){B.lastIndex=h;let a=B.exec(l);if(a===null){t.error(e.InvalidToolbarButton,`Invalid toolbar button '${r.content}' - unexpected '${l.substring(h).trim()}'; expected ${q}`,i(r)),m=!1;break}h=a.index+a[0].length;let o=a[1],c=a[2]!==void 0,g=a[3]!==void 0,_=c?n(a[2]):g?a[3]:a[4];(o===`title`?u!==void 0:o===`slice`?d!==void 0:o===`icon`?f!==void 0:p!==void 0)?t.error(e.InvalidToolbarButton,`Toolbar button '${s}' states '${o}' more than once`,i(r)):o===`title`?c||g?u=_:(t.error(e.InvalidToolbarButton,`Invalid title '${_}' on toolbar button '${s}' - expected a quoted string or a $strings.<key> token`,i(r)),m=!1):o===`slice`?!c&&!g&&V.test(_)?d=_:(t.error(e.InvalidToolbarButton,`Invalid slice '${_}' on toolbar button '${s}' - expected <Module>.<Feature>.<Slice>`,i(r)),m=!1):o===`emphasis`?!c&&!g&&[`primary`,`secondary`,`quiet`].includes(_)?p=_===`primary`?`Primary`:_===`secondary`?`Secondary`:`Quiet`:(t.error(e.InvalidToolbarButton,`Invalid emphasis '${_}' on toolbar button '${s}' - expected primary, secondary or quiet`,i(r)),m=!1):f=_}u===void 0&&m&&t.error(e.InvalidToolbarButton,`Toolbar button '${s}' has no title - expected 'button ${s} title "<text>"'`,i(r));let g=null,_;for(let n=t.peekChild(r.indent);n!==void 0;n=t.peekChild(r.indent)){if(t.reader.takeSignificant(),o(n.content)===`authorize`&&g===null){g=c(t,n);continue}let r=_===void 0?L.exec(n.content):null;r===null?(t.error(e.InvalidToolbarButton,`Unexpected '${n.content}' under toolbar button '${s}' - a button takes one 'authorize' line, one 'confirm' line and nothing else`,i(n)),t.skipBlock(n.indent)):_=operandText(r,1)}return{kind:`ToolbarButtonSyntax`,id:s,title:u??``,...d===void 0?{}:{slice:d},...p===void 0?{}:{emphasis:p},...f===void 0?{}:{icon:f},...g===null?{}:{authorize:g},..._===void 0?{}:{confirm:_},location:i(r)}}function parseToolbarItem(t,n){let r=h(t,n,/^item\s+\S+\s+action\s/u.test(n.content),e=>R.test(e)),a=R.exec(r.header);if(a===null){t.error(e.UnknownScreenDirective,`Invalid toolbar item '${n.content}' - expected 'item <name> action <Command>', 'item <name> navigate to <Screen>', 'item <name> dialog <DialogTemplate>' or 'button <id> title "<text>" slice <Slice>'`,i(n)),t.skipBlock(n.indent);return}let s=r.label??null,c=null,l,u=[],d=[];for(let e=t.peekChild(n.indent);e!==void 0;e=t.peekChild(n.indent)){t.reader.takeSignificant();let n=w.exec(e.content);if(n!==null){s=operandText(n,1);continue}let r=L.exec(e.content);if(r!==null){l=operandText(r,1);continue}let a=A.exec(e.content);a===null?o(e.content)===`icon`?c=e.content.substring(4).trim():parsePresentationValue(t,e,d):u.push({kind:`ScreenNavigationParameterSyntax`,name:a[1],binding:y(t,a[2],i(e)),location:i(e)})}let f=a[2]===`navigate`?`Navigate`:a[2]===`dialog`?`Dialog`:`Action`;return{kind:`ToolbarItemSyntax`,name:a[1],syntaxKind:f,target:a[3],label:s,icon:c,...r.subject===void 0?{}:{subject:r.subject},...l===void 0?{}:{confirm:l},parameters:u,presentation:d,location:i(n)}}function parseUiBindingValue(e,t,n){return y(e,t,i(n))}function parseCode(t,n){let r=n.content.startsWith("```")?n.content.substring(3):n.content;if(!t.languages.has(r)){t.error(e.ExpectedCodeFence,`Expected a registered language on the opening fence, not '${n.content}'`,i(n));return}n.content.startsWith("```")||t.warning(e.LegacyInlineCodeFence,`'${r}' on its own line is deprecated - use '\`\`\`${r}' instead`,i(n));let a=l(t,r,n);return a===null?void 0:{kind:`ScreenCodeSyntax`,code:{kind:`CodeBlockSyntax`,language:r,code:a,location:i(n)},location:i(n)}}export{parseScreen,parseToolbar};
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{stringBodyPattern as t,unescapeString as n}from"../Text/StringLiteral.js";import{pattern as r}from"../Text/patterns.js";import{locationOf as i}from"./SourceLine.js";import{parseAuthorize as a}from"./AuthorizeParser.js";import{parseMappingSource as o}from"./ExpressionParser.js";import{firstWord as s}from"./LineText.js";import{parseTypeRef as c}from"./PropertyLineParser.js";import{parseFencedText as l}from"./CodeBlockParser.js";import{parseDescription as u}from"./DescriptionParser.js";import{parseGuardedAction as d}from"./GuardedActionParser.js";import{collectInputUses as f}from"./InputUses.js";import{isFileDirective as p}from"./FileReferences.js";import{parsePlainActionInput as m,parseSubjectClause as h}from"./ActionSubjectClause.js";import{isValidTemplateVersionRange as g,parseBlueprintReference as _,startsBlueprintReference as v}from"./TemplateReferenceText.js";import{parseFromClause as y}from"./UiBindingParser.js";const b=`(?:"(${t})"|(\\$strings\\.\\w+(?:\\.\\w+)*))`,x=r(`^screen\\s+([A-Za-z_]\\w*)$`),S=r(`^data\\s+([\\w.]+(?:\\[\\])?)\\s+via\\s+query\\s+(\\w+(?:\\.\\w+)*)(?:\\s+by\\s+(\\w+))?$`),C=r(`^action\\s+([A-Za-z_]\\w*(?:\\.\\w+)*)$`),w=r(`^label\\s+${b}$`),T=r(`^action\\s+${b}$`),E=r(`^navigate\\s+to\\s+(\\w+(?:\\.\\w+)*)(?:\\s+by\\s+(\\w+))?$`),D=r(`^route\\s+${b}$`),O=r(`^outlet\\s+([A-Za-z_]\\w*)$`),k=r(`^contribute\\s+to\\s+([A-Za-z_]\\w*)(?:\\s+order\\s+(-?\\d+))?$`),A=r(`^parameter\\s+([A-Za-z_]\\w*)\\s+from\\s+(.+)$`),j=r(`^component\\s+([A-Za-z_]\\w*(?:\\.[A-Za-z_]\\w*)*)\\s+([A-Za-z_]\\w*)$`),M=r(`^id\\s+(?:"(${t})"|(\\S+))$`),N=r(`^property\\s+([\\w.]+)\\s+from\\s+(.+)$`),P=r(`^property\\s+([\\w.]+)\\s*=\\s+(.+)$`),F=r(`^exposes\\s+([A-Za-z_]\\w*)\\s+from\\s+(.+)$`),I=r(`^presentation\\s+([A-Za-z_]\\w*)\\s+${b}$`),L=r(`^confirm\\s+${b}$`),R=r(`^item\\s+([A-Za-z_]\\w*)\\s+(action|navigate|dialog)(?:\\s+to)?\\s+([A-Za-z_]\\w*(?:\\.\\w+)*)$`),z=r(`^button\\s+(?:"(${t})"|([A-Za-z_][\\w-]*))(?:\\s+(.*))?$`),B=new RegExp(r(`\\s*(title|slice|emphasis|icon)\\s+(?:"(${t})"|(\\$strings\\.\\w+(?:\\.\\w+)*)|([A-Za-z_][\\w.-]*))(?=\\s|$)`).source,`uy`),V=r(`^[A-Za-z_]\\w*(?:\\.[A-Za-z_]\\w*)*$`),H=r(`^[a-z_]\\w*$`),U=r(`^title\\s+${b}$`),W=r(`^column\\s+([\\w.]+)(?:\\s+label\\s+${b})?$`),G=r(`^on\\s+row-click\\s+(navigate\\s+to\\s+.+)$`),K=r(`^field\\s+([\\w.]+)\\s+label\\s+${b}$`),operandText=(e,t)=>e[t]===void 0?e[t+1]:n(e[t]),isInteraction=e=>[`on`,`uses`].includes(s(e.content)),isCodeLine=(e,t)=>t.content.startsWith("```")||e.languages.has(t.content);function parseScreen(t,n){let r=x.exec(n.content);r===null&&t.error(e.InvalidScreenDeclaration,`Invalid screen declaration '${n.content}' - expected 'screen <Name>'`,i(n));let a=[],o=[],c=null;for(let e=t.peekChild(n.indent);e!==void 0;e=t.peekChild(n.indent))if(t.reader.takeSignificant(),s(e.content)===`contribute`){let n=parseScreenContribution(t,e);n!==void 0&&o.push(n)}else s(e.content)===`description`?c=u(t,e,c,`Screen '${r?.[1]??``}'`):p(e)||pushDirective(t,e,a);return{kind:`ScreenSyntax`,name:r?.[1]??``,directives:a,description:c,...o.length>0?{contributions:o}:{},location:i(n)}}function parseScreenContribution(t,n){let r=k.exec(n.content);if(r===null)t.error(e.UnknownScreenDirective,`Invalid screen contribution '${n.content}' - expected 'contribute to <Point> [order <n>]'`,i(n)),t.skipBlock(n.indent);else return{kind:`ScreenContributionSyntax`,contributionPoint:r[1],order:r[2]===void 0?null:Number(r[2]),directives:parseDirectives(t,n),location:i(n)}}function pushDirective(e,t,n){let r=parseDirective(e,t);r!==void 0&&n.push(r)}function parseDirectives(e,t){let n=[];for(let r=e.peekChild(t.indent);r!==void 0;r=e.peekChild(t.indent))e.reader.takeSignificant(),pushDirective(e,r,n);return n}function parseDirective(t,n){switch(validateNonActionSubjectClause(t,n),s(n.content)){case`data`:return parseData(t,n);case`action`:return parseAction(t,n);case`template`:return parseTemplateReference(t,n);case`section`:return parseSection(t,n);case`title`:return parseTitle(t,n);case`table`:return parseTable(t,n);case`summary`:return parseSummary(t,n);case`component`:return parseComponent(t,n);case`toolbar`:return parseToolbar(t,n);case`navigate`:return parseNavigate(t,n.content,n);case`on`:return f(t,n),{kind:`ScreenBehaviorSyntax`,location:i(n)};case`uses`:return f(t,n),{kind:`ScreenUsesBehaviorSyntax`,location:i(n)};default:if(isCodeLine(t,n))return parseCode(t,n);t.error(e.UnknownScreenDirective,`Unexpected '${n.content}' in screen body`,i(n)),t.skipBlock(n.indent);return}}function parseData(t,n){let r=S.exec(n.content);if(r===null)t.error(e.InvalidDataDirective,`Invalid data directive '${n.content}' - expected 'data <ReadModel> via query <Query> [by <param>]'`,i(n));else return{kind:`ScreenDataSyntax`,type:c(r[1],i(n)),query:r[2],by:r[3]??null,location:i(n)}}function validateNonActionSubjectClause(e,t){let n=(/* @__PURE__ */ new Map([[`data`,S],[`navigate`,E],[`component`,j],[`title`,U]])).get(s(t.content));n!==void 0&&h(e,t,!1,e=>n.test(e))}function parseAction(e,t){let n=h(e,t,!0,e=>C.test(e)||T.test(e)),r=parseActionHeader(e,t,n);return r===void 0||n.subject===void 0?r:{...r,subject:n.subject}}function parseActionHeader(t,n,r){let a=T.exec(r.header);if(a!==null)return d(t,n,operandText(a,1),parseNavigate);let o=C.exec(r.header);if(o===null){t.error(e.InvalidActionDirective,`Invalid action directive '${n.content}' - expected 'action <Command>'`,i(n)),t.skipBlock(n.indent);return}let c=r.label??null,l=null,u=[];for(let r=t.peekChild(n.indent);r!==void 0;r=t.peekChild(n.indent)){t.reader.takeSignificant();let n=w.exec(r.content);n===null?s(r.content)===`navigate`?l=parseNavigate(t,r.content,r)??null:s(r.content)===`with`?addPlainActionInput(t,r,u):t.error(e.UnknownActionDirective,`Unexpected '${r.content}' in action - expected 'label "..."' or 'navigate to ...'`,i(r)):c=operandText(n,1)}return{kind:`ScreenActionSyntax`,command:o[1],label:c,navigate:l,...u.length===0?{}:{inputs:u},location:i(n)}}function addPlainActionInput(e,t,n){let r=m(e,t,n);r!==void 0&&n.push(r)}function parseNavigate(t,n,r){let a=E.exec(n);if(a===null){t.error(e.InvalidNavigation,`Invalid navigation '${n}' - expected 'navigate to <Screen> [by <param>]'`,i(r));return}let o=[],s=null,c=null;for(let n=t.peekChild(r.indent);n!==void 0;n=t.peekChild(r.indent)){t.reader.takeSignificant();let r=A.exec(n.content);if(r!==null){o.push({kind:`ScreenNavigationParameterSyntax`,name:r[1],binding:y(t,r[2],i(n)),location:i(n)});continue}let a=D.exec(n.content);if(a!==null){s=operandText(a,1);continue}let l=O.exec(n.content);l===null?t.error(e.InvalidNavigation,`Unexpected '${n.content}' in navigation - expected 'route "..."', 'outlet <name>' or 'parameter <name> from <binding>'`,i(n)):c=l[1]}return{kind:`ScreenNavigateSyntax`,screen:a[1],by:a[2]??null,route:s,...c===null?{}:{outlet:c},parameters:o,location:i(r)}}function parseTemplateReference(t,n){let r=n.content.substring(8).trim(),a=null,o=null;if(v(r)){let s=_(r);s===void 0?t.error(e.UnknownLayoutDirective,`Invalid template reference '${n.content}' - expected 'template <Name>' or 'template blueprint <Blueprint> <Name> [version "<range>"]'`,i(n)):({blueprint:a,name:r,version:o}=s,o!==null&&!g(o)&&t.error(e.InvalidTemplateVersionRange,`The template version range '${o}' is not one Scene understands - use '*', an exact version or a ^, ~, >=, >, <= or < range such as "^1.2"`,i(n)))}let s=[];for(let a=t.peekChild(n.indent);a!==void 0;a=t.peekChild(n.indent))t.reader.takeSignificant(),H.test(a.content)?s.push({kind:`ScreenSlotSyntax`,name:a.content,directives:parseDirectives(t,a),location:i(a)}):(t.error(e.InvalidScreenLayoutSlot,`Expected a slot name in template '${r}', got '${a.content}'`,i(a)),t.skipBlock(a.indent));return{kind:`ScreenTemplateReferenceSyntax`,name:r,slots:s,...a===null?{}:{blueprint:a},...o===null?{}:{version:o},location:i(n)}}function parseSection(e,t){return{kind:`ScreenSectionSyntax`,name:t.content.substring(7).trim(),directives:parseDirectives(e,t),location:i(t)}}function parseTitle(t,n){let r=U.exec(n.content);return r===null?(t.error(e.InvalidTitleDirective,`Invalid title directive '${n.content}' - expected 'title "..."'`,i(n)),{kind:`ScreenTitleSyntax`,text:``,location:i(n)}):{kind:`ScreenTitleSyntax`,text:operandText(r,1),location:i(n)}}function parseTable(t,n){let r=n.content.substring(5).trim(),a=[],o=null;for(let r=t.peekChild(n.indent);r!==void 0;r=t.peekChild(n.indent)){t.reader.takeSignificant();let n=W.exec(r.content),c=G.exec(r.content);if(n!==null){let e=n[2]!==void 0||n[3]!==void 0;a.push({kind:`ScreenColumnSyntax`,property:n[1],label:e?operandText(n,2):null,location:i(r)})}else c===null?s(r.content)===`on`||isInteraction(r)?f(t,r):t.error(e.UnknownTableDirective,`Unexpected '${r.content}' in table - expected 'column ...', 'on row-click navigate to ...', 'on <trigger>' or 'uses <Behavior>'`,i(r)):o=parseNavigate(t,c[1],r)??null}return{kind:`ScreenTableSyntax`,target:r,columns:a,rowClick:o,location:i(n)}}function parseSummary(t,n){let r=n.content.substring(7).trim(),a=[];for(let r=t.peekChild(n.indent);r!==void 0;r=t.peekChild(n.indent)){t.reader.takeSignificant();let n=K.exec(r.content);n===null?t.error(e.UnknownSummaryDirective,`Unexpected '${r.content}' in summary - expected 'field <property> label "..."'`,i(r)):a.push({kind:`ScreenFieldSyntax`,property:n[1],label:operandText(n,2),location:i(r)})}return{kind:`ScreenSummarySyntax`,target:r,fields:a,location:i(n)}}function parseComponent(t,n){let r=j.exec(n.content);if(r===null){t.error(e.UnknownScreenDirective,`Invalid component directive '${n.content}' - expected 'component <Package.Component> <name>'`,i(n)),t.skipBlock(n.indent);return}let a=null,o=null,c=null,l=[],u=[],d=[],p=[];for(let r=t.peekChild(n.indent);r!==void 0;r=t.peekChild(n.indent))switch(t.reader.takeSignificant(),s(r.content)){case`context`:a=parseUiContext(t,r);break;case`id`:o=parseStableId(t,r);break;case`property`:parseComponentProperty(t,r,l);break;case`icon`:c=r.content.substring(4).trim();break;case`presentation`:parsePresentationValue(t,r,d);break;case`exposes`:parseExposedValue(t,r,u);break;case`outlet`:p.push({kind:`ComponentOutletSyntax`,name:r.content.substring(6).trim(),directives:parseDirectives(t,r),location:i(r)});break;case`on`:f(t,r);break;case`uses`:f(t,r);break;default:t.error(e.UnknownScreenDirective,`Unexpected '${r.content}' in component - expected context, id, property, icon, presentation, exposes, outlet, on or uses`,i(r)),t.skipBlock(r.indent)}return{kind:`ScreenComponentSyntax`,component:r[1],name:r[2],stableId:o,context:a,properties:l,exposes:u,presentation:d,icon:c,outlets:p,location:i(n)}}function parseUiContext(e,t){return parseUiBindingValue(e,t.content.substring(7).trim(),t)}function parseComponentProperty(t,n,r){let a=N.exec(n.content);if(a!==null){r.push({kind:`ComponentPropertySyntax`,property:a[1],binding:y(t,a[2],i(n)),value:null,location:i(n)});return}let s=P.exec(n.content);s===null?t.error(e.UnknownScreenDirective,`Invalid component property '${n.content}' - expected 'property <path> from <binding>' or 'property <path> = <literal|object|array|null>'`,i(n)):r.push({kind:`ComponentPropertySyntax`,property:s[1],binding:null,value:o(s[2],i(n),t),location:i(n)})}function parseStableId(t,n){let r=M.exec(n.content);return r===null?(t.error(e.UnknownScreenDirective,`Invalid component id '${n.content}' - expected 'id "stable-id"'`,i(n)),null):operandText(r,1)}function parseExposedValue(t,n,r){let a=F.exec(n.content);a===null?t.error(e.UnknownScreenDirective,`Invalid exposed value '${n.content}' - expected 'exposes <name> from <binding>'`,i(n)):r.push({kind:`ComponentExposedValueSyntax`,name:a[1],binding:y(t,a[2],i(n)),location:i(n)})}function parsePresentationValue(t,n,r){let a=I.exec(n.content);a===null?t.error(e.UnknownScreenDirective,`Invalid presentation value '${n.content}' - expected 'presentation <key> "value"'`,i(n)):r.push({kind:`PresentationValueSyntax`,name:a[1],value:operandText(a,2),location:i(n)})}function parseToolbar(e,t){let n=t.content.substring(7).trim(),r=[],a=[];for(let n=e.peekChild(t.indent);n!==void 0;n=e.peekChild(t.indent)){if(e.reader.takeSignificant(),s(n.content)===`button`){let t=parseToolbarButton(e,n);t!==void 0&&a.push(t);continue}let t=parseToolbarItem(e,n);t!==void 0&&r.push(t)}return{kind:`ScreenToolbarSyntax`,name:n,items:r,...a.length>0?{buttons:a}:{},location:i(t)}}const q=`button <id> title "<text>" [slice <Module>.<Feature>.<Slice>] [emphasis primary|secondary|quiet] [icon <name>]`;function parseToolbarButton(t,r){let o=z.exec(r.content);if(o===null){t.error(e.InvalidToolbarButton,`Invalid toolbar button '${r.content}' - expected ${q}`,i(r)),t.skipBlock(r.indent);return}let c=o[1]===void 0?o[2]:n(o[1]),l=o[3]??``,u,d,f,p,m=!0,h=0;for(;h<l.length;){B.lastIndex=h;let a=B.exec(l);if(a===null){t.error(e.InvalidToolbarButton,`Invalid toolbar button '${r.content}' - unexpected '${l.substring(h).trim()}'; expected ${q}`,i(r)),m=!1;break}h=a.index+a[0].length;let o=a[1],s=a[2]!==void 0,g=a[3]!==void 0,_=s?n(a[2]):g?a[3]:a[4];(o===`title`?u!==void 0:o===`slice`?d!==void 0:o===`icon`?f!==void 0:p!==void 0)?t.error(e.InvalidToolbarButton,`Toolbar button '${c}' states '${o}' more than once`,i(r)):o===`title`?s||g?u=_:(t.error(e.InvalidToolbarButton,`Invalid title '${_}' on toolbar button '${c}' - expected a quoted string or a $strings.<key> token`,i(r)),m=!1):o===`slice`?!s&&!g&&V.test(_)?d=_:(t.error(e.InvalidToolbarButton,`Invalid slice '${_}' on toolbar button '${c}' - expected <Module>.<Feature>.<Slice>`,i(r)),m=!1):o===`emphasis`?!s&&!g&&[`primary`,`secondary`,`quiet`].includes(_)?p=_===`primary`?`Primary`:_===`secondary`?`Secondary`:`Quiet`:(t.error(e.InvalidToolbarButton,`Invalid emphasis '${_}' on toolbar button '${c}' - expected primary, secondary or quiet`,i(r)),m=!1):f=_}u===void 0&&m&&t.error(e.InvalidToolbarButton,`Toolbar button '${c}' has no title - expected 'button ${c} title "<text>"'`,i(r));let g=null,_;for(let n=t.peekChild(r.indent);n!==void 0;n=t.peekChild(r.indent)){if(t.reader.takeSignificant(),s(n.content)===`authorize`&&g===null){g=a(t,n);continue}let r=_===void 0?L.exec(n.content):null;r===null?(t.error(e.InvalidToolbarButton,`Unexpected '${n.content}' under toolbar button '${c}' - a button takes one 'authorize' line, one 'confirm' line and nothing else`,i(n)),t.skipBlock(n.indent)):_=operandText(r,1)}return{kind:`ToolbarButtonSyntax`,id:c,title:u??``,...d===void 0?{}:{slice:d},...p===void 0?{}:{emphasis:p},...f===void 0?{}:{icon:f},...g===null?{}:{authorize:g},..._===void 0?{}:{confirm:_},location:i(r)}}function parseToolbarItem(t,n){let r=h(t,n,/^item\s+\S+\s+action\s/u.test(n.content),e=>R.test(e)),a=R.exec(r.header);if(a===null){t.error(e.UnknownScreenDirective,`Invalid toolbar item '${n.content}' - expected 'item <name> action <Command>', 'item <name> navigate to <Screen>', 'item <name> dialog <DialogTemplate>' or 'button <id> title "<text>" slice <Slice>'`,i(n)),t.skipBlock(n.indent);return}let o=r.label??null,c=null,l,u=[],d=[];for(let e=t.peekChild(n.indent);e!==void 0;e=t.peekChild(n.indent)){t.reader.takeSignificant();let n=w.exec(e.content);if(n!==null){o=operandText(n,1);continue}let r=L.exec(e.content);if(r!==null){l=operandText(r,1);continue}let a=A.exec(e.content);a===null?s(e.content)===`icon`?c=e.content.substring(4).trim():parsePresentationValue(t,e,d):u.push({kind:`ScreenNavigationParameterSyntax`,name:a[1],binding:y(t,a[2],i(e)),location:i(e)})}let f=a[2]===`navigate`?`Navigate`:a[2]===`dialog`?`Dialog`:`Action`;return{kind:`ToolbarItemSyntax`,name:a[1],syntaxKind:f,target:a[3],label:o,icon:c,...r.subject===void 0?{}:{subject:r.subject},...l===void 0?{}:{confirm:l},parameters:u,presentation:d,location:i(n)}}function parseUiBindingValue(e,t,n){return y(e,t,i(n))}function parseCode(t,n){let r=n.content.startsWith("```")?n.content.substring(3):n.content;if(!t.languages.has(r)){t.error(e.ExpectedCodeFence,`Expected a registered language on the opening fence, not '${n.content}'`,i(n));return}n.content.startsWith("```")||t.warning(e.LegacyInlineCodeFence,`'${r}' on its own line is deprecated - use '\`\`\`${r}' instead`,i(n));let a=l(t,r,n);return a===null?void 0:{kind:`ScreenCodeSyntax`,code:{kind:`CodeBlockSyntax`,language:r,code:a,location:i(n)},location:i(n)}}export{parseScreen,parseToolbar};
|
|
2
2
|
//# sourceMappingURL=ScreenParser.js.map
|