import fs from 'node:fs' import crypto from 'node:crypto' const sourcePath='contracts/telemetry/kbx.telemetry.json' const source=fs.readFileSync(sourcePath,'utf8') const data=JSON.parse(source) const sha=crypto.createHash('sha256').update(source).digest('hex') const names=new Set(), allowedName=/^[a-z][a-z0-9_.-]+$/ for(const event of data.events){ if(!allowedName.test(event.name)) throw new Error(`invalid telemetry event name: ${event.name}`) if(names.has(event.name)) throw new Error(`duplicate telemetry event: ${event.name}`) names.add(event.name) const attrs=new Set() for(const key of event.allowedAttributes??[]){if(attrs.has(key))throw new Error(`duplicate attribute ${event.name}.${key}`);attrs.add(key)} } const manifest={schemaVersion:data.schemaVersion,telemetryVersion:data.telemetryVersion,sourceSha256:sha,principles:data.principles,events:data.events,metrics:data.metrics} fs.mkdirSync('generated',{recursive:true});fs.writeFileSync('generated/telemetry-manifest.json',JSON.stringify(manifest,null,2)+'\n') const ts=`// generated from ${sourcePath}; do not edit.\nexport const kbxTelemetryCatalog = ${JSON.stringify(Object.fromEntries(data.events.map(e=>[e.name,e])),null,2)} as const\nexport type KbxTelemetryEventName = keyof typeof kbxTelemetryCatalog\nexport const kbxUxMetricCatalog = ${JSON.stringify(Object.fromEntries(data.metrics.map(m=>[m.key,m])),null,2)} as const\nexport type KbxUxMetricKey = keyof typeof kbxUxMetricCatalog\nexport const kbxTelemetrySourceSha256 = '${sha}' as const\n` fs.mkdirSync('packages/kbx-contracts/src/generated',{recursive:true});fs.writeFileSync('packages/kbx-contracts/src/generated/telemetryCatalog.ts',ts) const esc=s=>s.replaceAll('"','\\"') const csEvents=data.events.map(e=>` ["${e.name}"] = new("${e.name}", "${e.category}", new[] { ${(e.allowedAttributes??[]).map(x=>`"${x}"`).join(', ')} }, ${e.requiresDuration?'true':'false'})`).join(',\n') const cs=`// generated from ${sourcePath}; do not edit.\nnamespace Kbx.Shared.Telemetry.Generated;\n\npublic sealed record KbxTelemetryEventDefinition(string Name,string Category,IReadOnlyList AllowedAttributes,bool RequiresDuration);\n\npublic static class KbxTelemetryCatalog\n{\n public const string SourceSha256 = "${sha}";\n public static readonly IReadOnlyDictionary Events = new Dictionary(StringComparer.Ordinal)\n {\n${csEvents}\n };\n}\n` fs.mkdirSync('backend/Shared/Telemetry/Generated',{recursive:true});fs.writeFileSync('backend/Shared/Telemetry/Generated/KbxTelemetryCatalog.g.cs',cs) console.log(`generated telemetry contracts: ${data.events.length} events, ${data.metrics.length} metrics`)