Files
KArtSell.Aegis/docs/Design/kbx-foundation-v36/scripts/validate-component-catalog.mjs
T

39 lines
3.0 KiB
JavaScript

import fs from 'node:fs'
import path from 'node:path'
const requiredCore=[
'KbxButton','KbxInput','KbxNumberField','KbxMoneyField','KbxQuantityField','KbxDateField','KbxDateRange','KbxSelect','KbxLookup',
'KbxPageHeader','KbxCommandBar','KbxSearchPanel','KbxFormSection','KbxDataGrid','KbxBulkActionBar','KbxStatus',
'KbxDialog','KbxDrawer','KbxToast','KbxConfirm','KbxExcelMenu','KbxExcelImport','KbxJobProgress','KbxAuditTrail','KbxHelpPanel','KbxAiPanel','KbxProposalPanel',
'KbxListPage','KbxMasterPage','KbxTransactionPage','KbxMasterDetailPage','KbxQueuePage','KbxReconcilePage','KbxWmsMobilePage',
]
const manifest=fs.readFileSync('packages/kbx-ui/src/registry/componentManifest.ts','utf8')
const index=fs.readFileSync('packages/kbx-ui/src/index.ts','utf8')
const catalog=JSON.parse(fs.readFileSync('generated/catalog-manifest.json','utf8'))
const generatedComponents=JSON.parse(fs.readFileSync('generated/component-manifest.json','utf8'))
const failures=[]
for(const entry of generatedComponents){ if(!/^\d+\.\d+\.\d+$/.test(entry.version)) failures.push(`invalid component semver ${entry.name}: ${entry.version}`) }
for(const name of requiredCore){
if(!manifest.includes(`name: '${name}'`)) failures.push(`component manifest missing ${name}`)
if(!generatedComponents.some(x=>x.name===name)) failures.push(`generated component manifest missing ${name}`)
if(!index.includes(`as ${name} }`) && !index.includes(`as ${name} } from`) && !index.includes(`default as ${name}`)) failures.push(`public API missing ${name}`)
}
for(const name of ['KbxInput','KbxLookup','KbxDataGrid','KbxCommandBar','KbxExcelImport','KbxWmsMobilePage','KbxApplicationShell']){
if(!catalog.some(x=>x.component===name)) failures.push(`catalog missing critical component ${name}`)
}
const css=fs.readFileSync('packages/kbx-ui/src/tokens/kbx.css','utf8')
if(!css.includes(':focus-visible')) failures.push('global focus-visible contract missing')
const uiFiles=[]
function walk(dir){for(const e of fs.readdirSync(dir,{withFileTypes:true})){const f=path.join(dir,e.name);e.isDirectory()?walk(f):uiFiles.push(f)}}
walk('packages/kbx-ui/src')
for(const file of uiFiles.filter(x=>x.endsWith('.vue'))){
const text=fs.readFileSync(file,'utf8')
if(/outline\s*:\s*none/i.test(text)) failures.push(`${file}: outline:none is forbidden`)
}
const visual=fs.readFileSync('tests/e2e/kbx-component-catalog.visual.spec.ts','utf8')
for(const d of ['compact','comfortable','touch']) if(!visual.includes(`density:'${d}'`)) failures.push(`visual regression missing ${d} density`)
const keyboard=fs.readFileSync('tests/e2e/kbx-keyboard-regression.spec.ts','utf8')
for(const key of ['F2','F3','F8','Tab','Shift+Tab','Enter','Escape']) if(!keyboard.includes(`'${key}'`) && !keyboard.includes(`('${key}')`)) failures.push(`keyboard regression missing ${key}`)
if(failures.length){console.error('KBX component catalog validation failed:\n- '+failures.join('\n- '));process.exit(1)}
console.log(`KBX component catalog validation passed: ${requiredCore.length} core APIs, ${catalog.length} catalog entries.`)