41 lines
2.9 KiB
JavaScript
41 lines
2.9 KiB
JavaScript
import fs from 'node:fs'
|
|
import crypto from 'node:crypto'
|
|
|
|
const source='contracts/screens/kbx.screen-recipes.json'
|
|
const scenarioSource='contracts/testing/kbx.test-scenarios.json'
|
|
const data=JSON.parse(fs.readFileSync(source,'utf8'))
|
|
const scenarios=JSON.parse(fs.readFileSync(scenarioSource,'utf8'))
|
|
const scenarioById=new Map(scenarios.scenarios.map(scenario=>[scenario.id,scenario]))
|
|
const sha=crypto.createHash('sha256').update(fs.readFileSync(source)).digest('hex')
|
|
const scenarioSha=crypto.createHash('sha256').update(fs.readFileSync(scenarioSource)).digest('hex')
|
|
const byCode=Object.fromEntries(data.recipes.map(recipe=>[recipe.code,recipe]))
|
|
|
|
const verification=data.recipes.map(recipe=>{
|
|
const canonical=recipe.canonicalScenarioIds.flatMap(id=>scenarioById.has(id)?[scenarioById.get(id)]:[])
|
|
const kinds=[...new Set(canonical.map(item=>item.kind))].sort()
|
|
const tags=[...new Set(canonical.flatMap(item=>item.tags??[]))].sort()
|
|
const evidence=[...new Set(canonical.flatMap(item=>item.evidence??[]))].sort()
|
|
const missingScenarioKinds=recipe.testProfile.requiredScenarioKinds.filter(item=>!kinds.includes(item))
|
|
const missingTags=recipe.testProfile.requiredTags.filter(item=>!tags.includes(item))
|
|
const missingEvidence=recipe.testProfile.requiredEvidence.filter(item=>!evidence.includes(item))
|
|
return {
|
|
code:recipe.code,
|
|
type:recipe.type,
|
|
canonicalScenarioIds:recipe.canonicalScenarioIds,
|
|
scenarioKinds:kinds,
|
|
tags,
|
|
evidence,
|
|
requiredChecks:recipe.testProfile.requiredChecks,
|
|
missingScenarioKinds,
|
|
missingTags,
|
|
missingEvidence,
|
|
complete:!missingScenarioKinds.length&&!missingTags.length&&!missingEvidence.length,
|
|
}
|
|
})
|
|
|
|
fs.writeFileSync('generated/screen-recipe-manifest.json',JSON.stringify({schemaVersion:data.schemaVersion,contractVersion:data.contractVersion,sourceSha256:sha,recipes:data.recipes},null,2)+'\n')
|
|
fs.writeFileSync('generated/screen-recipe-verification-manifest.json',JSON.stringify({schemaVersion:1,recipeContractVersion:data.contractVersion,scenarioContractVersion:scenarios.contractVersion,recipeSourceSha256:sha,scenarioSourceSha256:scenarioSha,recipes:verification},null,2)+'\n')
|
|
const ts=`// generated from ${source}; do not edit.\n// SHA256: ${sha}\nimport type { KbxScreenRecipeDefinition } from '../screen'\n\nexport const kbxScreenRecipeContractVersion=${JSON.stringify(data.contractVersion)} as const\nexport const kbxScreenRecipeCatalog=${JSON.stringify(byCode,null,2)} as const satisfies Record<string,KbxScreenRecipeDefinition>\nexport const kbxScreenRecipeVerificationCatalog=${JSON.stringify(Object.fromEntries(verification.map(item=>[item.code,item])),null,2)} as const\n`
|
|
fs.writeFileSync('packages/kbx-contracts/src/generated/screenRecipeCatalog.ts',ts)
|
|
console.log(`screen recipe contracts generated: recipes=${data.recipes.length}, verification=${verification.filter(item=>item.complete).length}/${verification.length}`)
|