routeSpec.mjs

/**
 * 六路由之差異表(單一來源)
 *
 * 供 WConverhpServer 之路由前置(ctxOf / admit)、錯誤回覆(replyOf)與下載欄位檢核(readOutput)查表;
 * 亦供 test/unit-routeSpec.test.mjs 與測試端之路由軸(test/api-axes.mjs)逐欄對照 —— 兩端各自一份, 不互相 import, 不一致即紅
 *
 * why 寫成表而非散在各路由之參數列(第十一輪 G6, 兩份複審一致): 差異(apiType 字面、handler 事件之 api 字面、authorization 之來源、錯誤狀態碼、下載欄位之讀取與檢核順序)
 * 原本手寫展開於六條路由之 40 處同型片段, 每加一條規則就得寫六遍而漏其一(第十輪 A5/A6/A9/F10 各改 3–6 處; 第十一輪 N2/N4 皆為「同一規則第二站點沒套」)。
 * 表上少一欄由測試直接對表斷言, 比數 grep 命中數有分辨力
 *
 * 欄位:
 *   apiType: verifyConn 所見之 apiType(對外契約)
 *   api: handler 事件所見之 api(對外契約)
 *   authFrom: 應用端所見之 authorization 來源 —— 'header' 為請求標頭原樣, token 為確認授權方案前綴相符後切出者(帳本 R15);
 *             'query' 為由 query 之 token 合成 `<tokenType> <token>`(/dwgf 之下載由瀏覽器導覽, 無標頭可用; 合成為刻意, 使應用端 verifyConn 於六路由所見同一形狀)
 *   statusOf: 各種錯誤之 HTTP 狀態碼 —— permission(verifyConn 未通過)、param(請求參數錯誤, 可證明不需重試, 另標示 retryable:false)、app(應用端拒絕或無人接聽)、
 *             output(應用端交出之內容不合契約)、packet(請求本體無法解析)、internal(套件內部失敗, 如回應無法序列化)。
 *             五路由由 JS 解析回應, 一律 200 並以 Return-Type 與錯誤封包表達(帳本 R6); /dwgf 之唯一消費者為瀏覽器下載管理器(只看狀態碼), 以非 2xx 表達(R6 之例外, 第十輪 A9)
 *   fields: 下載路由讀取與檢核應用端回傳欄位之**順序**(契約: 多重形狀錯誤時回哪一個訊息由此決定, 三路由各不相同, test/api-characterization.test.mjs 鎖住);
 *           optional 者判定不通過且判定本身未拋錯時視為未給
 */
let st200 = { permission: 200, param: 200, app: 200, output: 200, packet: 200, internal: 200 }

let routeSpec = {
    main: {
        apiType: 'main',
        api: 'apiMain',
        authFrom: 'header',
        statusOf: st200,
    },
    ulctr: {
        apiType: 'upload-controller',
        api: 'apiUploadCheck',
        authFrom: 'header',
        statusOf: st200,
    },
    slc: {
        apiType: 'upload-slice',
        api: 'apiUploadSlice',
        authFrom: 'header',
        statusOf: st200,
    },
    dwgfn: {
        apiType: 'download-get-filename',
        api: 'apiDownloadGetFilename',
        authFrom: 'header',
        statusOf: st200,
        fields: [{ name: 'streamRead' }, { name: 'filename' }],
    },
    dwgf: {
        apiType: 'download-get-file',
        api: 'apiDownloadGetFile',
        authFrom: 'query',
        statusOf: { permission: 403, param: 400, app: 404, output: 500, packet: 500, internal: 500 },
        fields: [{ name: 'streamRead' }, { name: 'fileSize' }, { name: 'fileType' }, { name: 'filename', optional: true }],
    },
    dw: {
        apiType: 'download',
        api: 'apiDownload',
        authFrom: 'header',
        statusOf: st200,
        fields: [{ name: 'streamRead' }, { name: 'filename' }, { name: 'fileSize' }, { name: 'fileType' }],
    },
}


export default routeSpec