@cratis/screenplay-language 4.128.0 → 4.130.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/AuthoredReadModelKeys.d.ts +13 -0
- package/dist/AuthoredReadModelKeys.d.ts.map +1 -0
- package/dist/EventSourceAnalysis.d.ts +11 -0
- package/dist/EventSourceAnalysis.d.ts.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/Parsing/CommandParser.js +1 -1
- package/dist/bundles/compiler/Parsing/CommandParser.js.map +1 -1
- package/dist/bundles/compiler/Parsing/DeclarationParsers.js +1 -1
- package/dist/bundles/compiler/Parsing/DeclarationParsers.js.map +1 -1
- package/dist/bundles/compiler/Parsing/DependencySourceParser.js +1 -1
- package/dist/bundles/compiler/Parsing/DependencySourceParser.js.map +1 -1
- package/dist/bundles/compiler/Parsing/EventSourceValidator.js +1 -1
- package/dist/bundles/compiler/Parsing/EventSourceValidator.js.map +1 -1
- package/dist/bundles/compiler/Parsing/IdentifierComplianceValidator.js +1 -1
- package/dist/bundles/compiler/Parsing/IdentifierComplianceValidator.js.map +1 -1
- package/dist/bundles/compiler/Parsing/ObserverFilterParser.js +2 -0
- package/dist/bundles/compiler/Parsing/ObserverFilterParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ObserverFilterValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/ObserverFilterValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ProducesParser.js +1 -1
- package/dist/bundles/compiler/Parsing/ProducesParser.js.map +1 -1
- package/dist/bundles/compiler/Parsing/PropertyLineParser.js +1 -1
- package/dist/bundles/compiler/Parsing/PropertyLineParser.js.map +1 -1
- package/dist/bundles/compiler/Parsing/QueryParser.js +1 -1
- package/dist/bundles/compiler/Parsing/QueryParser.js.map +1 -1
- package/dist/bundles/compiler/Parsing/ReactionParser.js +1 -1
- package/dist/bundles/compiler/Parsing/ReactionParser.js.map +1 -1
- package/dist/bundles/compiler/Parsing/ReadModelKeyValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/ReadModelKeyValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ReadsParser.js +2 -0
- package/dist/bundles/compiler/Parsing/ReadsParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/SpecificationStreamValidator.js +1 -1
- package/dist/bundles/compiler/Parsing/SpecificationStreamValidator.js.map +1 -1
- package/dist/bundles/compiler/Parsing/TriggerDataParser.js +1 -1
- package/dist/bundles/compiler/Parsing/TriggerDataParser.js.map +1 -1
- package/dist/bundles/compiler/ScreenplayCompiler.js +1 -1
- package/dist/bundles/compiler/ScreenplayCompiler.js.map +1 -1
- package/dist/bundles/compiler/Syntax/EventSourceCatalog.js +1 -1
- package/dist/bundles/compiler/Syntax/EventSourceCatalog.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/SyntaxInvariants.js +1 -1
- package/dist/bundles/compiler/Syntax/SyntaxInvariants.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/Syntax/index.js +1 -1
- package/dist/bundles/compiler/index.js +1 -1
- package/dist/bundles/completion-items.js +2 -2
- package/dist/bundles/completion-items.js.map +1 -1
- package/dist/bundles/completion-planner.js +2 -2
- package/dist/bundles/completion-planner.js.map +1 -1
- package/dist/bundles/diagnostic-codes.js +1 -1
- package/dist/bundles/diagnostic-codes.js.map +1 -1
- package/dist/bundles/event-source-authoring.js +10 -10
- package/dist/bundles/event-source-authoring.js.map +1 -1
- package/dist/bundles/keyword-docs.js +1 -1
- package/dist/bundles/keyword-docs.js.map +1 -1
- package/dist/bundles/read-model-key-completions.js +2 -0
- package/dist/bundles/read-model-key-completions.js.map +1 -0
- package/dist/bundles/response-analysis.js +6 -6
- package/dist/bundles/response-analysis.js.map +1 -1
- package/dist/bundles/scope-items.js +1 -1
- package/dist/bundles/scope-items.js.map +1 -1
- package/dist/bundles/tokens.js +1 -1
- package/dist/bundles/tokens.js.map +1 -1
- package/dist/bundles/validation.js +1 -1
- package/dist/bundles/validation.js.map +1 -1
- package/dist/completion-items.d.ts.map +1 -1
- package/dist/completion-planner.d.ts.map +1 -1
- package/dist/diagnostic-codes.d.ts +7 -0
- package/dist/diagnostic-codes.d.ts.map +1 -1
- package/dist/event-source-authoring.d.ts.map +1 -1
- package/dist/keyword-docs.d.ts.map +1 -1
- package/dist/read-model-key-completions.d.ts +4 -0
- package/dist/read-model-key-completions.d.ts.map +1 -0
- package/dist/response-analysis.d.ts +2 -0
- package/dist/response-analysis.d.ts.map +1 -1
- package/dist/scope-items.d.ts.map +1 -1
- package/dist/tokens.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PropertyLineParser.js","names":["propertyPattern","pattern","invalidGeneratedModifiers","reversedModifiers","match","line","location","locationOf","unescapeIdentifier","legacy","text","canonical","isOptional","isCollection","property","context","length","type","offset","name","
|
|
1
|
+
{"version":3,"file":"PropertyLineParser.js","names":["propertyPattern","pattern","invalidGeneratedModifiers","reversedModifiers","match","line","location","locationOf","unescapeIdentifier","legacy","text","canonical","isOptional","isCollection","property","context","DiagnosticCodes","length","type","offset","name","keyModifiers","subjectModifiers","modifiers","modifier"],"sources":["../../../../../../Compiler/Parsing/PropertyLineParser.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 { SourceLocation } from '../Diagnostics/SourceLocation';\nimport { PropertySyntax, TypeRefSyntax } from '../Syntax/Declarations';\nimport { pattern } from '../Text/patterns';\nimport { ParserContext } from './ParserContext';\nimport { unescapeIdentifier } from './LineText';\nimport { locationOf, SourceLine } from './SourceLine';\n\nconst propertyPattern = pattern('^(@?[a-z_]\\\\w*)\\\\s+([\\\\w.]+(?:\\\\[\\\\])?(?:\\\\?|\\\\s+optional)?)(?:\\\\s+(generated))?(?:\\\\s+(identifier))?(?:\\\\s+(subject))?(?:\\\\s+(key))?$');\nconst invalidGeneratedModifiers = pattern('^@?[a-z_]\\\\w*\\\\s+[\\\\w.]+(?:\\\\[\\\\])?\\\\??\\\\s+((?:optional|generated|identifier|subject|key)(?:\\\\s+(?:optional|generated|identifier|subject|key))*)$');\nconst reversedModifiers = pattern('^@?[a-z_]\\\\w*\\\\s+[\\\\w.]+(?:\\\\[\\\\])?\\\\s+identifier\\\\s+optional(?:\\\\s*=.*)?$');\n\n// A '<name> <Type>[[]][?] [identifier]' line, or undefined when the line does not have that shape.\nexport function tryParseProperty(line: SourceLine): PropertySyntax | undefined {\n const match = propertyPattern.exec(line.content);\n if (match === null) {\n return undefined;\n }\n const location = locationOf(line);\n return {\n kind: 'PropertySyntax',\n name: unescapeIdentifier(match[1]),\n type: parseTypeRef(match[2], { ...location, column: location.column + line.content.indexOf(match[2], match[1].length) }),\n isGenerated: match[3] !== undefined,\n nameWasEscaped: match[1].startsWith('@'),\n isIdentifier: match[4] !== undefined,\n ...(match[5] !== undefined ? { isSubject: true } : {}),\n ...(match[6] !== undefined ? { isKey: true } : {}),\n location,\n };\n}\n\nexport function parseTypeRef(text: string, location: SourceLocation): TypeRefSyntax {\n const legacy = text.endsWith('?');\n const canonical = /\\soptional$/.test(text);\n const isOptional = legacy || canonical;\n if (isOptional) {\n text = text.substring(0, text.length - (legacy ? 1 : 'optional'.length)).trimEnd();\n }\n const isCollection = text.endsWith('[]');\n if (isCollection) {\n text = text.substring(0, text.length - 2);\n }\n return { kind: 'TypeRefSyntax', name: text, isCollection, isOptional, location };\n}\n\n// Unlike tryParseProperty, this is only called once the owner commits to a property position.\nexport function parseProperty(context: ParserContext, line: SourceLine): PropertySyntax | undefined {\n const property = tryParseProperty(line);\n if (property !== undefined) {\n reportLegacyOptionalSuffix(context, property.type, line);\n if (property.isKey && (property.type.isOptional || property.type.isCollection || property.isGenerated || property.isIdentifier || property.isSubject)) {\n context.error(DiagnosticCodes.InvalidReadModelKey, 'A read-model key part must be required, not a collection, and cannot combine key with generated, identifier or subject.', locationOf(line));\n }\n } else {\n reportInvalidModifierOrder(context, line);\n }\n return property;\n}\n\nexport function reportLegacyOptionalSuffix(context: ParserContext, type: TypeRefSyntax, line: SourceLine): void {\n context.claimField(line);\n const length = type.name.length + (type.isCollection ? 2 : 0);\n const offset = type.location.column - line.indent - 1 + length;\n if (type.isOptional && line.content[offset] === '?') {\n const name = type.name + (type.isCollection ? '[]' : '');\n context.information(DiagnosticCodes.LegacyOptionalSuffix, `Write '${name} optional' instead of '${name}?'.`, type.location);\n }\n}\n\nexport function reportInvalidModifierOrder(context: ParserContext, line: SourceLine): boolean {\n const keyModifiers = invalidGeneratedModifiers.exec(line.content);\n if (keyModifiers !== null && keyModifiers[1].split(/\\s+/).includes('key')) {\n context.error(DiagnosticCodes.InvalidReadModelKey, \"Write 'key' once, without other modifiers: '<name> <Type> key'.\", locationOf(line));\n return true;\n }\n const subjectModifiers = invalidGeneratedModifiers.exec(line.content);\n if (subjectModifiers !== null && subjectModifiers[1].split(/\\s+/).includes('subject')) {\n context.error(DiagnosticCodes.InvalidSubjectModifierOrder, \"Write each modifier once in order: '<name> <Type> optional generated identifier subject'.\", locationOf(line));\n return true;\n }\n if (reversedModifiers.test(line.content)) {\n context.error(DiagnosticCodes.InvalidOptionalModifierOrder, \"Write 'optional' before 'identifier': '<name> <Type> optional identifier'.\", locationOf(line));\n return true;\n } else {\n const modifiers = invalidGeneratedModifiers.exec(line.content);\n if (modifiers !== null && modifiers[1].split(/\\s+/).some(modifier => modifier === 'generated' || modifier === 'identifier')) {\n context.error(DiagnosticCodes.InvalidGeneratedModifierOrder, \"Write each modifier once in order: '<name> <Type> optional generated identifier'.\", locationOf(line));\n return true;\n }\n }\n return false;\n}\n"],"mappings":"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"}
|
|
@@ -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{firstWord as i}from"./LineText.js";import{parseTypeRef as a,reportLegacyOptionalSuffix as o}from"./PropertyLineParser.js";import{combineAuthorize as s,parseAuthorize as c}from"./AuthorizeParser.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,r){let d=u.exec(r.content);if(d===null)return t.error(e.InvalidQueryDeclaration,`Invalid query declaration '${r.content}' - expected 'query <Name> => [observable] <ReadModel>'`,n(r)),t.skipBlock(r.indent),{kind:`QuerySyntax`,name:i(r.content),returnType:a(``,n(r)),by:null,filters:[],description:null,isObservable:!1,scope:null,authorize:null,location:n(r)};let f=d[1],m=a(d[3],{...n(r),column:r.indent+1+d[0].length-d[3].length});(d[2]!==void 0||m.name!==`observable`||!m.isOptional||m.isCollection)&&o(t,m,r);let h=null,g=[],_=null,
|
|
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{firstWord as i}from"./LineText.js";import{parseTypeRef as a,reportLegacyOptionalSuffix as o}from"./PropertyLineParser.js";import{combineAuthorize as s,parseAuthorize as c}from"./AuthorizeParser.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,r){let d=u.exec(r.content);if(d===null)return t.error(e.InvalidQueryDeclaration,`Invalid query declaration '${r.content}' - expected 'query <Name> => [observable] <ReadModel>'`,n(r)),t.skipBlock(r.indent),{kind:`QuerySyntax`,name:i(r.content),returnType:a(``,n(r)),by:null,filters:[],description:null,isObservable:!1,scope:null,authorize:null,location:n(r)};let f=d[1],m=a(d[3],{...n(r),column:r.indent+1+d[0].length-d[3].length});(d[2]!==void 0||m.name!==`observable`||!m.isOptional||m.isCollection)&&o(t,m,r);let h=null,g=[],_=!1,v=[],y=null,b=null,x=null;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===`description`)y=l(t,a,y,`Query '${f}'`);else if(r===`by`){if(a.content===`by`){_&&t.error(e.InvalidReadModelKeyLookup,`A query cannot combine a by block with another by declaration.`,n(a)),h=null,g.length=0;for(let e=t.peekChild(a.indent);e!==void 0;e=t.peekChild(a.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(a)),_=!0}else{let r=parseParameter(t,a,`by`);r!==void 0&&(_&&t.error(e.InvalidQueryParameter,`Query '${f}' already declares 'by' - a query can have at most one key parameter`,n(a)),g.length>0&&t.error(e.InvalidReadModelKeyLookup,`A query cannot combine a by block with a single by line.`,n(a)),g.length=0,h=r,_=!0)}}else if(r===`filter`){let e=parseParameter(t,a,`filter`);e!==void 0&&v.push(e)}else r===`authorize`?x=s(x,c(t,a)):r===`scoped`?b=parseScope(t,a,b,f)??b:p.has(r)?t.skipOpaqueBlock(a.indent):(t.error(e.UnknownQueryDirective,`Unexpected '${a.content}' in query body - expected description, by, filter, authorize, scoped or performer`,n(a)),t.skipBlock(a.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(r)}}function parseParameter(t,i,s){let c=d.exec(i.content.substring(s.length).trim());if(c===null){t.error(e.InvalidQueryParameter,`Invalid '${s}' parameter '${i.content}' - expected '${s} <name> <Type> [from <source>]'`,n(i));return}let l=i.content.indexOf(c[1],s.length),u=a(c[2],{...n(i),column:i.indent+1+i.content.indexOf(c[2],l+c[1].length)});return o(t,u,i),{kind:`QueryParameterSyntax`,name:c[1],type:u,source:c[3]===void 0?null:r(c[3],n(i),t.valueContext),location:n(i)}}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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryParser.js","names":["header","pattern","parameterPattern","scopePattern","opaqueDirectives","match","line","context","DiagnosticCodes","locationOf","firstWord","parseTypeRef","name","returnType","reportLegacyOptionalSuffix","by","filters","description","scope","authorize","child","keyword","parseDescription","parameter","filter","combineAuthorize","parseAuthorize","nameOffset","type","parseMappingSource","existing","queryName"],"sources":["../../../../../../Compiler/Parsing/QueryParser.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 { AuthorizeSyntax } from '../Syntax/Authorization';\nimport { QueryParameterSyntax, QuerySyntax } from '../Syntax/Queries';\nimport { pattern } from '../Text/patterns';\nimport { combineAuthorize, parseAuthorize } from './AuthorizeParser';\nimport { parseDescription } from './DescriptionParser';\nimport { parseMappingSource } from './ExpressionParser';\nimport { firstWord } from './LineText';\nimport { ParserContext } from './ParserContext';\nimport { parseTypeRef, reportLegacyOptionalSuffix } from './PropertyLineParser';\nimport { locationOf, SourceLine } from './SourceLine';\n\nconst header = pattern('^query\\\\s+([A-Za-z_]\\\\w*)\\\\s*=>\\\\s*(observable\\\\s+)?([\\\\w.]+(?:\\\\[\\\\])?(?:\\\\?|\\\\s+optional)?)$');\nconst parameterPattern = pattern('^([a-z_]\\\\w*)\\\\s+([\\\\w.]+(?:\\\\[\\\\])?(?:\\\\?|\\\\s+optional)?)(?:\\\\s+from\\\\s+(.+))?$');\nconst scopePattern = pattern('^scoped\\\\s+to\\\\s+([a-z_]\\\\w*)$');\n\n// Query directives this compiler does not model. They are skipped whole.\nconst opaqueDirectives = new Set(['performer']);\n\nexport function parseQuery(context: ParserContext, line: SourceLine): QuerySyntax {\n const match = header.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidQueryDeclaration, `Invalid query declaration '${line.content}' - expected 'query <Name> => [observable] <ReadModel>'`, locationOf(line));\n context.skipBlock(line.indent);\n return {\n kind: 'QuerySyntax', name: firstWord(line.content), returnType: parseTypeRef('', locationOf(line)), by: null, filters: [],\n description: null, isObservable: false, scope: null, authorize: null, location: locationOf(line),\n };\n }\n const name = match[1];\n const returnType = parseTypeRef(match[3], { ...locationOf(line), column: line.indent + 1 + match[0].length - match[3].length });\n // This one '?' has no equivalent keyword spelling: 'observable optional' is a live query\n // returning the type named 'optional'. It is neither deprecated nor a migration occurrence.\n if (!(match[2] === undefined && returnType.name === 'observable' && returnType.isOptional && !returnType.isCollection)) {\n reportLegacyOptionalSuffix(context, returnType, line);\n }\n let by: QueryParameterSyntax | null = null;\n const filters: QueryParameterSyntax[] = [];\n let description: string | null = null;\n let scope: string | null = null;\n let authorize: AuthorizeSyntax | 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 === 'description') {\n description = parseDescription(context, child, description, `Query '${name}'`);\n } else if (keyword === 'by') {\n const parameter = parseParameter(context, child, 'by');\n if (parameter !== undefined) {\n if (by !== null) {\n context.error(DiagnosticCodes.InvalidQueryParameter, `Query '${name}' already declares 'by' - a query can have at most one key parameter`, locationOf(child));\n }\n by = parameter;\n }\n } else if (keyword === 'filter') {\n const filter = parseParameter(context, child, 'filter');\n if (filter !== undefined) {\n filters.push(filter);\n }\n } else if (keyword === 'authorize') {\n authorize = combineAuthorize(authorize, parseAuthorize(context, child));\n } else if (keyword === 'scoped') {\n scope = parseScope(context, child, scope, name) ?? scope;\n } else if (opaqueDirectives.has(keyword)) {\n context.skipOpaqueBlock(child.indent);\n } else {\n context.error(DiagnosticCodes.UnknownQueryDirective, `Unexpected '${child.content}' in query body - expected description, by, filter, authorize, scoped or performer`, locationOf(child));\n context.skipBlock(child.indent);\n }\n }\n return {\n kind: 'QuerySyntax',\n name,\n returnType,\n by,\n filters,\n description,\n isObservable: match[2] !== undefined,\n scope,\n authorize,\n location: locationOf(line),\n };\n}\n\nfunction parseParameter(context: ParserContext, line: SourceLine, keyword: string): QueryParameterSyntax | undefined {\n const match = parameterPattern.exec(line.content.substring(keyword.length).trim());\n if (match === null) {\n context.error(DiagnosticCodes.InvalidQueryParameter, `Invalid '${keyword}' parameter '${line.content}' - expected '${keyword} <name> <Type> [from <source>]'`, locationOf(line));\n return undefined;\n }\n const nameOffset = line.content.indexOf(match[1], keyword.length);\n const type = parseTypeRef(match[2], { ...locationOf(line), column: line.indent + 1 + line.content.indexOf(match[2], nameOffset + match[1].length) });\n reportLegacyOptionalSuffix(context, type, line);\n return { kind: 'QueryParameterSyntax', name: match[1], type, source: match[3] === undefined ? null : parseMappingSource(match[3], locationOf(line), context.valueContext), location: locationOf(line) };\n}\n\nfunction parseScope(context: ParserContext, line: SourceLine, existing: string | null, queryName: string): string | undefined {\n const match = scopePattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidScopeDeclaration, `Invalid scope declaration '${line.content}' - expected 'scoped to <scope>'`, locationOf(line));\n return undefined;\n }\n if (existing !== null) {\n context.error(DiagnosticCodes.DuplicateScope, `Query '${queryName}' already declares a scope - results are narrowed one way`, locationOf(line));\n return undefined;\n }\n return match[1];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"QueryParser.js","names":["header","pattern","parameterPattern","scopePattern","opaqueDirectives","match","line","context","DiagnosticCodes","locationOf","firstWord","parseTypeRef","name","returnType","reportLegacyOptionalSuffix","by","byParts","hasBy","filters","description","scope","authorize","child","keyword","parseDescription","part","parsed","parameter","filter","combineAuthorize","parseAuthorize","nameOffset","type","parseMappingSource","existing","queryName"],"sources":["../../../../../../Compiler/Parsing/QueryParser.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 { AuthorizeSyntax } from '../Syntax/Authorization';\nimport { QueryParameterSyntax, QuerySyntax } from '../Syntax/Queries';\nimport { pattern } from '../Text/patterns';\nimport { combineAuthorize, parseAuthorize } from './AuthorizeParser';\nimport { parseDescription } from './DescriptionParser';\nimport { parseMappingSource } from './ExpressionParser';\nimport { firstWord } from './LineText';\nimport { ParserContext } from './ParserContext';\nimport { parseTypeRef, reportLegacyOptionalSuffix } from './PropertyLineParser';\nimport { locationOf, SourceLine } from './SourceLine';\n\nconst header = pattern('^query\\\\s+([A-Za-z_]\\\\w*)\\\\s*=>\\\\s*(observable\\\\s+)?([\\\\w.]+(?:\\\\[\\\\])?(?:\\\\?|\\\\s+optional)?)$');\nconst parameterPattern = pattern('^([a-z_]\\\\w*)\\\\s+([\\\\w.]+(?:\\\\[\\\\])?(?:\\\\?|\\\\s+optional)?)(?:\\\\s+from\\\\s+(.+))?$');\nconst scopePattern = pattern('^scoped\\\\s+to\\\\s+([a-z_]\\\\w*)$');\n\n// Query directives this compiler does not model. They are skipped whole.\nconst opaqueDirectives = new Set(['performer']);\n\nexport function parseQuery(context: ParserContext, line: SourceLine): QuerySyntax {\n const match = header.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidQueryDeclaration, `Invalid query declaration '${line.content}' - expected 'query <Name> => [observable] <ReadModel>'`, locationOf(line));\n context.skipBlock(line.indent);\n return {\n kind: 'QuerySyntax', name: firstWord(line.content), returnType: parseTypeRef('', locationOf(line)), by: null, filters: [],\n description: null, isObservable: false, scope: null, authorize: null, location: locationOf(line),\n };\n }\n const name = match[1];\n const returnType = parseTypeRef(match[3], { ...locationOf(line), column: line.indent + 1 + match[0].length - match[3].length });\n // This one '?' has no equivalent keyword spelling: 'observable optional' is a live query\n // returning the type named 'optional'. It is neither deprecated nor a migration occurrence.\n if (!(match[2] === undefined && returnType.name === 'observable' && returnType.isOptional && !returnType.isCollection)) {\n reportLegacyOptionalSuffix(context, returnType, line);\n }\n let by: QueryParameterSyntax | null = null;\n const byParts: QueryParameterSyntax[] = [];\n let hasBy = false;\n const filters: QueryParameterSyntax[] = [];\n let description: string | null = null;\n let scope: string | null = null;\n let authorize: AuthorizeSyntax | 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 === 'description') {\n description = parseDescription(context, child, description, `Query '${name}'`);\n } else if (keyword === 'by') {\n if (child.content === 'by') {\n if (hasBy) context.error(DiagnosticCodes.InvalidReadModelKeyLookup, 'A query cannot combine a by block with another by declaration.', locationOf(child));\n by = null;\n byParts.length = 0;\n for (let part = context.peekChild(child.indent); part !== undefined; part = context.peekChild(child.indent)) {\n context.reader.takeSignificant();\n const parsed = parseParameter(context, part, '');\n if (parsed !== undefined) byParts.push(parsed);\n }\n if (byParts.length < 2 || new Set(byParts.map(part => part.name)).size !== byParts.length) {\n context.error(DiagnosticCodes.InvalidReadModelKeyLookup, 'A query by block requires at least two distinct named key parts.', locationOf(child));\n }\n hasBy = true;\n } else {\n const parameter = parseParameter(context, child, 'by');\n if (parameter !== undefined) {\n if (hasBy) context.error(DiagnosticCodes.InvalidQueryParameter, `Query '${name}' already declares 'by' - a query can have at most one key parameter`, locationOf(child));\n if (byParts.length > 0) context.error(DiagnosticCodes.InvalidReadModelKeyLookup, 'A query cannot combine a by block with a single by line.', locationOf(child));\n byParts.length = 0;\n by = parameter;\n hasBy = true;\n }\n }\n } else if (keyword === 'filter') {\n const filter = parseParameter(context, child, 'filter');\n if (filter !== undefined) {\n filters.push(filter);\n }\n } else if (keyword === 'authorize') {\n authorize = combineAuthorize(authorize, parseAuthorize(context, child));\n } else if (keyword === 'scoped') {\n scope = parseScope(context, child, scope, name) ?? scope;\n } else if (opaqueDirectives.has(keyword)) {\n context.skipOpaqueBlock(child.indent);\n } else {\n context.error(DiagnosticCodes.UnknownQueryDirective, `Unexpected '${child.content}' in query body - expected description, by, filter, authorize, scoped or performer`, locationOf(child));\n context.skipBlock(child.indent);\n }\n }\n return {\n kind: 'QuerySyntax',\n name,\n returnType,\n by,\n ...(byParts.length > 0 ? { byParts } : {}),\n filters,\n description,\n isObservable: match[2] !== undefined,\n scope,\n authorize,\n location: locationOf(line),\n };\n}\n\nfunction parseParameter(context: ParserContext, line: SourceLine, keyword: string): QueryParameterSyntax | undefined {\n const match = parameterPattern.exec(line.content.substring(keyword.length).trim());\n if (match === null) {\n context.error(DiagnosticCodes.InvalidQueryParameter, `Invalid '${keyword}' parameter '${line.content}' - expected '${keyword} <name> <Type> [from <source>]'`, locationOf(line));\n return undefined;\n }\n const nameOffset = line.content.indexOf(match[1], keyword.length);\n const type = parseTypeRef(match[2], { ...locationOf(line), column: line.indent + 1 + line.content.indexOf(match[2], nameOffset + match[1].length) });\n reportLegacyOptionalSuffix(context, type, line);\n return { kind: 'QueryParameterSyntax', name: match[1], type, source: match[3] === undefined ? null : parseMappingSource(match[3], locationOf(line), context.valueContext), location: locationOf(line) };\n}\n\nfunction parseScope(context: ParserContext, line: SourceLine, existing: string | null, queryName: string): string | undefined {\n const match = scopePattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidScopeDeclaration, `Invalid scope declaration '${line.content}' - expected 'scoped to <scope>'`, locationOf(line));\n return undefined;\n }\n if (existing !== null) {\n context.error(DiagnosticCodes.DuplicateScope, `Query '${queryName}' already declares a scope - results are narrowed one way`, locationOf(line));\n return undefined;\n }\n return match[1];\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{nativePattern as t,pattern as n}from"../Text/patterns.js";import{locationOf as r}from"./SourceLine.js";import{dependencySources as i}from"../Syntax/DependencySources.js";import{parseModeledMappingSource as a}from"./ExpressionParser.js";import{firstWord as o}from"./LineText.js";import{parseDescription as s}from"./DescriptionParser.js";import{parseDocumentation as c}from"./DocumentationParser.js";import{parseCondition as l}from"./ConditionParser.js";import{ParserContext as u}from"./ParserContext.js";import{collectInputUses as d}from"./InputUses.js";import{isReactionIdentityLine as f,misplacedReactionIdentity as p,parseReactionIdentity as m}from"./ReactionIdentityParser.js";import{
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{nativePattern as t,pattern as n}from"../Text/patterns.js";import{locationOf as r}from"./SourceLine.js";import{dependencySources as i}from"../Syntax/DependencySources.js";import{parseModeledMappingSource as a}from"./ExpressionParser.js";import{firstWord as o}from"./LineText.js";import{parseDescription as s}from"./DescriptionParser.js";import{parseDocumentation as c}from"./DocumentationParser.js";import{parseCondition as l}from"./ConditionParser.js";import{ParserContext as u}from"./ParserContext.js";import{collectInputUses as d}from"./InputUses.js";import{isReactionIdentityLine as f,misplacedReactionIdentity as p,parseReactionIdentity as m}from"./ReactionIdentityParser.js";import{parseObserverFilter as h}from"./ObserverFilterParser.js";import{parseReads as g}from"./ReadsParser.js";import{parseProduces as _}from"./ProducesParser.js";import{parseTriggerData as v}from"./TriggerDataParser.js";const y=n(`^reaction\\s+([A-Za-z_]\\w*)$`),b=n(`^when\\s+([A-Za-z_]\\w*)$`),x=n(`^every\\s+(\\d+)\\s+(seconds?|minutes?|hours?|days?)$`),S=n(`^at\\s+(\\d{2}:\\d{2})(?:\\s+on\\s+(?:(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)|day\\s+(\\d{1,2})))?$`),C=/* @__PURE__ */ new Set([`when`,`every`,`at`]),w=n(`^invokes\\s+([A-Z]\\w*)$`),T=t(`^(@?[\\w.]+)\\s*=(?!=|>)\\s*(.+)$`),E=t(`^on\\s+refused\\b(?=$|\\s+by\\b)`),D=t(`^on\\s+refused(?:\\s+by\\s+(validation|constraint|authorization)(?:\\s+([A-Za-z_]\\w*(?:\\.\\w+)*))?)?$`),O=n(`^reads\\s+[A-Z]\\w*\\s+optional(?:\\s|$)`);function parseReaction(t,n){let i=y.exec(n.content)?.[1]??``;i===``&&t.error(e.InvalidReactionDeclaration,`Invalid reaction declaration '${n.content}' - expected 'reaction <Name>'`,r(n));let a=null,u=null,d=null,f=null,p=null,g=!1,_=[],v=/* @__PURE__ */ new Set,b=!1;for(let y=t.peekChild(n.indent);y!==void 0;y=t.peekChild(n.indent)){t.reader.takeSignificant();let n=o(y.content);if(n===`description`){a=s(t,y,a,`Reaction '${i}'`);continue}if(n===`documentation`){u=c(t,y,u,`Reaction '${i}'`);continue}if(n===`from`){f=h(t,y,f);continue}if(n===`runs`){p=m(t,y,g)??p,g=!0;continue}if(n===`where`){d=l(t,y.content.substring(5).trim(),r(y));continue}if(E.test(y.content)){t.error(e.InvalidRefusalBranch,`A refusal branch belongs inside 'invokes <Command>'.`,r(y)),t.skipBlock(y.indent),b=!0;continue}if(!C.has(n)){t.error(e.InvalidReactionTrigger,`Expected a trigger in reaction body, got '${y.content}' - a reaction is set off by 'when <Name>', 'every <n> <unit>' or 'at <HH:mm>'`,r(y)),t.skipBlock(y.indent),b=!0;continue}let x=parseTriggerSource(t,y);if(x===void 0){b=!0;continue}let S=sourceKey(x);v.has(S)?(t.error(e.DuplicateReactionTrigger,`Reaction '${i}' already declares '${y.content}' - a second says nothing the first did not`,r(y)),t.skipBlock(y.indent)):(v.add(S),_.push(parseTrigger(t,y,x)))}return _.length===0&&!b&&t.error(e.ReactionWithoutTrigger,`Reaction '${i}' must declare at least one trigger - nothing sets it off`,r(n)),{kind:`ReactionSyntax`,name:i,description:a,documentation:u,from:f,runsAs:p,where:d,triggers:_,location:r(n)}}function parseTrigger(t,n,c){let l=null,m=[],h=[],y=[],b=[],x=!1;for(let i=t.peekChild(n.indent);i!==void 0;i=t.peekChild(n.indent)){t.reader.takeSignificant();let n=o(i.content);if(n===`runs`&&f(i))p(t,i);else if(n===`description`)l=s(t,i,l,`Trigger '${i.content}'`);else if(n===`produces`){let e=_(t,i);e!==void 0&&m.push(e)}else if(n===`invokes`){let n=w.exec(i.content);if(n===null)t.error(e.InvalidInvokesDeclaration,`Invalid invokes declaration '${i.content}' - expected 'invokes <Command>'`,r(i)),t.skipBlock(i.indent);else{let o=new u(t.reader.fork(),t.path,t.languages);o.scope=t.scope,o.sourceOptions=t.sourceOptions,d(o,i),t.inputUses.push(...o.inputUses);let s=[],c=[];for(let n=t.peekChild(i.indent);n!==void 0;n=t.peekChild(i.indent)){if(t.reader.takeSignificant(),f(n)){p(t,n);continue}if(E.test(n.content)){let e=parseRefusal(t,n);e!==void 0&&c.push(e);continue}let i=T.exec(n.content);i===null?t.error(e.InvalidPropertyMapping,`Invalid property mapping '${n.content}' - expected '<property> = <source>'`,r(n)):s.push({kind:`PropertyMappingSyntax`,property:i[1].replaceAll(`@`,``),source:a(i[2],r(n),t.valueContext),location:r(n)})}h.push({kind:`InvokesSyntax`,command:n[1],mappings:s,onRefused:c,location:r(i)})}}else if(E.test(i.content))t.error(e.InvalidRefusalBranch,`A refusal branch belongs inside 'invokes <Command>'.`,r(i)),t.skipBlock(i.indent);else if(n===`reads`||n===`file`||i.content===`csharp`||i.content.startsWith("```")){x||=n===`file`||i.content===`csharp`||i.content.startsWith("```");let a=n===`reads`?g(t,i):void 0;a!==void 0&&y.push(a),O.test(i.content)&&t.error(e.OptionalReadsNotSupported,`Optional reads are not yet supported (see #308).`,r(i)),i.content.startsWith("```")&&t.skipFencedBody(),t.skipOpaqueBlock(i.indent)}else{let e=t.triggerData.length;v(t,i);for(let n of t.triggerData.slice(e))b.push({kind:`TriggerDataSyntax`,name:n.name,type:n.type,location:n.location})}}let S={kind:`ReactionTriggerSyntax`,source:c,description:l,produces:m,invokes:h,location:r(n)};return i.set(S,{reads:y,data:b,implementation:x}),S}function parseRefusal(t,n){let i=D.exec(n.content);if(i===null||i[2]!==void 0&&i[1]!==`constraint`){t.error(e.InvalidRefusalBranch,`Expected 'on refused [by validation | by constraint [<Name>] | by authorization]'.`,r(n)),t.skipBlock(n.indent);return}let a=[],s=!1,c=!1;for(let i=t.peekChild(n.indent);i!==void 0;i=t.peekChild(n.indent))if(t.reader.takeSignificant(),f(i))p(t,i),c=!0;else if(i.content===`acknowledge`)(s||a.length>0||t.peekChild(i.indent)!==void 0)&&(t.error(e.InvalidRefusalBranchBody,`A refusal branch contains 'acknowledge' alone or one or more 'produces' blocks.`,r(i)),c=!0),s=!0,t.skipBlock(i.indent);else if(o(i.content)===`produces`){s&&(t.error(e.InvalidRefusalBranchBody,`A refusal branch cannot combine 'acknowledge' and 'produces'.`,r(i)),c=!0);let n=_(t,i);n===void 0?c=!0:a.push(n)}else t.error(e.InvalidRefusalBranchBody,`Expected 'acknowledge' or 'produces <Event>' in a refusal branch.`,r(i)),t.skipBlock(i.indent),c=!0;return!s&&a.length===0&&!c&&t.error(e.InvalidRefusalBranchBody,`A refusal branch must acknowledge or produce an event.`,r(n)),{kind:`InvocationRefusalSyntax`,selector:i[1]??`any`,constraint:i[2]??null,acknowledge:s,produces:a,location:r(n)}}function sourceKey(e){switch(e.kind){case`NamedTriggerSourceSyntax`:return JSON.stringify([e.kind,e.name]);case`IntervalTriggerSourceSyntax`:return JSON.stringify([e.kind,e.amount,e.unit]);case`ScheduleTriggerSourceSyntax`:return JSON.stringify([e.kind,e.time,e.dayOfWeek,e.dayOfMonth])}}function parseTriggerSource(t,n){let i=r(n);switch(o(n.content)){case`when`:{let r=b.exec(n.content);if(r===null){t.error(e.InvalidReactionTrigger,`Invalid trigger '${n.content}' - expected 'when <Name>'`,i),t.skipBlock(n.indent);return}return{kind:`NamedTriggerSourceSyntax`,name:r[1],location:i}}case`every`:{let r=x.exec(n.content),a=r===null?NaN:Number(r[1]);if(r===null||!Number.isInteger(a)||a<1||a>2147483647){t.error(e.InvalidIntervalTrigger,`Invalid interval '${n.content}' - expected 'every <n> <seconds|minutes|hours|days>'`,i),t.skipBlock(n.indent);return}return{kind:`IntervalTriggerSourceSyntax`,amount:a,unit:unitOf(r[2]),location:i}}default:return parseSchedule(t,n)}}function parseSchedule(t,n){let i=r(n),a=S.exec(n.content),o=a===null?void 0:timeOf(a[1]);if(a===null||o===void 0)t.error(e.InvalidScheduleTrigger,`Invalid schedule '${n.content}' - expected 'at <HH:mm>', optionally followed by 'on <Weekday>' or 'on day <n>'`,i),t.skipBlock(n.indent);else{if(a[3]!==void 0){let r=Number(a[3]);if(r<1||r>31){t.error(e.InvalidScheduleTrigger,`Invalid day of month '${r}' in '${n.content}' - a day of the month is between 1 and 31`,i),t.skipBlock(n.indent);return}return{kind:`ScheduleTriggerSourceSyntax`,time:o,dayOfWeek:null,dayOfMonth:r,location:i}}return{kind:`ScheduleTriggerSourceSyntax`,time:o,dayOfWeek:a[2]??null,dayOfMonth:null,location:i}}}function timeOf(e){let[t,n]=e.split(`:`).map(Number);if(t>=0&&t<=23&&n>=0&&n<=59)return`${e}:00.0000000`}function unitOf(e){switch(e.replace(/s+$/,``)){case`second`:return`Seconds`;case`minute`:return`Minutes`;case`hour`:return`Hours`;default:return`Days`}}export{parseReaction,parseTriggerSource};
|
|
2
2
|
//# sourceMappingURL=ReactionParser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReactionParser.js","names":["parseMappingSource","header","pattern","whenPattern","everyPattern","atPattern","clauseKeywords","invokesPattern","mappingPattern","nativePattern","refusalPrefix","refusalHeader","optionalReads","name","line","context","DiagnosticCodes","locationOf","description","documentation","where","runsAs","identityDeclared","triggers","sources","reported","child","keyword","firstWord","parseDescription","parseDocumentation","parseReactionIdentity","parseCondition","source","key","produces","invokes","reads","data","implementation","isReactionIdentityLine","misplacedReactionIdentity","produced","parseProduces","match","uses","ParserContext","collectInputUses","mappings","onRefused","value","refusal","mapped","parseModeledMappingSource","read","captureReads","start","parseTriggerData","property","syntax","dependencySources","acknowledge","location","amount","time","day","hours","minutes","text"],"sources":["../../../../../../Compiler/Parsing/ReactionParser.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 { ConditionSyntax } from '../Syntax/Conditions';\nimport { PropertyMappingSyntax } from '../Syntax/Expressions';\nimport { InvocationRefusalSyntax } from '../Syntax/InvocationRefusalSyntax';\nimport { parseCondition } from './ConditionParser';\nimport { parseModeledMappingSource as parseMappingSource } from './ExpressionParser';\nimport { DayOfWeek, IntervalUnit, InvokesSyntax, ProducesSyntax, ReactionSyntax, ReactionTriggerSyntax, TriggerSourceSyntax } from '../Syntax/Reactions';\nimport { nativePattern, pattern } from '../Text/patterns';\nimport { ReactionIdentitySyntax } from '../Syntax/ReactionIdentitySyntax';\nimport { isReactionIdentityLine, misplacedReactionIdentity, parseReactionIdentity } from './ReactionIdentityParser';\nimport { parseDescription } from './DescriptionParser';\nimport { parseDocumentation } from './DocumentationParser';\nimport { collectInputUses } from './InputUses';\nimport { firstWord } from './LineText';\nimport { ParserContext } from './ParserContext';\nimport { parseTriggerData } from './TriggerDataParser';\nimport { dependencySources, ReadsSyntax, TriggerDataSyntax } from '../Syntax/DependencySources';\nimport { captureReads } from './DependencySourceParser';\nimport { parseProduces } from './ProducesParser';\nimport { locationOf, SourceLine } from './SourceLine';\n\nconst header = pattern('^reaction\\\\s+([A-Za-z_]\\\\w*)$');\nconst whenPattern = pattern('^when\\\\s+([A-Za-z_]\\\\w*)$');\nconst everyPattern = pattern('^every\\\\s+(\\\\d+)\\\\s+(seconds?|minutes?|hours?|days?)$');\nconst atPattern = pattern('^at\\\\s+(\\\\d{2}:\\\\d{2})(?:\\\\s+on\\\\s+(?:(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)|day\\\\s+(\\\\d{1,2})))?$');\nconst clauseKeywords = new Set(['when', 'every', 'at']);\nconst invokesPattern = pattern('^invokes\\\\s+([A-Z]\\\\w*)$');\nconst mappingPattern = nativePattern('^(@?[\\\\w.]+)\\\\s*=(?!=|>)\\\\s*(.+)$');\nconst refusalPrefix = nativePattern('^on\\\\s+refused\\\\b(?=$|\\\\s+by\\\\b)');\nconst refusalHeader = nativePattern('^on\\\\s+refused(?:\\\\s+by\\\\s+(validation|constraint|authorization)(?:\\\\s+([A-Za-z_]\\\\w*(?:\\\\.\\\\w+)*))?)?$');\nconst optionalReads = pattern('^reads\\\\s+[A-Z]\\\\w*\\\\s+optional(?:\\\\s|$)');\n\nexport function parseReaction(context: ParserContext, line: SourceLine): ReactionSyntax {\n const name = header.exec(line.content)?.[1] ?? '';\n if (name === '') {\n context.error(DiagnosticCodes.InvalidReactionDeclaration, `Invalid reaction declaration '${line.content}' - expected 'reaction <Name>'`, locationOf(line));\n }\n let description: string | null = null;\n let documentation: string | null = null;\n let where: ConditionSyntax | null = null;\n let runsAs: ReactionIdentitySyntax | null = null;\n let identityDeclared = false;\n const triggers: ReactionTriggerSyntax[] = [];\n const sources = new Set<string>();\n // A reaction whose only trigger is misspelled has no trigger, but saying so as well turns one mistake\n // into two diagnostics.\n let reported = false;\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 === 'description') {\n description = parseDescription(context, child, description, `Reaction '${name}'`);\n continue;\n }\n if (keyword === 'documentation') {\n documentation = parseDocumentation(context, child, documentation, `Reaction '${name}'`);\n continue;\n }\n if (keyword === 'runs') {\n runsAs = parseReactionIdentity(context, child, identityDeclared) ?? runsAs;\n identityDeclared = true;\n continue;\n }\n if (keyword === 'where') {\n where = parseCondition(context, child.content.substring('where'.length).trim(), locationOf(child));\n continue;\n }\n if (refusalPrefix.test(child.content)) {\n context.error(DiagnosticCodes.InvalidRefusalBranch, \"A refusal branch belongs inside 'invokes <Command>'.\", locationOf(child));\n context.skipBlock(child.indent);\n reported = true;\n continue;\n }\n if (!clauseKeywords.has(keyword)) {\n context.error(DiagnosticCodes.InvalidReactionTrigger, `Expected a trigger in reaction body, got '${child.content}' - a reaction is set off by 'when <Name>', 'every <n> <unit>' or 'at <HH:mm>'`, locationOf(child));\n context.skipBlock(child.indent);\n reported = true;\n continue;\n }\n const source = parseTriggerSource(context, child);\n if (source === undefined) {\n reported = true;\n continue;\n }\n const key = sourceKey(source);\n if (sources.has(key)) {\n context.error(DiagnosticCodes.DuplicateReactionTrigger, `Reaction '${name}' already declares '${child.content}' - a second says nothing the first did not`, locationOf(child));\n context.skipBlock(child.indent);\n continue;\n }\n sources.add(key);\n triggers.push(parseTrigger(context, child, source));\n }\n if (triggers.length === 0 && !reported) {\n context.error(DiagnosticCodes.ReactionWithoutTrigger, `Reaction '${name}' must declare at least one trigger - nothing sets it off`, locationOf(line));\n }\n return { kind: 'ReactionSyntax', name, description, documentation, runsAs, where, triggers, location: locationOf(line) };\n}\n\n// What a trigger does - the events it produces and the commands it invokes - is read by name; its reads,\n// values and code are not modeled. The C# compiler remains the authority on whether what is skipped is valid.\nfunction parseTrigger(context: ParserContext, line: SourceLine, source: TriggerSourceSyntax): ReactionTriggerSyntax {\n let description: string | null = null;\n const produces: ProducesSyntax[] = [];\n const invokes: InvokesSyntax[] = [];\n const reads: ReadsSyntax[] = [];\n const data: TriggerDataSyntax[] = [];\n let implementation = false;\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 === 'runs' && isReactionIdentityLine(child)) {\n misplacedReactionIdentity(context, child);\n } else if (keyword === 'description') {\n description = parseDescription(context, child, description, `Trigger '${child.content}'`);\n } else if (keyword === 'produces') {\n const produced = parseProduces(context, child);\n if (produced !== undefined) {\n produces.push(produced);\n }\n } else if (keyword === 'invokes') {\n const match = invokesPattern.exec(child.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidInvokesDeclaration, `Invalid invokes declaration '${child.content}' - expected 'invokes <Command>'`, locationOf(child));\n context.skipBlock(child.indent);\n } else {\n const uses = new ParserContext(context.reader.fork(), context.path, context.languages);\n uses.scope = context.scope;\n uses.sourceOptions = context.sourceOptions;\n collectInputUses(uses, child);\n context.inputUses.push(...uses.inputUses);\n const mappings: PropertyMappingSyntax[] = [];\n const onRefused: InvocationRefusalSyntax[] = [];\n for (let value = context.peekChild(child.indent); value !== undefined; value = context.peekChild(child.indent)) {\n context.reader.takeSignificant();\n if (isReactionIdentityLine(value)) {\n misplacedReactionIdentity(context, value);\n continue;\n }\n if (refusalPrefix.test(value.content)) {\n const refusal = parseRefusal(context, value);\n if (refusal !== undefined) onRefused.push(refusal);\n continue;\n }\n const mapped = mappingPattern.exec(value.content);\n if (mapped !== null) mappings.push({ kind: 'PropertyMappingSyntax', property: mapped[1].replaceAll('@', ''), source: parseMappingSource(mapped[2], locationOf(value), context.valueContext), location: locationOf(value) });\n else context.error(DiagnosticCodes.InvalidPropertyMapping, `Invalid property mapping '${value.content}' - expected '<property> = <source>'`, locationOf(value));\n }\n invokes.push({ kind: 'InvokesSyntax', command: match[1], mappings, onRefused, location: locationOf(child) });\n }\n } else if (refusalPrefix.test(child.content)) {\n context.error(DiagnosticCodes.InvalidRefusalBranch, \"A refusal branch belongs inside 'invokes <Command>'.\", locationOf(child));\n context.skipBlock(child.indent);\n } else if (keyword === 'reads' || keyword === 'file' || child.content === 'csharp' || child.content.startsWith('```')) {\n implementation ||= keyword === 'file' || child.content === 'csharp' || child.content.startsWith('```');\n const read = captureReads(child);\n if (read !== undefined) reads.push(read);\n if (optionalReads.test(child.content)) {\n context.error(DiagnosticCodes.OptionalReadsNotSupported, 'Optional reads are not yet supported (see #308).', locationOf(child));\n }\n if (child.content.startsWith('```')) {\n context.skipFencedBody();\n }\n context.skipOpaqueBlock(child.indent);\n } else {\n const start = context.triggerData.length;\n parseTriggerData(context, child);\n for (const property of context.triggerData.slice(start)) data.push({ kind: 'TriggerDataSyntax', name: property.name, type: property.type, location: property.location });\n }\n }\n const syntax: ReactionTriggerSyntax = { kind: 'ReactionTriggerSyntax', source, description, produces, invokes, location: locationOf(line) };\n dependencySources.set(syntax, { reads, data, implementation });\n return syntax;\n}\n\nfunction parseRefusal(context: ParserContext, line: SourceLine): InvocationRefusalSyntax | undefined {\n const match = refusalHeader.exec(line.content);\n if (match === null || (match[2] !== undefined && match[1] !== 'constraint')) {\n context.error(DiagnosticCodes.InvalidRefusalBranch, \"Expected 'on refused [by validation | by constraint [<Name>] | by authorization]'.\", locationOf(line));\n context.skipBlock(line.indent);\n return undefined;\n }\n const produces: ProducesSyntax[] = [];\n let acknowledge = false;\n let reported = false;\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n if (isReactionIdentityLine(child)) {\n misplacedReactionIdentity(context, child);\n reported = true;\n } else if (child.content === 'acknowledge') {\n if (acknowledge || produces.length > 0 || context.peekChild(child.indent) !== undefined) {\n context.error(DiagnosticCodes.InvalidRefusalBranchBody, \"A refusal branch contains 'acknowledge' alone or one or more 'produces' blocks.\", locationOf(child));\n reported = true;\n }\n acknowledge = true;\n context.skipBlock(child.indent);\n } else if (firstWord(child.content) === 'produces') {\n if (acknowledge) {\n context.error(DiagnosticCodes.InvalidRefusalBranchBody, \"A refusal branch cannot combine 'acknowledge' and 'produces'.\", locationOf(child));\n reported = true;\n }\n const produced = parseProduces(context, child);\n if (produced !== undefined) produces.push(produced);\n else reported = true;\n } else {\n context.error(DiagnosticCodes.InvalidRefusalBranchBody, \"Expected 'acknowledge' or 'produces <Event>' in a refusal branch.\", locationOf(child));\n context.skipBlock(child.indent);\n reported = true;\n }\n }\n if (!acknowledge && produces.length === 0 && !reported) {\n context.error(DiagnosticCodes.InvalidRefusalBranchBody, 'A refusal branch must acknowledge or produce an event.', locationOf(line));\n }\n return { kind: 'InvocationRefusalSyntax', selector: match[1] ?? 'any', constraint: match[2] ?? null, acknowledge, produces, location: locationOf(line) };\n}\n\nfunction sourceKey(source: TriggerSourceSyntax): string {\n switch (source.kind) {\n case 'NamedTriggerSourceSyntax': return JSON.stringify([source.kind, source.name]);\n case 'IntervalTriggerSourceSyntax': return JSON.stringify([source.kind, source.amount, source.unit]);\n case 'ScheduleTriggerSourceSyntax': return JSON.stringify([source.kind, source.time, source.dayOfWeek, source.dayOfMonth]);\n }\n}\n\n// Reads a 'when', 'every' or 'at' clause - the port of the C# TriggerParser.ParseSource. The caller only\n// hands it a line starting with one of the three, so anything that is not 'when' or 'every' is 'at'.\nexport function parseTriggerSource(context: ParserContext, line: SourceLine): TriggerSourceSyntax | undefined {\n const location = locationOf(line);\n switch (firstWord(line.content)) {\n case 'when': {\n const match = whenPattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidReactionTrigger, `Invalid trigger '${line.content}' - expected 'when <Name>'`, location);\n context.skipBlock(line.indent);\n return undefined;\n }\n return { kind: 'NamedTriggerSourceSyntax', name: match[1], location };\n }\n case 'every': {\n const match = everyPattern.exec(line.content);\n const amount = match === null ? NaN : Number(match[1]);\n if (match === null || !Number.isInteger(amount) || amount < 1 || amount > 2147483647) {\n context.error(DiagnosticCodes.InvalidIntervalTrigger, `Invalid interval '${line.content}' - expected 'every <n> <seconds|minutes|hours|days>'`, location);\n context.skipBlock(line.indent);\n return undefined;\n }\n return { kind: 'IntervalTriggerSourceSyntax', amount, unit: unitOf(match[2]), location };\n }\n default:\n return parseSchedule(context, line);\n }\n}\n\nfunction parseSchedule(context: ParserContext, line: SourceLine): TriggerSourceSyntax | undefined {\n const location = locationOf(line);\n const match = atPattern.exec(line.content);\n const time = match === null ? undefined : timeOf(match[1]);\n if (match === null || time === undefined) {\n context.error(DiagnosticCodes.InvalidScheduleTrigger, `Invalid schedule '${line.content}' - expected 'at <HH:mm>', optionally followed by 'on <Weekday>' or 'on day <n>'`, location);\n context.skipBlock(line.indent);\n return undefined;\n }\n if (match[3] !== undefined) {\n const day = Number(match[3]);\n if (day < 1 || day > 31) {\n context.error(DiagnosticCodes.InvalidScheduleTrigger, `Invalid day of month '${day}' in '${line.content}' - a day of the month is between 1 and 31`, location);\n context.skipBlock(line.indent);\n return undefined;\n }\n return { kind: 'ScheduleTriggerSourceSyntax', time, dayOfWeek: null, dayOfMonth: day, location };\n }\n return { kind: 'ScheduleTriggerSourceSyntax', time, dayOfWeek: (match[2] as DayOfWeek | undefined) ?? null, dayOfMonth: null, location };\n}\n\n// 'HH:mm' as SyntaxJson writes a TimeOnly, or undefined when it is not a time of day.\nfunction timeOf(text: string): string | undefined {\n const [hours, minutes] = text.split(':').map(Number);\n if (!(hours >= 0 && hours <= 23 && minutes >= 0 && minutes <= 59)) {\n return undefined;\n }\n return `${text}:00.0000000`;\n}\n\nfunction unitOf(text: string): IntervalUnit {\n switch (text.replace(/s+$/, '')) {\n case 'second':\n return 'Seconds';\n case 'minute':\n return 'Minutes';\n case 'hour':\n return 'Hours';\n default:\n return 'Days';\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ReactionParser.js","names":["parseMappingSource","header","pattern","whenPattern","everyPattern","atPattern","clauseKeywords","invokesPattern","mappingPattern","nativePattern","refusalPrefix","refusalHeader","optionalReads","name","line","context","DiagnosticCodes","locationOf","description","documentation","where","from","runsAs","identityDeclared","triggers","sources","reported","child","keyword","firstWord","parseDescription","parseDocumentation","parseObserverFilter","parseReactionIdentity","parseCondition","source","key","produces","invokes","reads","data","implementation","isReactionIdentityLine","misplacedReactionIdentity","produced","parseProduces","match","uses","ParserContext","collectInputUses","mappings","onRefused","value","refusal","mapped","parseModeledMappingSource","read","parseReads","start","parseTriggerData","property","syntax","dependencySources","acknowledge","location","amount","time","day","hours","minutes","text"],"sources":["../../../../../../Compiler/Parsing/ReactionParser.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 { ConditionSyntax } from '../Syntax/Conditions';\nimport { PropertyMappingSyntax } from '../Syntax/Expressions';\nimport { InvocationRefusalSyntax } from '../Syntax/InvocationRefusalSyntax';\nimport { parseCondition } from './ConditionParser';\nimport { ObserverFilterSyntax } from '../Syntax/ObserverFilterSyntax';\nimport { parseObserverFilter } from './ObserverFilterParser';\nimport { parseModeledMappingSource as parseMappingSource } from './ExpressionParser';\nimport { DayOfWeek, IntervalUnit, InvokesSyntax, ProducesSyntax, ReactionSyntax, ReactionTriggerSyntax, TriggerSourceSyntax } from '../Syntax/Reactions';\nimport { nativePattern, pattern } from '../Text/patterns';\nimport { ReactionIdentitySyntax } from '../Syntax/ReactionIdentitySyntax';\nimport { isReactionIdentityLine, misplacedReactionIdentity, parseReactionIdentity } from './ReactionIdentityParser';\nimport { parseDescription } from './DescriptionParser';\nimport { parseDocumentation } from './DocumentationParser';\nimport { collectInputUses } from './InputUses';\nimport { firstWord } from './LineText';\nimport { ParserContext } from './ParserContext';\nimport { parseTriggerData } from './TriggerDataParser';\nimport { dependencySources, ReadsSyntax, TriggerDataSyntax } from '../Syntax/DependencySources';\nimport { parseReads } from './ReadsParser';\nimport { parseProduces } from './ProducesParser';\nimport { locationOf, SourceLine } from './SourceLine';\n\nconst header = pattern('^reaction\\\\s+([A-Za-z_]\\\\w*)$');\nconst whenPattern = pattern('^when\\\\s+([A-Za-z_]\\\\w*)$');\nconst everyPattern = pattern('^every\\\\s+(\\\\d+)\\\\s+(seconds?|minutes?|hours?|days?)$');\nconst atPattern = pattern('^at\\\\s+(\\\\d{2}:\\\\d{2})(?:\\\\s+on\\\\s+(?:(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)|day\\\\s+(\\\\d{1,2})))?$');\nconst clauseKeywords = new Set(['when', 'every', 'at']);\nconst invokesPattern = pattern('^invokes\\\\s+([A-Z]\\\\w*)$');\nconst mappingPattern = nativePattern('^(@?[\\\\w.]+)\\\\s*=(?!=|>)\\\\s*(.+)$');\nconst refusalPrefix = nativePattern('^on\\\\s+refused\\\\b(?=$|\\\\s+by\\\\b)');\nconst refusalHeader = nativePattern('^on\\\\s+refused(?:\\\\s+by\\\\s+(validation|constraint|authorization)(?:\\\\s+([A-Za-z_]\\\\w*(?:\\\\.\\\\w+)*))?)?$');\nconst optionalReads = pattern('^reads\\\\s+[A-Z]\\\\w*\\\\s+optional(?:\\\\s|$)');\n\nexport function parseReaction(context: ParserContext, line: SourceLine): ReactionSyntax {\n const name = header.exec(line.content)?.[1] ?? '';\n if (name === '') {\n context.error(DiagnosticCodes.InvalidReactionDeclaration, `Invalid reaction declaration '${line.content}' - expected 'reaction <Name>'`, locationOf(line));\n }\n let description: string | null = null;\n let documentation: string | null = null;\n let where: ConditionSyntax | null = null;\n let from: ObserverFilterSyntax | null = null;\n let runsAs: ReactionIdentitySyntax | null = null;\n let identityDeclared = false;\n const triggers: ReactionTriggerSyntax[] = [];\n const sources = new Set<string>();\n // A reaction whose only trigger is misspelled has no trigger, but saying so as well turns one mistake\n // into two diagnostics.\n let reported = false;\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 === 'description') {\n description = parseDescription(context, child, description, `Reaction '${name}'`);\n continue;\n }\n if (keyword === 'documentation') {\n documentation = parseDocumentation(context, child, documentation, `Reaction '${name}'`);\n continue;\n }\n if (keyword === 'from') {\n from = parseObserverFilter(context, child, from);\n continue;\n }\n if (keyword === 'runs') {\n runsAs = parseReactionIdentity(context, child, identityDeclared) ?? runsAs;\n identityDeclared = true;\n continue;\n }\n if (keyword === 'where') {\n where = parseCondition(context, child.content.substring('where'.length).trim(), locationOf(child));\n continue;\n }\n if (refusalPrefix.test(child.content)) {\n context.error(DiagnosticCodes.InvalidRefusalBranch, \"A refusal branch belongs inside 'invokes <Command>'.\", locationOf(child));\n context.skipBlock(child.indent);\n reported = true;\n continue;\n }\n if (!clauseKeywords.has(keyword)) {\n context.error(DiagnosticCodes.InvalidReactionTrigger, `Expected a trigger in reaction body, got '${child.content}' - a reaction is set off by 'when <Name>', 'every <n> <unit>' or 'at <HH:mm>'`, locationOf(child));\n context.skipBlock(child.indent);\n reported = true;\n continue;\n }\n const source = parseTriggerSource(context, child);\n if (source === undefined) {\n reported = true;\n continue;\n }\n const key = sourceKey(source);\n if (sources.has(key)) {\n context.error(DiagnosticCodes.DuplicateReactionTrigger, `Reaction '${name}' already declares '${child.content}' - a second says nothing the first did not`, locationOf(child));\n context.skipBlock(child.indent);\n continue;\n }\n sources.add(key);\n triggers.push(parseTrigger(context, child, source));\n }\n if (triggers.length === 0 && !reported) {\n context.error(DiagnosticCodes.ReactionWithoutTrigger, `Reaction '${name}' must declare at least one trigger - nothing sets it off`, locationOf(line));\n }\n return { kind: 'ReactionSyntax', name, description, documentation, from, runsAs, where, triggers, location: locationOf(line) };\n}\n\n// What a trigger does - the events it produces and the commands it invokes - is read by name; its reads,\n// values and code are not modeled. The C# compiler remains the authority on whether what is skipped is valid.\nfunction parseTrigger(context: ParserContext, line: SourceLine, source: TriggerSourceSyntax): ReactionTriggerSyntax {\n let description: string | null = null;\n const produces: ProducesSyntax[] = [];\n const invokes: InvokesSyntax[] = [];\n const reads: ReadsSyntax[] = [];\n const data: TriggerDataSyntax[] = [];\n let implementation = false;\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 === 'runs' && isReactionIdentityLine(child)) {\n misplacedReactionIdentity(context, child);\n } else if (keyword === 'description') {\n description = parseDescription(context, child, description, `Trigger '${child.content}'`);\n } else if (keyword === 'produces') {\n const produced = parseProduces(context, child);\n if (produced !== undefined) {\n produces.push(produced);\n }\n } else if (keyword === 'invokes') {\n const match = invokesPattern.exec(child.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidInvokesDeclaration, `Invalid invokes declaration '${child.content}' - expected 'invokes <Command>'`, locationOf(child));\n context.skipBlock(child.indent);\n } else {\n const uses = new ParserContext(context.reader.fork(), context.path, context.languages);\n uses.scope = context.scope;\n uses.sourceOptions = context.sourceOptions;\n collectInputUses(uses, child);\n context.inputUses.push(...uses.inputUses);\n const mappings: PropertyMappingSyntax[] = [];\n const onRefused: InvocationRefusalSyntax[] = [];\n for (let value = context.peekChild(child.indent); value !== undefined; value = context.peekChild(child.indent)) {\n context.reader.takeSignificant();\n if (isReactionIdentityLine(value)) {\n misplacedReactionIdentity(context, value);\n continue;\n }\n if (refusalPrefix.test(value.content)) {\n const refusal = parseRefusal(context, value);\n if (refusal !== undefined) onRefused.push(refusal);\n continue;\n }\n const mapped = mappingPattern.exec(value.content);\n if (mapped !== null) mappings.push({ kind: 'PropertyMappingSyntax', property: mapped[1].replaceAll('@', ''), source: parseMappingSource(mapped[2], locationOf(value), context.valueContext), location: locationOf(value) });\n else context.error(DiagnosticCodes.InvalidPropertyMapping, `Invalid property mapping '${value.content}' - expected '<property> = <source>'`, locationOf(value));\n }\n invokes.push({ kind: 'InvokesSyntax', command: match[1], mappings, onRefused, location: locationOf(child) });\n }\n } else if (refusalPrefix.test(child.content)) {\n context.error(DiagnosticCodes.InvalidRefusalBranch, \"A refusal branch belongs inside 'invokes <Command>'.\", locationOf(child));\n context.skipBlock(child.indent);\n } else if (keyword === 'reads' || keyword === 'file' || child.content === 'csharp' || child.content.startsWith('```')) {\n implementation ||= keyword === 'file' || child.content === 'csharp' || child.content.startsWith('```');\n const read = keyword === 'reads' ? parseReads(context, child) : undefined;\n if (read !== undefined) reads.push(read);\n if (optionalReads.test(child.content)) {\n context.error(DiagnosticCodes.OptionalReadsNotSupported, 'Optional reads are not yet supported (see #308).', locationOf(child));\n }\n if (child.content.startsWith('```')) {\n context.skipFencedBody();\n }\n context.skipOpaqueBlock(child.indent);\n } else {\n const start = context.triggerData.length;\n parseTriggerData(context, child);\n for (const property of context.triggerData.slice(start)) data.push({ kind: 'TriggerDataSyntax', name: property.name, type: property.type, location: property.location });\n }\n }\n const syntax: ReactionTriggerSyntax = { kind: 'ReactionTriggerSyntax', source, description, produces, invokes, location: locationOf(line) };\n dependencySources.set(syntax, { reads, data, implementation });\n return syntax;\n}\n\nfunction parseRefusal(context: ParserContext, line: SourceLine): InvocationRefusalSyntax | undefined {\n const match = refusalHeader.exec(line.content);\n if (match === null || (match[2] !== undefined && match[1] !== 'constraint')) {\n context.error(DiagnosticCodes.InvalidRefusalBranch, \"Expected 'on refused [by validation | by constraint [<Name>] | by authorization]'.\", locationOf(line));\n context.skipBlock(line.indent);\n return undefined;\n }\n const produces: ProducesSyntax[] = [];\n let acknowledge = false;\n let reported = false;\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n if (isReactionIdentityLine(child)) {\n misplacedReactionIdentity(context, child);\n reported = true;\n } else if (child.content === 'acknowledge') {\n if (acknowledge || produces.length > 0 || context.peekChild(child.indent) !== undefined) {\n context.error(DiagnosticCodes.InvalidRefusalBranchBody, \"A refusal branch contains 'acknowledge' alone or one or more 'produces' blocks.\", locationOf(child));\n reported = true;\n }\n acknowledge = true;\n context.skipBlock(child.indent);\n } else if (firstWord(child.content) === 'produces') {\n if (acknowledge) {\n context.error(DiagnosticCodes.InvalidRefusalBranchBody, \"A refusal branch cannot combine 'acknowledge' and 'produces'.\", locationOf(child));\n reported = true;\n }\n const produced = parseProduces(context, child);\n if (produced !== undefined) produces.push(produced);\n else reported = true;\n } else {\n context.error(DiagnosticCodes.InvalidRefusalBranchBody, \"Expected 'acknowledge' or 'produces <Event>' in a refusal branch.\", locationOf(child));\n context.skipBlock(child.indent);\n reported = true;\n }\n }\n if (!acknowledge && produces.length === 0 && !reported) {\n context.error(DiagnosticCodes.InvalidRefusalBranchBody, 'A refusal branch must acknowledge or produce an event.', locationOf(line));\n }\n return { kind: 'InvocationRefusalSyntax', selector: match[1] ?? 'any', constraint: match[2] ?? null, acknowledge, produces, location: locationOf(line) };\n}\n\nfunction sourceKey(source: TriggerSourceSyntax): string {\n switch (source.kind) {\n case 'NamedTriggerSourceSyntax': return JSON.stringify([source.kind, source.name]);\n case 'IntervalTriggerSourceSyntax': return JSON.stringify([source.kind, source.amount, source.unit]);\n case 'ScheduleTriggerSourceSyntax': return JSON.stringify([source.kind, source.time, source.dayOfWeek, source.dayOfMonth]);\n }\n}\n\n// Reads a 'when', 'every' or 'at' clause - the port of the C# TriggerParser.ParseSource. The caller only\n// hands it a line starting with one of the three, so anything that is not 'when' or 'every' is 'at'.\nexport function parseTriggerSource(context: ParserContext, line: SourceLine): TriggerSourceSyntax | undefined {\n const location = locationOf(line);\n switch (firstWord(line.content)) {\n case 'when': {\n const match = whenPattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidReactionTrigger, `Invalid trigger '${line.content}' - expected 'when <Name>'`, location);\n context.skipBlock(line.indent);\n return undefined;\n }\n return { kind: 'NamedTriggerSourceSyntax', name: match[1], location };\n }\n case 'every': {\n const match = everyPattern.exec(line.content);\n const amount = match === null ? NaN : Number(match[1]);\n if (match === null || !Number.isInteger(amount) || amount < 1 || amount > 2147483647) {\n context.error(DiagnosticCodes.InvalidIntervalTrigger, `Invalid interval '${line.content}' - expected 'every <n> <seconds|minutes|hours|days>'`, location);\n context.skipBlock(line.indent);\n return undefined;\n }\n return { kind: 'IntervalTriggerSourceSyntax', amount, unit: unitOf(match[2]), location };\n }\n default:\n return parseSchedule(context, line);\n }\n}\n\nfunction parseSchedule(context: ParserContext, line: SourceLine): TriggerSourceSyntax | undefined {\n const location = locationOf(line);\n const match = atPattern.exec(line.content);\n const time = match === null ? undefined : timeOf(match[1]);\n if (match === null || time === undefined) {\n context.error(DiagnosticCodes.InvalidScheduleTrigger, `Invalid schedule '${line.content}' - expected 'at <HH:mm>', optionally followed by 'on <Weekday>' or 'on day <n>'`, location);\n context.skipBlock(line.indent);\n return undefined;\n }\n if (match[3] !== undefined) {\n const day = Number(match[3]);\n if (day < 1 || day > 31) {\n context.error(DiagnosticCodes.InvalidScheduleTrigger, `Invalid day of month '${day}' in '${line.content}' - a day of the month is between 1 and 31`, location);\n context.skipBlock(line.indent);\n return undefined;\n }\n return { kind: 'ScheduleTriggerSourceSyntax', time, dayOfWeek: null, dayOfMonth: day, location };\n }\n return { kind: 'ScheduleTriggerSourceSyntax', time, dayOfWeek: (match[2] as DayOfWeek | undefined) ?? null, dayOfMonth: null, location };\n}\n\n// 'HH:mm' as SyntaxJson writes a TimeOnly, or undefined when it is not a time of day.\nfunction timeOf(text: string): string | undefined {\n const [hours, minutes] = text.split(':').map(Number);\n if (!(hours >= 0 && hours <= 23 && minutes >= 0 && minutes <= 59)) {\n return undefined;\n }\n return `${text}:00.0000000`;\n}\n\nfunction unitOf(text: string): IntervalUnit {\n switch (text.replace(/s+$/, '')) {\n case 'second':\n return 'Seconds';\n case 'minute':\n return 'Minutes';\n case 'hour':\n return 'Hours';\n default:\n return 'Days';\n }\n}\n"],"mappings":"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"}
|
|
@@ -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{ScreenplaySyntaxWalker as n}from"../Syntax/ScreenplaySyntaxWalker.js";function validateReadModelKeys(r,i){let a=new t(r).slices.flatMap(({slice:e})=>e.readModels),o=new Set(a.flatMap(e=>e.properties));class KeyOwners extends n{visitProperty(t){t.isKey&&!o.has(t)&&i.error(e.InvalidReadModelKey,`The key modifier is only valid on top-level read-model properties.`,t.location),super.visitProperty(t)}}new KeyOwners().visitApplication(r);for(let t of a){let n=t.properties.filter(e=>e.isKey),a=/* @__PURE__ */ new Set;for(let t of n)a.has(t.name)&&i.error(e.InvalidReadModelKey,`Read-model key part '${t.name}' must be declared exactly once.`,t.location),a.add(t.name);for(let t of n)n.length>1&&r.types.filter(e=>e.name===t.type.name).length===1&&i.error(e.InvalidReadModelKey,`A read-model key part must be required and noncollection, cannot combine modifiers, and a multipart key must have scalar parts.`,t.location)}}export{validateReadModelKeys};
|
|
2
|
+
//# sourceMappingURL=ReadModelKeyValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReadModelKeyValidator.js","names":["models","AuthoringProductionResolver","application","slice","allowed","model","ScreenplaySyntaxWalker","syntax","context","DiagnosticCodes","keys","property","names","type"],"sources":["../../../../../../Compiler/Parsing/ReadModelKeyValidator.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 { PropertySyntax } from '../Syntax/Declarations';\nimport { ScreenplaySyntaxWalker } from '../Syntax/ScreenplaySyntaxWalker';\nimport { ApplicationSyntax } from '../Syntax/Structure';\nimport { ParserContext } from './ParserContext';\n\n// Only key-owner and property-shape checks are shared. Lookup resolution remains C# only.\nexport function validateReadModelKeys(application: ApplicationSyntax, context: ParserContext): void {\n const models = new AuthoringProductionResolver(application).slices.flatMap(({ slice }) => slice.readModels);\n const allowed = new Set(models.flatMap(model => model.properties));\n class KeyOwners extends ScreenplaySyntaxWalker {\n visitProperty(syntax: PropertySyntax): void {\n if (syntax.isKey && !allowed.has(syntax)) {\n context.error(DiagnosticCodes.InvalidReadModelKey, 'The key modifier is only valid on top-level read-model properties.', syntax.location);\n }\n super.visitProperty(syntax);\n }\n }\n new KeyOwners().visitApplication(application);\n for (const model of models) {\n const keys = model.properties.filter(property => property.isKey);\n const names = new Set<string>();\n for (const property of keys) {\n if (names.has(property.name)) context.error(DiagnosticCodes.InvalidReadModelKey, `Read-model key part '${property.name}' must be declared exactly once.`, property.location);\n names.add(property.name);\n }\n for (const property of keys) {\n if (keys.length > 1 && application.types.filter(type => type.name === property.type.name).length === 1) {\n context.error(DiagnosticCodes.InvalidReadModelKey, 'A read-model key part must be required and noncollection, cannot combine modifiers, and a multipart key must have scalar parts.', property.location);\n }\n }\n }\n}\n"],"mappings":"6RAWA,SAAgB,sBAAsB,EAAgC,EAA8B,CAChG,IAAMA,EAAS,IAAIC,EAA4BC,CAAW,CAAC,CAAC,OAAO,SAAS,CAAE,WAAYC,EAAM,UAAU,EACpGC,EAAU,IAAI,IAAIJ,EAAO,QAAQ,GAASK,EAAM,UAAU,CAAC,EACjE,MAAM,kBAAkBC,CAAuB,CAC3C,cAAc,EAA8B,CACpCC,EAAO,OAAS,CAACH,EAAQ,IAAIG,CAAM,GACnCC,EAAQ,MAAMC,EAAgB,oBAAqB,qEAAsEF,EAAO,QAAQ,EAE5I,MAAM,cAAcA,CAAM,CAC9B,CACJ,CACA,IAAI,UAAU,CAAC,CAAC,iBAAiBL,CAAW,EAC5C,IAAK,IAAMG,KAASL,EAAQ,CACxB,IAAMU,EAAOL,EAAM,WAAW,OAAO,GAAYM,EAAS,KAAK,EACzDC,kBAAQ,IAAI,IAClB,IAAK,IAAMD,KAAYD,EACfE,EAAM,IAAID,EAAS,IAAI,GAAGH,EAAQ,MAAMC,EAAgB,oBAAqB,wBAAwBE,EAAS,KAAK,kCAAmCA,EAAS,QAAQ,EAC3KC,EAAM,IAAID,EAAS,IAAI,EAE3B,IAAK,IAAMA,KAAYD,EACfA,EAAK,OAAS,GAAKR,EAAY,MAAM,OAAO,GAAQW,EAAK,OAASF,EAAS,KAAK,IAAI,CAAC,CAAC,SAAW,GACjGH,EAAQ,MAAMC,EAAgB,oBAAqB,kIAAmIE,EAAS,QAAQ,CAGnN,CACJ"}
|
|
@@ -0,0 +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{captureReads as i}from"./DependencySourceParser.js";const a=t(`^([a-z_]\\w*)\\s*=\\s*(.+)$`);function parseReads(t,o){let s=i(o);if(s===void 0){t.skipOpaqueBlock(o.indent);return}let c=[],l=!1;for(let i=t.peekChild(o.indent);i!==void 0;i=t.peekChild(o.indent))if(t.reader.takeSignificant(),i.content!==`by`||l||s.by!==null)t.error(e.ReadsWithChildren,`A reads line allows only one by child block, without a single by value.`,n(i)),t.skipBlock(i.indent);else{l=!0;for(let o=t.peekChild(i.indent);o!==void 0;o=t.peekChild(i.indent)){t.reader.takeSignificant();let i=a.exec(o.content);if(i===null){t.error(e.InvalidReadModelKeyLookup,`A reads by part must be '<part> = <source>'.`,n(o)),t.skipBlock(o.indent);continue}let s=o.content.indexOf(`=`)+1,l=s+o.content.substring(s).length-o.content.substring(s).trimStart().length;c.push({kind:`PropertyMappingSyntax`,property:i[1],source:r(i[2],{...n(o),column:o.indent+1+l},t.valueContext),location:n(o)})}}return l&&(c.length<2||new Set(c.map(e=>e.property)).size!==c.length)&&t.error(e.InvalidReadModelKeyLookup,`A reads by block requires at least two distinct named key parts.`,n(o)),{...s,...l?{byParts:c}:{}}}export{parseReads};
|
|
2
|
+
//# sourceMappingURL=ReadsParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReadsParser.js","names":["partPattern","pattern","read","captureReads","line","context","parts","hasBlock","child","DiagnosticCodes","locationOf","part","match","offset","sourceOffset","parseMappingSource"],"sources":["../../../../../../Compiler/Parsing/ReadsParser.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 { PropertyMappingSyntax } from '../Syntax/Expressions';\nimport { ReadsSyntax } from '../Syntax/ReadsSyntax';\nimport { pattern } from '../Text/patterns';\nimport { captureReads } from './DependencySourceParser';\nimport { parseMappingSource } from './ExpressionParser';\nimport { ParserContext } from './ParserContext';\nimport { locationOf, SourceLine } from './SourceLine';\n\nconst partPattern = pattern('^([a-z_]\\\\w*)\\\\s*=\\\\s*(.+)$');\n\nexport function parseReads(context: ParserContext, line: SourceLine): ReadsSyntax | undefined {\n const read = captureReads(line);\n if (read === undefined) {\n context.skipOpaqueBlock(line.indent);\n return undefined;\n }\n const parts: PropertyMappingSyntax[] = [];\n let hasBlock = false;\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n if (child.content !== 'by' || hasBlock || read.by !== null) {\n context.error(DiagnosticCodes.ReadsWithChildren, 'A reads line allows only one by child block, without a single by value.', locationOf(child));\n context.skipBlock(child.indent);\n continue;\n }\n hasBlock = true;\n for (let part = context.peekChild(child.indent); part !== undefined; part = context.peekChild(child.indent)) {\n context.reader.takeSignificant();\n const match = partPattern.exec(part.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidReadModelKeyLookup, \"A reads by part must be '<part> = <source>'.\", locationOf(part));\n context.skipBlock(part.indent);\n continue;\n }\n const offset = part.content.indexOf('=') + 1;\n const sourceOffset = offset + part.content.substring(offset).length - part.content.substring(offset).trimStart().length;\n parts.push({ kind: 'PropertyMappingSyntax', property: match[1], source: parseMappingSource(match[2], { ...locationOf(part), column: part.indent + 1 + sourceOffset }, context.valueContext), location: locationOf(part) });\n }\n }\n if (hasBlock && (parts.length < 2 || new Set(parts.map(part => part.property)).size !== parts.length)) {\n context.error(DiagnosticCodes.InvalidReadModelKeyLookup, 'A reads by block requires at least two distinct named key parts.', locationOf(line));\n }\n return { ...read, ...(hasBlock ? { byParts: parts } : {}) };\n}\n"],"mappings":"0UAYA,MAAMA,EAAcC,EAAQ,6BAA6B,EAEzD,SAAgB,WAAW,EAAwB,EAA2C,CAC1F,IAAMC,EAAOC,EAAaC,CAAI,EAC9B,GAAIF,IAAS,IAAA,GAAW,CACpBG,EAAQ,gBAAgBD,EAAK,MAAM,EACnC,MACJ,CACA,IAAME,EAAiC,CAAC,EACpCC,EAAW,GACf,IAAK,IAAIC,EAAQH,EAAQ,UAAUD,EAAK,MAAM,EAAGI,IAAU,IAAA,GAAW,EAAQH,EAAQ,UAAUD,EAAK,MAAM,EAEvG,GADAC,EAAQ,OAAO,gBAAgB,EAC3BG,EAAM,UAAY,MAAQD,GAAYL,EAAK,KAAO,KAClDG,EAAQ,MAAMI,EAAgB,kBAAmB,0EAA2EC,EAAWF,CAAK,CAAC,EAC7IH,EAAQ,UAAUG,EAAM,MAAM,MAGlC,GAAW,GACX,IAAK,IAAIG,EAAON,EAAQ,UAAUG,EAAM,MAAM,EAAGG,IAAS,IAAA,GAAW,EAAON,EAAQ,UAAUG,EAAM,MAAM,EAAG,CACzGH,EAAQ,OAAO,gBAAgB,EAC/B,IAAMO,EAAQZ,EAAY,KAAKW,EAAK,OAAO,EAC3C,GAAIC,IAAU,KAAM,CAChBP,EAAQ,MAAMI,EAAgB,0BAA2B,+CAAgDC,EAAWC,CAAI,CAAC,EACzHN,EAAQ,UAAUM,EAAK,MAAM,EAC7B,QACJ,CACA,IAAME,EAASF,EAAK,QAAQ,QAAQ,GAAG,EAAI,EACrCG,EAAeD,EAASF,EAAK,QAAQ,UAAUE,CAAM,CAAC,CAAC,OAASF,EAAK,QAAQ,UAAUE,CAAM,CAAC,CAAC,UAAU,CAAC,CAAC,OACjHP,EAAM,KAAK,CAAE,KAAM,wBAAyB,SAAUM,EAAM,GAAI,OAAQG,EAAmBH,EAAM,GAAI,CAAE,GAAGF,EAAWC,CAAI,EAAG,OAAQA,EAAK,OAAS,EAAIG,CAAa,EAAGT,EAAQ,YAAY,EAAG,SAAUK,EAAWC,CAAI,CAAE,CAAC,CAC7N,CAZW,CAiBf,OAHIJ,IAAaD,EAAM,OAAS,GAAK,IAAI,IAAIA,EAAM,IAAI,GAAQK,EAAK,QAAQ,CAAC,CAAC,CAAC,OAASL,EAAM,SAC1FD,EAAQ,MAAMI,EAAgB,0BAA2B,mEAAoEC,EAAWN,CAAI,CAAC,EAE1I,CAAE,GAAGF,EAAM,GAAIK,EAAW,CAAE,QAASD,CAAM,EAAI,CAAC,CAAG,CAC9D"}
|
|
@@ -1,2 +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{EventSourceCatalog as n}from"../Syntax/EventSourceCatalog.js";import{expandEffectiveSpecificationExamples as r,specificationExamples as i}from"./SpecificationCommandExamples.js";import{compatibleValue as a,uniqueByName as o}from"./ResponseValidator.js";import{commandDestinationType as s}from"./CommandDestinationTypes.js";import{LineReader as c}from"./LineReader.js";import{ParserContext as l}from"./ParserContext.js";import{streamIdFailureMessage as u}from"../Syntax/StreamIdFormatter.js";import{validateStreamIdParts as d}from"./CompositeStreamIdValidator.js";import{formatSpecificationStreamId as f}from"./SpecificationRouteComparison.js";import{formatStreamIdLiteral as p}from"./EventSourceValidator.js";function validateSpecificationStreams(n,r){let i=new t(n).slices.flatMap(({slice:e})=>e.specifications.flatMap(e=>e.cases??[]));if(i.length===0)return validateRoutes(n,r);let a=new l(new c([]));validateRoutes(n,a);let o=/* @__PURE__ */ new Set,s=/* @__PURE__ */ new Set;for(let t of a.diagnostics){let n=JSON.stringify([t.code,t.location.path,t.location.line,t.location.column,t.message]);if(s.has(n))continue;s.add(n);let a=t.code===e.InvalidSpecificationStreamRoute?i.find(e=>e.values.some(e=>e.source.location.line===t.location.line&&e.source.location.column===t.location.column&&e.source.location.path===t.location.path)):void 0;if(a===void 0)r.error(t.code,t.message,t.location);else{let e=JSON.stringify(t.location);o.has(e)||r.error(t.code,`Case '${a.name}': ${t.message}`,t.location),o.add(e)}}}function validateRoutes(c,l){let m=i(c).resolvedExamples,h=r(c);c=h.application;let g=new t(c),_=/* @__PURE__ */ new Set,v=m.flatMap(t=>{if(t.kind!==`event`)return(t.kind===`command`||t.kind===`readmodel`)&&(t.example.stream!=null||t.example.noStream!=null)&&l.error(e.InvalidSpecificationExampleBody,`only event examples carry routes; a command's route comes from its declaration, and read models have none`,(t.example.stream??t.example.noStream).location),[];let n={kind:`SpecificationEventSyntax`,eventType:t.name,values:t.example.values,for:t.example.for,stream:t.example.stream,noStream:t.example.noStream,location:t.example.location};return _.add(n),[{scope:t.scope,specification:{when:null,given:[],whenAppended:null,thenEvents:[n],whenRedelivered:null}}]}),y=new n(c),b=o(c.concepts),x=o(c.types),S=new Map([...x].map(([e,t])=>[e,o(t.properties)])),compatible=(e,t)=>a(e,t,b,S),C=/* @__PURE__ */ new Set([`String`,`Uuid`,`Int`,`Decimal`,`Bool`,`Date`,`DateTime`,...b.keys(),...x.keys()]),nominallyCompatible=(e,t)=>C.has(e.name)&&C.has(t.name)?e.name===t.name&&e.isCollection===t.isCollection&&(!e.isOptional||t.isOptional):null,formatStreamId=(e,t)=>f(e,t,c),eventOf=(e,t)=>{let n=g.resolve(e,t).declaration;return n?.node.kind===`EventSyntax`?n.node:null},w=[];for(let{slice:e}of g.slices){for(let t of e.commands)for(let n of t.produces){if(!g.isEventProduction(n,e))continue;let r=eventOf(n.event,e);if(r===null)continue;let i=s(t,n,c,{resolver:g,slice:e});w.push({event:r,command:t,type:i})}for(let t of e.reactions.flatMap(e=>e.triggers).flatMap(e=>e.produces)){let n=eventOf(t.event,e);n!==null&&w.push({event:n,command:null,type:null})}for(let t of e.captures)for(let n of[...t.appends,...t.children.flatMap(e=>e.appends),...t.nested.flatMap(e=>e.appends)]){let t=eventOf(n.event,e);t!==null&&w.push({event:t,command:null,type:null})}}let T=[...v.flatMap(e=>g.slices.filter(t=>t.scope.join(`.`)===e.scope.join(`.`)).map(({slice:t,scope:n})=>({slice:t,scope:n,specification:e.specification}))),...g.slices.flatMap(({slice:e,scope:t})=>e.specifications.map(n=>({slice:e,scope:t,specification:n})))];for(let{slice:t,scope:n,specification:r}of T){let i=g.slices.flatMap(e=>e.slice.commands.map(t=>({command:t,scope:e.scope}))),a=r.when?.commandType.split(`.`)??[],o=a.slice(0,-1),s=i.filter(e=>e.command.name===a.at(-1)&&o.every((t,n)=>e.scope[e.scope.length-o.length+n]===t)),f=o.length>0&&s.length===1?s[0].command:null;for(let e=n.length;o.length===0&&e>=0&&f===null;e--){let t=s.filter(t=>n.slice(0,e).every((e,n)=>t.scope[n]===e));if(t.length>0){f=t.length===1?t[0].command:null;break}}let m=[...r.given.map(e=>({node:e,required:!0,expected:!1})),...r.whenAppended===null?[]:[{node:r.whenAppended,required:!0,expected:!1}],...r.thenEvents.map(e=>({node:e,required:!1,expected:!_.has(e)})),...r.whenRedelivered==null?[]:[{node:{...r.whenRedelivered,kind:`SpecificationEventSyntax`},required:!1,expected:!1}]];for(let{node:n,required:r,expected:i}of m){let a=h.specifications.flatMap(e=>e.steps).find(e=>e.effective===n),o=a?.route?.origin!==`example`,s=o||n.for!==a?.example?.for,contextualError=(e,t,n)=>{l.error(e,a?.example==null?t:`${t} Example '${a.example.name}' is used here.`,a?.example==null?n:a.authored.location)};if(n.stream==null&&n.noStream==null)continue;r&&n.noStream!=null&&contextualError(e.InvalidSpecificationStream,`Expected 'stream Source.Stream', or 'no stream' on a then event.`,n.noStream.location);let m=null,g=eventOf(n.eventType,t),_=w.filter(e=>e.event===g);if(n.stream!=null){let t=n.stream,i=y.resolve(t.eventSource,t.stream);if(i.kind!==`unique`){let n={ambiguous:`Ambiguous`,notFound:`NotFound`,wrongKind:`WrongKind`}[i.kind];o&&l.error(e.InvalidSpecificationStreamRoute,`Stream '${t.eventSource}.${t.stream}' is ${n}; routing requires one physical source and stream.`,t.location);continue}let f=i.sources[0],h=i.streams[0],validateLiteral=(t,n)=>{let r=t.source,i=p(r,n,c);i?.failure==null?(r.kind!==`LiteralExpressionSyntax`||r.value===null||n!==null&&!compatible(r,n))&&l.error(e.InvalidSpecificationStreamRoute,`A specification stream id needs a nonempty concrete scalar literal compatible with the stream's declared type.`,r.location):l.error(e.InvalidSpecificationStreamRoute,u(i.failure),r.location)};if(o&&(h.streamIdParts.length>0?d(h,t.streamIdParts,t.streamId!==null,t.location,e.InvalidSpecificationStreamRoute,l,validateLiteral):t.streamIdParts.length>0?l.error(e.InvalidSpecificationStreamRoute,`A streamId part block requires a composite stream.`,t.location):(h.streamId===null!=(t.streamId===null)&&l.error(e.InvalidSpecificationStreamRoute,h.streamId===null?`An unkeyed stream cannot take a streamId mapping.`:`This keyed stream requires a streamId mapping.`,t.location),t.streamId!==null&&validateLiteral(t.streamId,h.streamId))),m=f.identifier,m===null){let n=_.map(e=>e.type),r=new Set(n.filter(e=>e!==null).map(e=>`${e.name}:${e.isOptional}:${e.isCollection}`));n.length===0||n.some(e=>e===null)||r.size!==1?o&&l.error(e.InvalidSpecificationStreamEventSource,`Declare an identifier on source '${f.name}'; the event's producers do not supply one unambiguous destination type.`,t.location):m=n[0]}let g=!1;if(a?.example?.stream!=null&&n.for!==null&&n.for===a.example.for){let e=y.resolve(a.example.stream.eventSource,a.example.stream.stream);if(e.kind===`unique`){let t=_.map(e=>e.type),r=new Set(t.filter(e=>e!==null).map(e=>`${e.name}:${e.isOptional}:${e.isCollection}`)),i=e.sources[0].identifier??(t.length>0&&!t.some(e=>e===null)&&r.size===1?t[0]:null);i!==null&&(g=n.for.kind!==`LiteralExpressionSyntax`||n.for.value===null||i.isCollection||i.isOptional||!compatible(n.for,i))}}r&&n.for===null?contextualError(e.InvalidSpecificationStreamEventSource,`A routed given or when append event requires 'for <literal>'.`,t.location):s&&!g&&n.for!==null&&(n.for.kind!==`LiteralExpressionSyntax`||n.for.value===null||m!==null&&(m.isCollection||m.isOptional||!compatible(n.for,m)))&&contextualError(e.InvalidSpecificationStreamEventSource,`A routed event's for value must be a concrete literal compatible with the source's identifier type.`,n.for.location)}if(!i||f===null||_.length===0||_.some(e=>e.command!==f))continue;let v=
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{AuthoringProductionResolver as t}from"../Syntax/AuthoringProductionResolver.js";import{EventSourceCatalog as n}from"../Syntax/EventSourceCatalog.js";import{expandEffectiveSpecificationExamples as r,specificationExamples as i}from"./SpecificationCommandExamples.js";import{compatibleValue as a,uniqueByName as o}from"./ResponseValidator.js";import{commandDestinationType as s}from"./CommandDestinationTypes.js";import{LineReader as c}from"./LineReader.js";import{ParserContext as l}from"./ParserContext.js";import{streamIdFailureMessage as u}from"../Syntax/StreamIdFormatter.js";import{validateStreamIdParts as d}from"./CompositeStreamIdValidator.js";import{formatSpecificationStreamId as f}from"./SpecificationRouteComparison.js";import{formatStreamIdLiteral as p}from"./EventSourceValidator.js";function validateSpecificationStreams(n,r){let i=new t(n).slices.flatMap(({slice:e})=>e.specifications.flatMap(e=>e.cases??[]));if(i.length===0)return validateRoutes(n,r);let a=new l(new c([]));validateRoutes(n,a);let o=/* @__PURE__ */ new Set,s=/* @__PURE__ */ new Set;for(let t of a.diagnostics){let n=JSON.stringify([t.code,t.location.path,t.location.line,t.location.column,t.message]);if(s.has(n))continue;s.add(n);let a=t.code===e.InvalidSpecificationStreamRoute?i.find(e=>e.values.some(e=>e.source.location.line===t.location.line&&e.source.location.column===t.location.column&&e.source.location.path===t.location.path)):void 0;if(a===void 0)r.error(t.code,t.message,t.location);else{let e=JSON.stringify(t.location);o.has(e)||r.error(t.code,`Case '${a.name}': ${t.message}`,t.location),o.add(e)}}}function validateRoutes(c,l){let m=i(c).resolvedExamples,h=r(c);c=h.application;let g=new t(c),_=/* @__PURE__ */ new Set,v=m.flatMap(t=>{if(t.kind!==`event`)return(t.kind===`command`||t.kind===`readmodel`)&&(t.example.stream!=null||t.example.noStream!=null)&&l.error(e.InvalidSpecificationExampleBody,`only event examples carry routes; a command's route comes from its declaration, and read models have none`,(t.example.stream??t.example.noStream).location),[];let n={kind:`SpecificationEventSyntax`,eventType:t.name,values:t.example.values,for:t.example.for,stream:t.example.stream,noStream:t.example.noStream,location:t.example.location};return _.add(n),[{scope:t.scope,specification:{when:null,given:[],whenAppended:null,thenEvents:[n],whenRedelivered:null}}]}),y=new n(c),b=o(c.concepts),x=o(c.types),S=new Map([...x].map(([e,t])=>[e,o(t.properties)])),compatible=(e,t)=>a(e,t,b,S),C=/* @__PURE__ */ new Set([`String`,`Uuid`,`Int`,`Decimal`,`Bool`,`Date`,`DateTime`,...b.keys(),...x.keys()]),nominallyCompatible=(e,t)=>C.has(e.name)&&C.has(t.name)?e.name===t.name&&e.isCollection===t.isCollection&&(!e.isOptional||t.isOptional):null,formatStreamId=(e,t)=>f(e,t,c),eventOf=(e,t)=>{let n=g.resolve(e,t).declaration;return n?.node.kind===`EventSyntax`?n.node:null},w=[];for(let{slice:e}of g.slices){for(let t of e.commands)for(let n of t.produces){if(!g.isEventProduction(n,e))continue;let r=eventOf(n.event,e);if(r===null)continue;let i=s(t,n,c,{resolver:g,slice:e});w.push({event:r,command:t,type:i,route:n.stream??t.stream})}for(let t of e.reactions.flatMap(e=>e.triggers).flatMap(e=>e.produces)){let n=eventOf(t.event,e);n!==null&&w.push({event:n,command:null,type:null})}for(let t of e.captures)for(let n of[...t.appends,...t.children.flatMap(e=>e.appends),...t.nested.flatMap(e=>e.appends)]){let t=eventOf(n.event,e);t!==null&&w.push({event:t,command:null,type:null})}}let T=[...v.flatMap(e=>g.slices.filter(t=>t.scope.join(`.`)===e.scope.join(`.`)).map(({slice:t,scope:n})=>({slice:t,scope:n,specification:e.specification}))),...g.slices.flatMap(({slice:e,scope:t})=>e.specifications.map(n=>({slice:e,scope:t,specification:n})))];for(let{slice:t,scope:n,specification:r}of T){let i=g.slices.flatMap(e=>e.slice.commands.map(t=>({command:t,scope:e.scope}))),a=r.when?.commandType.split(`.`)??[],o=a.slice(0,-1),s=i.filter(e=>e.command.name===a.at(-1)&&o.every((t,n)=>e.scope[e.scope.length-o.length+n]===t)),f=o.length>0&&s.length===1?s[0].command:null;for(let e=n.length;o.length===0&&e>=0&&f===null;e--){let t=s.filter(t=>n.slice(0,e).every((e,n)=>t.scope[n]===e));if(t.length>0){f=t.length===1?t[0].command:null;break}}let m=[...r.given.map(e=>({node:e,required:!0,expected:!1})),...r.whenAppended===null?[]:[{node:r.whenAppended,required:!0,expected:!1}],...r.thenEvents.map(e=>({node:e,required:!1,expected:!_.has(e)})),...r.whenRedelivered==null?[]:[{node:{...r.whenRedelivered,kind:`SpecificationEventSyntax`},required:!1,expected:!1}]];for(let{node:n,required:r,expected:i}of m){let a=h.specifications.flatMap(e=>e.steps).find(e=>e.effective===n),o=a?.route?.origin!==`example`,s=o||n.for!==a?.example?.for,contextualError=(e,t,n)=>{l.error(e,a?.example==null?t:`${t} Example '${a.example.name}' is used here.`,a?.example==null?n:a.authored.location)};if(n.stream==null&&n.noStream==null)continue;r&&n.noStream!=null&&contextualError(e.InvalidSpecificationStream,`Expected 'stream Source.Stream', or 'no stream' on a then event.`,n.noStream.location);let m=null,g=eventOf(n.eventType,t),_=w.filter(e=>e.event===g);if(n.stream!=null){let t=n.stream,i=y.resolve(t.eventSource,t.stream);if(i.kind!==`unique`){let n={ambiguous:`Ambiguous`,notFound:`NotFound`,wrongKind:`WrongKind`}[i.kind];o&&l.error(e.InvalidSpecificationStreamRoute,`Stream '${t.eventSource}.${t.stream}' is ${n}; routing requires one physical source and stream.`,t.location);continue}let f=i.sources[0],h=i.streams[0],validateLiteral=(t,n)=>{let r=t.source,i=p(r,n,c);i?.failure==null?(r.kind!==`LiteralExpressionSyntax`||r.value===null||n!==null&&!compatible(r,n))&&l.error(e.InvalidSpecificationStreamRoute,`A specification stream id needs a nonempty concrete scalar literal compatible with the stream's declared type.`,r.location):l.error(e.InvalidSpecificationStreamRoute,u(i.failure),r.location)};if(o&&(h.streamIdParts.length>0?d(h,t.streamIdParts,t.streamId!==null,t.location,e.InvalidSpecificationStreamRoute,l,validateLiteral):t.streamIdParts.length>0?l.error(e.InvalidSpecificationStreamRoute,`A streamId part block requires a composite stream.`,t.location):(h.streamId===null!=(t.streamId===null)&&l.error(e.InvalidSpecificationStreamRoute,h.streamId===null?`An unkeyed stream cannot take a streamId mapping.`:`This keyed stream requires a streamId mapping.`,t.location),t.streamId!==null&&validateLiteral(t.streamId,h.streamId))),m=f.identifier,m===null){let n=_.map(e=>e.type),r=new Set(n.filter(e=>e!==null).map(e=>`${e.name}:${e.isOptional}:${e.isCollection}`));n.length===0||n.some(e=>e===null)||r.size!==1?o&&l.error(e.InvalidSpecificationStreamEventSource,`Declare an identifier on source '${f.name}'; the event's producers do not supply one unambiguous destination type.`,t.location):m=n[0]}let g=!1;if(a?.example?.stream!=null&&n.for!==null&&n.for===a.example.for){let e=y.resolve(a.example.stream.eventSource,a.example.stream.stream);if(e.kind===`unique`){let t=_.map(e=>e.type),r=new Set(t.filter(e=>e!==null).map(e=>`${e.name}:${e.isOptional}:${e.isCollection}`)),i=e.sources[0].identifier??(t.length>0&&!t.some(e=>e===null)&&r.size===1?t[0]:null);i!==null&&(g=n.for.kind!==`LiteralExpressionSyntax`||n.for.value===null||i.isCollection||i.isOptional||!compatible(n.for,i))}}r&&n.for===null?contextualError(e.InvalidSpecificationStreamEventSource,`A routed given or when append event requires 'for <literal>'.`,t.location):s&&!g&&n.for!==null&&(n.for.kind!==`LiteralExpressionSyntax`||n.for.value===null||m!==null&&(m.isCollection||m.isOptional||!compatible(n.for,m)))&&contextualError(e.InvalidSpecificationStreamEventSource,`A routed event's for value must be a concrete literal compatible with the source's identifier type.`,n.for.location)}if(!i||f===null||_.length===0||_.some(e=>e.command!==f))continue;let v=_.every(e=>{let t=e.route?.propertyCandidate===null?e.route:null,r=n.noStream==null?t==null||t.eventSource!==n.stream.eventSource||t.stream!==n.stream.stream:t!=null;if(!r&&n.stream!=null&&t!=null){let e=y.resolve(n.stream.eventSource,n.stream.stream),i=e.kind===`unique`?e.streams[0]:null;if(i!==null&&i.streamIdParts.length>0){if(t.streamId===null&&n.stream.streamId===null&&t.streamIdParts.length>0&&n.stream.streamIdParts.length>0)for(let e of i.streamIdParts){let i=t.streamIdParts.filter(t=>t.property===e.name),a=n.stream.streamIdParts.filter(t=>t.property===e.name);if(i.length!==1||a.length!==1)continue;let o=formatStreamId(i[0].source,e.type),s=formatStreamId(a[0].source,e.type);o!==null&&s!==null&&o!==s&&(r=!0)}}else if(i?.streamId!=null&&t.streamIdParts.length===0&&n.stream.streamIdParts.length===0){let e=formatStreamId(t.streamId?.source,i.streamId),a=formatStreamId(n.stream.streamId?.source,i.streamId);e!==null&&a!==null&&e!==a&&(r=!0)}}return r});n.for?.kind===`LiteralExpressionSyntax`&&_.every(e=>e.type!==null&&(m===null?!compatible(n.for,e.type):nominallyCompatible(e.type,m)===!1))&&(v=!0),v&&contextualError(e.SpecificationStreamContradictsCommand,`The expected event route contradicts its only producer, the command under test.`,(n.stream??n.noStream).location)}}}export{validateSpecificationStreams};
|
|
2
2
|
//# sourceMappingURL=SpecificationStreamValidator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpecificationStreamValidator.js","names":["rows","AuthoringProductionResolver","application","slice","specification","context","sink","ParserContext","LineReader","reported","distinct","diagnostic","key","row","DiagnosticCodes","value","examples","specificationExamples","expansion","expandEffectiveSpecificationExamples","resolver","declarationSteps","exampleSpecifications","entry","node","catalog","EventSourceCatalog","concepts","uniqueByName","composites","properties","name","type","compatibleValue","known","source","target","formatSpecificationStreamId","expression","declared","reference","producers","command","produced","event","commandDestinationType","reaction","trigger","capture","appended","child","nested","validationSpecifications","owner","commands","parts","qualifiers","candidates","index","segment","depth","scope","visible","occurrences","step","pair","validateRoute","validateFor","code","message","location","required","identifier","eventProducers","producer","route","resolution","state","stream","mapping","formatted","formatStreamIdLiteral","streamIdFailureMessage","validateStreamIdParts","types","inheritedIdentityIsInvalid","prior","priorIdentifier","expected","commandRoute","contradicts","part","actual","actualId","expectedId"],"sources":["../../../../../../Compiler/Parsing/SpecificationStreamValidator.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 { CommandSyntax } from '../Syntax/Commands';\nimport { EventSyntax, TypeRefSyntax } from '../Syntax/Declarations';\nimport { EventSourceCatalog } from '../Syntax/EventSourceCatalog';\nimport { EventSourceResolutionKind } from '../Syntax/EventSources';\nimport { formatSpecificationStreamId } from './SpecificationRouteComparison';\nimport { streamIdFailureMessage } from '../Syntax/StreamIdFormatter';\nimport { ExpressionSyntax } from '../Syntax/Expressions';\nimport { commandDestinationType } from './CommandDestinationTypes';\nimport { formatStreamIdLiteral } from './EventSourceValidator';\nimport { ApplicationSyntax } from '../Syntax/Structure';\nimport { PropertyMappingSyntax } from '../Syntax/Expressions';\nimport { validateStreamIdParts } from './CompositeStreamIdValidator';\nimport { ParserContext } from './ParserContext';\nimport { LineReader } from './LineReader';\nimport { compatibleValue, uniqueByName } from './ResponseValidator';\nimport { expandEffectiveSpecificationExamples, specificationExamples } from './SpecificationCommandExamples';\nimport { SpecificationEventSyntax } from '../Syntax/Specifications';\n\ninterface Producer { event: EventSyntax; command: CommandSyntax | null; type: TypeRefSyntax | null }\n\nexport function validateSpecificationStreams(application: ApplicationSyntax, context: ParserContext): void {\n const rows = new AuthoringProductionResolver(application).slices.flatMap(({ slice }) => slice.specifications.flatMap(specification => specification.cases ?? []));\n if (rows.length === 0) return validateRoutes(application, context);\n const sink = new ParserContext(new LineReader([]));\n validateRoutes(application, sink);\n const reported = new Set<string>();\n const distinct = new Set<string>();\n for (const diagnostic of sink.diagnostics) {\n const key = JSON.stringify([diagnostic.code, diagnostic.location.path, diagnostic.location.line, diagnostic.location.column, diagnostic.message]);\n if (distinct.has(key)) continue;\n distinct.add(key);\n const row = diagnostic.code === DiagnosticCodes.InvalidSpecificationStreamRoute ? rows.find(row => row.values.some(value => value.source.location.line === diagnostic.location.line && value.source.location.column === diagnostic.location.column && value.source.location.path === diagnostic.location.path)) : undefined;\n if (row === undefined) context.error(diagnostic.code, diagnostic.message, diagnostic.location);\n else {\n const key = JSON.stringify(diagnostic.location);\n if (!reported.has(key)) context.error(diagnostic.code, `Case '${row.name}': ${diagnostic.message}`, diagnostic.location);\n reported.add(key);\n }\n }\n}\n\nfunction validateRoutes(application: ApplicationSyntax, context: ParserContext): void {\n const examples = specificationExamples(application).resolvedExamples;\n const expansion = expandEffectiveSpecificationExamples(application);\n application = expansion.application;\n const resolver = new AuthoringProductionResolver(application);\n const declarationSteps = new Set<SpecificationEventSyntax>();\n const exampleSpecifications = examples.flatMap(entry => {\n if (entry.kind !== 'event') {\n if ((entry.kind === 'command' || entry.kind === 'readmodel') && (entry.example.stream != null || entry.example.noStream != null))\n context.error(DiagnosticCodes.InvalidSpecificationExampleBody, \"only event examples carry routes; a command's route comes from its declaration, and read models have none\", (entry.example.stream ?? entry.example.noStream)!.location);\n return [];\n }\n const node: SpecificationEventSyntax = { kind: 'SpecificationEventSyntax', eventType: entry.name, values: entry.example.values, for: entry.example.for, stream: entry.example.stream, noStream: entry.example.noStream, location: entry.example.location };\n declarationSteps.add(node);\n return [{ scope: entry.scope, specification: { when: null, given: [], whenAppended: null, thenEvents: [node], whenRedelivered: null } }];\n });\n const catalog = new EventSourceCatalog(application);\n const concepts = uniqueByName(application.concepts);\n const composites = uniqueByName(application.types);\n const properties = new Map([...composites].map(([name, type]) => [name, uniqueByName(type.properties)]));\n const compatible = (value: Parameters<typeof compatibleValue>[0], type: TypeRefSyntax): boolean => compatibleValue(value, type, concepts, properties);\n const known = new Set(['String', 'Uuid', 'Int', 'Decimal', 'Bool', 'Date', 'DateTime', ...concepts.keys(), ...composites.keys()]);\n const nominallyCompatible = (source: TypeRefSyntax, target: TypeRefSyntax): boolean | null => known.has(source.name) && known.has(target.name)\n ? source.name === target.name && source.isCollection === target.isCollection && (!source.isOptional || target.isOptional) : null;\n const formatStreamId = (expression: ExpressionSyntax | null | undefined, type: TypeRefSyntax): string | null => formatSpecificationStreamId(expression, type, application);\n const eventOf = (reference: string, slice: typeof resolver.slices[number]['slice']): EventSyntax | null => {\n const declared = resolver.resolve(reference, slice).declaration;\n return declared?.node.kind === 'EventSyntax' ? declared.node : null;\n };\n const producers: Producer[] = [];\n for (const { slice } of resolver.slices) {\n for (const command of slice.commands) for (const produced of command.produces) {\n if (!resolver.isEventProduction(produced, slice)) continue;\n const event = eventOf(produced.event, slice);\n if (event === null) continue;\n const type = commandDestinationType(command, produced, application, { resolver, slice });\n producers.push({ event, command, type });\n }\n for (const produced of slice.reactions.flatMap(reaction => reaction.triggers).flatMap(trigger => trigger.produces)) {\n const event = eventOf(produced.event, slice);\n if (event !== null) producers.push({ event, command: null, type: null });\n }\n for (const capture of slice.captures) for (const appended of [...capture.appends, ...capture.children.flatMap(child => child.appends), ...capture.nested.flatMap(nested => nested.appends)]) {\n const event = eventOf(appended.event, slice);\n if (event !== null) producers.push({ event, command: null, type: null });\n }\n }\n const validationSpecifications = [\n ...exampleSpecifications.flatMap(entry => resolver.slices.filter(owner => owner.scope.join('.') === entry.scope.join('.')).map(({ slice, scope }) => ({ slice, scope, specification: entry.specification }))),\n ...resolver.slices.flatMap(({ slice, scope }) => slice.specifications.map(specification => ({ slice, scope, specification })))\n ];\n for (const { slice, scope, specification } of validationSpecifications) {\n const commands = resolver.slices.flatMap(entry => entry.slice.commands.map(command => ({ command, scope: entry.scope })));\n const parts = specification.when?.commandType.split('.') ?? [];\n const qualifiers = parts.slice(0, -1);\n const candidates = commands.filter(entry => entry.command.name === parts.at(-1) && qualifiers.every((segment, index) => entry.scope[entry.scope.length - qualifiers.length + index] === segment));\n let command: CommandSyntax | null = qualifiers.length > 0 && candidates.length === 1 ? candidates[0].command : null;\n for (let depth = scope.length; qualifiers.length === 0 && depth >= 0 && command === null; depth--) {\n const visible = candidates.filter(entry => scope.slice(0, depth).every((segment, index) => entry.scope[index] === segment));\n if (visible.length > 0) { command = visible.length === 1 ? visible[0].command : null; break; }\n }\n const occurrences = [...specification.given.map(node => ({ node, required: true, expected: false })),\n ...(specification.whenAppended === null ? [] : [{ node: specification.whenAppended, required: true, expected: false }]),\n ...specification.thenEvents.map(node => ({ node, required: false, expected: !declarationSteps.has(node) })),\n ...(specification.whenRedelivered == null ? [] : [{ node: { ...specification.whenRedelivered, kind: 'SpecificationEventSyntax' as const }, required: false, expected: false }])];\n for (const { node, required, expected } of occurrences) {\n const step = expansion.specifications.flatMap(pair => pair.steps).find(step => step.effective === node);\n const validateRoute = step?.route?.origin !== 'example';\n const validateFor = validateRoute || node.for !== step?.example?.for;\n const contextualError = (code: string, message: string, location: typeof node.location): void => {\n context.error(code, step?.example == null ? message : `${message} Example '${step.example.name}' is used here.`, step?.example == null ? location : step.authored.location);\n };\n if (node.stream == null && node.noStream == null) continue;\n if (required && node.noStream != null)\n contextualError(DiagnosticCodes.InvalidSpecificationStream, \"Expected 'stream Source.Stream', or 'no stream' on a then event.\", node.noStream.location);\n let identifier: TypeRefSyntax | null = null;\n const event = eventOf(node.eventType, slice);\n const eventProducers = producers.filter(producer => producer.event === event);\n if (node.stream != null) {\n const route = node.stream;\n const resolution = catalog.resolve(route.eventSource, route.stream);\n if (resolution.kind !== EventSourceResolutionKind.Unique) {\n const state = { ambiguous: 'Ambiguous', notFound: 'NotFound', wrongKind: 'WrongKind' }[resolution.kind];\n if (validateRoute) context.error(DiagnosticCodes.InvalidSpecificationStreamRoute, `Stream '${route.eventSource}.${route.stream}' is ${state}; routing requires one physical source and stream.`, route.location);\n continue;\n }\n const source = resolution.sources[0];\n const stream = resolution.streams[0];\n const validateLiteral = (mapping: PropertyMappingSyntax, target: TypeRefSyntax | null): void => {\n const value = mapping.source;\n const formatted = formatStreamIdLiteral(value, target, application);\n if (formatted?.failure != null) context.error(DiagnosticCodes.InvalidSpecificationStreamRoute, streamIdFailureMessage(formatted.failure), value.location);\n else if (value.kind !== 'LiteralExpressionSyntax' || value.value === null || target !== null && !compatible(value, target))\n context.error(DiagnosticCodes.InvalidSpecificationStreamRoute, \"A specification stream id needs a nonempty concrete scalar literal compatible with the stream's declared type.\", value.location);\n };\n if (!validateRoute) { /* The authored example's route is checked once at its declaration. */ }\n else if (stream.streamIdParts.length > 0)\n validateStreamIdParts(stream, route.streamIdParts, route.streamId !== null, route.location, DiagnosticCodes.InvalidSpecificationStreamRoute, context, validateLiteral);\n else if (route.streamIdParts.length > 0)\n context.error(DiagnosticCodes.InvalidSpecificationStreamRoute, 'A streamId part block requires a composite stream.', route.location);\n else {\n if ((stream.streamId === null) !== (route.streamId === null))\n context.error(DiagnosticCodes.InvalidSpecificationStreamRoute, stream.streamId === null ? 'An unkeyed stream cannot take a streamId mapping.' : 'This keyed stream requires a streamId mapping.', route.location);\n if (route.streamId !== null) validateLiteral(route.streamId, stream.streamId);\n }\n identifier = source.identifier;\n if (identifier === null) {\n const types = eventProducers.map(producer => producer.type);\n const distinct = new Set(types.filter(type => type !== null).map(type => `${type.name}:${type.isOptional}:${type.isCollection}`));\n if (types.length === 0 || types.some(type => type === null) || distinct.size !== 1) {\n if (validateRoute) context.error(DiagnosticCodes.InvalidSpecificationStreamEventSource, `Declare an identifier on source '${source.name}'; the event's producers do not supply one unambiguous destination type.`, route.location);\n } else identifier = types[0];\n }\n let inheritedIdentityIsInvalid = false;\n if (step?.example?.stream != null && node.for !== null && node.for === step.example.for) {\n const prior = catalog.resolve(step.example.stream.eventSource, step.example.stream.stream);\n if (prior.kind === EventSourceResolutionKind.Unique) {\n const types = eventProducers.map(producer => producer.type);\n const distinct = new Set(types.filter(type => type !== null).map(type => `${type.name}:${type.isOptional}:${type.isCollection}`));\n const priorIdentifier = prior.sources[0].identifier ?? (types.length > 0 && !types.some(type => type === null) && distinct.size === 1 ? types[0] : null);\n if (priorIdentifier !== null)\n inheritedIdentityIsInvalid = node.for.kind !== 'LiteralExpressionSyntax' || node.for.value === null || priorIdentifier.isCollection || priorIdentifier.isOptional || !compatible(node.for, priorIdentifier);\n }\n }\n if (required && node.for === null)\n contextualError(DiagnosticCodes.InvalidSpecificationStreamEventSource, \"A routed given or when append event requires 'for <literal>'.\", route.location);\n else if (validateFor && !inheritedIdentityIsInvalid && node.for !== null && (node.for.kind !== 'LiteralExpressionSyntax' || node.for.value === null || identifier !== null && (identifier.isCollection || identifier.isOptional || !compatible(node.for, identifier))))\n contextualError(DiagnosticCodes.InvalidSpecificationStreamEventSource, \"A routed event's for value must be a concrete literal compatible with the source's identifier type.\", node.for.location);\n }\n if (!expected || command === null || eventProducers.length === 0 || eventProducers.some(producer => producer.command !== command)) continue;\n const commandRoute = command.stream?.propertyCandidate === null ? command.stream : null;\n let contradicts = node.noStream != null ? commandRoute != null : commandRoute == null || commandRoute.eventSource !== node.stream!.eventSource || commandRoute.stream !== node.stream!.stream;\n if (!contradicts && node.stream != null && commandRoute != null) {\n const resolution = catalog.resolve(node.stream.eventSource, node.stream.stream);\n const stream = resolution.kind === EventSourceResolutionKind.Unique ? resolution.streams[0] : null;\n if (stream !== null && stream.streamIdParts.length > 0) {\n if (commandRoute.streamId === null && node.stream.streamId === null && commandRoute.streamIdParts.length > 0 && node.stream.streamIdParts.length > 0) {\n for (const part of stream.streamIdParts) {\n const actual = commandRoute.streamIdParts.filter(mapping => mapping.property === part.name);\n const expected = node.stream.streamIdParts.filter(mapping => mapping.property === part.name);\n if (actual.length !== 1 || expected.length !== 1) continue;\n const actualId = formatStreamId(actual[0].source, part.type);\n const expectedId = formatStreamId(expected[0].source, part.type);\n if (actualId !== null && expectedId !== null && actualId !== expectedId) contradicts = true;\n }\n }\n } else if (stream?.streamId != null && commandRoute.streamIdParts.length === 0 && node.stream.streamIdParts.length === 0) {\n const actualId = formatStreamId(commandRoute.streamId?.source, stream.streamId);\n const expectedId = formatStreamId(node.stream.streamId?.source, stream.streamId);\n if (actualId !== null && expectedId !== null && actualId !== expectedId) contradicts = true;\n }\n }\n if (node.for?.kind === 'LiteralExpressionSyntax' && eventProducers.every(producer => producer.type !== null &&\n (identifier !== null ? nominallyCompatible(producer.type, identifier) === false : !compatible(node.for!, producer.type)))) contradicts = true;\n if (contradicts) contextualError(DiagnosticCodes.SpecificationStreamContradictsCommand, 'The expected event route contradicts its only producer, the command under test.', (node.stream ?? node.noStream)!.location);\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SpecificationStreamValidator.js","names":["rows","AuthoringProductionResolver","application","slice","specification","context","sink","ParserContext","LineReader","reported","distinct","diagnostic","key","row","DiagnosticCodes","value","examples","specificationExamples","expansion","expandEffectiveSpecificationExamples","resolver","declarationSteps","exampleSpecifications","entry","node","catalog","EventSourceCatalog","concepts","uniqueByName","composites","properties","name","type","compatibleValue","known","source","target","formatSpecificationStreamId","expression","declared","reference","producers","command","produced","event","commandDestinationType","reaction","trigger","capture","appended","child","nested","validationSpecifications","owner","commands","parts","qualifiers","candidates","index","segment","depth","scope","visible","occurrences","step","pair","validateRoute","validateFor","code","message","location","required","identifier","eventProducers","producer","route","resolution","state","stream","mapping","formatted","formatStreamIdLiteral","streamIdFailureMessage","validateStreamIdParts","types","inheritedIdentityIsInvalid","prior","priorIdentifier","expected","contradicts","commandRoute","differs","part","actual","actualId","expectedId"],"sources":["../../../../../../Compiler/Parsing/SpecificationStreamValidator.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 { CommandSyntax } from '../Syntax/Commands';\nimport { EventSyntax, TypeRefSyntax } from '../Syntax/Declarations';\nimport { EventSourceCatalog } from '../Syntax/EventSourceCatalog';\nimport { CommandStreamSyntax, EventSourceResolutionKind } from '../Syntax/EventSources';\nimport { formatSpecificationStreamId } from './SpecificationRouteComparison';\nimport { streamIdFailureMessage } from '../Syntax/StreamIdFormatter';\nimport { ExpressionSyntax } from '../Syntax/Expressions';\nimport { commandDestinationType } from './CommandDestinationTypes';\nimport { formatStreamIdLiteral } from './EventSourceValidator';\nimport { ApplicationSyntax } from '../Syntax/Structure';\nimport { PropertyMappingSyntax } from '../Syntax/Expressions';\nimport { validateStreamIdParts } from './CompositeStreamIdValidator';\nimport { ParserContext } from './ParserContext';\nimport { LineReader } from './LineReader';\nimport { compatibleValue, uniqueByName } from './ResponseValidator';\nimport { expandEffectiveSpecificationExamples, specificationExamples } from './SpecificationCommandExamples';\nimport { SpecificationEventSyntax } from '../Syntax/Specifications';\n\ninterface Producer { event: EventSyntax; command: CommandSyntax | null; type: TypeRefSyntax | null; route?: CommandStreamSyntax | null }\n\nexport function validateSpecificationStreams(application: ApplicationSyntax, context: ParserContext): void {\n const rows = new AuthoringProductionResolver(application).slices.flatMap(({ slice }) => slice.specifications.flatMap(specification => specification.cases ?? []));\n if (rows.length === 0) return validateRoutes(application, context);\n const sink = new ParserContext(new LineReader([]));\n validateRoutes(application, sink);\n const reported = new Set<string>();\n const distinct = new Set<string>();\n for (const diagnostic of sink.diagnostics) {\n const key = JSON.stringify([diagnostic.code, diagnostic.location.path, diagnostic.location.line, diagnostic.location.column, diagnostic.message]);\n if (distinct.has(key)) continue;\n distinct.add(key);\n const row = diagnostic.code === DiagnosticCodes.InvalidSpecificationStreamRoute ? rows.find(row => row.values.some(value => value.source.location.line === diagnostic.location.line && value.source.location.column === diagnostic.location.column && value.source.location.path === diagnostic.location.path)) : undefined;\n if (row === undefined) context.error(diagnostic.code, diagnostic.message, diagnostic.location);\n else {\n const key = JSON.stringify(diagnostic.location);\n if (!reported.has(key)) context.error(diagnostic.code, `Case '${row.name}': ${diagnostic.message}`, diagnostic.location);\n reported.add(key);\n }\n }\n}\n\nfunction validateRoutes(application: ApplicationSyntax, context: ParserContext): void {\n const examples = specificationExamples(application).resolvedExamples;\n const expansion = expandEffectiveSpecificationExamples(application);\n application = expansion.application;\n const resolver = new AuthoringProductionResolver(application);\n const declarationSteps = new Set<SpecificationEventSyntax>();\n const exampleSpecifications = examples.flatMap(entry => {\n if (entry.kind !== 'event') {\n if ((entry.kind === 'command' || entry.kind === 'readmodel') && (entry.example.stream != null || entry.example.noStream != null))\n context.error(DiagnosticCodes.InvalidSpecificationExampleBody, \"only event examples carry routes; a command's route comes from its declaration, and read models have none\", (entry.example.stream ?? entry.example.noStream)!.location);\n return [];\n }\n const node: SpecificationEventSyntax = { kind: 'SpecificationEventSyntax', eventType: entry.name, values: entry.example.values, for: entry.example.for, stream: entry.example.stream, noStream: entry.example.noStream, location: entry.example.location };\n declarationSteps.add(node);\n return [{ scope: entry.scope, specification: { when: null, given: [], whenAppended: null, thenEvents: [node], whenRedelivered: null } }];\n });\n const catalog = new EventSourceCatalog(application);\n const concepts = uniqueByName(application.concepts);\n const composites = uniqueByName(application.types);\n const properties = new Map([...composites].map(([name, type]) => [name, uniqueByName(type.properties)]));\n const compatible = (value: Parameters<typeof compatibleValue>[0], type: TypeRefSyntax): boolean => compatibleValue(value, type, concepts, properties);\n const known = new Set(['String', 'Uuid', 'Int', 'Decimal', 'Bool', 'Date', 'DateTime', ...concepts.keys(), ...composites.keys()]);\n const nominallyCompatible = (source: TypeRefSyntax, target: TypeRefSyntax): boolean | null => known.has(source.name) && known.has(target.name)\n ? source.name === target.name && source.isCollection === target.isCollection && (!source.isOptional || target.isOptional) : null;\n const formatStreamId = (expression: ExpressionSyntax | null | undefined, type: TypeRefSyntax): string | null => formatSpecificationStreamId(expression, type, application);\n const eventOf = (reference: string, slice: typeof resolver.slices[number]['slice']): EventSyntax | null => {\n const declared = resolver.resolve(reference, slice).declaration;\n return declared?.node.kind === 'EventSyntax' ? declared.node : null;\n };\n const producers: Producer[] = [];\n for (const { slice } of resolver.slices) {\n for (const command of slice.commands) for (const produced of command.produces) {\n if (!resolver.isEventProduction(produced, slice)) continue;\n const event = eventOf(produced.event, slice);\n if (event === null) continue;\n const type = commandDestinationType(command, produced, application, { resolver, slice });\n producers.push({ event, command, type, route: produced.stream ?? command.stream });\n }\n for (const produced of slice.reactions.flatMap(reaction => reaction.triggers).flatMap(trigger => trigger.produces)) {\n const event = eventOf(produced.event, slice);\n if (event !== null) producers.push({ event, command: null, type: null });\n }\n for (const capture of slice.captures) for (const appended of [...capture.appends, ...capture.children.flatMap(child => child.appends), ...capture.nested.flatMap(nested => nested.appends)]) {\n const event = eventOf(appended.event, slice);\n if (event !== null) producers.push({ event, command: null, type: null });\n }\n }\n const validationSpecifications = [\n ...exampleSpecifications.flatMap(entry => resolver.slices.filter(owner => owner.scope.join('.') === entry.scope.join('.')).map(({ slice, scope }) => ({ slice, scope, specification: entry.specification }))),\n ...resolver.slices.flatMap(({ slice, scope }) => slice.specifications.map(specification => ({ slice, scope, specification })))\n ];\n for (const { slice, scope, specification } of validationSpecifications) {\n const commands = resolver.slices.flatMap(entry => entry.slice.commands.map(command => ({ command, scope: entry.scope })));\n const parts = specification.when?.commandType.split('.') ?? [];\n const qualifiers = parts.slice(0, -1);\n const candidates = commands.filter(entry => entry.command.name === parts.at(-1) && qualifiers.every((segment, index) => entry.scope[entry.scope.length - qualifiers.length + index] === segment));\n let command: CommandSyntax | null = qualifiers.length > 0 && candidates.length === 1 ? candidates[0].command : null;\n for (let depth = scope.length; qualifiers.length === 0 && depth >= 0 && command === null; depth--) {\n const visible = candidates.filter(entry => scope.slice(0, depth).every((segment, index) => entry.scope[index] === segment));\n if (visible.length > 0) { command = visible.length === 1 ? visible[0].command : null; break; }\n }\n const occurrences = [...specification.given.map(node => ({ node, required: true, expected: false })),\n ...(specification.whenAppended === null ? [] : [{ node: specification.whenAppended, required: true, expected: false }]),\n ...specification.thenEvents.map(node => ({ node, required: false, expected: !declarationSteps.has(node) })),\n ...(specification.whenRedelivered == null ? [] : [{ node: { ...specification.whenRedelivered, kind: 'SpecificationEventSyntax' as const }, required: false, expected: false }])];\n for (const { node, required, expected } of occurrences) {\n const step = expansion.specifications.flatMap(pair => pair.steps).find(step => step.effective === node);\n const validateRoute = step?.route?.origin !== 'example';\n const validateFor = validateRoute || node.for !== step?.example?.for;\n const contextualError = (code: string, message: string, location: typeof node.location): void => {\n context.error(code, step?.example == null ? message : `${message} Example '${step.example.name}' is used here.`, step?.example == null ? location : step.authored.location);\n };\n if (node.stream == null && node.noStream == null) continue;\n if (required && node.noStream != null)\n contextualError(DiagnosticCodes.InvalidSpecificationStream, \"Expected 'stream Source.Stream', or 'no stream' on a then event.\", node.noStream.location);\n let identifier: TypeRefSyntax | null = null;\n const event = eventOf(node.eventType, slice);\n const eventProducers = producers.filter(producer => producer.event === event);\n if (node.stream != null) {\n const route = node.stream;\n const resolution = catalog.resolve(route.eventSource, route.stream);\n if (resolution.kind !== EventSourceResolutionKind.Unique) {\n const state = { ambiguous: 'Ambiguous', notFound: 'NotFound', wrongKind: 'WrongKind' }[resolution.kind];\n if (validateRoute) context.error(DiagnosticCodes.InvalidSpecificationStreamRoute, `Stream '${route.eventSource}.${route.stream}' is ${state}; routing requires one physical source and stream.`, route.location);\n continue;\n }\n const source = resolution.sources[0];\n const stream = resolution.streams[0];\n const validateLiteral = (mapping: PropertyMappingSyntax, target: TypeRefSyntax | null): void => {\n const value = mapping.source;\n const formatted = formatStreamIdLiteral(value, target, application);\n if (formatted?.failure != null) context.error(DiagnosticCodes.InvalidSpecificationStreamRoute, streamIdFailureMessage(formatted.failure), value.location);\n else if (value.kind !== 'LiteralExpressionSyntax' || value.value === null || target !== null && !compatible(value, target))\n context.error(DiagnosticCodes.InvalidSpecificationStreamRoute, \"A specification stream id needs a nonempty concrete scalar literal compatible with the stream's declared type.\", value.location);\n };\n if (!validateRoute) { /* The authored example's route is checked once at its declaration. */ }\n else if (stream.streamIdParts.length > 0)\n validateStreamIdParts(stream, route.streamIdParts, route.streamId !== null, route.location, DiagnosticCodes.InvalidSpecificationStreamRoute, context, validateLiteral);\n else if (route.streamIdParts.length > 0)\n context.error(DiagnosticCodes.InvalidSpecificationStreamRoute, 'A streamId part block requires a composite stream.', route.location);\n else {\n if ((stream.streamId === null) !== (route.streamId === null))\n context.error(DiagnosticCodes.InvalidSpecificationStreamRoute, stream.streamId === null ? 'An unkeyed stream cannot take a streamId mapping.' : 'This keyed stream requires a streamId mapping.', route.location);\n if (route.streamId !== null) validateLiteral(route.streamId, stream.streamId);\n }\n identifier = source.identifier;\n if (identifier === null) {\n const types = eventProducers.map(producer => producer.type);\n const distinct = new Set(types.filter(type => type !== null).map(type => `${type.name}:${type.isOptional}:${type.isCollection}`));\n if (types.length === 0 || types.some(type => type === null) || distinct.size !== 1) {\n if (validateRoute) context.error(DiagnosticCodes.InvalidSpecificationStreamEventSource, `Declare an identifier on source '${source.name}'; the event's producers do not supply one unambiguous destination type.`, route.location);\n } else identifier = types[0];\n }\n let inheritedIdentityIsInvalid = false;\n if (step?.example?.stream != null && node.for !== null && node.for === step.example.for) {\n const prior = catalog.resolve(step.example.stream.eventSource, step.example.stream.stream);\n if (prior.kind === EventSourceResolutionKind.Unique) {\n const types = eventProducers.map(producer => producer.type);\n const distinct = new Set(types.filter(type => type !== null).map(type => `${type.name}:${type.isOptional}:${type.isCollection}`));\n const priorIdentifier = prior.sources[0].identifier ?? (types.length > 0 && !types.some(type => type === null) && distinct.size === 1 ? types[0] : null);\n if (priorIdentifier !== null)\n inheritedIdentityIsInvalid = node.for.kind !== 'LiteralExpressionSyntax' || node.for.value === null || priorIdentifier.isCollection || priorIdentifier.isOptional || !compatible(node.for, priorIdentifier);\n }\n }\n if (required && node.for === null)\n contextualError(DiagnosticCodes.InvalidSpecificationStreamEventSource, \"A routed given or when append event requires 'for <literal>'.\", route.location);\n else if (validateFor && !inheritedIdentityIsInvalid && node.for !== null && (node.for.kind !== 'LiteralExpressionSyntax' || node.for.value === null || identifier !== null && (identifier.isCollection || identifier.isOptional || !compatible(node.for, identifier))))\n contextualError(DiagnosticCodes.InvalidSpecificationStreamEventSource, \"A routed event's for value must be a concrete literal compatible with the source's identifier type.\", node.for.location);\n }\n if (!expected || command === null || eventProducers.length === 0 || eventProducers.some(producer => producer.command !== command)) continue;\n let contradicts = eventProducers.every(producer => {\n const commandRoute = producer.route?.propertyCandidate === null ? producer.route : null;\n let differs = node.noStream != null ? commandRoute != null : commandRoute == null || commandRoute.eventSource !== node.stream!.eventSource || commandRoute.stream !== node.stream!.stream;\n if (!differs && node.stream != null && commandRoute != null) {\n const resolution = catalog.resolve(node.stream.eventSource, node.stream.stream);\n const stream = resolution.kind === EventSourceResolutionKind.Unique ? resolution.streams[0] : null;\n if (stream !== null && stream.streamIdParts.length > 0) {\n if (commandRoute.streamId === null && node.stream.streamId === null && commandRoute.streamIdParts.length > 0 && node.stream.streamIdParts.length > 0) {\n for (const part of stream.streamIdParts) {\n const actual = commandRoute.streamIdParts.filter(mapping => mapping.property === part.name);\n const expected = node.stream.streamIdParts.filter(mapping => mapping.property === part.name);\n if (actual.length !== 1 || expected.length !== 1) continue;\n const actualId = formatStreamId(actual[0].source, part.type);\n const expectedId = formatStreamId(expected[0].source, part.type);\n if (actualId !== null && expectedId !== null && actualId !== expectedId) differs = true;\n }\n }\n } else if (stream?.streamId != null && commandRoute.streamIdParts.length === 0 && node.stream.streamIdParts.length === 0) {\n const actualId = formatStreamId(commandRoute.streamId?.source, stream.streamId);\n const expectedId = formatStreamId(node.stream.streamId?.source, stream.streamId);\n if (actualId !== null && expectedId !== null && actualId !== expectedId) differs = true;\n }\n }\n return differs;\n });\n if (node.for?.kind === 'LiteralExpressionSyntax' && eventProducers.every(producer => producer.type !== null &&\n (identifier !== null ? nominallyCompatible(producer.type, identifier) === false : !compatible(node.for!, producer.type)))) contradicts = true;\n if (contradicts) contextualError(DiagnosticCodes.SpecificationStreamContradictsCommand, 'The expected event route contradicts its only producer, the command under test.', (node.stream ?? node.noStream)!.location);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -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{firstWord as r}from"./LineText.js";import{parseProperty as i}from"./PropertyLineParser.js";import{parseDescription as a}from"./DescriptionParser.js";import{isFileDirective as o}from"./FileReferences.js";const s=t(`^@?[a-z_]\\w*\\s+[\\w.]+`);function parseTriggerData(t,r){let a=i(t,r);a===void 0?(s.test(r.content)&&/\?|\boptional\b/.test(r.content)&&t.error(e.InvalidTriggerData,`Invalid trigger value '${r.content}' - expected '<name>' or '<name> <Type>'`,n(r)),t.skipOpaqueBlock(r.indent)):(a.isGenerated&&t.error(e.GeneratedPropertyOutsideCommand,`Generated properties can only be declared on commands.`,a.location),a.isSubject&&t.error(e.InvalidSubjectOwner,`The subject modifier is only valid on event properties, not trigger or reaction data properties (decision 0008: one data subject per event).`,a.location),t.triggerData.push(a))}function parseTriggerDeclaration(e,t){let n=e.triggerData.length;for(let n=e.peekChild(t.indent);n!==void 0;n=e.peekChild(t.indent))e.reader.takeSignificant(),r(n.content)===`description`?a(e,n,null,`Trigger '${t.content}'`):o(n)||parseTriggerData(e,n);return e.triggerData.slice(n)}export{parseTriggerData,parseTriggerDeclaration};
|
|
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{firstWord as r}from"./LineText.js";import{parseProperty as i}from"./PropertyLineParser.js";import{parseDescription as a}from"./DescriptionParser.js";import{isFileDirective as o}from"./FileReferences.js";const s=t(`^@?[a-z_]\\w*\\s+[\\w.]+`);function parseTriggerData(t,r){let a=i(t,r);a===void 0?(s.test(r.content)&&/\?|\boptional\b/.test(r.content)&&t.error(e.InvalidTriggerData,`Invalid trigger value '${r.content}' - expected '<name>' or '<name> <Type>'`,n(r)),t.skipOpaqueBlock(r.indent)):(a.isKey&&t.error(e.InvalidReadModelKey,`The key modifier is only valid on top-level read-model properties.`,a.location),a.isGenerated&&t.error(e.GeneratedPropertyOutsideCommand,`Generated properties can only be declared on commands.`,a.location),a.isSubject&&t.error(e.InvalidSubjectOwner,`The subject modifier is only valid on event properties, not trigger or reaction data properties (decision 0008: one data subject per event).`,a.location),t.triggerData.push(a))}function parseTriggerDeclaration(e,t){let n=e.triggerData.length;for(let n=e.peekChild(t.indent);n!==void 0;n=e.peekChild(t.indent))e.reader.takeSignificant(),r(n.content)===`description`?a(e,n,null,`Trigger '${t.content}'`):o(n)||parseTriggerData(e,n);return e.triggerData.slice(n)}export{parseTriggerData,parseTriggerDeclaration};
|
|
2
2
|
//# sourceMappingURL=TriggerDataParser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TriggerDataParser.js","names":["typedValue","pattern","property","parseProperty","context","line","DiagnosticCodes","locationOf","start","header","firstWord","parseDescription","isFileDirective"],"sources":["../../../../../../Compiler/Parsing/TriggerDataParser.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 { PropertySyntax } from '../Syntax/Declarations';\nimport { pattern } from '../Text/patterns';\nimport { parseDescription } from './DescriptionParser';\nimport { isFileDirective } from './FileReferences';\nimport { firstWord } from './LineText';\nimport { ParserContext } from './ParserContext';\nimport { parseProperty } from './PropertyLineParser';\nimport { locationOf, SourceLine } from './SourceLine';\n\nconst typedValue = pattern('^@?[a-z_]\\\\w*\\\\s+[\\\\w.]+');\n\n// Trigger values are kept as parser-owned diagnostic metadata, outside the syntax wire projection. Recognize their type spelling in\n// exactly the C# data positions, without scanning descriptions, attachments, code or mapping expressions.\nexport function parseTriggerData(context: ParserContext, line: SourceLine): void {\n const property = parseProperty(context, line);\n if (property !== undefined) {\n if (property.isGenerated) context.error(DiagnosticCodes.GeneratedPropertyOutsideCommand, 'Generated properties can only be declared on commands.', property.location);\n if (property.isSubject) context.error(DiagnosticCodes.InvalidSubjectOwner, 'The subject modifier is only valid on event properties, not trigger or reaction data properties (decision 0008: one data subject per event).', property.location);\n context.triggerData.push(property);\n return;\n }\n // Keep the existing opaque projection for other trigger values and implementation bodies.\n // Only optionality-shaped failures belong to this spelling change.\n if (typedValue.test(line.content) && /\\?|\\boptional\\b/.test(line.content)) {\n context.error(DiagnosticCodes.InvalidTriggerData, `Invalid trigger value '${line.content}' - expected '<name>' or '<name> <Type>'`, locationOf(line));\n }\n context.skipOpaqueBlock(line.indent);\n}\n\nexport function parseTriggerDeclaration(context: ParserContext, header: SourceLine): readonly PropertySyntax[] {\n const start = context.triggerData.length;\n for (let line = context.peekChild(header.indent); line !== undefined; line = context.peekChild(header.indent)) {\n context.reader.takeSignificant();\n if (firstWord(line.content) === 'description') {\n parseDescription(context, line, null, `Trigger '${header.content}'`);\n } else if (!isFileDirective(line)) {\n parseTriggerData(context, line);\n }\n }\n return context.triggerData.slice(start);\n}\n"],"mappings":"saAaA,MAAMA,EAAaC,EAAQ,0BAA0B,EAIrD,SAAgB,iBAAiB,EAAwB,EAAwB,CAC7E,IAAMC,EAAWC,EAAcC,EAASC,CAAI,EACxCH,IAAa,IAAA,
|
|
1
|
+
{"version":3,"file":"TriggerDataParser.js","names":["typedValue","pattern","property","parseProperty","context","line","DiagnosticCodes","locationOf","start","header","firstWord","parseDescription","isFileDirective"],"sources":["../../../../../../Compiler/Parsing/TriggerDataParser.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 { PropertySyntax } from '../Syntax/Declarations';\nimport { pattern } from '../Text/patterns';\nimport { parseDescription } from './DescriptionParser';\nimport { isFileDirective } from './FileReferences';\nimport { firstWord } from './LineText';\nimport { ParserContext } from './ParserContext';\nimport { parseProperty } from './PropertyLineParser';\nimport { locationOf, SourceLine } from './SourceLine';\n\nconst typedValue = pattern('^@?[a-z_]\\\\w*\\\\s+[\\\\w.]+');\n\n// Trigger values are kept as parser-owned diagnostic metadata, outside the syntax wire projection. Recognize their type spelling in\n// exactly the C# data positions, without scanning descriptions, attachments, code or mapping expressions.\nexport function parseTriggerData(context: ParserContext, line: SourceLine): void {\n const property = parseProperty(context, line);\n if (property !== undefined) {\n if (property.isKey) context.error(DiagnosticCodes.InvalidReadModelKey, 'The key modifier is only valid on top-level read-model properties.', property.location);\n if (property.isGenerated) context.error(DiagnosticCodes.GeneratedPropertyOutsideCommand, 'Generated properties can only be declared on commands.', property.location);\n if (property.isSubject) context.error(DiagnosticCodes.InvalidSubjectOwner, 'The subject modifier is only valid on event properties, not trigger or reaction data properties (decision 0008: one data subject per event).', property.location);\n context.triggerData.push(property);\n return;\n }\n // Keep the existing opaque projection for other trigger values and implementation bodies.\n // Only optionality-shaped failures belong to this spelling change.\n if (typedValue.test(line.content) && /\\?|\\boptional\\b/.test(line.content)) {\n context.error(DiagnosticCodes.InvalidTriggerData, `Invalid trigger value '${line.content}' - expected '<name>' or '<name> <Type>'`, locationOf(line));\n }\n context.skipOpaqueBlock(line.indent);\n}\n\nexport function parseTriggerDeclaration(context: ParserContext, header: SourceLine): readonly PropertySyntax[] {\n const start = context.triggerData.length;\n for (let line = context.peekChild(header.indent); line !== undefined; line = context.peekChild(header.indent)) {\n context.reader.takeSignificant();\n if (firstWord(line.content) === 'description') {\n parseDescription(context, line, null, `Trigger '${header.content}'`);\n } else if (!isFileDirective(line)) {\n parseTriggerData(context, line);\n }\n }\n return context.triggerData.slice(start);\n}\n"],"mappings":"saAaA,MAAMA,EAAaC,EAAQ,0BAA0B,EAIrD,SAAgB,iBAAiB,EAAwB,EAAwB,CAC7E,IAAMC,EAAWC,EAAcC,EAASC,CAAI,EACxCH,IAAa,IAAA,IASbF,EAAW,KAAKK,EAAK,OAAO,GAAK,kBAAkB,KAAKA,EAAK,OAAO,GACpED,EAAQ,MAAME,EAAgB,mBAAoB,0BAA0BD,EAAK,QAAQ,0CAA2CE,EAAWF,CAAI,CAAC,EAExJD,EAAQ,gBAAgBC,EAAK,MAAM,IAX3BH,EAAS,OAAOE,EAAQ,MAAME,EAAgB,oBAAqB,qEAAsEJ,EAAS,QAAQ,EAC1JA,EAAS,aAAaE,EAAQ,MAAME,EAAgB,gCAAiC,yDAA0DJ,EAAS,QAAQ,EAChKA,EAAS,WAAWE,EAAQ,MAAME,EAAgB,oBAAqB,+IAAgJJ,EAAS,QAAQ,EAC5OE,EAAQ,YAAY,KAAKF,CAAQ,EASzC,CAEA,SAAgB,wBAAwB,EAAwB,EAA+C,CAC3G,IAAMM,EAAQJ,EAAQ,YAAY,OAClC,IAAK,IAAIC,EAAOD,EAAQ,UAAUK,EAAO,MAAM,EAAGJ,IAAS,IAAA,GAAW,EAAOD,EAAQ,UAAUK,EAAO,MAAM,EACxGL,EAAQ,OAAO,gBAAgB,EAC3BM,EAAUL,EAAK,OAAO,IAAM,cAC5BM,EAAiBP,EAASC,EAAM,KAAM,YAAYI,EAAO,QAAQ,EAAE,EAC3DG,EAAgBP,CAAI,GAC5B,iBAAiBD,EAASC,CAAI,EAGtC,OAAOD,EAAQ,YAAY,MAAMI,CAAK,CAC1C"}
|