Files
trans-form-middleware/DESIGN.md
T
windychen e5077aeefa
Node.js Build / build (push) Has been skipped
docs: 补全 Q1-Q61 完整设计决策文档
2026-08-07 10:25:54 +08:00

5.3 KiB
Raw Blame History

@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 适配器消费输出。

import { parseFilters } from '@windychen/trans-form-middleware';

const filters = parseFilters(
  [
    { field: 'name', value: 'xx', query: 'EQ' },
    { field: 'age', value: '18,30', query: 'BETWEEN', logic: 'AND' }
  ],
  { allowedFields: ['name', 'age'] }
);
// → [{ field: 'name', query: 'EQ', op: '=', value: 'xx' },
//    { field: 'age', query: 'BETWEEN', op: 'BETWEEN', value: '18,30', values: ['18', '30'], logic: 'AND' }]

一、架构与发布

# 决策
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 支持 setFilters() / loadFilters() 回填
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'] 默认跳过的状态标记

五、输出示例

[
  {
    "field": "name",
    "query": "EQ",
    "op": "=",
    "value": "xx"
  },
  {
    "field": "tags",
    "query": "IN",
    "op": "IN",
    "value": "a,b,c",
    "values": ["a", "b", "c"],
    "logic": "OR"
  },
  {
    "field": "status",
    "query": "IS_NULL",
    "op": "IS NULL",
    "value": "",
    "empty": true,
    "logic": "AND"
  }
]

六、与 component 的协议对齐

项 约定
输入 component getFilters() / @change 输出
输出字段 field、value、query、op、logic?、values?、empty?
状态标记 disabled / hidden 默认跳过;readOnly 正常解析
空值 empty: true 默认保留,skipEmpty 可配

七、CI 触发约定

commit message 必须同时包含 chore + 版本 + 更新 才触发构建发布;否则 job 显示 skipped(设计行为,防误触)。

git commit -m "chore: 版本 0.1.0 更新 ..."