@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.
Files changed (181) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +43 -6
  3. package/dist/cn.d.ts +19 -0
  4. package/dist/cn.d.ts.map +1 -0
  5. package/dist/entity-capabilities.d.ts +31 -0
  6. package/dist/entity-capabilities.d.ts.map +1 -0
  7. package/dist/entity-detail/detail-tabs.d.ts +13 -2
  8. package/dist/entity-detail/detail-tabs.d.ts.map +1 -1
  9. package/dist/entity-detail/index.d.ts +5 -0
  10. package/dist/entity-detail/index.d.ts.map +1 -1
  11. package/dist/entity-detail/interfaces.d.ts +29 -1
  12. package/dist/entity-detail/interfaces.d.ts.map +1 -1
  13. package/dist/entity-field.utils.d.ts +60 -2
  14. package/dist/entity-field.utils.d.ts.map +1 -1
  15. package/dist/entity-form/form-data.d.ts +22 -1
  16. package/dist/entity-form/form-data.d.ts.map +1 -1
  17. package/dist/entity-form/form-fields.d.ts +25 -2
  18. package/dist/entity-form/form-fields.d.ts.map +1 -1
  19. package/dist/entity-form/form-validation.d.ts +20 -2
  20. package/dist/entity-form/form-validation.d.ts.map +1 -1
  21. package/dist/entity-form/index.d.ts +5 -0
  22. package/dist/entity-form/index.d.ts.map +1 -1
  23. package/dist/entity-form/interfaces.d.ts +65 -1
  24. package/dist/entity-form/interfaces.d.ts.map +1 -1
  25. package/dist/entity-list/manual-order-list.d.ts +99 -0
  26. package/dist/entity-list/manual-order-list.d.ts.map +1 -0
  27. package/dist/entity-table/columns/build-editable-columns.d.ts +26 -4
  28. package/dist/entity-table/columns/build-editable-columns.d.ts.map +1 -1
  29. package/dist/entity-table/columns/column-utils.d.ts +78 -12
  30. package/dist/entity-table/columns/column-utils.d.ts.map +1 -1
  31. package/dist/entity-table/editors/color-editor.d.ts +23 -0
  32. package/dist/entity-table/editors/color-editor.d.ts.map +1 -0
  33. package/dist/entity-table/editors/date-editor.d.ts +6 -1
  34. package/dist/entity-table/editors/date-editor.d.ts.map +1 -1
  35. package/dist/entity-table/editors/enum-editor.d.ts +11 -1
  36. package/dist/entity-table/editors/enum-editor.d.ts.map +1 -1
  37. package/dist/entity-table/editors/global-overlay-editor.d.ts +27 -4
  38. package/dist/entity-table/editors/global-overlay-editor.d.ts.map +1 -1
  39. package/dist/entity-table/editors/icon-list-editor.d.ts +13 -1
  40. package/dist/entity-table/editors/icon-list-editor.d.ts.map +1 -1
  41. package/dist/entity-table/editors/json-editor.d.ts +6 -1
  42. package/dist/entity-table/editors/json-editor.d.ts.map +1 -1
  43. package/dist/entity-table/editors/key-value-editor.d.ts +12 -2
  44. package/dist/entity-table/editors/key-value-editor.d.ts.map +1 -1
  45. package/dist/entity-table/editors/lucide-svg.d.ts +3 -2
  46. package/dist/entity-table/editors/lucide-svg.d.ts.map +1 -1
  47. package/dist/entity-table/editors/multiselect-editor.d.ts +24 -6
  48. package/dist/entity-table/editors/multiselect-editor.d.ts.map +1 -1
  49. package/dist/entity-table/editors/number-editor.d.ts +33 -3
  50. package/dist/entity-table/editors/number-editor.d.ts.map +1 -1
  51. package/dist/entity-table/editors/relation-editor.d.ts +14 -2
  52. package/dist/entity-table/editors/relation-editor.d.ts.map +1 -1
  53. package/dist/entity-table/editors/safe-list-editor.d.ts +1 -0
  54. package/dist/entity-table/editors/safe-list-editor.d.ts.map +1 -1
  55. package/dist/entity-table/editors/tags-editor.d.ts +12 -1
  56. package/dist/entity-table/editors/tags-editor.d.ts.map +1 -1
  57. package/dist/entity-table/editors/text-format-editor.d.ts +32 -0
  58. package/dist/entity-table/editors/text-format-editor.d.ts.map +1 -0
  59. package/dist/entity-table/editors/uuid-editor.d.ts +14 -1
  60. package/dist/entity-table/editors/uuid-editor.d.ts.map +1 -1
  61. package/dist/entity-table/index.d.ts +13 -3
  62. package/dist/entity-table/index.d.ts.map +1 -1
  63. package/dist/entity-table/interfaces.d.ts +13 -0
  64. package/dist/entity-table/interfaces.d.ts.map +1 -1
  65. package/dist/entity-table/vtable/table-clipboard.d.ts +31 -2
  66. package/dist/entity-table/vtable/table-clipboard.d.ts.map +1 -1
  67. package/dist/entity-table/vtable/table-factory.d.ts +25 -5
  68. package/dist/entity-table/vtable/table-factory.d.ts.map +1 -1
  69. package/dist/entity-table/vtable/table-keyboard.d.ts +18 -1
  70. package/dist/entity-table/vtable/table-keyboard.d.ts.map +1 -1
  71. package/dist/entity-table/vtable/table-operations.d.ts +44 -3
  72. package/dist/entity-table/vtable/table-operations.d.ts.map +1 -1
  73. package/dist/entity-table/vtable/table-row-move.d.ts +88 -0
  74. package/dist/entity-table/vtable/table-row-move.d.ts.map +1 -0
  75. package/dist/entity-table/vtable/table-theme.d.ts +47 -2
  76. package/dist/entity-table/vtable/table-theme.d.ts.map +1 -1
  77. package/dist/entity-table/vtable/table-tooltip.d.ts +7 -1
  78. package/dist/entity-table/vtable/table-tooltip.d.ts.map +1 -1
  79. package/dist/entity-table/vtable/vtable-compat.d.ts +33 -5
  80. package/dist/entity-table/vtable/vtable-compat.d.ts.map +1 -1
  81. package/dist/entity-value.utils.d.ts +50 -2
  82. package/dist/entity-value.utils.d.ts.map +1 -1
  83. package/dist/index.d.ts +9 -0
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js +4392 -64471
  86. package/dist/query-builder/models/config.interface.d.ts +2 -2
  87. package/dist/query-builder/models/operator.interface.d.ts +6 -2
  88. package/dist/query-builder/models/operator.interface.d.ts.map +1 -1
  89. package/dist/query-builder/models/query-builder-state.d.ts +31 -2
  90. package/dist/query-builder/models/query-builder-state.d.ts.map +1 -1
  91. package/dist/query-builder/models/validation.interface.d.ts +2 -2
  92. package/dist/query-builder/services/operator-registry.service.d.ts +13 -3
  93. package/dist/query-builder/services/operator-registry.service.d.ts.map +1 -1
  94. package/dist/query-builder/services/query-builder.service.d.ts +16 -6
  95. package/dist/query-builder/services/query-builder.service.d.ts.map +1 -1
  96. package/dist/query-builder/services/query-converter.service.d.ts +10 -2
  97. package/dist/query-builder/services/query-converter.service.d.ts.map +1 -1
  98. package/dist/query-builder/services/schema-parser.service.d.ts +10 -2
  99. package/dist/query-builder/services/schema-parser.service.d.ts.map +1 -1
  100. package/dist/query-builder/services/validation.service.d.ts +34 -4
  101. package/dist/query-builder/services/validation.service.d.ts.map +1 -1
  102. package/dist/query-builder/utils/date.d.ts +12 -0
  103. package/dist/query-builder/utils/date.d.ts.map +1 -1
  104. package/dist/query-builder/utils/field-tree.d.ts +7 -1
  105. package/dist/query-builder/utils/field-tree.d.ts.map +1 -1
  106. package/dist/query-builder/utils/id.d.ts +2 -0
  107. package/dist/query-builder/utils/id.d.ts.map +1 -1
  108. package/dist/query-builder/utils/metadata-field-extractor.d.ts +15 -3
  109. package/dist/query-builder/utils/metadata-field-extractor.d.ts.map +1 -1
  110. package/dist/query-builder/utils/popover-position.d.ts +11 -0
  111. package/dist/query-builder/utils/popover-position.d.ts.map +1 -1
  112. package/dist/query-builder/utils/schema-factory.d.ts +7 -3
  113. package/dist/query-builder/utils/structural-equal.d.ts +4 -0
  114. package/dist/query-builder/utils/structural-equal.d.ts.map +1 -1
  115. package/dist/query-builder/utils/value-input.d.ts +21 -1
  116. package/dist/query-builder/utils/value-input.d.ts.map +1 -1
  117. package/dist/structural-equal.d.ts +5 -1
  118. package/dist/structural-equal.d.ts.map +1 -1
  119. package/package.json +34 -10
  120. package/src/cn.ts +21 -0
  121. package/src/entity-capabilities.ts +37 -0
  122. package/src/entity-detail/detail-tabs.ts +48 -0
  123. package/src/entity-detail/index.ts +7 -0
  124. package/src/entity-detail/interfaces.ts +55 -0
  125. package/src/entity-field.utils.ts +205 -0
  126. package/src/entity-form/form-data.ts +83 -0
  127. package/src/entity-form/form-fields.ts +48 -0
  128. package/src/entity-form/form-validation.ts +34 -0
  129. package/src/entity-form/index.ts +9 -0
  130. package/src/entity-form/interfaces.ts +116 -0
  131. package/src/entity-list/manual-order-list.ts +159 -0
  132. package/src/entity-table/columns/build-editable-columns.ts +184 -0
  133. package/src/entity-table/columns/column-utils.ts +657 -0
  134. package/src/entity-table/editors/color-editor.ts +239 -0
  135. package/src/entity-table/editors/date-editor.ts +169 -0
  136. package/src/entity-table/editors/enum-editor.ts +167 -0
  137. package/src/entity-table/editors/global-overlay-editor.ts +277 -0
  138. package/src/entity-table/editors/icon-list-editor.ts +130 -0
  139. package/src/entity-table/editors/json-editor.ts +212 -0
  140. package/src/entity-table/editors/key-value-editor.ts +595 -0
  141. package/src/entity-table/editors/lucide-svg.ts +78 -0
  142. package/src/entity-table/editors/multiselect-editor.ts +171 -0
  143. package/src/entity-table/editors/number-editor.ts +322 -0
  144. package/src/entity-table/editors/relation-editor.ts +316 -0
  145. package/src/entity-table/editors/safe-list-editor.ts +17 -0
  146. package/src/entity-table/editors/tags-editor.ts +239 -0
  147. package/src/entity-table/editors/text-format-editor.ts +220 -0
  148. package/src/entity-table/editors/uuid-editor.ts +198 -0
  149. package/src/entity-table/index.ts +96 -0
  150. package/src/entity-table/interfaces.ts +72 -0
  151. package/src/entity-table/vtable/table-clipboard.ts +419 -0
  152. package/src/entity-table/vtable/table-factory.ts +117 -0
  153. package/src/entity-table/vtable/table-keyboard.ts +89 -0
  154. package/src/entity-table/vtable/table-operations.ts +123 -0
  155. package/src/entity-table/vtable/table-row-move.ts +122 -0
  156. package/src/entity-table/vtable/table-theme.ts +181 -0
  157. package/src/entity-table/vtable/table-tooltip.ts +70 -0
  158. package/src/entity-table/vtable/vtable-compat.ts +84 -0
  159. package/src/entity-value.utils.ts +456 -0
  160. package/src/index.ts +57 -0
  161. package/src/query-builder/models/config.interface.ts +31 -0
  162. package/src/query-builder/models/index.ts +8 -0
  163. package/src/query-builder/models/operator.interface.ts +191 -0
  164. package/src/query-builder/models/query-builder-state.ts +222 -0
  165. package/src/query-builder/models/validation.interface.ts +184 -0
  166. package/src/query-builder/services/index.ts +9 -0
  167. package/src/query-builder/services/operator-registry.service.ts +243 -0
  168. package/src/query-builder/services/query-builder.service.ts +568 -0
  169. package/src/query-builder/services/query-converter.service.ts +153 -0
  170. package/src/query-builder/services/schema-parser.service.ts +309 -0
  171. package/src/query-builder/services/validation.service.ts +390 -0
  172. package/src/query-builder/utils/date.ts +35 -0
  173. package/src/query-builder/utils/field-tree.ts +400 -0
  174. package/src/query-builder/utils/id.ts +15 -0
  175. package/src/query-builder/utils/index.ts +12 -0
  176. package/src/query-builder/utils/metadata-field-extractor.ts +460 -0
  177. package/src/query-builder/utils/popover-position.ts +59 -0
  178. package/src/query-builder/utils/schema-factory.ts +75 -0
  179. package/src/query-builder/utils/structural-equal.ts +5 -0
  180. package/src/query-builder/utils/value-input.ts +105 -0
  181. 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';