pa-ruler-factory 0.0.14
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 +21 -0
- package/README.md +297 -0
- package/README.zh-CN.md +288 -0
- package/dist/index.d.mts +55 -0
- package/dist/index.mjs +340 -0
- package/package.json +71 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 puijs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
# ruler-factory
|
|
2
|
+
|
|
3
|
+
[English](./README.md) · [简体中文](./README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
A flexible, chainable validation rule factory for TypeScript/JavaScript.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- Chainable API for building complex validation rules
|
|
10
|
+
- Supports string, number, array, boolean, object, symbol, bigint, null, undefined
|
|
11
|
+
- Customizable error messages
|
|
12
|
+
- Easy to extend and integrate
|
|
13
|
+
- TypeScript support
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm add ruler-factory
|
|
19
|
+
# or
|
|
20
|
+
npm install ruler-factory
|
|
21
|
+
# or
|
|
22
|
+
yarn add ruler-factory
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Integration with UI frameworks
|
|
26
|
+
|
|
27
|
+
### Pui UI
|
|
28
|
+
|
|
29
|
+
```vue
|
|
30
|
+
<script setup lang="ts">
|
|
31
|
+
import { ref } from 'vue'
|
|
32
|
+
import { rulerFactory } from 'ruler-factory'
|
|
33
|
+
|
|
34
|
+
const r = rulerFactory((validator) => {
|
|
35
|
+
return (value) => {
|
|
36
|
+
const e = validator(value)
|
|
37
|
+
return e ? e.message : true
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const model = ref({
|
|
42
|
+
name: '',
|
|
43
|
+
email: '',
|
|
44
|
+
})
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<template>
|
|
48
|
+
<var-form>
|
|
49
|
+
<var-input
|
|
50
|
+
v-model="model.name"
|
|
51
|
+
placeholder="Name"
|
|
52
|
+
:rules="r().required('Required').min(2, 'Wrong length').done()"
|
|
53
|
+
/>
|
|
54
|
+
<var-input v-model="model.age" placeholder="Email" :rules="r().email('Must be email format').done()" />
|
|
55
|
+
</var-form>
|
|
56
|
+
</template>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Vant
|
|
60
|
+
|
|
61
|
+
```vue
|
|
62
|
+
<script setup lang="ts">
|
|
63
|
+
import { ref } from 'vue'
|
|
64
|
+
import { rulerFactory } from 'ruler-factory'
|
|
65
|
+
import type { FieldRule } from 'vant'
|
|
66
|
+
|
|
67
|
+
const r = rulerFactory<FieldRule>((validator, params) => ({
|
|
68
|
+
validator(value) {
|
|
69
|
+
const e = validator(value)
|
|
70
|
+
|
|
71
|
+
return e ? e.message : true
|
|
72
|
+
},
|
|
73
|
+
trigger: ['onChange', 'onBlur', 'onSubmit'],
|
|
74
|
+
...params,
|
|
75
|
+
}))
|
|
76
|
+
|
|
77
|
+
const model = ref({
|
|
78
|
+
name: '',
|
|
79
|
+
email: '',
|
|
80
|
+
})
|
|
81
|
+
</script>
|
|
82
|
+
|
|
83
|
+
<template>
|
|
84
|
+
<van-form>
|
|
85
|
+
<van-cell-group inset>
|
|
86
|
+
<van-field v-model="model.name" label="Name" placeholder="Name" :rules="r().required('Required').done()" />
|
|
87
|
+
<van-field
|
|
88
|
+
v-model="model.email"
|
|
89
|
+
label="Email"
|
|
90
|
+
placeholder="Email"
|
|
91
|
+
:rules="r().email('Must be email format').done()"
|
|
92
|
+
/>
|
|
93
|
+
</van-cell-group>
|
|
94
|
+
</van-form>
|
|
95
|
+
</template>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Naive UI
|
|
99
|
+
|
|
100
|
+
```vue
|
|
101
|
+
<script setup lang="ts">
|
|
102
|
+
import { ref } from 'vue'
|
|
103
|
+
import type { FormItemRule } from 'naive-ui'
|
|
104
|
+
import { rulerFactory } from 'ruler-factory'
|
|
105
|
+
|
|
106
|
+
const r = rulerFactory<FormItemRule>((validator, params = {}) => ({
|
|
107
|
+
trigger: ['blur', 'change', 'input'],
|
|
108
|
+
validator: (_, value) => validator(value),
|
|
109
|
+
...params,
|
|
110
|
+
}))
|
|
111
|
+
|
|
112
|
+
const model = ref({
|
|
113
|
+
name: '',
|
|
114
|
+
age: 20,
|
|
115
|
+
})
|
|
116
|
+
</script>
|
|
117
|
+
|
|
118
|
+
<template>
|
|
119
|
+
<n-form :model>
|
|
120
|
+
<n-form-item path="name" label="Name" :rule="r().required('Required').min(2, 'Wrong length').done()">
|
|
121
|
+
<n-input v-model:value="model.name" />
|
|
122
|
+
</n-form-item>
|
|
123
|
+
<n-form-item path="age" label="Age" :rule="r().number().required('Required').negative('Must be negative').done()">
|
|
124
|
+
<n-input-number v-model:value="model.age" />
|
|
125
|
+
</n-form-item>
|
|
126
|
+
</n-form>
|
|
127
|
+
</template>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Element Plus
|
|
131
|
+
|
|
132
|
+
```vue
|
|
133
|
+
<script setup lang="ts">
|
|
134
|
+
import { ref } from 'vue'
|
|
135
|
+
import type { FormItemRule } from 'element-plus'
|
|
136
|
+
import { rulerFactory } from 'ruler-factory'
|
|
137
|
+
|
|
138
|
+
const r = rulerFactory<FormItemRule>((validator, params) => ({
|
|
139
|
+
validator(_, value, callback) {
|
|
140
|
+
const e = validator(value)
|
|
141
|
+
|
|
142
|
+
e ? callback(e) : callback()
|
|
143
|
+
},
|
|
144
|
+
trigger: ['blur', 'change', 'input'],
|
|
145
|
+
...params,
|
|
146
|
+
}))
|
|
147
|
+
|
|
148
|
+
const model = ref({
|
|
149
|
+
name: '',
|
|
150
|
+
email: '',
|
|
151
|
+
})
|
|
152
|
+
</script>
|
|
153
|
+
|
|
154
|
+
<template>
|
|
155
|
+
<el-form :model>
|
|
156
|
+
<el-form-item prop="name" label="Name" :rules="r().required('Required').done()">
|
|
157
|
+
<el-input v-model="model.name" />
|
|
158
|
+
</el-form-item>
|
|
159
|
+
<el-form-item prop="email" label="Email" :rules="r().email('Must be email format').done()">
|
|
160
|
+
<el-input v-model="model.email" />
|
|
161
|
+
</el-form-item>
|
|
162
|
+
</el-form>
|
|
163
|
+
</template>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Extend API
|
|
167
|
+
|
|
168
|
+
Take `Naive UI` as an example
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
import { FormItemRule } from 'naive-ui'
|
|
172
|
+
import { RulerContext, rulerFactory, RulerFactoryMessage } from 'ruler-factory'
|
|
173
|
+
|
|
174
|
+
interface RulerExtendedContext {
|
|
175
|
+
ip(message: RulerFactoryMessage, params?: FormItemRule): RulerContext<FormItemRule, FormItemRule, this>
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const r = rulerFactory<FormItemRule, FormItemRule, RulerExtendedContext>(
|
|
179
|
+
(validator, params = {}) => ({
|
|
180
|
+
trigger: ['blur', 'change', 'input'],
|
|
181
|
+
validator: (_, value) => validator(value),
|
|
182
|
+
...params,
|
|
183
|
+
}),
|
|
184
|
+
(ctx) => {
|
|
185
|
+
function ip(message: RulerFactoryMessage, params?: FormItemRule) {
|
|
186
|
+
ctx.addRule((value) => {
|
|
187
|
+
// Implement isString and isIP by yourself
|
|
188
|
+
if (!isString(value) || !isIP(value)) {
|
|
189
|
+
return new Error(ctx.getMessage(message))
|
|
190
|
+
}
|
|
191
|
+
}, params)
|
|
192
|
+
|
|
193
|
+
return ctx
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return { ip }
|
|
197
|
+
},
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
r().ip('ip format error').done()
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## API
|
|
204
|
+
|
|
205
|
+
### Types Validation
|
|
206
|
+
|
|
207
|
+
- `.string(message?, params?)`
|
|
208
|
+
- `.number(message?, params?)`
|
|
209
|
+
- `.array(message?, params?)`
|
|
210
|
+
- `.boolean(message?, params?)`
|
|
211
|
+
- `.object(message?, params?)`
|
|
212
|
+
- `.symbol(message?, params?)`
|
|
213
|
+
- `.bigint(message?, params?)`
|
|
214
|
+
- `.null(message?, params?)`
|
|
215
|
+
- `.undefined(message?, params?)`
|
|
216
|
+
- `.true(message?, params?)`
|
|
217
|
+
- `.false(message?, params?)`
|
|
218
|
+
|
|
219
|
+
### Non Empty Validation
|
|
220
|
+
|
|
221
|
+
- `.required(message)`
|
|
222
|
+
|
|
223
|
+
### String Validation
|
|
224
|
+
|
|
225
|
+
- `.min(value, message, params?)`
|
|
226
|
+
- `.max(value, message, params?)`
|
|
227
|
+
- `.length(value, message, params?)`
|
|
228
|
+
- `.regex(regexp, message, params?)`
|
|
229
|
+
- `.startsWith(value, message, params?)`
|
|
230
|
+
- `.endsWith(value, message, params?)`
|
|
231
|
+
- `.includes(value, message, params?)`
|
|
232
|
+
- `.uppercase(message, params?)`
|
|
233
|
+
- `.lowercase(message, params?)`
|
|
234
|
+
- `.email(message, params?)`
|
|
235
|
+
|
|
236
|
+
### Number Validation
|
|
237
|
+
|
|
238
|
+
- `.number().min(value, message, params?)`
|
|
239
|
+
- `.number().max(value, message, params?)`
|
|
240
|
+
- `.number().gt(value, message, params?)`
|
|
241
|
+
- `.number().gte(value, message, params?)` alias .min
|
|
242
|
+
- `.number().lt(value, message, params?)`
|
|
243
|
+
- `.number().lte(value, message, params?)` alias .max
|
|
244
|
+
- `.number().positive(value, message, params?)`
|
|
245
|
+
- `.number().negative(value, message, params?)`
|
|
246
|
+
|
|
247
|
+
### Bigint Validation
|
|
248
|
+
|
|
249
|
+
- `.bigint().min(value, message, params?)`
|
|
250
|
+
- `.bigint().max(value, message, params?)`
|
|
251
|
+
- `.bigint().gt(value, message, params?)`
|
|
252
|
+
- `.bigint().gte(value, message, params?)` alias .min
|
|
253
|
+
- `.bigint().lt(value, message, params?)`
|
|
254
|
+
- `.bigint().lte(value, message, params?)` alias .max
|
|
255
|
+
- `.bigint().positive(value, message, params?)`
|
|
256
|
+
- `.bigint().negative(value, message, params?)`
|
|
257
|
+
|
|
258
|
+
### Array Validation
|
|
259
|
+
|
|
260
|
+
- `.array().min(value, message, params?)`
|
|
261
|
+
- `.array().max(value, message, params?)`
|
|
262
|
+
- `.array().length(value, message, params?)`
|
|
263
|
+
- `.array().includes(value, message, params?)`
|
|
264
|
+
|
|
265
|
+
### Predicate Validation
|
|
266
|
+
|
|
267
|
+
- `.is(fn, message, params?)`
|
|
268
|
+
- `.not(fn, message, params?)`
|
|
269
|
+
|
|
270
|
+
### Complete rule building
|
|
271
|
+
|
|
272
|
+
- `.done()`
|
|
273
|
+
|
|
274
|
+
### Custom Rule
|
|
275
|
+
|
|
276
|
+
- `.addRule(validator)`
|
|
277
|
+
|
|
278
|
+
### Value Transformer
|
|
279
|
+
|
|
280
|
+
- `.trim()`
|
|
281
|
+
- `.toLowerCase()`
|
|
282
|
+
- `.toUpperCase()`
|
|
283
|
+
- `.transform(fn)`
|
|
284
|
+
|
|
285
|
+
## License
|
|
286
|
+
|
|
287
|
+
MIT
|
|
288
|
+
|
|
289
|
+
## Links
|
|
290
|
+
|
|
291
|
+
- [GitHub Repository](https://github.com/puijs/ruler-factory)
|
|
292
|
+
- [Issues](https://github.com/puijs/ruler-factory/issues)
|
|
293
|
+
|
|
294
|
+
## Inspired By
|
|
295
|
+
|
|
296
|
+
[`zod`](https://zod.dev/)
|
|
297
|
+
[`yup`](https://github.com/jquense/yup)
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
# ruler-factory
|
|
2
|
+
|
|
3
|
+
[English](./README.md) · [简体中文](./README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
一个灵活、可链式调用的 TypeScript/JavaScript 校验规则工厂。
|
|
6
|
+
|
|
7
|
+
## 特性
|
|
8
|
+
|
|
9
|
+
- 链式 API,可构建复杂校验规则
|
|
10
|
+
- 支持 string、number、array、boolean、object、symbol、bigint、null、undefined
|
|
11
|
+
- 可自定义错误信息
|
|
12
|
+
- 易于扩展与集成
|
|
13
|
+
- 支持 TypeScript
|
|
14
|
+
|
|
15
|
+
## 安装
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm add ruler-factory
|
|
19
|
+
# 或
|
|
20
|
+
npm install ruler-factory
|
|
21
|
+
# 或
|
|
22
|
+
yarn add ruler-factory
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 与 UI 框架集成
|
|
26
|
+
|
|
27
|
+
### Pui UI
|
|
28
|
+
|
|
29
|
+
```vue
|
|
30
|
+
<script setup lang="ts">
|
|
31
|
+
import { ref } from 'vue'
|
|
32
|
+
import { rulerFactory } from 'ruler-factory'
|
|
33
|
+
|
|
34
|
+
const r = rulerFactory((validator) => {
|
|
35
|
+
return (value) => {
|
|
36
|
+
const e = validator(value)
|
|
37
|
+
return e ? e.message : true
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const model = ref({
|
|
42
|
+
name: '',
|
|
43
|
+
email: '',
|
|
44
|
+
})
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<template>
|
|
48
|
+
<var-form>
|
|
49
|
+
<var-input v-model="model.name" placeholder="姓名" :rules="r().required('必填').min(2, '长度不正确').done()" />
|
|
50
|
+
<var-input v-model="model.age" placeholder="邮箱" :rules="r().email('必须是邮箱格式').done()" />
|
|
51
|
+
</var-form>
|
|
52
|
+
</template>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Vant
|
|
56
|
+
|
|
57
|
+
```vue
|
|
58
|
+
<script setup lang="ts">
|
|
59
|
+
import { ref } from 'vue'
|
|
60
|
+
import { rulerFactory } from 'ruler-factory'
|
|
61
|
+
import type { FieldRule } from 'vant'
|
|
62
|
+
|
|
63
|
+
const r = rulerFactory<FieldRule>((validator, params) => ({
|
|
64
|
+
validator(value) {
|
|
65
|
+
const e = validator(value)
|
|
66
|
+
|
|
67
|
+
return e ? e.message : true
|
|
68
|
+
},
|
|
69
|
+
trigger: ['onChange', 'onBlur', 'onSubmit'],
|
|
70
|
+
...params,
|
|
71
|
+
}))
|
|
72
|
+
|
|
73
|
+
const model = ref({
|
|
74
|
+
name: '',
|
|
75
|
+
email: '',
|
|
76
|
+
})
|
|
77
|
+
</script>
|
|
78
|
+
|
|
79
|
+
<template>
|
|
80
|
+
<van-form>
|
|
81
|
+
<van-cell-group inset>
|
|
82
|
+
<van-field v-model="model.name" label="姓名" placeholder="姓名" :rules="r().required('必填').done()" />
|
|
83
|
+
<van-field v-model="model.email" label="邮箱" placeholder="邮箱" :rules="r().email('必须是邮箱格式').done()" />
|
|
84
|
+
</van-cell-group>
|
|
85
|
+
</van-form>
|
|
86
|
+
</template>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Naive UI
|
|
90
|
+
|
|
91
|
+
```vue
|
|
92
|
+
<script setup lang="ts">
|
|
93
|
+
import { ref } from 'vue'
|
|
94
|
+
import type { FormItemRule } from 'naive-ui'
|
|
95
|
+
import { rulerFactory } from 'ruler-factory'
|
|
96
|
+
|
|
97
|
+
const r = rulerFactory<FormItemRule>((validator, params = {}) => ({
|
|
98
|
+
trigger: ['blur', 'change', 'input'],
|
|
99
|
+
validator: (_, value) => validator(value),
|
|
100
|
+
...params,
|
|
101
|
+
}))
|
|
102
|
+
|
|
103
|
+
const model = ref({
|
|
104
|
+
name: '',
|
|
105
|
+
age: 20,
|
|
106
|
+
})
|
|
107
|
+
</script>
|
|
108
|
+
|
|
109
|
+
<template>
|
|
110
|
+
<n-form :model>
|
|
111
|
+
<n-form-item path="name" label="姓名" :rule="r().required('必填').min(2, '长度不正确').done()">
|
|
112
|
+
<n-input v-model:value="model.name" />
|
|
113
|
+
</n-form-item>
|
|
114
|
+
<n-form-item path="age" label="年龄" :rule="r().number().required('必填').negative('必须为负数').done()">
|
|
115
|
+
<n-input-number v-model:value="model.age" />
|
|
116
|
+
</n-form-item>
|
|
117
|
+
</n-form>
|
|
118
|
+
</template>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Element Plus
|
|
122
|
+
|
|
123
|
+
```vue
|
|
124
|
+
<script setup lang="ts">
|
|
125
|
+
import { ref } from 'vue'
|
|
126
|
+
import type { FormItemRule } from 'element-plus'
|
|
127
|
+
import { rulerFactory } from 'ruler-factory'
|
|
128
|
+
|
|
129
|
+
const r = rulerFactory<FormItemRule>((validator, params) => ({
|
|
130
|
+
validator(_, value, callback) {
|
|
131
|
+
const e = validator(value)
|
|
132
|
+
|
|
133
|
+
e ? callback(e) : callback()
|
|
134
|
+
},
|
|
135
|
+
trigger: ['blur', 'change', 'input'],
|
|
136
|
+
...params,
|
|
137
|
+
}))
|
|
138
|
+
|
|
139
|
+
const model = ref({
|
|
140
|
+
name: '',
|
|
141
|
+
email: '',
|
|
142
|
+
})
|
|
143
|
+
</script>
|
|
144
|
+
|
|
145
|
+
<template>
|
|
146
|
+
<el-form :model>
|
|
147
|
+
<el-form-item prop="name" label="姓名" :rules="r().required('必填').done()">
|
|
148
|
+
<el-input v-model="model.name" />
|
|
149
|
+
</el-form-item>
|
|
150
|
+
<el-form-item prop="email" label="邮箱" :rules="r().email('必须是邮箱格式').done()">
|
|
151
|
+
<el-input v-model="model.email" />
|
|
152
|
+
</el-form-item>
|
|
153
|
+
</el-form>
|
|
154
|
+
</template>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### 扩展 API
|
|
158
|
+
|
|
159
|
+
以 Naive UI 为例
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
import { FormItemRule } from 'naive-ui'
|
|
163
|
+
import { RulerContext, rulerFactory, RulerFactoryMessage } from 'ruler-factory'
|
|
164
|
+
|
|
165
|
+
interface RulerExtendedContext {
|
|
166
|
+
ip(message: RulerFactoryMessage, params?: FormItemRule): RulerContext<FormItemRule, FormItemRule, this>
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const r = rulerFactory<FormItemRule, FormItemRule, RulerExtendedContext>(
|
|
170
|
+
(validator, params = {}) => ({
|
|
171
|
+
trigger: ['blur', 'change', 'input'],
|
|
172
|
+
validator: (_, value) => validator(value),
|
|
173
|
+
...params,
|
|
174
|
+
}),
|
|
175
|
+
(ctx) => {
|
|
176
|
+
function ip(message: RulerFactoryMessage, params?: FormItemRule) {
|
|
177
|
+
ctx.addRule((value) => {
|
|
178
|
+
// 自行实现 isString 和 isIP
|
|
179
|
+
if (!isString(value) || !isIP(value)) {
|
|
180
|
+
return new Error(ctx.getMessage(message))
|
|
181
|
+
}
|
|
182
|
+
}, params)
|
|
183
|
+
|
|
184
|
+
return ctx
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return { ip }
|
|
188
|
+
},
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
r().ip('IP 格式错误').done()
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## API
|
|
195
|
+
|
|
196
|
+
### 类型校验
|
|
197
|
+
|
|
198
|
+
- `.string(message?, params?)`
|
|
199
|
+
- `.number(message?, params?)`
|
|
200
|
+
- `.array(message?, params?)`
|
|
201
|
+
- `.boolean(message?, params?)`
|
|
202
|
+
- `.object(message?, params?)`
|
|
203
|
+
- `.symbol(message?, params?)`
|
|
204
|
+
- `.bigint(message?, params?)`
|
|
205
|
+
- `.null(message?, params?)`
|
|
206
|
+
- `.undefined(message?, params?)`
|
|
207
|
+
- `.true(message?, params?)`
|
|
208
|
+
- `.false(message?, params?)`
|
|
209
|
+
|
|
210
|
+
### 非空校验
|
|
211
|
+
|
|
212
|
+
- `.required(message)`
|
|
213
|
+
|
|
214
|
+
### 字符串校验
|
|
215
|
+
|
|
216
|
+
- `.min(value, message, params?)`
|
|
217
|
+
- `.max(value, message, params?)`
|
|
218
|
+
- `.length(value, message, params?)`
|
|
219
|
+
- `.regex(regexp, message, params?)`
|
|
220
|
+
- `.startsWith(value, message, params?)`
|
|
221
|
+
- `.endsWith(value, message, params?)`
|
|
222
|
+
- `.includes(value, message, params?)`
|
|
223
|
+
- `.uppercase(message, params?)`
|
|
224
|
+
- `.lowercase(message, params?)`
|
|
225
|
+
- `.email(message, params?)`
|
|
226
|
+
|
|
227
|
+
### 数字校验
|
|
228
|
+
|
|
229
|
+
- `.number().min(value, message, params?)`
|
|
230
|
+
- `.number().max(value, message, params?)`
|
|
231
|
+
- `.number().gt(value, message, params?)`
|
|
232
|
+
- `.number().gte(value, message, params?)` 别名 .min
|
|
233
|
+
- `.number().lt(value, message, params?)`
|
|
234
|
+
- `.number().lte(value, message, params?)` 别名 .max
|
|
235
|
+
- `.number().positive(value, message, params?)`
|
|
236
|
+
- `.number().negative(value, message, params?)`
|
|
237
|
+
|
|
238
|
+
### Bigint 校验
|
|
239
|
+
|
|
240
|
+
- `.bigint().min(value, message, params?)`
|
|
241
|
+
- `.bigint().max(value, message, params?)`
|
|
242
|
+
- `.bigint().gt(value, message, params?)`
|
|
243
|
+
- `.bigint().gte(value, message, params?)` 别名 .min
|
|
244
|
+
- `.bigint().lt(value, message, params?)`
|
|
245
|
+
- `.bigint().lte(value, message, params?)` 别名 .max
|
|
246
|
+
- `.bigint().positive(value, message, params?)`
|
|
247
|
+
- `.bigint().negative(value, message, params?)`
|
|
248
|
+
|
|
249
|
+
### 数组校验
|
|
250
|
+
|
|
251
|
+
- `.array().min(value, message, params?)`
|
|
252
|
+
- `.array().max(value, message, params?)`
|
|
253
|
+
- `.array().length(value, message, params?)`
|
|
254
|
+
- `.array().includes(value, message, params?)`
|
|
255
|
+
|
|
256
|
+
### 谓词校验
|
|
257
|
+
|
|
258
|
+
- `.is(fn, message, params?)`
|
|
259
|
+
- `.not(fn, message, params?)`
|
|
260
|
+
|
|
261
|
+
### 完成规则构建
|
|
262
|
+
|
|
263
|
+
- `.done()`
|
|
264
|
+
|
|
265
|
+
### 自定义规则
|
|
266
|
+
|
|
267
|
+
- `.addRule(validator)`
|
|
268
|
+
|
|
269
|
+
### 值转换
|
|
270
|
+
|
|
271
|
+
- `.trim()`
|
|
272
|
+
- `.toLowerCase()`
|
|
273
|
+
- `.toUpperCase()`
|
|
274
|
+
- `.transform(fn)`
|
|
275
|
+
|
|
276
|
+
## 许可证
|
|
277
|
+
|
|
278
|
+
MIT
|
|
279
|
+
|
|
280
|
+
## 链接
|
|
281
|
+
|
|
282
|
+
- [GitHub 仓库](https://github.com/puijs/ruler-factory)
|
|
283
|
+
- [Issues](https://github.com/puijs/ruler-factory/issues)
|
|
284
|
+
|
|
285
|
+
## 灵感来源
|
|
286
|
+
|
|
287
|
+
[`zod`](https://zod.dev/)
|
|
288
|
+
[`yup`](https://github.com/jquense/yup)
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
//#region src/index.d.ts
|
|
2
|
+
type RulerFactoryMessage = string | (() => string);
|
|
3
|
+
type RulerFactoryValidator = (value: any) => undefined | Error;
|
|
4
|
+
type RulerFactoryGenerator<R, P> = (validator: RulerFactoryValidator, params?: P) => R;
|
|
5
|
+
type RulerContext<R, P, E> = Omit<{
|
|
6
|
+
rules: R[];
|
|
7
|
+
addRule: (validator: RulerFactoryValidator, params?: P) => RulerContext<R, P, E>;
|
|
8
|
+
generator: RulerFactoryGenerator<R, P>;
|
|
9
|
+
getMessage: (message: RulerFactoryMessage) => string;
|
|
10
|
+
type: string;
|
|
11
|
+
string: (message?: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
12
|
+
number: (message?: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
13
|
+
array: (message?: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
14
|
+
boolean: (message?: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
15
|
+
object: (message?: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
16
|
+
symbol: (message?: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
17
|
+
bigint: (message?: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
18
|
+
null: (message?: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
19
|
+
undefined: (message?: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
20
|
+
true: (message?: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
21
|
+
false: (message?: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
22
|
+
length: (v: number, message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
23
|
+
min: (v: number | bigint, message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
24
|
+
max: (v: number | bigint, message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
25
|
+
regex: (v: RegExp, message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
26
|
+
required: (message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
27
|
+
startsWith: (v: string, message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
28
|
+
endsWith: (v: string, message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
29
|
+
includes: (v: string, message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
30
|
+
uppercase: (message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
31
|
+
lowercase: (message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
32
|
+
email: (message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
33
|
+
gt: (v: number | bigint, message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
34
|
+
gte: (v: number | bigint, message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
35
|
+
lt: (v: number | bigint, message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
36
|
+
lte: (v: number | bigint, message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
37
|
+
positive: (message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
38
|
+
negative: (message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
39
|
+
uniq: (message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
40
|
+
uniqBy: (v: (a: any, b: any) => any, message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
41
|
+
is: (v: (value: any) => boolean, message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
42
|
+
not: (v: (value: any) => boolean, message: RulerFactoryMessage, params?: P) => RulerContext<R, P, E>;
|
|
43
|
+
done: () => R[];
|
|
44
|
+
transformer: (value: any) => any;
|
|
45
|
+
transform: (v: (value: any) => any) => void;
|
|
46
|
+
trim: () => RulerContext<R, P, E>;
|
|
47
|
+
shouldTrim: boolean;
|
|
48
|
+
toLowerCase: () => RulerContext<R, P, E>;
|
|
49
|
+
shouldToLowerCase: boolean;
|
|
50
|
+
toUpperCase: () => RulerContext<R, P, E>;
|
|
51
|
+
shouldToUpperCase: boolean;
|
|
52
|
+
}, keyof E> & E;
|
|
53
|
+
declare function rulerFactory<R, P = R, E extends Record<string, any> = {}>(generator: RulerFactoryGenerator<R, P>, extend?: (ctx: RulerContext<R, P, E>) => E): () => RulerContext<R, P, E>;
|
|
54
|
+
//#endregion
|
|
55
|
+
export { RulerContext, RulerFactoryGenerator, RulerFactoryMessage, RulerFactoryValidator, rulerFactory };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
import { hasDuplicates, hasDuplicatesBy, isArray, isBoolean, isEmpty, isFunction, isNumber, isPlainObject, isString, isSymbol } from "rattail";
|
|
2
|
+
//#region src/index.ts
|
|
3
|
+
const EMAIL_REGEX = /^(?!\.)(?!.*\.\.)([a-z0-9_'+\-\\.]*)[a-z0-9_+-]@([a-z0-9][a-z0-9\\-]*\.)+[a-z]{2,}$/i;
|
|
4
|
+
function rulerFactory(generator, extend) {
|
|
5
|
+
return function ruler() {
|
|
6
|
+
const rules = [];
|
|
7
|
+
const ctx = {
|
|
8
|
+
rules,
|
|
9
|
+
addRule,
|
|
10
|
+
generator,
|
|
11
|
+
getMessage,
|
|
12
|
+
type: "string",
|
|
13
|
+
string,
|
|
14
|
+
number,
|
|
15
|
+
array,
|
|
16
|
+
boolean,
|
|
17
|
+
object,
|
|
18
|
+
symbol,
|
|
19
|
+
bigint,
|
|
20
|
+
null: _null,
|
|
21
|
+
undefined: _undefined,
|
|
22
|
+
true: _true,
|
|
23
|
+
false: _false,
|
|
24
|
+
length,
|
|
25
|
+
min,
|
|
26
|
+
max,
|
|
27
|
+
regex,
|
|
28
|
+
required,
|
|
29
|
+
startsWith,
|
|
30
|
+
endsWith,
|
|
31
|
+
includes,
|
|
32
|
+
uppercase,
|
|
33
|
+
lowercase,
|
|
34
|
+
email,
|
|
35
|
+
gt,
|
|
36
|
+
gte,
|
|
37
|
+
lt,
|
|
38
|
+
lte,
|
|
39
|
+
positive,
|
|
40
|
+
negative,
|
|
41
|
+
uniq,
|
|
42
|
+
uniqBy,
|
|
43
|
+
is,
|
|
44
|
+
not,
|
|
45
|
+
done,
|
|
46
|
+
transformer,
|
|
47
|
+
transform,
|
|
48
|
+
trim,
|
|
49
|
+
shouldTrim: false,
|
|
50
|
+
toLowerCase,
|
|
51
|
+
shouldToLowerCase: false,
|
|
52
|
+
toUpperCase,
|
|
53
|
+
shouldToUpperCase: false
|
|
54
|
+
};
|
|
55
|
+
Object.assign(ctx, extend?.(ctx) ?? {});
|
|
56
|
+
function string(message, params) {
|
|
57
|
+
ctx.type = "string";
|
|
58
|
+
addRule((value) => {
|
|
59
|
+
if (message == null) return;
|
|
60
|
+
if (!isString(value)) return new Error(getMessage(message));
|
|
61
|
+
}, params);
|
|
62
|
+
return ctx;
|
|
63
|
+
}
|
|
64
|
+
function number(message, params) {
|
|
65
|
+
ctx.type = "number";
|
|
66
|
+
addRule((value) => {
|
|
67
|
+
if (message == null) return;
|
|
68
|
+
if (!isNumber(value)) return new Error(getMessage(message));
|
|
69
|
+
}, params);
|
|
70
|
+
return ctx;
|
|
71
|
+
}
|
|
72
|
+
function object(message, params) {
|
|
73
|
+
ctx.type = "object";
|
|
74
|
+
addRule((value) => {
|
|
75
|
+
if (message == null) return;
|
|
76
|
+
if (!isPlainObject(value)) return new Error(getMessage(message));
|
|
77
|
+
}, params);
|
|
78
|
+
return ctx;
|
|
79
|
+
}
|
|
80
|
+
function array(message, params) {
|
|
81
|
+
ctx.type = "array";
|
|
82
|
+
addRule((value) => {
|
|
83
|
+
if (message == null) return;
|
|
84
|
+
if (!isArray(value)) return new Error(getMessage(message));
|
|
85
|
+
}, params);
|
|
86
|
+
return ctx;
|
|
87
|
+
}
|
|
88
|
+
function boolean(message, params) {
|
|
89
|
+
ctx.type = "boolean";
|
|
90
|
+
addRule((value) => {
|
|
91
|
+
if (message == null) return;
|
|
92
|
+
if (!isBoolean(value)) return new Error(getMessage(message));
|
|
93
|
+
}, params);
|
|
94
|
+
return ctx;
|
|
95
|
+
}
|
|
96
|
+
function _true(message, params) {
|
|
97
|
+
ctx.type = "boolean";
|
|
98
|
+
addRule((value) => {
|
|
99
|
+
if (message == null) return;
|
|
100
|
+
if (value !== true) return new Error(getMessage(message));
|
|
101
|
+
}, params);
|
|
102
|
+
return ctx;
|
|
103
|
+
}
|
|
104
|
+
function _false(message, params) {
|
|
105
|
+
ctx.type = "boolean";
|
|
106
|
+
addRule((value) => {
|
|
107
|
+
if (message == null) return;
|
|
108
|
+
if (value !== false) return new Error(getMessage(message));
|
|
109
|
+
}, params);
|
|
110
|
+
return ctx;
|
|
111
|
+
}
|
|
112
|
+
function symbol(message, params) {
|
|
113
|
+
ctx.type = "symbol";
|
|
114
|
+
addRule((value) => {
|
|
115
|
+
if (message == null) return;
|
|
116
|
+
if (!isSymbol(value)) return new Error(getMessage(message));
|
|
117
|
+
}, params);
|
|
118
|
+
return ctx;
|
|
119
|
+
}
|
|
120
|
+
function _null(message, params) {
|
|
121
|
+
ctx.type = "null";
|
|
122
|
+
addRule((value) => {
|
|
123
|
+
if (message == null) return;
|
|
124
|
+
if (value !== null) return new Error(getMessage(message));
|
|
125
|
+
}, params);
|
|
126
|
+
return ctx;
|
|
127
|
+
}
|
|
128
|
+
function _undefined(message, params) {
|
|
129
|
+
ctx.type = "undefined";
|
|
130
|
+
addRule((value) => {
|
|
131
|
+
if (message == null) return;
|
|
132
|
+
if (value !== void 0) return new Error(getMessage(message));
|
|
133
|
+
}, params);
|
|
134
|
+
return ctx;
|
|
135
|
+
}
|
|
136
|
+
function bigint(message, params) {
|
|
137
|
+
ctx.type = "bigint";
|
|
138
|
+
addRule((value) => {
|
|
139
|
+
if (message == null) return;
|
|
140
|
+
if (typeof value !== "bigint") return new Error(getMessage(message));
|
|
141
|
+
}, params);
|
|
142
|
+
return ctx;
|
|
143
|
+
}
|
|
144
|
+
function required(message, params) {
|
|
145
|
+
addRule((value) => {
|
|
146
|
+
if (isEmpty(value)) return new Error(getMessage(message));
|
|
147
|
+
}, params);
|
|
148
|
+
return ctx;
|
|
149
|
+
}
|
|
150
|
+
function email(message, params) {
|
|
151
|
+
addRule((value) => {
|
|
152
|
+
if (ctx.type === "string" && (!isString(value) || !EMAIL_REGEX.test(value))) return new Error(getMessage(message));
|
|
153
|
+
}, params);
|
|
154
|
+
return ctx;
|
|
155
|
+
}
|
|
156
|
+
function min(v, message, params) {
|
|
157
|
+
addRule((value) => {
|
|
158
|
+
if (ctx.type === "string" && (!isString(value) || value.length < v)) return new Error(getMessage(message));
|
|
159
|
+
if (ctx.type === "number" || ctx.type === "bigint") {
|
|
160
|
+
if (!isNumber(value) && typeof value !== "bigint") return new Error(getMessage(message));
|
|
161
|
+
if (value < v) return new Error(getMessage(message));
|
|
162
|
+
}
|
|
163
|
+
if (ctx.type === "array" && (!isArray(value) || value.length < v)) return new Error(getMessage(message));
|
|
164
|
+
}, params);
|
|
165
|
+
return ctx;
|
|
166
|
+
}
|
|
167
|
+
function max(v, message, params) {
|
|
168
|
+
addRule((value) => {
|
|
169
|
+
if (ctx.type === "string" && (!isString(value) || value.length > v)) return new Error(getMessage(message));
|
|
170
|
+
if (ctx.type === "number" || ctx.type === "bigint") {
|
|
171
|
+
if (!isNumber(value) && typeof value !== "bigint") return new Error(getMessage(message));
|
|
172
|
+
if (value > v) return new Error(getMessage(message));
|
|
173
|
+
}
|
|
174
|
+
if (ctx.type === "array" && (!isArray(value) || value.length > v)) return new Error(getMessage(message));
|
|
175
|
+
}, params);
|
|
176
|
+
return ctx;
|
|
177
|
+
}
|
|
178
|
+
function length(v, message, params) {
|
|
179
|
+
addRule((value) => {
|
|
180
|
+
if (ctx.type === "string" && (!isString(value) || value.length !== v)) return new Error(getMessage(message));
|
|
181
|
+
if (ctx.type === "array" && (!isArray(value) || value.length !== v)) return new Error(getMessage(message));
|
|
182
|
+
}, params);
|
|
183
|
+
return ctx;
|
|
184
|
+
}
|
|
185
|
+
function regex(v, message, params) {
|
|
186
|
+
addRule((value) => {
|
|
187
|
+
if (ctx.type === "string" && (!isString(value) || !v.test(value))) return new Error(getMessage(message));
|
|
188
|
+
}, params);
|
|
189
|
+
return ctx;
|
|
190
|
+
}
|
|
191
|
+
function startsWith(v, message, params) {
|
|
192
|
+
addRule((value) => {
|
|
193
|
+
if (ctx.type === "string" && (!isString(value) || !value.startsWith(v))) return new Error(getMessage(message));
|
|
194
|
+
}, params);
|
|
195
|
+
return ctx;
|
|
196
|
+
}
|
|
197
|
+
function endsWith(v, message, params) {
|
|
198
|
+
addRule((value) => {
|
|
199
|
+
if (ctx.type === "string" && (!isString(value) || !value.endsWith(v))) return new Error(getMessage(message));
|
|
200
|
+
}, params);
|
|
201
|
+
return ctx;
|
|
202
|
+
}
|
|
203
|
+
function includes(v, message, params) {
|
|
204
|
+
addRule((value) => {
|
|
205
|
+
if (ctx.type === "string" && (!isString(value) || !value.includes(v))) return new Error(getMessage(message));
|
|
206
|
+
if (ctx.type === "array" && (!isArray(value) || !value.includes(v))) return new Error(getMessage(message));
|
|
207
|
+
}, params);
|
|
208
|
+
return ctx;
|
|
209
|
+
}
|
|
210
|
+
function uppercase(message, params) {
|
|
211
|
+
addRule((value) => {
|
|
212
|
+
if (ctx.type === "string" && (!isString(value) || value !== value.toUpperCase())) return new Error(getMessage(message));
|
|
213
|
+
}, params);
|
|
214
|
+
return ctx;
|
|
215
|
+
}
|
|
216
|
+
function lowercase(message, params) {
|
|
217
|
+
addRule((value) => {
|
|
218
|
+
if (ctx.type === "string" && (!isString(value) || value !== value.toLowerCase())) return new Error(getMessage(message));
|
|
219
|
+
}, params);
|
|
220
|
+
return ctx;
|
|
221
|
+
}
|
|
222
|
+
function gt(v, message, params) {
|
|
223
|
+
addRule((value) => {
|
|
224
|
+
if (ctx.type === "number" || ctx.type === "bigint") {
|
|
225
|
+
if (!isNumber(value) && typeof value !== "bigint") return new Error(getMessage(message));
|
|
226
|
+
if (value <= v) return new Error(getMessage(message));
|
|
227
|
+
}
|
|
228
|
+
}, params);
|
|
229
|
+
return ctx;
|
|
230
|
+
}
|
|
231
|
+
function gte(v, message, params) {
|
|
232
|
+
addRule((value) => {
|
|
233
|
+
if (ctx.type === "number" || ctx.type === "bigint") {
|
|
234
|
+
if (!isNumber(value) && typeof value !== "bigint") return new Error(getMessage(message));
|
|
235
|
+
if (value < v) return new Error(getMessage(message));
|
|
236
|
+
}
|
|
237
|
+
}, params);
|
|
238
|
+
return ctx;
|
|
239
|
+
}
|
|
240
|
+
function lt(v, message, params) {
|
|
241
|
+
addRule((value) => {
|
|
242
|
+
if (ctx.type === "number" || ctx.type === "bigint") {
|
|
243
|
+
if (!isNumber(value) && typeof value !== "bigint") return new Error(getMessage(message));
|
|
244
|
+
if (value >= v) return new Error(getMessage(message));
|
|
245
|
+
}
|
|
246
|
+
}, params);
|
|
247
|
+
return ctx;
|
|
248
|
+
}
|
|
249
|
+
function lte(v, message, params) {
|
|
250
|
+
addRule((value) => {
|
|
251
|
+
if (ctx.type === "number" || ctx.type === "bigint") {
|
|
252
|
+
if (!isNumber(value) && typeof value !== "bigint") return new Error(getMessage(message));
|
|
253
|
+
if (value > v) return new Error(getMessage(message));
|
|
254
|
+
}
|
|
255
|
+
}, params);
|
|
256
|
+
return ctx;
|
|
257
|
+
}
|
|
258
|
+
function positive(message, params) {
|
|
259
|
+
addRule((value) => {
|
|
260
|
+
if (ctx.type === "number" || ctx.type === "bigint") {
|
|
261
|
+
if (!isNumber(value) && typeof value !== "bigint") return new Error(getMessage(message));
|
|
262
|
+
if (value <= 0) return new Error(getMessage(message));
|
|
263
|
+
}
|
|
264
|
+
}, params);
|
|
265
|
+
return ctx;
|
|
266
|
+
}
|
|
267
|
+
function negative(message, params) {
|
|
268
|
+
addRule((value) => {
|
|
269
|
+
if (ctx.type === "number" || ctx.type === "bigint") {
|
|
270
|
+
if (!isNumber(value) && typeof value !== "bigint") return new Error(getMessage(message));
|
|
271
|
+
if (value >= 0) return new Error(getMessage(message));
|
|
272
|
+
}
|
|
273
|
+
}, params);
|
|
274
|
+
return ctx;
|
|
275
|
+
}
|
|
276
|
+
function uniq(message, params) {
|
|
277
|
+
addRule((value) => {
|
|
278
|
+
if (ctx.type === "array" && hasDuplicates(value)) return new Error(getMessage(message));
|
|
279
|
+
}, params);
|
|
280
|
+
return ctx;
|
|
281
|
+
}
|
|
282
|
+
function uniqBy(v, message, params) {
|
|
283
|
+
addRule((value) => {
|
|
284
|
+
if (ctx.type === "array" && hasDuplicatesBy(value, v)) return new Error(getMessage(message));
|
|
285
|
+
}, params);
|
|
286
|
+
return ctx;
|
|
287
|
+
}
|
|
288
|
+
function is(v, message, params) {
|
|
289
|
+
addRule((value) => {
|
|
290
|
+
if (!v(value)) return new Error(getMessage(message));
|
|
291
|
+
}, params);
|
|
292
|
+
return ctx;
|
|
293
|
+
}
|
|
294
|
+
function not(v, message, params) {
|
|
295
|
+
addRule((value) => {
|
|
296
|
+
if (v(value)) return new Error(getMessage(message));
|
|
297
|
+
}, params);
|
|
298
|
+
return ctx;
|
|
299
|
+
}
|
|
300
|
+
function trim() {
|
|
301
|
+
ctx.shouldTrim = true;
|
|
302
|
+
return ctx;
|
|
303
|
+
}
|
|
304
|
+
function toLowerCase() {
|
|
305
|
+
ctx.shouldToLowerCase = true;
|
|
306
|
+
return ctx;
|
|
307
|
+
}
|
|
308
|
+
function toUpperCase() {
|
|
309
|
+
ctx.shouldToUpperCase = true;
|
|
310
|
+
return ctx;
|
|
311
|
+
}
|
|
312
|
+
function transformer(value) {
|
|
313
|
+
if (ctx.type === "string" && isString(value)) {
|
|
314
|
+
ctx.shouldTrim && (value = value.trim());
|
|
315
|
+
ctx.shouldToLowerCase && (value = value.toLowerCase());
|
|
316
|
+
ctx.shouldToUpperCase && (value = value.toUpperCase());
|
|
317
|
+
}
|
|
318
|
+
return value;
|
|
319
|
+
}
|
|
320
|
+
function transform(v) {
|
|
321
|
+
ctx.transformer = v;
|
|
322
|
+
}
|
|
323
|
+
function addRule(validator, params) {
|
|
324
|
+
rules.push(generator((value) => {
|
|
325
|
+
value = ctx.transformer(value);
|
|
326
|
+
return validator(value);
|
|
327
|
+
}, params));
|
|
328
|
+
return ctx;
|
|
329
|
+
}
|
|
330
|
+
function done() {
|
|
331
|
+
return rules;
|
|
332
|
+
}
|
|
333
|
+
function getMessage(message) {
|
|
334
|
+
return isFunction(message) ? message() : message;
|
|
335
|
+
}
|
|
336
|
+
return ctx;
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
//#endregion
|
|
340
|
+
export { rulerFactory };
|
package/package.json
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pa-ruler-factory",
|
|
3
|
+
"version": "0.0.14",
|
|
4
|
+
"description": "A flexible, chainable validation rule factory for typeScript/javaScript.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"chainable",
|
|
7
|
+
"data",
|
|
8
|
+
"factory",
|
|
9
|
+
"form",
|
|
10
|
+
"javascript",
|
|
11
|
+
"rules",
|
|
12
|
+
"validation",
|
|
13
|
+
"validator"
|
|
14
|
+
],
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/puijs/ruler-factory/issues"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"author": "haoziqaq <357229046@qq.com>",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/puijs/ruler-factory.git"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist"
|
|
26
|
+
],
|
|
27
|
+
"type": "module",
|
|
28
|
+
"sideEffects": false,
|
|
29
|
+
"main": "dist/index.mjs",
|
|
30
|
+
"module": "dist/index.mjs",
|
|
31
|
+
"types": "dist/index.d.mts",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/index.d.mts",
|
|
35
|
+
"import": "./dist/index.mjs"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "vp pack",
|
|
40
|
+
"clean": "rimraf node_modules dist",
|
|
41
|
+
"dev": "vp test watch",
|
|
42
|
+
"format": "vp fmt",
|
|
43
|
+
"lint": "vp lint --fix",
|
|
44
|
+
"prepare": "vp config --hooks-dir .vite-hooks",
|
|
45
|
+
"release": "pnpm build && vr release",
|
|
46
|
+
"test": "vp test run --coverage"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"rattail": "^1.8.3"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/node": "^22.8.1",
|
|
53
|
+
"@nanawan/release": "^2.2.8",
|
|
54
|
+
"@vitest/coverage-istanbul": "^4.1.0",
|
|
55
|
+
"jsdom": "^25.0.1",
|
|
56
|
+
"rimraf": "^6.0.1",
|
|
57
|
+
"typescript": "5.3.3",
|
|
58
|
+
"vite-plus": "0.1.16",
|
|
59
|
+
"vitest": "$vitest"
|
|
60
|
+
},
|
|
61
|
+
"engines": {
|
|
62
|
+
"pnpm": ">=10.0.0"
|
|
63
|
+
},
|
|
64
|
+
"packageManager": "pnpm@10.0.0",
|
|
65
|
+
"pnpm": {
|
|
66
|
+
"overrides": {
|
|
67
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@0.1.16",
|
|
68
|
+
"vitest": "npm:@voidzero-dev/vite-plus-test@0.1.16"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|