@windychen/trans-form-middleware — Design (Q1–Q61)
设计基线:grill-me 61 题访谈结论(2026-08-06)。配套包:@windychen/trans-form-component(Vue 3 动态查询表单)。
角色定位
接收组件输出的 filter 数组,解析为结构化条件 { field, query, op, value, logic?, values?, empty? }[]。不生成 SQL —— 由上层 ORM/DAO 适配器消费输出。
一、架构与发布
| # |
决策 |
| 1 |
middleware:Node.js 纯 JS |
| 2 |
middleware 输出:结构化过滤器,不碰 SQL |
| 3 |
两个独立 Gitea 仓库,各自 CI、各自发版 |
| 24 |
middleware:零依赖;后续另做 Knex/TypeORM 适配包 |
| 25 |
middleware 发布:ESM only |
| 27 |
middleware 构建:不打包,package.json 指向 src/index.js |
| 28 |
测试:Vitest,CI 里 npm test 通过才发布 |
| 29 |
版本号:完全独立,兼容性写 README |
| 21 |
CI:复制 windychen-utils 模式(三关键词 → Verdaccio + Gitea Packages + Release + 钉钉) |
二、解析规则
输出形态
| # |
决策 |
| 8 |
输出同时保留 query(原始码)和 op(标准符号) |
| 14 |
parseOptions.mode:flat / tree / pass-through,默认透传 logic |
| 46 |
多值:同时保留 value(原串)和 values(解析数组) |
过滤与校验
| # |
决策 |
| 44 |
parseOptions.strict,默认 false(宽松) |
| 49 |
必须传 parseOptions.allowedFields 白名单 |
| 50 |
unknownField: 'error' | 'skip',默认 'error' |
状态标记处理(Q60–Q61)
| # |
决策 |
| 60 |
组件 filters 全部带状态标记输出;middleware 默认忽略 disabled,readOnly 正常解析 |
| 61 |
hidden: true 默认跳过(与 disabled 一致);empty: true 默认保留(原样透传),可通过 parseOptions.skipEmpty: true/false 控制是否跳过 |
空值
| # |
决策 |
| 38 |
empty: true:原样保留,调用方自行过滤(skipEmpty 可覆盖) |
| 9 |
组件侧空 value 带 empty: true 标记输出 |
三、操作符
内置码表(Q39)
| # |
决策 |
| 39 |
内置默认 DEFAULT_OPERATOR_MAP,可 merge/覆盖(operatorMap 选项) |
| 12 |
v1 操作符:比较 + LIKE/IN/NOT_IN + BETWEEN/IS_NULL/IS_NOT_NULL |
| 码 |
符号 |
说明 |
EQ |
= |
等于 |
NE |
<> |
不等于 |
GT |
> |
大于 |
GTE |
>= |
大于等于 |
LT |
< |
小于 |
LTE |
<= |
小于等于 |
LIKE |
LIKE |
模糊 |
IN |
IN |
属于 |
NOT_IN |
NOT IN |
不属于 |
BETWEEN |
BETWEEN |
区间 |
IS_NULL |
IS NULL |
为空 |
IS_NOT_NULL |
IS NOT NULL |
非空 |
四、API 表面
| # |
决策 |
| 40 |
回填能力在 component 侧(setFilters() / loadFilters() / reset() ref API,见 component DESIGN 输出协议);middleware 只做单向解析 |
| 41 |
多函数导出:parseFilters / toTree / mapOperators / splitMultiValue 等 |
导出函数
| 函数 |
作用 |
parseFilters(filters, parseOptions?) |
主入口:校验白名单、映射操作符、处理状态标记、多值拆分 |
toTree(filters, parseOptions?) |
按 logic 组装嵌套分组树 |
mapOperators(filters, operatorMap?) |
只做操作符码 → 符号映射 |
splitMultiValue(value, separator?) |
逗号分隔字符串 → 数组 |
parseOptions 汇总
| 选项 |
默认 |
说明 |
allowedFields |
必传 |
字段白名单 |
unknownField |
'error' |
未知字段:报错或跳过 |
strict |
false |
宽松/严格模式 |
mode |
pass-through |
flat / tree / pass-through |
operatorMap |
DEFAULT_OPERATOR_MAP |
合并/覆盖码表 |
skipEmpty |
false |
是否跳过 empty: true 项 |
skipFlags |
['disabled', 'hidden'] |
默认跳过的状态标记 |
五、输出示例
六、与 component 的协议对齐
| 项 |
约定 |
| 输入 |
component getFilters() / @change 输出 |
| 输出字段 |
field、value、query、op、logic?、values?、empty? |
| 状态标记 |
disabled / hidden 默认跳过;readOnly 正常解析 |
| 空值 |
empty: true 默认保留,skipEmpty 可配 |
七、CI 触发约定
commit message 必须同时包含 chore + 版本 + 更新 才触发构建发布;否则 job 显示 skipped(设计行为,防误触)。