@aiao/rxdb-model 0.0.19 → 0.0.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +43 -6
- package/dist/cn.d.ts +19 -0
- package/dist/cn.d.ts.map +1 -0
- package/dist/entity-capabilities.d.ts +31 -0
- package/dist/entity-capabilities.d.ts.map +1 -0
- package/dist/entity-detail/detail-tabs.d.ts +13 -2
- package/dist/entity-detail/detail-tabs.d.ts.map +1 -1
- package/dist/entity-detail/index.d.ts +5 -0
- package/dist/entity-detail/index.d.ts.map +1 -1
- package/dist/entity-detail/interfaces.d.ts +29 -1
- package/dist/entity-detail/interfaces.d.ts.map +1 -1
- package/dist/entity-field.utils.d.ts +60 -2
- package/dist/entity-field.utils.d.ts.map +1 -1
- package/dist/entity-form/form-data.d.ts +22 -1
- package/dist/entity-form/form-data.d.ts.map +1 -1
- package/dist/entity-form/form-fields.d.ts +25 -2
- package/dist/entity-form/form-fields.d.ts.map +1 -1
- package/dist/entity-form/form-validation.d.ts +20 -2
- package/dist/entity-form/form-validation.d.ts.map +1 -1
- package/dist/entity-form/index.d.ts +5 -0
- package/dist/entity-form/index.d.ts.map +1 -1
- package/dist/entity-form/interfaces.d.ts +65 -1
- package/dist/entity-form/interfaces.d.ts.map +1 -1
- package/dist/entity-list/manual-order-list.d.ts +99 -0
- package/dist/entity-list/manual-order-list.d.ts.map +1 -0
- package/dist/entity-table/columns/build-editable-columns.d.ts +26 -4
- package/dist/entity-table/columns/build-editable-columns.d.ts.map +1 -1
- package/dist/entity-table/columns/column-utils.d.ts +78 -12
- package/dist/entity-table/columns/column-utils.d.ts.map +1 -1
- package/dist/entity-table/editors/color-editor.d.ts +23 -0
- package/dist/entity-table/editors/color-editor.d.ts.map +1 -0
- package/dist/entity-table/editors/date-editor.d.ts +6 -1
- package/dist/entity-table/editors/date-editor.d.ts.map +1 -1
- package/dist/entity-table/editors/enum-editor.d.ts +11 -1
- package/dist/entity-table/editors/enum-editor.d.ts.map +1 -1
- package/dist/entity-table/editors/global-overlay-editor.d.ts +27 -4
- package/dist/entity-table/editors/global-overlay-editor.d.ts.map +1 -1
- package/dist/entity-table/editors/icon-list-editor.d.ts +13 -1
- package/dist/entity-table/editors/icon-list-editor.d.ts.map +1 -1
- package/dist/entity-table/editors/json-editor.d.ts +6 -1
- package/dist/entity-table/editors/json-editor.d.ts.map +1 -1
- package/dist/entity-table/editors/key-value-editor.d.ts +12 -2
- package/dist/entity-table/editors/key-value-editor.d.ts.map +1 -1
- package/dist/entity-table/editors/lucide-svg.d.ts +3 -2
- package/dist/entity-table/editors/lucide-svg.d.ts.map +1 -1
- package/dist/entity-table/editors/multiselect-editor.d.ts +24 -6
- package/dist/entity-table/editors/multiselect-editor.d.ts.map +1 -1
- package/dist/entity-table/editors/number-editor.d.ts +33 -3
- package/dist/entity-table/editors/number-editor.d.ts.map +1 -1
- package/dist/entity-table/editors/relation-editor.d.ts +14 -2
- package/dist/entity-table/editors/relation-editor.d.ts.map +1 -1
- package/dist/entity-table/editors/safe-list-editor.d.ts +1 -0
- package/dist/entity-table/editors/safe-list-editor.d.ts.map +1 -1
- package/dist/entity-table/editors/tags-editor.d.ts +12 -1
- package/dist/entity-table/editors/tags-editor.d.ts.map +1 -1
- package/dist/entity-table/editors/text-format-editor.d.ts +32 -0
- package/dist/entity-table/editors/text-format-editor.d.ts.map +1 -0
- package/dist/entity-table/editors/uuid-editor.d.ts +14 -1
- package/dist/entity-table/editors/uuid-editor.d.ts.map +1 -1
- package/dist/entity-table/index.d.ts +13 -3
- package/dist/entity-table/index.d.ts.map +1 -1
- package/dist/entity-table/interfaces.d.ts +13 -0
- package/dist/entity-table/interfaces.d.ts.map +1 -1
- package/dist/entity-table/vtable/table-clipboard.d.ts +31 -2
- package/dist/entity-table/vtable/table-clipboard.d.ts.map +1 -1
- package/dist/entity-table/vtable/table-factory.d.ts +25 -5
- package/dist/entity-table/vtable/table-factory.d.ts.map +1 -1
- package/dist/entity-table/vtable/table-keyboard.d.ts +18 -1
- package/dist/entity-table/vtable/table-keyboard.d.ts.map +1 -1
- package/dist/entity-table/vtable/table-operations.d.ts +44 -3
- package/dist/entity-table/vtable/table-operations.d.ts.map +1 -1
- package/dist/entity-table/vtable/table-row-move.d.ts +88 -0
- package/dist/entity-table/vtable/table-row-move.d.ts.map +1 -0
- package/dist/entity-table/vtable/table-theme.d.ts +47 -2
- package/dist/entity-table/vtable/table-theme.d.ts.map +1 -1
- package/dist/entity-table/vtable/table-tooltip.d.ts +7 -1
- package/dist/entity-table/vtable/table-tooltip.d.ts.map +1 -1
- package/dist/entity-table/vtable/vtable-compat.d.ts +33 -5
- package/dist/entity-table/vtable/vtable-compat.d.ts.map +1 -1
- package/dist/entity-value.utils.d.ts +50 -2
- package/dist/entity-value.utils.d.ts.map +1 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4392 -64471
- package/dist/query-builder/models/config.interface.d.ts +2 -2
- package/dist/query-builder/models/operator.interface.d.ts +6 -2
- package/dist/query-builder/models/operator.interface.d.ts.map +1 -1
- package/dist/query-builder/models/query-builder-state.d.ts +31 -2
- package/dist/query-builder/models/query-builder-state.d.ts.map +1 -1
- package/dist/query-builder/models/validation.interface.d.ts +2 -2
- package/dist/query-builder/services/operator-registry.service.d.ts +13 -3
- package/dist/query-builder/services/operator-registry.service.d.ts.map +1 -1
- package/dist/query-builder/services/query-builder.service.d.ts +16 -6
- package/dist/query-builder/services/query-builder.service.d.ts.map +1 -1
- package/dist/query-builder/services/query-converter.service.d.ts +10 -2
- package/dist/query-builder/services/query-converter.service.d.ts.map +1 -1
- package/dist/query-builder/services/schema-parser.service.d.ts +10 -2
- package/dist/query-builder/services/schema-parser.service.d.ts.map +1 -1
- package/dist/query-builder/services/validation.service.d.ts +34 -4
- package/dist/query-builder/services/validation.service.d.ts.map +1 -1
- package/dist/query-builder/utils/date.d.ts +12 -0
- package/dist/query-builder/utils/date.d.ts.map +1 -1
- package/dist/query-builder/utils/field-tree.d.ts +7 -1
- package/dist/query-builder/utils/field-tree.d.ts.map +1 -1
- package/dist/query-builder/utils/id.d.ts +2 -0
- package/dist/query-builder/utils/id.d.ts.map +1 -1
- package/dist/query-builder/utils/metadata-field-extractor.d.ts +15 -3
- package/dist/query-builder/utils/metadata-field-extractor.d.ts.map +1 -1
- package/dist/query-builder/utils/popover-position.d.ts +11 -0
- package/dist/query-builder/utils/popover-position.d.ts.map +1 -1
- package/dist/query-builder/utils/schema-factory.d.ts +7 -3
- package/dist/query-builder/utils/structural-equal.d.ts +4 -0
- package/dist/query-builder/utils/structural-equal.d.ts.map +1 -1
- package/dist/query-builder/utils/value-input.d.ts +21 -1
- package/dist/query-builder/utils/value-input.d.ts.map +1 -1
- package/dist/structural-equal.d.ts +5 -1
- package/dist/structural-equal.d.ts.map +1 -1
- package/package.json +34 -10
- package/src/cn.ts +21 -0
- package/src/entity-capabilities.ts +37 -0
- package/src/entity-detail/detail-tabs.ts +48 -0
- package/src/entity-detail/index.ts +7 -0
- package/src/entity-detail/interfaces.ts +55 -0
- package/src/entity-field.utils.ts +205 -0
- package/src/entity-form/form-data.ts +83 -0
- package/src/entity-form/form-fields.ts +48 -0
- package/src/entity-form/form-validation.ts +34 -0
- package/src/entity-form/index.ts +9 -0
- package/src/entity-form/interfaces.ts +116 -0
- package/src/entity-list/manual-order-list.ts +159 -0
- package/src/entity-table/columns/build-editable-columns.ts +184 -0
- package/src/entity-table/columns/column-utils.ts +657 -0
- package/src/entity-table/editors/color-editor.ts +239 -0
- package/src/entity-table/editors/date-editor.ts +169 -0
- package/src/entity-table/editors/enum-editor.ts +167 -0
- package/src/entity-table/editors/global-overlay-editor.ts +277 -0
- package/src/entity-table/editors/icon-list-editor.ts +130 -0
- package/src/entity-table/editors/json-editor.ts +212 -0
- package/src/entity-table/editors/key-value-editor.ts +595 -0
- package/src/entity-table/editors/lucide-svg.ts +78 -0
- package/src/entity-table/editors/multiselect-editor.ts +171 -0
- package/src/entity-table/editors/number-editor.ts +322 -0
- package/src/entity-table/editors/relation-editor.ts +316 -0
- package/src/entity-table/editors/safe-list-editor.ts +17 -0
- package/src/entity-table/editors/tags-editor.ts +239 -0
- package/src/entity-table/editors/text-format-editor.ts +220 -0
- package/src/entity-table/editors/uuid-editor.ts +198 -0
- package/src/entity-table/index.ts +96 -0
- package/src/entity-table/interfaces.ts +72 -0
- package/src/entity-table/vtable/table-clipboard.ts +419 -0
- package/src/entity-table/vtable/table-factory.ts +117 -0
- package/src/entity-table/vtable/table-keyboard.ts +89 -0
- package/src/entity-table/vtable/table-operations.ts +123 -0
- package/src/entity-table/vtable/table-row-move.ts +122 -0
- package/src/entity-table/vtable/table-theme.ts +181 -0
- package/src/entity-table/vtable/table-tooltip.ts +70 -0
- package/src/entity-table/vtable/vtable-compat.ts +84 -0
- package/src/entity-value.utils.ts +456 -0
- package/src/index.ts +57 -0
- package/src/query-builder/models/config.interface.ts +31 -0
- package/src/query-builder/models/index.ts +8 -0
- package/src/query-builder/models/operator.interface.ts +191 -0
- package/src/query-builder/models/query-builder-state.ts +222 -0
- package/src/query-builder/models/validation.interface.ts +184 -0
- package/src/query-builder/services/index.ts +9 -0
- package/src/query-builder/services/operator-registry.service.ts +243 -0
- package/src/query-builder/services/query-builder.service.ts +568 -0
- package/src/query-builder/services/query-converter.service.ts +153 -0
- package/src/query-builder/services/schema-parser.service.ts +309 -0
- package/src/query-builder/services/validation.service.ts +390 -0
- package/src/query-builder/utils/date.ts +35 -0
- package/src/query-builder/utils/field-tree.ts +400 -0
- package/src/query-builder/utils/id.ts +15 -0
- package/src/query-builder/utils/index.ts +12 -0
- package/src/query-builder/utils/metadata-field-extractor.ts +460 -0
- package/src/query-builder/utils/popover-position.ts +59 -0
- package/src/query-builder/utils/schema-factory.ts +75 -0
- package/src/query-builder/utils/structural-equal.ts +5 -0
- package/src/query-builder/utils/value-input.ts +105 -0
- package/src/structural-equal.ts +49 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import type { OperatorName } from '@aiao/rxdb';
|
|
2
|
+
import type { PropertyType } from './query-builder-state.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 操作符定义
|
|
6
|
+
* 包含操作符的元数据和约束
|
|
7
|
+
*/
|
|
8
|
+
export interface OperatorDefinition {
|
|
9
|
+
/**
|
|
10
|
+
* 操作符键值(使用 RxDB 的 OperatorName)
|
|
11
|
+
*/
|
|
12
|
+
key: OperatorName;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 显示标签(支持国际化)
|
|
16
|
+
*/
|
|
17
|
+
label: string;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 值类型
|
|
21
|
+
* - single: 单个值 (例如 "=")
|
|
22
|
+
* - array: 值数组 (例如 "in")
|
|
23
|
+
* - range: 范围值 [min, max] (例如 "between")
|
|
24
|
+
* - none: 无需值 (例如 "null")
|
|
25
|
+
* - subquery: 子查询条件 (例如 "exists" - 可选的嵌套规则组)
|
|
26
|
+
*/
|
|
27
|
+
valueType: 'single' | 'array' | 'range' | 'none' | 'subquery';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 适用的字段类型
|
|
31
|
+
*/
|
|
32
|
+
applicableTypes: PropertyType[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* 操作符类型(直接复用 RxDB 定义)
|
|
37
|
+
*/
|
|
38
|
+
export type QueryBuilderOperator = OperatorName;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 默认操作符定义列表
|
|
42
|
+
*/
|
|
43
|
+
export const DEFAULT_OPERATORS: OperatorDefinition[] = [
|
|
44
|
+
// 相等操作符
|
|
45
|
+
{
|
|
46
|
+
key: '=',
|
|
47
|
+
label: '等于',
|
|
48
|
+
valueType: 'single',
|
|
49
|
+
applicableTypes: ['uuid', 'string', 'number', 'boolean', 'date', 'enum']
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
key: '!=',
|
|
53
|
+
label: '不等于',
|
|
54
|
+
valueType: 'single',
|
|
55
|
+
applicableTypes: ['uuid', 'string', 'number', 'boolean', 'date', 'enum']
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
// 比较操作符
|
|
59
|
+
{
|
|
60
|
+
key: '<',
|
|
61
|
+
label: '小于',
|
|
62
|
+
valueType: 'single',
|
|
63
|
+
applicableTypes: ['number', 'date', 'string']
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
key: '>',
|
|
67
|
+
label: '大于',
|
|
68
|
+
valueType: 'single',
|
|
69
|
+
applicableTypes: ['number', 'date', 'string']
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
key: '<=',
|
|
73
|
+
label: '小于等于',
|
|
74
|
+
valueType: 'single',
|
|
75
|
+
applicableTypes: ['number', 'date', 'string']
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
key: '>=',
|
|
79
|
+
label: '大于等于',
|
|
80
|
+
valueType: 'single',
|
|
81
|
+
applicableTypes: ['number', 'date', 'string']
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
// 字符串操作符
|
|
85
|
+
{
|
|
86
|
+
key: 'contains',
|
|
87
|
+
label: '包含',
|
|
88
|
+
valueType: 'single',
|
|
89
|
+
applicableTypes: ['string', 'array']
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
key: 'notContains',
|
|
93
|
+
label: '不包含',
|
|
94
|
+
valueType: 'single',
|
|
95
|
+
applicableTypes: ['string', 'array']
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
key: 'startsWith',
|
|
99
|
+
label: '开头是',
|
|
100
|
+
valueType: 'single',
|
|
101
|
+
applicableTypes: ['string']
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
key: 'notStartsWith',
|
|
105
|
+
label: '开头不是',
|
|
106
|
+
valueType: 'single',
|
|
107
|
+
applicableTypes: ['string']
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
key: 'endsWith',
|
|
111
|
+
label: '结尾是',
|
|
112
|
+
valueType: 'single',
|
|
113
|
+
applicableTypes: ['string']
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
key: 'notEndsWith',
|
|
117
|
+
label: '结尾不是',
|
|
118
|
+
valueType: 'single',
|
|
119
|
+
applicableTypes: ['string']
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
// 空值操作符(仅在 nullable 字段时通过 getForField() 动态添加)
|
|
123
|
+
{
|
|
124
|
+
key: 'null',
|
|
125
|
+
label: '为空',
|
|
126
|
+
valueType: 'none',
|
|
127
|
+
applicableTypes: []
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
key: 'notNull',
|
|
131
|
+
label: '不为空',
|
|
132
|
+
valueType: 'none',
|
|
133
|
+
applicableTypes: []
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
// 集合操作符
|
|
137
|
+
{
|
|
138
|
+
key: 'in',
|
|
139
|
+
label: '在列表中',
|
|
140
|
+
valueType: 'array',
|
|
141
|
+
applicableTypes: ['string', 'number', 'enum']
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
key: 'notIn',
|
|
145
|
+
label: '不在列表中',
|
|
146
|
+
valueType: 'array',
|
|
147
|
+
applicableTypes: ['string', 'number', 'enum']
|
|
148
|
+
},
|
|
149
|
+
|
|
150
|
+
// 范围操作符
|
|
151
|
+
{
|
|
152
|
+
key: 'between',
|
|
153
|
+
label: '在范围内',
|
|
154
|
+
valueType: 'range',
|
|
155
|
+
applicableTypes: ['number', 'date']
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
key: 'notBetween',
|
|
159
|
+
label: '不在范围内',
|
|
160
|
+
valueType: 'range',
|
|
161
|
+
applicableTypes: ['number', 'date']
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
// 关系操作符
|
|
165
|
+
{
|
|
166
|
+
key: 'exists',
|
|
167
|
+
label: '存在',
|
|
168
|
+
valueType: 'subquery',
|
|
169
|
+
applicableTypes: ['relation']
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
key: 'notExists',
|
|
173
|
+
label: '不存在',
|
|
174
|
+
valueType: 'subquery',
|
|
175
|
+
applicableTypes: ['relation']
|
|
176
|
+
}
|
|
177
|
+
];
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* 根据字段类型获取适用的操作符
|
|
181
|
+
*
|
|
182
|
+
* @param type - 字段类型
|
|
183
|
+
* @param operators - 操作符定义列表(默认使用内置操作符 DEFAULT_OPERATORS)
|
|
184
|
+
* @returns 适用于该字段类型的操作符数组
|
|
185
|
+
*/
|
|
186
|
+
export function getOperatorsForType(
|
|
187
|
+
type: PropertyType,
|
|
188
|
+
operators: OperatorDefinition[] = DEFAULT_OPERATORS
|
|
189
|
+
): OperatorDefinition[] {
|
|
190
|
+
return operators.filter(op => op.applicableTypes.includes(type));
|
|
191
|
+
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { OperatorName, Rule, RuleGroup } from '@aiao/rxdb';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* UI 规则(宽松类型,用于查询构建器组件内部)
|
|
5
|
+
*
|
|
6
|
+
* @description
|
|
7
|
+
* 由于 Rule<T> 是联合类型,在 UI 组件中难以处理部分更新。
|
|
8
|
+
* 此类型提供宽松的字段类型,方便 UI 组件操作。
|
|
9
|
+
*/
|
|
10
|
+
export interface UIRule {
|
|
11
|
+
/**
|
|
12
|
+
* 规则唯一标识符
|
|
13
|
+
*/
|
|
14
|
+
id: string;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 字段名
|
|
18
|
+
*/
|
|
19
|
+
field: string;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 操作符
|
|
23
|
+
*/
|
|
24
|
+
operator: string;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 规则值(可选)
|
|
28
|
+
*/
|
|
29
|
+
value?: unknown;
|
|
30
|
+
/**
|
|
31
|
+
* EXISTS/NOT EXISTS 操作符的子查询条件
|
|
32
|
+
*/
|
|
33
|
+
where?: QueryBuilderRuleGroup<Record<string, unknown>>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 查询规则(复用 RxDB Rule 类型 + UI 元数据)
|
|
38
|
+
*
|
|
39
|
+
* @template T - 实体类型
|
|
40
|
+
* @template K - 字段键类型(自动推断)
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* interface User {
|
|
45
|
+
* name: string;
|
|
46
|
+
* age: number;
|
|
47
|
+
* active: boolean;
|
|
48
|
+
* }
|
|
49
|
+
*
|
|
50
|
+
* const rule: QueryBuilderRule<User> = {
|
|
51
|
+
* id: 'rule-1',
|
|
52
|
+
* field: 'name', // ✅ 类型安全:只能是 'name' | 'age' | 'active'
|
|
53
|
+
* operator: 'contains',
|
|
54
|
+
* value: 'John' // ✅ 类型推断为 string
|
|
55
|
+
* };
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export type QueryBuilderRule<T = Record<string, unknown>> = UIRule & {
|
|
59
|
+
/**
|
|
60
|
+
* 规则唯一标识符
|
|
61
|
+
* 用于 React key, Angular trackBy, Vue :key
|
|
62
|
+
*/
|
|
63
|
+
id: string;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 字段名(类型安全的实体字段键或字符串)
|
|
67
|
+
*/
|
|
68
|
+
field: string | (keyof T & string);
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* 操作符(RxDB OperatorName 或自定义字符串)
|
|
72
|
+
*/
|
|
73
|
+
operator: OperatorName | string;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* 规则组(复用 RxDB RuleGroup 类型 + UI 元数据)
|
|
78
|
+
*
|
|
79
|
+
* @template T - 实体类型
|
|
80
|
+
*/
|
|
81
|
+
export interface QueryBuilderRuleGroup<T = Record<string, unknown>> {
|
|
82
|
+
/**
|
|
83
|
+
* 规则组唯一标识符
|
|
84
|
+
*/
|
|
85
|
+
id: string;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* 逻辑组合符
|
|
89
|
+
*/
|
|
90
|
+
combinator: 'and' | 'or';
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* 子规则列表(支持嵌套)
|
|
94
|
+
*/
|
|
95
|
+
rules: Array<QueryBuilderRule<T> | QueryBuilderRuleGroup<T>>;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 查询构建器状态(简化版本,只包含必要字段)
|
|
100
|
+
*/
|
|
101
|
+
export interface QueryBuilderState<T = Record<string, unknown>> {
|
|
102
|
+
/**
|
|
103
|
+
* 根规则组
|
|
104
|
+
*/
|
|
105
|
+
rootGroup: QueryBuilderRuleGroup<T>;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Schema 信息
|
|
110
|
+
*/
|
|
111
|
+
export interface SchemaInfo {
|
|
112
|
+
/**
|
|
113
|
+
* 实体名称
|
|
114
|
+
*/
|
|
115
|
+
entityName: string;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* 字段列表
|
|
119
|
+
*/
|
|
120
|
+
fields: FieldMetadata[];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* 字段元数据
|
|
125
|
+
*/
|
|
126
|
+
export interface FieldMetadata {
|
|
127
|
+
/**
|
|
128
|
+
* 字段名称
|
|
129
|
+
*/
|
|
130
|
+
name: string;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 显示名称
|
|
134
|
+
*/
|
|
135
|
+
displayName: string;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* 字段类型
|
|
139
|
+
*/
|
|
140
|
+
type: PropertyType;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* 字段描述
|
|
144
|
+
*/
|
|
145
|
+
description?: string;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* 是否必填
|
|
149
|
+
*/
|
|
150
|
+
required?: boolean;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 是否可空
|
|
154
|
+
*/
|
|
155
|
+
nullable?: boolean;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* 枚举值(如果适用)
|
|
159
|
+
*/
|
|
160
|
+
enum?: unknown[];
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* 正则验证(字符串类型)
|
|
164
|
+
*/
|
|
165
|
+
pattern?: string;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* 是否是关系字段
|
|
169
|
+
*/
|
|
170
|
+
isRelation?: boolean;
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* 关系目标实体名称
|
|
174
|
+
*/
|
|
175
|
+
relationTarget?: string;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* 关系类型(1:1, 1:m, m:1, m:n)
|
|
179
|
+
*/
|
|
180
|
+
relationKind?: '1:1' | '1:m' | 'm:1' | 'm:n';
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* 关系目标实体的字段列表(用于 EXISTS 子查询)
|
|
184
|
+
*/
|
|
185
|
+
relationFields?: FieldMetadata[];
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* keyValue 子属性字段列表(用于嵌套属性查询)
|
|
189
|
+
*/
|
|
190
|
+
keyValueFields?: FieldMetadata[];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* 属性类型
|
|
195
|
+
*/
|
|
196
|
+
export type PropertyType =
|
|
197
|
+
'uuid' | 'string' | 'number' | 'boolean' | 'date' | 'array' | 'object' | 'relation' | 'enum' | 'keyValue';
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 类型守卫:判断是否为规则组
|
|
201
|
+
*
|
|
202
|
+
* @param item - 待判断的规则或规则组
|
|
203
|
+
* @returns 若为规则组则返回 true,否则返回 false
|
|
204
|
+
*/
|
|
205
|
+
export function isRuleGroup<T>(item: QueryBuilderRule<T> | QueryBuilderRuleGroup<T>): item is QueryBuilderRuleGroup<T> {
|
|
206
|
+
return 'combinator' in item && 'rules' in item;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* 类型守卫:判断是否为规则
|
|
211
|
+
*
|
|
212
|
+
* @param item - 待判断的规则或规则组
|
|
213
|
+
* @returns 若为规则则返回 true,否则返回 false
|
|
214
|
+
*/
|
|
215
|
+
export function isRule<T>(item: QueryBuilderRule<T> | QueryBuilderRuleGroup<T>): item is QueryBuilderRule<T> {
|
|
216
|
+
return 'field' in item && 'operator' in item;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* 类型重导出:操作符名及 RxDB 原生规则、规则组类型
|
|
221
|
+
*/
|
|
222
|
+
export type { OperatorName, Rule, RuleGroup };
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import type { OperatorName } from '@aiao/rxdb';
|
|
2
|
+
import type { PropertyType } from './query-builder-state.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 验证规则
|
|
6
|
+
*/
|
|
7
|
+
export interface ValidationRule {
|
|
8
|
+
/**
|
|
9
|
+
* 规则名称
|
|
10
|
+
*/
|
|
11
|
+
name: string;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 适用的字段类型(可选,undefined 表示适用于所有类型)
|
|
15
|
+
*/
|
|
16
|
+
appliesTo?: PropertyType[];
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 错误消息
|
|
20
|
+
*/
|
|
21
|
+
message: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 验证函数
|
|
25
|
+
* @returns true 表示通过,false 表示失败
|
|
26
|
+
*/
|
|
27
|
+
validate: (context: ValidationContext) => boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 验证上下文
|
|
32
|
+
*/
|
|
33
|
+
export interface ValidationContext {
|
|
34
|
+
/**
|
|
35
|
+
* 字段类型
|
|
36
|
+
*/
|
|
37
|
+
fieldType: PropertyType;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 操作符
|
|
41
|
+
*/
|
|
42
|
+
operator: OperatorName;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 当前值
|
|
46
|
+
*/
|
|
47
|
+
value: unknown;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 是否必填
|
|
51
|
+
*/
|
|
52
|
+
required?: boolean;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 枚举值
|
|
56
|
+
*/
|
|
57
|
+
enum?: unknown[];
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 正则验证
|
|
61
|
+
*/
|
|
62
|
+
pattern?: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 验证错误项
|
|
67
|
+
*/
|
|
68
|
+
export interface ValidationError {
|
|
69
|
+
/**
|
|
70
|
+
* 字段名
|
|
71
|
+
*/
|
|
72
|
+
field: string;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 规则名
|
|
76
|
+
*/
|
|
77
|
+
rule: string;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* 错误消息
|
|
81
|
+
*/
|
|
82
|
+
message: string;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* 验证结果
|
|
87
|
+
*/
|
|
88
|
+
export interface ValidationResult {
|
|
89
|
+
/**
|
|
90
|
+
* 是否有效
|
|
91
|
+
*/
|
|
92
|
+
valid: boolean;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* 错误列表
|
|
96
|
+
*/
|
|
97
|
+
errors?: ValidationError[];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* 跳过 nil 和数组值的前置检查。
|
|
102
|
+
* 内置验证规则共用:值为 null/undefined 时不验证,数组由 valueType 规则处理。
|
|
103
|
+
*
|
|
104
|
+
* @returns `true` 表示应跳过后续验证(值为 nil 或数组)
|
|
105
|
+
*/
|
|
106
|
+
function shouldSkipValidation(value: unknown): boolean {
|
|
107
|
+
return value === undefined || value === null || Array.isArray(value);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* 内置验证规则
|
|
112
|
+
*/
|
|
113
|
+
export const BUILTIN_VALIDATION_RULES: ValidationRule[] = [
|
|
114
|
+
{
|
|
115
|
+
name: 'stringType',
|
|
116
|
+
appliesTo: ['string'],
|
|
117
|
+
message: '值必须是字符串类型',
|
|
118
|
+
validate: context => {
|
|
119
|
+
if (shouldSkipValidation(context.value)) return true;
|
|
120
|
+
return typeof context.value === 'string';
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: 'numberType',
|
|
125
|
+
appliesTo: ['number'],
|
|
126
|
+
message: '值必须是数字类型',
|
|
127
|
+
validate: context => {
|
|
128
|
+
if (shouldSkipValidation(context.value)) return true;
|
|
129
|
+
return typeof context.value === 'number' && !isNaN(context.value);
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: 'booleanType',
|
|
134
|
+
appliesTo: ['boolean'],
|
|
135
|
+
message: '值必须是布尔类型',
|
|
136
|
+
validate: context => {
|
|
137
|
+
if (shouldSkipValidation(context.value)) return true;
|
|
138
|
+
return typeof context.value === 'boolean';
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: 'dateType',
|
|
143
|
+
appliesTo: ['date'],
|
|
144
|
+
message: '值必须是有效日期',
|
|
145
|
+
validate: context => {
|
|
146
|
+
if (shouldSkipValidation(context.value)) return true;
|
|
147
|
+
if (context.value instanceof Date) {
|
|
148
|
+
return !isNaN(context.value.getTime());
|
|
149
|
+
}
|
|
150
|
+
if (typeof context.value === 'string') {
|
|
151
|
+
const date = new Date(context.value);
|
|
152
|
+
return !isNaN(date.getTime());
|
|
153
|
+
}
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: 'enumType',
|
|
159
|
+
appliesTo: ['enum'],
|
|
160
|
+
message: '值必须是枚举中的有效选项',
|
|
161
|
+
validate: context => {
|
|
162
|
+
if (context.value === undefined || context.value === null) return true;
|
|
163
|
+
if (!context.enum || context.enum.length === 0) return true;
|
|
164
|
+
if (Array.isArray(context.value)) {
|
|
165
|
+
return (context.value as unknown[]).every(v => (context.enum as unknown[]).includes(v));
|
|
166
|
+
}
|
|
167
|
+
return context.enum.includes(context.value);
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
name: 'patternType',
|
|
172
|
+
appliesTo: ['string'],
|
|
173
|
+
message: '值不符合要求的格式',
|
|
174
|
+
validate: context => {
|
|
175
|
+
if (shouldSkipValidation(context.value)) return true;
|
|
176
|
+
if (!context.pattern || typeof context.value !== 'string') return true;
|
|
177
|
+
try {
|
|
178
|
+
return new RegExp(context.pattern).test(context.value);
|
|
179
|
+
} catch {
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Services 导出
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export * from './operator-registry.service.js';
|
|
6
|
+
export * from './query-builder.service.js';
|
|
7
|
+
export * from './query-converter.service.js';
|
|
8
|
+
export * from './schema-parser.service.js';
|
|
9
|
+
export * from './validation.service.js';
|