Files
KArtSell.Aegis/docs/Design/kbx-foundation-v36/scripts/validate-design-code-parity.mjs
T

29 lines
2.6 KiB
JavaScript

import fs from 'node:fs'
import { spawnSync } from 'node:child_process'
const tokens=JSON.parse(fs.readFileSync('generated/token-manifest.json','utf8'))
const figmaVars=JSON.parse(fs.readFileSync('design/figma/variables.contract.json','utf8'))
const figmaComponents=JSON.parse(fs.readFileSync('design/figma/components.contract.json','utf8'))
const catalog=JSON.parse(fs.readFileSync('generated/catalog-manifest.json','utf8'))
const requiredTokenPaths=[
'typography.size.xs','typography.size.sm','typography.size.md','typography.size.lg','typography.size.xl','typography.size.2xl',
'spacing.0','spacing.1','spacing.2','spacing.3','spacing.4','spacing.5','spacing.6','spacing.8','spacing.10','spacing.12',
'radius.sm','radius.md','radius.lg','semantic.surface.default','semantic.text.default','semantic.border.default','semantic.action.primary','semantic.status.success','semantic.status.warning','semantic.status.danger','semantic.focus',
'component.control.height','component.grid.rowHeight','component.grid.headerHeight','component.pageHeader.height','component.commandBar.height','component.form.labelWidth','component.touch.controlHeight'
]
const tokenSet=new Set(tokens.tokens.map(t=>t.path))
const missingTokens=requiredTokenPaths.filter(x=>!tokenSet.has(x))
if(missingTokens.length){console.error(`missing standard tokens: ${missingTokens.join(', ')}`);process.exit(1)}
for(const mode of ['compact','comfortable','touch'])if(!tokens.modes?.[mode]){console.error(`missing density mode: ${mode}`);process.exit(1)}
const catalogSet=new Set(catalog.map(x=>x.component))
const requiredDesign=figmaComponents.components.filter(x=>x.designRequired)
const missingCatalog=requiredDesign.filter(x=>!catalogSet.has(x.codeName))
if(missingCatalog.length){console.error(`core components missing catalog/design states: ${missingCatalog.map(x=>x.codeName).join(', ')}`);process.exit(1)}
const badNames=figmaComponents.components.filter(x=>x.figmaName!==`KBX/${x.figmaName.split('/')[1]}/${x.codeName}`)
if(badNames.length){console.error(`invalid Figma names: ${badNames.map(x=>x.codeName).join(', ')}`);process.exit(1)}
const varCount=Object.values(figmaVars.collections).reduce((n,a)=>n+a.length,0)
if(varCount!==tokens.tokens.length){console.error(`Figma variable count ${varCount} != token count ${tokens.tokens.length}`);process.exit(1)}
const debt=spawnSync(process.execPath,['scripts/measure-design-debt.mjs'],{stdio:'inherit'})
if(debt.status!==0)process.exit(debt.status??1)
console.log(`design-code parity PASS: ${tokens.tokens.length} tokens, ${requiredDesign.length} core components, ${figmaComponents.componentCount} total components`)