47 lines
3.3 KiB
JavaScript
47 lines
3.3 KiB
JavaScript
import fs from 'node:fs'
|
|
const failures=[]
|
|
const read=p=>fs.readFileSync(p,'utf8')
|
|
|
|
const ui=read('packages/kbx-contracts/src/ui.ts')
|
|
for(const token of ["'changed'","'warning'","'ai-suggested'","'application'","'page'","'grid'","'dialog'","'editor'"])if(!ui.includes(token))failures.push(`ui interaction contract missing ${token}`)
|
|
|
|
const stateful=[
|
|
'KbxInput.vue','KbxNumberField.vue','KbxDateField.vue','KbxDateRange.vue','KbxSelect.vue','KbxTextarea.vue','KbxLookup.vue','KbxCheckbox.vue','KbxRadio.vue','KbxTextField.vue','KbxBarcodeField.vue','KbxMoneyField.vue','KbxQuantityField.vue',
|
|
]
|
|
for(const file of stateful){
|
|
const text=read(`packages/kbx-ui/src/components/${file}`)
|
|
if(!text.includes('KbxFieldState'))failures.push(`${file} must consume KbxFieldState`)
|
|
}
|
|
|
|
const searchContract=read('packages/kbx-contracts/src/search.ts')
|
|
if(!searchContract.includes("'checkbox'"))failures.push('KbxSearchFieldType must include checkbox')
|
|
const search=read('packages/kbx-ui/src/components/KbxSearchPanel.vue')
|
|
for(const token of ['rememberChecked','savedSearchRequested',"field.type==='checkbox'",'field.defaultValue'])if(!search.includes(token))failures.push(`KbxSearchPanel missing ${token}`)
|
|
|
|
const grid=read('packages/kbx-ui/src/components/KbxDataGrid.vue')
|
|
for(const token of ['KbxDataState','changedCells','personalization','savedPreference','preferenceChanged','exportable','emptyText','errorText','savePreference','KbxSummaryBar'])if(!grid.includes(token))failures.push(`KbxDataGrid missing ${token}`)
|
|
|
|
const keyboard=read('packages/kbx-ui/src/keyboard/manager.ts')
|
|
for(const token of ['scopeRank','protectedBrowserShortcuts','F5','CTRL+L','CTRL+T','CTRL+W','CTRL+R','registerKbxShortcuts'])if(!keyboard.includes(token))failures.push(`keyboard manager missing ${token}`)
|
|
const composable=read('packages/kbx-ui/src/composables/useKbxShortcuts.ts')
|
|
if(!composable.includes('registerKbxShortcuts'))failures.push('useKbxShortcuts must delegate to central keyboard manager')
|
|
|
|
|
|
for(const file of ['apps/web/src/shell/KbxAppFrame.vue','packages/kbx-ui/src/components/KbxExceptionDetailDrawer.vue']){
|
|
if(read(file).includes("addEventListener('keydown'"))failures.push(`${file} bypasses central keyboard manager`)
|
|
}
|
|
|
|
const tabs=read('packages/kbx-ui/src/components/KbxTabs.vue')
|
|
for(const token of ['ArrowRight','ArrowLeft','Home','End','aria-controls','tabpanel'])if(!tabs.includes(token))failures.push(`KbxTabs missing ${token}`)
|
|
|
|
const index=read('packages/kbx-ui/src/index.ts')
|
|
if(!index.includes('KbxDataState'))failures.push('public API missing KbxDataState')
|
|
const manifest=read('packages/kbx-ui/src/registry/componentManifest.ts')
|
|
if(!manifest.includes("name: 'KbxDataState'"))failures.push('component manifest missing KbxDataState')
|
|
const catalog=read('packages/kbx-ui/src/catalog/componentCatalog.ts')
|
|
if(!catalog.includes("component:'KbxDataState'"))failures.push('component catalog missing KbxDataState')
|
|
for(const state of ["state:'changed'","state:'warning'","state:'ai-suggested'","state:'empty'"])if(!catalog.includes(state))failures.push(`component catalog missing ${state}`)
|
|
|
|
if(failures.length){console.error('KBX interaction contract validation failed:\n- '+failures.join('\n- '));process.exit(1)}
|
|
console.log(`Interaction contracts PASS: ${stateful.length} stateful inputs, SearchPanel, DataGrid runtime states, scoped keyboard manager, accessible Tabs.`)
|