adaptform 2.0.4 → 2.0.5
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/CHANGELOG.md +51 -0
- package/LICENSE.md +2 -2
- package/README.md +420 -1
- package/dist/{Form-DOdrOtbT.d.cts → Form-Be3I6LX0.d.cts} +83 -3
- package/dist/{Form-DOdrOtbT.d.ts → Form-Be3I6LX0.d.ts} +83 -3
- package/dist/index.cjs +341 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +341 -20
- package/dist/index.mjs.map +1 -1
- package/dist/luxon.cjs.map +1 -1
- package/dist/luxon.d.cts +1 -1
- package/dist/luxon.d.ts +1 -1
- package/dist/luxon.mjs.map +1 -1
- package/package.json +15 -5
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [2.0.0 - 2.0.4] - 2026-05-29
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Complete TypeScript rewrite with full type inference
|
|
10
|
+
- Plugin system with MaskPlugin, FieldPlugin, and DecoratorPlugin
|
|
11
|
+
- ArrayField for dynamic field arrays
|
|
12
|
+
- ArrayFormField for nested form arrays
|
|
13
|
+
- New field types: DecimalType, DateLuxonType, BooleanType
|
|
14
|
+
- Optional Luxon integration via `adaptform/luxon` subpath export
|
|
15
|
+
- Input mask support with flexible configuration
|
|
16
|
+
- Conditional required fields based on form state
|
|
17
|
+
- Custom validation messages for all field types
|
|
18
|
+
- Global error handling for server-side errors
|
|
19
|
+
- Form serialization (`toJSON()`, `toFormData()`)
|
|
20
|
+
- Tree-shakeable exports for smaller bundles
|
|
21
|
+
- ESM and CJS module support
|
|
22
|
+
- Full TypeScript declarations with proper types
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- **Complete API redesign** - new class-based architecture
|
|
27
|
+
- Field creation now uses `new Field(TypeClass, defaultValue, options)` pattern
|
|
28
|
+
- Form validation now requires explicit field declarations in class body
|
|
29
|
+
- Plugin system replaces old middleware approach
|
|
30
|
+
- Error handling unified across all field types
|
|
31
|
+
- Validation methods now return string arrays instead of boolean
|
|
32
|
+
- Options interface restructured for better type inference
|
|
33
|
+
|
|
34
|
+
### Breaking Changes
|
|
35
|
+
|
|
36
|
+
- **Full rewrite from v1.x** - no backward compatibility
|
|
37
|
+
- Form must extend base `Form` class with field declarations
|
|
38
|
+
- Field constructors require TypeClass as first argument
|
|
39
|
+
- `validate()` now returns `string[]` instead of `boolean`
|
|
40
|
+
- Plugin API completely redesigned
|
|
41
|
+
- Import paths changed for tree-shaking support
|
|
42
|
+
- Luxon date type moved to separate entry point `adaptform/luxon`
|
|
43
|
+
|
|
44
|
+
### Removed
|
|
45
|
+
|
|
46
|
+
- Legacy function-based API
|
|
47
|
+
- Old validation middleware system
|
|
48
|
+
- Global configuration singleton
|
|
49
|
+
- Automatic Luxon dependency (now optional)
|
|
50
|
+
|
|
51
|
+
[2.0.4]: https://github.com/ArhiMEN/adaptform/releases/tag/v2.0.4
|
package/LICENSE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2025
|
|
3
|
+
Copyright (c) 2025 Stanislav Orlov (ArhiMEN)
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1 +1,420 @@
|
|
|
1
|
-
|
|
1
|
+
# AdaptForm
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/adaptform)
|
|
4
|
+
[](https://www.npmjs.com/package/adaptform)
|
|
5
|
+
[](https://bundlephobia.com/package/adaptform)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
8
|
+
|
|
9
|
+
AdaptForm is a TypeScript-first form modeling framework inspired by Django Forms and Pydantic.
|
|
10
|
+
|
|
11
|
+
Instead of describing validation schemas, you describe forms as classes with typed fields. Each field is responsible for
|
|
12
|
+
its own state lifecycle, validation, transformation pipeline, and serialization logic.
|
|
13
|
+
|
|
14
|
+
## AdaptForm provides:
|
|
15
|
+
|
|
16
|
+
- Typed form models
|
|
17
|
+
- Field-level validation
|
|
18
|
+
- Cross-field validation
|
|
19
|
+
- Input transformation plugins
|
|
20
|
+
- Nested forms and arrays
|
|
21
|
+
- Automatic TypeScript inference
|
|
22
|
+
- Framework-agnostic integration
|
|
23
|
+
|
|
24
|
+
## Features
|
|
25
|
+
|
|
26
|
+
- Form-as-a-domain-model architecture
|
|
27
|
+
- Field-level state + validation ownership
|
|
28
|
+
- Cross-field validation support
|
|
29
|
+
- Plugin-based transformation pipeline
|
|
30
|
+
- Strong TypeScript inference
|
|
31
|
+
- Nested forms & collections
|
|
32
|
+
- Built-in serialization (JSON / FormData)
|
|
33
|
+
- Optional date engine (Luxon)
|
|
34
|
+
- Framework-agnostic design
|
|
35
|
+
- Zero-core-dependencies
|
|
36
|
+
|
|
37
|
+
## Philosophy
|
|
38
|
+
|
|
39
|
+
Most form libraries treat forms as validation schemas:
|
|
40
|
+
|
|
41
|
+
```TypeScript
|
|
42
|
+
const schema = z.object({
|
|
43
|
+
login: z.string(),
|
|
44
|
+
password: z.string(),
|
|
45
|
+
})
|
|
46
|
+
````
|
|
47
|
+
|
|
48
|
+
AdaptForm treats forms as stateful domain models:
|
|
49
|
+
|
|
50
|
+
```TypeScript
|
|
51
|
+
class LoginForm extends Form {
|
|
52
|
+
login = new Field(StringType)
|
|
53
|
+
password = new Field(StringType)
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
field is not just a validator — it is a state container that owns:
|
|
58
|
+
|
|
59
|
+
- value
|
|
60
|
+
- validation
|
|
61
|
+
- errors
|
|
62
|
+
- transformation
|
|
63
|
+
- plugins
|
|
64
|
+
- type casting
|
|
65
|
+
|
|
66
|
+
The form itself becomes a single source of truth.
|
|
67
|
+
|
|
68
|
+
Simple Vue:
|
|
69
|
+
|
|
70
|
+
## Without AdaptForm
|
|
71
|
+
|
|
72
|
+
A typical Vue form consists of multiple disconnected parts:
|
|
73
|
+
|
|
74
|
+
- reactive state
|
|
75
|
+
- validation schema
|
|
76
|
+
- error store
|
|
77
|
+
- input masks
|
|
78
|
+
- submission mapping
|
|
79
|
+
|
|
80
|
+
## With AdaptForm
|
|
81
|
+
|
|
82
|
+
Everything is unified into a single form model:
|
|
83
|
+
|
|
84
|
+
```TypeScript
|
|
85
|
+
class RegistrationForm extends Form {
|
|
86
|
+
phone = new Field(StringType)
|
|
87
|
+
}
|
|
88
|
+
````
|
|
89
|
+
|
|
90
|
+
## Installation
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
npm install adaptform
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Optional: Luxon integration
|
|
97
|
+
|
|
98
|
+
```Bash
|
|
99
|
+
npm install luxon
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Quick Start
|
|
103
|
+
|
|
104
|
+
```TypeScript
|
|
105
|
+
import {Form, Field, StringType, NumberType} from 'adaptform';
|
|
106
|
+
|
|
107
|
+
class LoginForm extends Form {
|
|
108
|
+
login = new Field(StringType, null, {maxLength: 50});
|
|
109
|
+
password = new Field(StringType, null, {minLength: 8});
|
|
110
|
+
remember = new Field(BooleanType, false);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const form = new LoginForm();
|
|
114
|
+
|
|
115
|
+
form.fields = {
|
|
116
|
+
login: 'john_doe',
|
|
117
|
+
password: 'securepass123'
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
console.log(form.isValid); // true
|
|
121
|
+
console.log(form.fieldsValue); // { login: 'john_doe', password: 'securepass123', remember: false }
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Usage Examples
|
|
125
|
+
|
|
126
|
+
## Field Types
|
|
127
|
+
|
|
128
|
+
```TypeScript
|
|
129
|
+
import {Field, StringType, NumberType, BooleanType, DecimalType, DateType} from 'adaptform';
|
|
130
|
+
|
|
131
|
+
// String with validation
|
|
132
|
+
const name = new Field(StringType, null, {
|
|
133
|
+
minLength: 2,
|
|
134
|
+
maxLength: 50,
|
|
135
|
+
pattern: /^[a-zA-Z]+$/
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Number with range
|
|
139
|
+
const age = new Field(NumberType, null, {
|
|
140
|
+
gt: 0, // greater than
|
|
141
|
+
lt: 120 // less than
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Boolean with requirement
|
|
145
|
+
const agreed = new Field(BooleanType, false, {
|
|
146
|
+
mustBeTrue: true,
|
|
147
|
+
messages: {
|
|
148
|
+
mustBeTrue: 'You must agree to the terms'
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Custom Validation
|
|
154
|
+
|
|
155
|
+
```TypeScript
|
|
156
|
+
const email = new Field(StringType, null, {
|
|
157
|
+
validate: (value) => {
|
|
158
|
+
return value.includes('@') || 'Invalid email format';
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Async validation with form context
|
|
163
|
+
const passwordConfirmation = new Field(StringType, null, {
|
|
164
|
+
validate: (value, form) => {
|
|
165
|
+
return value === form?.password?.valueClear || 'Passwords do not match';
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Conditional Required Fields
|
|
171
|
+
|
|
172
|
+
```TypeScript
|
|
173
|
+
class SignUpForm extends Form {
|
|
174
|
+
country = new Field(StringType, null);
|
|
175
|
+
|
|
176
|
+
state = new Field(StringType, null, {
|
|
177
|
+
isRequired: (form) => form?.country?.valueClear === 'USA',
|
|
178
|
+
messages: {
|
|
179
|
+
isRequired: 'State is required for USA residents'
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Input Masks
|
|
186
|
+
|
|
187
|
+
```TypeScript
|
|
188
|
+
import {Field, StringType, MaskPlugin} from 'adaptform';
|
|
189
|
+
|
|
190
|
+
const phone = new Field(StringType, null, {
|
|
191
|
+
plugins: [
|
|
192
|
+
new MaskPlugin({
|
|
193
|
+
maskFormat: '+7 (___) ___-__-__',
|
|
194
|
+
maskPlaceholder: '_',
|
|
195
|
+
digitPattern: /\d/
|
|
196
|
+
})
|
|
197
|
+
]
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
phone.rawValue = '9991234567';
|
|
201
|
+
console.log(phone.valueClear); // '+7 (999) 123-45-67'
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Nested Forms
|
|
205
|
+
|
|
206
|
+
```TypeScript
|
|
207
|
+
import {ArrayField, Field, NumberType} from 'adaptform';
|
|
208
|
+
|
|
209
|
+
const gameIds = new ArrayField(
|
|
210
|
+
(value?: number) => new Field(NumberType, value, {gt: 0}),
|
|
211
|
+
{minItems: 1}
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
gameIds.itemsValue = [1, 2, 3];
|
|
215
|
+
gameIds.add(4);
|
|
216
|
+
console.log(gameIds.itemsValue); // [1, 2, 3, 4]
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Luxon Date Integration
|
|
220
|
+
|
|
221
|
+
```Bash
|
|
222
|
+
npm install luxon
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
```TypeScript
|
|
226
|
+
import {DateLuxonType} from 'adaptform/luxon';
|
|
227
|
+
import {DateTime} from 'luxon';
|
|
228
|
+
|
|
229
|
+
const birthdate = new Field(DateLuxonType, null, {
|
|
230
|
+
isDatetime: false,
|
|
231
|
+
minDate: DateTime.fromISO('1900-01-01'),
|
|
232
|
+
maxDate: DateTime.now(),
|
|
233
|
+
inputFormat: 'dd.MM.yyyy',
|
|
234
|
+
messages: {
|
|
235
|
+
minDate: 'Date must be after 1900',
|
|
236
|
+
maxDate: 'Date cannot be in the future'
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
birthdate.rawValue = '15.06.1990';
|
|
241
|
+
console.log(birthdate.valueClear); // Luxon DateTime object
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Form Submission
|
|
245
|
+
|
|
246
|
+
```TypeScript
|
|
247
|
+
class ContactForm extends Form {
|
|
248
|
+
name = new Field(StringType, null, {maxLength: 100});
|
|
249
|
+
email = new Field(StringType, null, {
|
|
250
|
+
pattern: /^[^@]+@[^@.]+\.[^@.]+$/
|
|
251
|
+
});
|
|
252
|
+
message = new Field(StringType, null, {maxLength: 1000});
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const form = new ContactForm();
|
|
256
|
+
form.fields = {
|
|
257
|
+
name: 'John',
|
|
258
|
+
email: 'john@example.com',
|
|
259
|
+
message: 'Hello!'
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
if (form.checkValid()) {
|
|
263
|
+
// Submit form
|
|
264
|
+
const formData = form.toFormData();
|
|
265
|
+
const json = form.toJSON();
|
|
266
|
+
|
|
267
|
+
await fetch('/api/contact', {
|
|
268
|
+
method: 'POST',
|
|
269
|
+
body: formData
|
|
270
|
+
});
|
|
271
|
+
} else {
|
|
272
|
+
console.log(form.allErrors);
|
|
273
|
+
// {
|
|
274
|
+
// name: [],
|
|
275
|
+
// email: [],
|
|
276
|
+
// message: []
|
|
277
|
+
// }
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Global Errors
|
|
282
|
+
|
|
283
|
+
```TypeScript
|
|
284
|
+
class LoginForm extends Form {
|
|
285
|
+
login = new Field(StringType, null);
|
|
286
|
+
password = new Field(StringType, null);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const form = new LoginForm();
|
|
290
|
+
|
|
291
|
+
// Add server-side errors
|
|
292
|
+
form.errors = {
|
|
293
|
+
login: 'Account not found',
|
|
294
|
+
password: 'Invalid password'
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
// Or set global error
|
|
298
|
+
form.setGlobalError('auth', 'Authentication failed');
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## Plugin System
|
|
302
|
+
|
|
303
|
+
### Built-in Plugins
|
|
304
|
+
|
|
305
|
+
* **MaskPlugin** - Input masking (phone, date, credit card)
|
|
306
|
+
|
|
307
|
+
* **FieldPlugin** - Base plugin for custom extensions
|
|
308
|
+
|
|
309
|
+
### Creating Custom Plugins
|
|
310
|
+
|
|
311
|
+
```TypeScript
|
|
312
|
+
import {BasePlugin} from 'adaptform';
|
|
313
|
+
import type {FieldPlugin} from 'adaptform';
|
|
314
|
+
|
|
315
|
+
class UppercasePlugin extends BasePlugin implements FieldPlugin<string> {
|
|
316
|
+
toRawValue(value: string): string {
|
|
317
|
+
return value?.toUpperCase() || '';
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
toValueClear(value: string): string {
|
|
321
|
+
return value?.toLowerCase() || '';
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const field = new Field(StringType, null, {
|
|
326
|
+
plugins: [new UppercasePlugin()]
|
|
327
|
+
});
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## API Reference
|
|
331
|
+
|
|
332
|
+
### Form
|
|
333
|
+
|
|
334
|
+
* `checkValid(form?)` - Validate all fields
|
|
335
|
+
|
|
336
|
+
* `fieldsValue` - Get all field values
|
|
337
|
+
|
|
338
|
+
* `allErrors` - Get all validation errors
|
|
339
|
+
|
|
340
|
+
* `globalErrors` - Get global errors
|
|
341
|
+
|
|
342
|
+
* `toFormData()` - Convert to FormData
|
|
343
|
+
|
|
344
|
+
* `toJSON()` - Convert to JSON
|
|
345
|
+
|
|
346
|
+
* `reset()` - Reset all fields
|
|
347
|
+
|
|
348
|
+
### Field
|
|
349
|
+
|
|
350
|
+
* `rawValue` - Set raw input value
|
|
351
|
+
|
|
352
|
+
* `valueClear` - Get cleaned/validated value
|
|
353
|
+
|
|
354
|
+
* `isValid` - Check if field is valid
|
|
355
|
+
|
|
356
|
+
* `error` - Get first error message
|
|
357
|
+
|
|
358
|
+
* `errors` - Get all error messages
|
|
359
|
+
|
|
360
|
+
* `isTouched` - Check if field was modified
|
|
361
|
+
|
|
362
|
+
* `isEmpty` - Check if field is empty
|
|
363
|
+
|
|
364
|
+
* `reset()` - Reset to default value
|
|
365
|
+
|
|
366
|
+
### ArrayField
|
|
367
|
+
|
|
368
|
+
* `add(value?)` - Add new field
|
|
369
|
+
|
|
370
|
+
* `remove(index)` - Remove field at index
|
|
371
|
+
|
|
372
|
+
* `clear()` - Remove all fields
|
|
373
|
+
|
|
374
|
+
* `itemsValue` - Get array of values
|
|
375
|
+
|
|
376
|
+
* `items` - Get array of Field instances
|
|
377
|
+
|
|
378
|
+
### ArrayFormField
|
|
379
|
+
|
|
380
|
+
* `add(data?)` - Add new form
|
|
381
|
+
|
|
382
|
+
* `remove(index)` - Remove form at index
|
|
383
|
+
|
|
384
|
+
* `clear()` - Remove all forms
|
|
385
|
+
|
|
386
|
+
* `forms` - Get array of Form instances
|
|
387
|
+
|
|
388
|
+
* `formsFieldsValue` - Get array of form values
|
|
389
|
+
|
|
390
|
+
## TypeScript Support
|
|
391
|
+
|
|
392
|
+
```TypeScript
|
|
393
|
+
import {Form, Field, StringType, NumberType} from 'adaptform';
|
|
394
|
+
|
|
395
|
+
class UserForm extends Form {
|
|
396
|
+
name = new Field(StringType, null);
|
|
397
|
+
age = new Field(NumberType, null);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const form = new UserForm();
|
|
401
|
+
|
|
402
|
+
// Full type inference
|
|
403
|
+
type UserData = typeof form.fieldsValue;
|
|
404
|
+
// { name: string | null; age: number | null; }
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
## License
|
|
408
|
+
|
|
409
|
+
MIT © [Stanislav Orlov](https://github.com/ArhiMEN)
|
|
410
|
+
|
|
411
|
+
## Links
|
|
412
|
+
|
|
413
|
+
* [GitHub Repository](https://github.com/ArhiMEN/adaptform)
|
|
414
|
+
* [npm Package](https://www.npmjs.com/package/adaptform)
|
|
415
|
+
* [Bug Reports](https://github.com/ArhiMEN/adaptform/issues)
|
|
416
|
+
* [Changelog](https://github.com/ArhiMEN/adaptform/blob/master/CHANGELOG.md)
|
|
417
|
+
|
|
418
|
+
## Support
|
|
419
|
+
|
|
420
|
+
If you find this project useful, please give it a star on GitHub!
|
|
@@ -170,7 +170,7 @@ type FieldTypeConstructor<T, O extends FieldOptions = FieldOptions> = new (optio
|
|
|
170
170
|
declare class Field<T = any, O extends FieldOptions = FieldOptions> {
|
|
171
171
|
protected _rawValue: any;
|
|
172
172
|
protected _valueClear: T | null;
|
|
173
|
-
protected
|
|
173
|
+
protected fieldType: FieldType<T, O>;
|
|
174
174
|
protected defaultValue: T | null;
|
|
175
175
|
protected _errors: string[];
|
|
176
176
|
isValid: boolean | null;
|
|
@@ -192,15 +192,95 @@ declare class Field<T = any, O extends FieldOptions = FieldOptions> {
|
|
|
192
192
|
reset(): void;
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
interface ParsedError {
|
|
196
|
+
fieldName: string;
|
|
197
|
+
message: string;
|
|
198
|
+
sourceKey: string;
|
|
199
|
+
matchedBy: 'static' | 'dynamic' | 'fallback';
|
|
200
|
+
}
|
|
201
|
+
declare class ErrorsSchema {
|
|
202
|
+
private _staticRules;
|
|
203
|
+
private _dynamicRules;
|
|
204
|
+
private _fallbackHandler?;
|
|
205
|
+
private _valueTransformers;
|
|
206
|
+
/**
|
|
207
|
+
* Добавляет статическое правило - точное соответствие ключа ошибки
|
|
208
|
+
* @param errorKey - точный ключ ошибки из ответа сервера
|
|
209
|
+
* @param fieldName - имя поля в форме или функция для динамического определения
|
|
210
|
+
*/
|
|
211
|
+
staticKey(errorKey: string, fieldName: string | ((errorValue: any) => string)): this;
|
|
212
|
+
/**
|
|
213
|
+
* Добавляет динамическое правило с регулярным выражением
|
|
214
|
+
* @param pattern - регулярное выражение для сопоставления ключа ошибки
|
|
215
|
+
* @param mapping - имя поля или функция для извлечения имени поля из совпадения
|
|
216
|
+
* @param options - дополнительные опции (приоритет и т.д.)
|
|
217
|
+
*/
|
|
218
|
+
dynamicKey(pattern: RegExp, mapping: string | ((match: RegExpMatchArray) => string), options?: {
|
|
219
|
+
priority?: number;
|
|
220
|
+
}): this;
|
|
221
|
+
/**
|
|
222
|
+
* Устанавливает обработчик для ошибок, которые не подошли ни под одно правило
|
|
223
|
+
*/
|
|
224
|
+
fallback(handler: (key: string, value: any) => string | null): this;
|
|
225
|
+
/**
|
|
226
|
+
* Добавляет трансформер для значений ошибок
|
|
227
|
+
* Полезно для нормализации сообщений (например, если сервер возвращает массив ошибок)
|
|
228
|
+
*/
|
|
229
|
+
transformValue(transformer: (value: any) => any): this;
|
|
230
|
+
/**
|
|
231
|
+
* Быстрый метод для создания схемы из простого объекта маппинга
|
|
232
|
+
*/
|
|
233
|
+
static fromObject(mapping: Record<string, string>): ErrorsSchema;
|
|
234
|
+
/**
|
|
235
|
+
* Создает схему для массива однотипных форм
|
|
236
|
+
*/
|
|
237
|
+
static forArray(itemSchema: ErrorsSchema, arrayFieldName: string, indexExtractor?: (key: string) => number): ErrorsSchema;
|
|
238
|
+
/**
|
|
239
|
+
* Основной метод парсинга ошибок с поддержкой трансформеров
|
|
240
|
+
* Поддерживает вложенные структуры через точечную нотацию
|
|
241
|
+
*/
|
|
242
|
+
parseErrors(errors: Record<string, any>, prefix?: string): Record<string, string>;
|
|
243
|
+
/**
|
|
244
|
+
* Парсит ошибки сервера и возвращает расширенную информацию
|
|
245
|
+
*/
|
|
246
|
+
parseErrorsDetailed(errors: Record<string, any>, prefix?: string): Record<string, ParsedError>;
|
|
247
|
+
/**
|
|
248
|
+
* Создает схему для вложенной формы
|
|
249
|
+
*/
|
|
250
|
+
nest(prefix: string): ErrorsSchema;
|
|
251
|
+
/**
|
|
252
|
+
* Клонирует текущую схему
|
|
253
|
+
*/
|
|
254
|
+
clone(): ErrorsSchema;
|
|
255
|
+
/**
|
|
256
|
+
* Объединяет текущую схему с другой
|
|
257
|
+
*/
|
|
258
|
+
merge(other: ErrorsSchema): ErrorsSchema;
|
|
259
|
+
private isNestedObject;
|
|
260
|
+
private findMappingDetailed;
|
|
261
|
+
private findMapping;
|
|
262
|
+
}
|
|
263
|
+
|
|
195
264
|
declare abstract class Form {
|
|
196
265
|
private _globalErrors;
|
|
266
|
+
errorsShema: ErrorsSchema;
|
|
197
267
|
protected get _fields(): Record<string, Field<any> | ArrayField<any> | ArrayFormField<any>>;
|
|
198
268
|
checkValid(form?: this): boolean;
|
|
199
269
|
get fieldsValue(): Record<string, any>;
|
|
200
270
|
set fields(data: Record<string, any>);
|
|
201
271
|
get allErrors(): Record<string, string[]>;
|
|
272
|
+
/**
|
|
273
|
+
* Рекурсивно собирает все ошибки из ArrayFormField
|
|
274
|
+
*/
|
|
275
|
+
private collectArrayFormErrors;
|
|
202
276
|
get globalErrors(): Record<string, string>;
|
|
203
|
-
set errors(errors: Record<string,
|
|
277
|
+
set errors(errors: Record<string, any>);
|
|
278
|
+
/**
|
|
279
|
+
* Применяет ошибку к соответствующему полю
|
|
280
|
+
* Поддерживает вложенные поля через точечную нотацию
|
|
281
|
+
*/
|
|
282
|
+
private applyErrorToField;
|
|
283
|
+
private applyNestedError;
|
|
204
284
|
setGlobalError(key: string, message: string): void;
|
|
205
285
|
clearGlobalErrors(): void;
|
|
206
286
|
reset(): void;
|
|
@@ -210,4 +290,4 @@ declare abstract class Form {
|
|
|
210
290
|
toJSON(): Record<string, any>;
|
|
211
291
|
}
|
|
212
292
|
|
|
213
|
-
export {
|
|
293
|
+
export { ArrayField as A, BasePlugin as B, type DecimalOptions as D, Field as F, type MaskPluginOptions as M, type NumberOptions as N, type PluginOptions as P, type StringOptions as S, FieldType as a, type BooleanOptions as b, type DateOptions as c, type ArrayFieldOptions as d, ArrayFormField as e, type ArrayFormFieldOptions as f, type FieldOptions as g, type FieldPlugin as h, Form as i, type messagesArrayFormFieldOptions as j, type messagesBooleanOptions as k, type messagesDateOptions as l, type messagesArrayFieldOptions as m, type messagesDecimalOptions as n, type messagesNumberOptions as o, type messagesOptions as p, type messagesStringOptions as q };
|