Files
KArtSell.Aegis/docs/Design/kbx-foundation-v60-status-canonical-contract-hardening/scripts/validate-fe-grid-status-v59.mjs
T
kjh2064 3f293d8aa8
deploy / deploy (push) Successful in 1m52s
deploy / notify (push) Successful in 1s
V13-FE-006: consolidate approved UI and contract hardening
2026-08-13 02:41:00 +09:00

55 lines
5.1 KiB
JavaScript

import fs from 'node:fs'
import path from 'node:path'
const read=file=>fs.readFileSync(file,'utf8')
const expect=(condition,message)=>{if(!condition){console.error(`FAIL: ${message}`);process.exit(1)}console.log(`PASS: ${message}`)}
const app=read('apps/web/src/App.vue')
expect(/app-version="v(?:59|6[0-9])-/.test(app),'Runtime metadata identifies v59 or a later grid-status-compatible build')
const statusContract=read('packages/kbx-contracts/src/status.ts')
expect(statusContract.includes("| 'ready'")&&statusContract.includes("| 'info'"),'Status semantic contract covers ready/info without overloading pending')
const gridContract=read('packages/kbx-contracts/src/grid.ts')
expect(gridContract.includes('export interface KbxGridStatusMap')&&gridContract.includes('statusMap?: KbxGridStatusMap'),'Grid status columns require an explicit raw-value mapping contract')
const resolver=read('packages/kbx-ui/src/grid/status.ts')
expect(resolver.includes('resolveKbxGridStatus')&&resolver.includes("semantic:'warning'")&&resolver.includes("unknown:true"),'Unknown domain states fail visibly through the pure status resolver')
const status=read('packages/kbx-ui/src/components/KbxStatus.vue')
expect(status.includes('data-unknown')&&status.includes('정의되지 않은 상태값')&&status.includes('info-surface'),'KbxStatus renders semantic surfaces and a color-independent unknown-state signal')
const grid=read('packages/kbx-ui/src/components/KbxDataGrid.vue')
for(const marker of ["cellRenderer:c.type==='status'?KbxStatus",'filterValueGetter:c.type===\'status\'','statusDisplay(column,params.value)','resolveKbxGridStatus(column.statusMap,value)'])expect(grid.includes(marker),`KbxDataGrid status renderer contract: ${marker}`)
expect(grid.includes("processCellCallback")&&grid.includes("column?.type==='status'?statusDisplay(column,params.value):params.value"),'CSV exports user labels for statuses while non-status values remain raw')
const catalog=read('apps/web/src/registry/statusCatalog.ts')
for(const marker of ['orderLifecycle','orderShipment','claim','workSeverity','workItem','reconcile','wmsWork','experiment','externalData'])expect(catalog.includes(marker),`Product status dictionary includes ${marker}`)
expect(catalog.includes("{ value:'READY', label:'출고대기', semantic:'ready' }")&&catalog.includes("{ value:'BLOCKED', label:'예외', semantic:'error' }"),'Canonical OMS/WMS values map to familiar Korean labels')
const sourceFiles=[]
function walk(dir){for(const entry of fs.readdirSync(dir,{withFileTypes:true})){const full=path.join(dir,entry.name);if(entry.isDirectory())walk(full);else if(entry.isFile()&&(entry.name.endsWith('.ts')||entry.name.endsWith('.vue')))sourceFiles.push(full)}}
walk('apps/web/src')
const missing=[]
for(const file of sourceFiles){const source=read(file);for(const match of source.matchAll(/\{[^{}]*type\s*:\s*['"]status['"][^{}]*\}/gs)){if(!match[0].includes('statusMap'))missing.push(`${file}: ${match[0].slice(0,90).replace(/\s+/g,' ')}`)}}
expect(missing.length===0,`Every application Grid status column has a statusMap; missing: ${missing.join(' | ')||'none'}`)
const demo=read('apps/web/src/http/demo/installFrontendDemoApi.ts')
expect(demo.includes("shipmentStatus:'READY'")&&demo.includes("shipmentStatus:'NEW'")&&demo.includes("shipmentStatus:'SHIPPED'")&&!demo.includes("shipmentStatus:'출고대기'"),'Demo order projection uses canonical shipment values instead of pre-translated labels')
const orderDrawer=read('apps/web/src/modules/oms/orders/search/OrderDetailDrawer.vue')
expect(orderDrawer.includes('resolveKbxGridStatus')&&orderDrawer.includes('kbxStatusCatalog.orderLifecycle')&&!orderDrawer.includes('function statusSemantic'),'Order detail removes page-local status semantics and reuses the product dictionary')
const unit=read('tests/unit/kbx-grid-status.contract.spec.ts')
expect(unit.includes("rawValue:'READY'")&&unit.includes('NEW_VENDOR_STATE')&&unit.includes('unknown:true'),'Unit contract covers canonical preservation and unknown-state visibility')
const reference=read('apps/web/fe-reference/kbx-fe.js')
const referenceCss=read('apps/web/fe-reference/kbx-fe.css')
expect(reference.includes('function statusSemantic')&&reference.includes('function statusChip')&&reference.includes('정의되지 않음 ·'),'Static HTML/JS reference mirrors semantic status and unknown-state behavior')
expect(referenceCss.includes('.business-status[data-semantic="completed"]')&&referenceCss.includes('.business-status[data-unknown="true"]'),'Static reference uses text-plus-semantic status styling')
const referenceHtml=read('apps/web/fe-reference/index.html')
expect(/KBX FE Reference Lab v(?:59|6[0-9]) ·/.test(referenceHtml),'Static HTML reference identifies v59 or a later status-compatible build')
const manifest=read('packages/kbx-ui/src/registry/componentManifest.ts')
expect(manifest.includes("name: 'KbxDataGrid'")&&manifest.includes("version: '1.6.0'")&&manifest.includes("name: 'KbxStatus'")&&manifest.includes("version: '1.1.0'"),'Component versions identify the strengthened Grid/Status contracts')
console.log('PASS: FE grid status dictionary + unknown-state hardening v59 contract')