import fs from 'node:fs' import path from 'node:path' const root=process.cwd() const base=path.join(root,'apps/web/fe-reference') const required=['index.html','kbx-fe.css','kbx-fe.js','README.md'] const errors=[] for(const file of required){if(!fs.existsSync(path.join(base,file)))errors.push(`missing ${file}`)} if(!errors.length){ const html=fs.readFileSync(path.join(base,'index.html'),'utf8') const css=fs.readFileSync(path.join(base,'kbx-fe.css'),'utf8') const js=fs.readFileSync(path.join(base,'kbx-fe.js'),'utf8') for(const token of ['global-header','side-nav','workspaceTabs','menuSearchDialog','lookupDialog','unsavedDialog','quantityDialog','exceptionDialog','drawerBackdrop','Content-Security-Policy']){ if(!html.includes(token))errors.push(`html missing ${token}`) } for(const token of ['--header-h:56px','--nav-w:220px','--nav-collapsed:56px','--control-h:34px','.wms-phone','.data-state','.confirm-dialog','.cell-editor','.scan-box.scan-error','.validation-summary','.action-result']){ if(!css.includes(token))errors.push(`css missing ${token}`) } for(const template of ['T01','T02','T03','T04','T05','T06','T07','T08','T09']){ if(!js.includes(template))errors.push(`js missing ${template}`) } for(const behavior of ['requestCloseTab','pendingNavigationId','openLookup','bindLookups','showUtilityPanel','applyIntent','orderQuickFilter','orderDataState','fastRows','inventoryItemId','queueFilter','mismatchOnly','importStep','importJobStatus','startImportJob','applyScan','lastScanValue','networkStatus','selectedOrders','toggleFavorite','orderSearch','captureOrderSearch','masterDraft','validateMasterDraft','transactionHeader','validateTransaction','selectedQueueRows','selectedReconcileRows','trySaveDirtyScreen','beforeunload']){ if(!js.includes(behavior))errors.push(`js missing behavior ${behavior}`) } for(const security of ["const esc =",'knownIds','try{ localStorage.setItem','localStorage.getItem']){ if(!js.includes(security))errors.push(`security/stability contract missing ${security}`) } for(const forbidden of ['prompt(','eval(','document.write(']){ if(js.includes(forbidden))errors.push(`forbidden FE pattern ${forbidden}`) } if(!js.includes("selection===0"))errors.push('selection-dependent command disabling missing') if(!js.includes("e.key==='Enter'"))errors.push('keyboard Enter flow missing') if(!js.includes("e.key==='Escape'"))errors.push('Escape recovery flow missing') } if(errors.length){ console.error('FE reference validation failed') for(const error of errors)console.error(`- ${error}`) process.exit(1) } console.log('FE reference validation passed: v44 completion loops + themed state/recovery + non-modal runtime center + secure shell + async import + WMS guards')