unischema 1.0.1 → 1.1.0

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 (70) hide show
  1. package/README.md +634 -231
  2. package/dist/adapters/backend/index.d.mts +2 -1
  3. package/dist/adapters/backend/index.d.ts +2 -1
  4. package/dist/adapters/backend/index.js +17 -441
  5. package/dist/adapters/backend/index.mjs +9 -433
  6. package/dist/adapters/frontend/index.d.mts +2 -1
  7. package/dist/adapters/frontend/index.d.ts +2 -1
  8. package/dist/adapters/frontend/index.js +10 -421
  9. package/dist/adapters/frontend/index.mjs +8 -419
  10. package/dist/chunk-2JYFKT3R.js +103 -0
  11. package/dist/chunk-3FANCMEF.js +206 -0
  12. package/dist/chunk-3TS35CVJ.mjs +478 -0
  13. package/dist/chunk-ASKTY6EG.js +131 -0
  14. package/dist/chunk-BJLVOIAP.js +491 -0
  15. package/dist/chunk-BNIB23NQ.js +90 -0
  16. package/dist/chunk-BVRXGZLS.js +17 -0
  17. package/dist/chunk-CQYXR2LZ.js +353 -0
  18. package/dist/chunk-ELL7U7IC.mjs +237 -0
  19. package/dist/chunk-FKDWSZIV.mjs +39 -0
  20. package/dist/chunk-FRBZHN4K.mjs +335 -0
  21. package/dist/chunk-FZ7K2PC7.js +248 -0
  22. package/dist/chunk-KHHJD6QK.mjs +85 -0
  23. package/dist/chunk-NUW55QTO.js +48 -0
  24. package/dist/chunk-TTK77YBI.mjs +15 -0
  25. package/dist/chunk-VWP24NYS.mjs +194 -0
  26. package/dist/chunk-XC4DKEXP.mjs +97 -0
  27. package/dist/chunk-XGTUU27F.mjs +124 -0
  28. package/dist/index-BQR7OrY7.d.mts +80 -0
  29. package/dist/index-BQR7OrY7.d.ts +80 -0
  30. package/dist/index.d.mts +3 -2
  31. package/dist/index.d.ts +3 -2
  32. package/dist/index.js +527 -494
  33. package/dist/index.mjs +476 -482
  34. package/dist/{schema-D9DGC9E_.d.mts → schema-CpAjXgEF.d.ts} +182 -79
  35. package/dist/{schema-D9DGC9E_.d.ts → schema-DYU1zGVm.d.mts} +182 -79
  36. package/dist/validators/array.d.mts +15 -0
  37. package/dist/validators/array.d.ts +15 -0
  38. package/dist/validators/array.js +31 -0
  39. package/dist/validators/array.mjs +2 -0
  40. package/dist/validators/common.d.mts +13 -0
  41. package/dist/validators/common.d.ts +13 -0
  42. package/dist/validators/common.js +27 -0
  43. package/dist/validators/common.mjs +2 -0
  44. package/dist/validators/date.d.mts +23 -0
  45. package/dist/validators/date.d.ts +23 -0
  46. package/dist/validators/date.js +47 -0
  47. package/dist/validators/date.mjs +2 -0
  48. package/dist/validators/index.d.mts +46 -0
  49. package/dist/validators/index.d.ts +46 -0
  50. package/dist/validators/index.js +256 -0
  51. package/dist/validators/index.mjs +7 -0
  52. package/dist/validators/number.d.mts +25 -0
  53. package/dist/validators/number.d.ts +25 -0
  54. package/dist/validators/number.js +51 -0
  55. package/dist/validators/number.mjs +2 -0
  56. package/dist/validators/object.d.mts +11 -0
  57. package/dist/validators/object.d.ts +11 -0
  58. package/dist/validators/object.js +23 -0
  59. package/dist/validators/object.mjs +2 -0
  60. package/dist/validators/string.d.mts +37 -0
  61. package/dist/validators/string.d.ts +37 -0
  62. package/dist/validators/string.js +75 -0
  63. package/dist/validators/string.mjs +2 -0
  64. package/package.json +36 -1
  65. package/dist/adapters/backend/index.js.map +0 -1
  66. package/dist/adapters/backend/index.mjs.map +0 -1
  67. package/dist/adapters/frontend/index.js.map +0 -1
  68. package/dist/adapters/frontend/index.mjs.map +0 -1
  69. package/dist/index.js.map +0 -1
  70. package/dist/index.mjs.map +0 -1
@@ -0,0 +1,206 @@
1
+ 'use strict';
2
+
3
+ var chunkNUW55QTO_js = require('./chunk-NUW55QTO.js');
4
+
5
+ // src/validators/number/port.ts
6
+ var portValidator = (value, params, context) => {
7
+ if (chunkNUW55QTO_js.isEmpty(value)) return null;
8
+ const soft = params?.soft;
9
+ const message = params?.message;
10
+ if (!chunkNUW55QTO_js.isNumber(value)) return null;
11
+ if (!Number.isInteger(value) || value < 0 || value > 65535) {
12
+ return chunkNUW55QTO_js.createError(
13
+ context,
14
+ "INVALID_PORT",
15
+ message || "Must be a valid port number (0-65535)",
16
+ soft
17
+ );
18
+ }
19
+ return null;
20
+ };
21
+
22
+ // src/validators/number/latitude.ts
23
+ var latitudeValidator = (value, params, context) => {
24
+ if (chunkNUW55QTO_js.isEmpty(value)) return null;
25
+ const soft = params?.soft;
26
+ const message = params?.message;
27
+ if (!chunkNUW55QTO_js.isNumber(value)) return null;
28
+ if (value < -90 || value > 90) {
29
+ return chunkNUW55QTO_js.createError(
30
+ context,
31
+ "INVALID_LATITUDE",
32
+ message || "Latitude must be between -90 and 90",
33
+ soft
34
+ );
35
+ }
36
+ return null;
37
+ };
38
+
39
+ // src/validators/number/longitude.ts
40
+ var longitudeValidator = (value, params, context) => {
41
+ if (chunkNUW55QTO_js.isEmpty(value)) return null;
42
+ const soft = params?.soft;
43
+ const message = params?.message;
44
+ if (!chunkNUW55QTO_js.isNumber(value)) return null;
45
+ if (value < -180 || value > 180) {
46
+ return chunkNUW55QTO_js.createError(
47
+ context,
48
+ "INVALID_LONGITUDE",
49
+ message || "Longitude must be between -180 and 180",
50
+ soft
51
+ );
52
+ }
53
+ return null;
54
+ };
55
+
56
+ // src/validators/number/percentage.ts
57
+ var percentageValidator = (value, params, context) => {
58
+ if (chunkNUW55QTO_js.isEmpty(value)) return null;
59
+ const soft = params?.soft;
60
+ const message = params?.message;
61
+ if (!chunkNUW55QTO_js.isNumber(value)) return null;
62
+ if (value < 0 || value > 100) {
63
+ return chunkNUW55QTO_js.createError(
64
+ context,
65
+ "INVALID_PERCENTAGE",
66
+ message || "Percentage must be between 0 and 100",
67
+ soft
68
+ );
69
+ }
70
+ return null;
71
+ };
72
+
73
+ // src/validators/number/between.ts
74
+ var betweenValidator = (value, params, context) => {
75
+ if (chunkNUW55QTO_js.isEmpty(value)) return null;
76
+ const min = params?.min;
77
+ const max = params?.max;
78
+ const soft = params?.soft;
79
+ const message = params?.message;
80
+ if (!chunkNUW55QTO_js.isNumber(value)) return null;
81
+ if (value < min || value > max) {
82
+ return chunkNUW55QTO_js.createError(
83
+ context,
84
+ "INVALID_BETWEEN",
85
+ message || `Must be between ${min} and ${max}`,
86
+ soft
87
+ );
88
+ }
89
+ return null;
90
+ };
91
+
92
+ // src/validators/number/divisibleBy.ts
93
+ var divisibleByValidator = (value, params, context) => {
94
+ if (chunkNUW55QTO_js.isEmpty(value)) return null;
95
+ const divisor = params?.divisor;
96
+ const soft = params?.soft;
97
+ const message = params?.message;
98
+ if (!chunkNUW55QTO_js.isNumber(value)) return null;
99
+ if (value % divisor !== 0) {
100
+ return chunkNUW55QTO_js.createError(
101
+ context,
102
+ "INVALID_DIVISIBLE_BY",
103
+ message || `Must be divisible by ${divisor}`,
104
+ soft
105
+ );
106
+ }
107
+ return null;
108
+ };
109
+
110
+ // src/validators/number/multipleOf.ts
111
+ var multipleOfValidator = (value, params, context) => {
112
+ if (chunkNUW55QTO_js.isEmpty(value)) return null;
113
+ const multiple = params?.multiple;
114
+ const soft = params?.soft;
115
+ const message = params?.message;
116
+ if (!chunkNUW55QTO_js.isNumber(value)) return null;
117
+ if (value % multiple !== 0) {
118
+ return chunkNUW55QTO_js.createError(
119
+ context,
120
+ "INVALID_MULTIPLE_OF",
121
+ message || `Must be a multiple of ${multiple}`,
122
+ soft
123
+ );
124
+ }
125
+ return null;
126
+ };
127
+
128
+ // src/validators/number/even.ts
129
+ var evenValidator = (value, params, context) => {
130
+ if (chunkNUW55QTO_js.isEmpty(value)) return null;
131
+ const soft = params?.soft;
132
+ const message = params?.message;
133
+ if (!chunkNUW55QTO_js.isNumber(value)) return null;
134
+ if (value % 2 !== 0) {
135
+ return chunkNUW55QTO_js.createError(
136
+ context,
137
+ "INVALID_EVEN",
138
+ message || "Must be an even number",
139
+ soft
140
+ );
141
+ }
142
+ return null;
143
+ };
144
+
145
+ // src/validators/number/odd.ts
146
+ var oddValidator = (value, params, context) => {
147
+ if (chunkNUW55QTO_js.isEmpty(value)) return null;
148
+ const soft = params?.soft;
149
+ const message = params?.message;
150
+ if (!chunkNUW55QTO_js.isNumber(value)) return null;
151
+ if (value % 2 === 0) {
152
+ return chunkNUW55QTO_js.createError(
153
+ context,
154
+ "INVALID_ODD",
155
+ message || "Must be an odd number",
156
+ soft
157
+ );
158
+ }
159
+ return null;
160
+ };
161
+
162
+ // src/validators/number/safe.ts
163
+ var safeValidator = (value, params, context) => {
164
+ if (chunkNUW55QTO_js.isEmpty(value)) return null;
165
+ const soft = params?.soft;
166
+ const message = params?.message;
167
+ if (!chunkNUW55QTO_js.isNumber(value)) return null;
168
+ if (!Number.isSafeInteger(value)) {
169
+ return chunkNUW55QTO_js.createError(
170
+ context,
171
+ "INVALID_SAFE_INTEGER",
172
+ message || "Must be a safe integer",
173
+ soft
174
+ );
175
+ }
176
+ return null;
177
+ };
178
+
179
+ // src/validators/number/finite.ts
180
+ var finiteValidator = (value, params, context) => {
181
+ if (chunkNUW55QTO_js.isEmpty(value)) return null;
182
+ const soft = params?.soft;
183
+ const message = params?.message;
184
+ if (!chunkNUW55QTO_js.isNumber(value)) return null;
185
+ if (!Number.isFinite(value)) {
186
+ return chunkNUW55QTO_js.createError(
187
+ context,
188
+ "INVALID_FINITE",
189
+ message || "Must be a finite number",
190
+ soft
191
+ );
192
+ }
193
+ return null;
194
+ };
195
+
196
+ exports.betweenValidator = betweenValidator;
197
+ exports.divisibleByValidator = divisibleByValidator;
198
+ exports.evenValidator = evenValidator;
199
+ exports.finiteValidator = finiteValidator;
200
+ exports.latitudeValidator = latitudeValidator;
201
+ exports.longitudeValidator = longitudeValidator;
202
+ exports.multipleOfValidator = multipleOfValidator;
203
+ exports.oddValidator = oddValidator;
204
+ exports.percentageValidator = percentageValidator;
205
+ exports.portValidator = portValidator;
206
+ exports.safeValidator = safeValidator;
@@ -0,0 +1,478 @@
1
+ import { strictValidator, omitValidator, pickValidator, keysValidator } from './chunk-KHHJD6QK.mjs';
2
+ import { dependsOnValidator, whenValidator, lessThanValidator, greaterThanValidator, notMatchesValidator } from './chunk-XC4DKEXP.mjs';
3
+ import { endsWithValidator, startsWithValidator, containsValidator, lengthValidator, jsonValidator, base64Validator, hexValidator, slugValidator, uppercaseValidator, lowercaseValidator, numericValidator, alphanumericValidator, alphaValidator, ipv6Validator, ipAddressValidator, urlValidator, emailValidator } from './chunk-FRBZHN4K.mjs';
4
+ import { finiteValidator, safeValidator, oddValidator, evenValidator, multipleOfValidator, divisibleByValidator, betweenValidator as betweenValidator$1, percentageValidator, longitudeValidator, latitudeValidator, portValidator } from './chunk-VWP24NYS.mjs';
5
+ import { betweenValidator, ageValidator, weekendValidator, weekdayValidator, thisYearValidator, thisMonthValidator, thisWeekValidator, tomorrowValidator, yesterdayValidator, todayValidator } from './chunk-ELL7U7IC.mjs';
6
+ import { compactValidator, sortedValidator, notEmptyValidator, emptyValidator, excludesValidator, includesValidator } from './chunk-XGTUU27F.mjs';
7
+
8
+ // src/core/validators.ts
9
+ function createError(context, code, message, soft = false) {
10
+ return {
11
+ field: context.path,
12
+ code,
13
+ message,
14
+ severity: soft ? "soft" : "hard"
15
+ };
16
+ }
17
+ var typeValidators = {
18
+ string: (value, _params, context) => {
19
+ if (value !== void 0 && value !== null && typeof value !== "string") {
20
+ return createError(context, "INVALID_TYPE", `Expected string, got ${typeof value}`);
21
+ }
22
+ return null;
23
+ },
24
+ number: (value, _params, context) => {
25
+ if (value !== void 0 && value !== null && typeof value !== "number") {
26
+ return createError(context, "INVALID_TYPE", `Expected number, got ${typeof value}`);
27
+ }
28
+ if (typeof value === "number" && isNaN(value)) {
29
+ return createError(context, "INVALID_NUMBER", "Value is not a valid number");
30
+ }
31
+ return null;
32
+ },
33
+ boolean: (value, _params, context) => {
34
+ if (value !== void 0 && value !== null && typeof value !== "boolean") {
35
+ return createError(context, "INVALID_TYPE", `Expected boolean, got ${typeof value}`);
36
+ }
37
+ return null;
38
+ },
39
+ date: (value, _params, context) => {
40
+ if (value === void 0 || value === null) return null;
41
+ if (value instanceof Date) {
42
+ if (isNaN(value.getTime())) {
43
+ return createError(context, "INVALID_DATE", "Invalid date value");
44
+ }
45
+ return null;
46
+ }
47
+ if (typeof value === "string") {
48
+ const parsed = new Date(value);
49
+ if (isNaN(parsed.getTime())) {
50
+ return createError(context, "INVALID_DATE", "Invalid date format");
51
+ }
52
+ return null;
53
+ }
54
+ return createError(context, "INVALID_TYPE", `Expected date, got ${typeof value}`);
55
+ },
56
+ array: (value, _params, context) => {
57
+ if (value !== void 0 && value !== null && !Array.isArray(value)) {
58
+ return createError(context, "INVALID_TYPE", `Expected array, got ${typeof value}`);
59
+ }
60
+ return null;
61
+ },
62
+ object: (value, _params, context) => {
63
+ if (value !== void 0 && value !== null) {
64
+ if (typeof value !== "object" || Array.isArray(value)) {
65
+ return createError(context, "INVALID_TYPE", `Expected object, got ${typeof value}`);
66
+ }
67
+ }
68
+ return null;
69
+ }
70
+ };
71
+ var ruleValidators = {
72
+ required: (value, _params, context) => {
73
+ const isEmpty = value === void 0 || value === null || value === "" || Array.isArray(value) && value.length === 0;
74
+ if (isEmpty) {
75
+ return createError(context, "REQUIRED", "This field is required");
76
+ }
77
+ return null;
78
+ },
79
+ min: (value, params, context) => {
80
+ const min = params?.value;
81
+ const soft = params?.soft;
82
+ const message = params?.message;
83
+ if (value === void 0 || value === null) return null;
84
+ if (typeof value === "number") {
85
+ if (value < min) {
86
+ return createError(
87
+ context,
88
+ "MIN_VALUE",
89
+ message || `Value must be at least ${min}`,
90
+ soft
91
+ );
92
+ }
93
+ }
94
+ if (typeof value === "string") {
95
+ if (value.length < min) {
96
+ return createError(
97
+ context,
98
+ "MIN_LENGTH",
99
+ message || `Must be at least ${min} characters`,
100
+ soft
101
+ );
102
+ }
103
+ }
104
+ if (Array.isArray(value)) {
105
+ if (value.length < min) {
106
+ return createError(
107
+ context,
108
+ "MIN_ITEMS",
109
+ message || `Must have at least ${min} items`,
110
+ soft
111
+ );
112
+ }
113
+ }
114
+ return null;
115
+ },
116
+ max: (value, params, context) => {
117
+ const max = params?.value;
118
+ const soft = params?.soft;
119
+ const message = params?.message;
120
+ if (value === void 0 || value === null) return null;
121
+ if (typeof value === "number") {
122
+ if (value > max) {
123
+ return createError(
124
+ context,
125
+ "MAX_VALUE",
126
+ message || `Value must be at most ${max}`,
127
+ soft
128
+ );
129
+ }
130
+ }
131
+ if (typeof value === "string") {
132
+ if (value.length > max) {
133
+ return createError(
134
+ context,
135
+ "MAX_LENGTH",
136
+ message || `Must be at most ${max} characters`,
137
+ soft
138
+ );
139
+ }
140
+ }
141
+ if (Array.isArray(value)) {
142
+ if (value.length > max) {
143
+ return createError(
144
+ context,
145
+ "MAX_ITEMS",
146
+ message || `Must have at most ${max} items`,
147
+ soft
148
+ );
149
+ }
150
+ }
151
+ return null;
152
+ },
153
+ // String validators
154
+ email: emailValidator,
155
+ url: urlValidator,
156
+ ipAddress: ipAddressValidator,
157
+ ipv6: ipv6Validator,
158
+ alpha: alphaValidator,
159
+ alphanumeric: alphanumericValidator,
160
+ numeric: numericValidator,
161
+ lowercase: lowercaseValidator,
162
+ uppercase: uppercaseValidator,
163
+ slug: slugValidator,
164
+ hex: hexValidator,
165
+ base64: base64Validator,
166
+ json: jsonValidator,
167
+ length: lengthValidator,
168
+ contains: containsValidator,
169
+ startsWith: startsWithValidator,
170
+ endsWith: endsWithValidator,
171
+ // Number validators
172
+ port: portValidator,
173
+ latitude: latitudeValidator,
174
+ longitude: longitudeValidator,
175
+ percentage: percentageValidator,
176
+ numberBetween: betweenValidator$1,
177
+ divisibleBy: divisibleByValidator,
178
+ multipleOf: multipleOfValidator,
179
+ even: evenValidator,
180
+ odd: oddValidator,
181
+ safe: safeValidator,
182
+ finite: finiteValidator,
183
+ // Date validators
184
+ today: todayValidator,
185
+ yesterday: yesterdayValidator,
186
+ tomorrow: tomorrowValidator,
187
+ thisWeek: thisWeekValidator,
188
+ thisMonth: thisMonthValidator,
189
+ thisYear: thisYearValidator,
190
+ weekday: weekdayValidator,
191
+ weekend: weekendValidator,
192
+ age: ageValidator,
193
+ dateBetween: betweenValidator,
194
+ // Array validators
195
+ includes: includesValidator,
196
+ excludes: excludesValidator,
197
+ empty: emptyValidator,
198
+ notEmpty: notEmptyValidator,
199
+ sorted: sortedValidator,
200
+ compact: compactValidator,
201
+ // Object validators
202
+ keys: keysValidator,
203
+ pick: pickValidator,
204
+ omit: omitValidator,
205
+ strict: strictValidator,
206
+ // Cross-field validators
207
+ notMatches: notMatchesValidator,
208
+ greaterThan: greaterThanValidator,
209
+ lessThan: lessThanValidator,
210
+ when: whenValidator,
211
+ dependsOn: dependsOnValidator,
212
+ pattern: (value, params, context) => {
213
+ if (value === void 0 || value === null || value === "") return null;
214
+ const pattern = params?.pattern;
215
+ const soft = params?.soft;
216
+ const message = params?.message;
217
+ if (typeof value !== "string") return null;
218
+ const regex = new RegExp(pattern);
219
+ if (!regex.test(value)) {
220
+ return createError(
221
+ context,
222
+ "PATTERN_MISMATCH",
223
+ message || `Value does not match required pattern`,
224
+ soft
225
+ );
226
+ }
227
+ return null;
228
+ },
229
+ enum: (value, params, context) => {
230
+ if (value === void 0 || value === null) return null;
231
+ const values = params?.values;
232
+ const soft = params?.soft;
233
+ const message = params?.message;
234
+ if (!values.includes(value)) {
235
+ return createError(
236
+ context,
237
+ "INVALID_ENUM",
238
+ message || `Value must be one of: ${values.join(", ")}`,
239
+ soft
240
+ );
241
+ }
242
+ return null;
243
+ },
244
+ custom: (value, params, context) => {
245
+ const validate2 = params?.validate;
246
+ const soft = params?.soft;
247
+ const message = params?.message;
248
+ if (!validate2) return null;
249
+ const result = validate2(value, context);
250
+ if (typeof result === "boolean") {
251
+ if (!result) {
252
+ return createError(
253
+ context,
254
+ "CUSTOM_VALIDATION",
255
+ message || "Validation failed",
256
+ soft
257
+ );
258
+ }
259
+ return null;
260
+ }
261
+ if (!result.valid) {
262
+ return createError(
263
+ context,
264
+ "CUSTOM_VALIDATION",
265
+ result.message || message || "Validation failed",
266
+ soft
267
+ );
268
+ }
269
+ return null;
270
+ },
271
+ // Enterprise patterns - matches field against another field
272
+ matches: (value, params, context) => {
273
+ if (value === void 0 || value === null) return null;
274
+ const otherField = params?.field;
275
+ const soft = params?.soft;
276
+ const message = params?.message;
277
+ const root = context.root;
278
+ const otherValue = root[otherField];
279
+ if (value !== otherValue) {
280
+ return createError(
281
+ context,
282
+ "FIELD_MISMATCH",
283
+ message || `Must match ${otherField}`,
284
+ soft
285
+ );
286
+ }
287
+ return null;
288
+ },
289
+ // Integer validation
290
+ integer: (value, params, context) => {
291
+ if (value === void 0 || value === null) return null;
292
+ const soft = params?.soft;
293
+ const message = params?.message;
294
+ if (typeof value !== "number" || !Number.isInteger(value)) {
295
+ return createError(
296
+ context,
297
+ "NOT_INTEGER",
298
+ message || "Value must be an integer",
299
+ soft
300
+ );
301
+ }
302
+ return null;
303
+ },
304
+ // Positive number validation
305
+ positive: (value, params, context) => {
306
+ if (value === void 0 || value === null) return null;
307
+ const soft = params?.soft;
308
+ const message = params?.message;
309
+ if (typeof value === "number" && value <= 0) {
310
+ return createError(
311
+ context,
312
+ "NOT_POSITIVE",
313
+ message || "Value must be positive",
314
+ soft
315
+ );
316
+ }
317
+ return null;
318
+ },
319
+ // Negative number validation
320
+ negative: (value, params, context) => {
321
+ if (value === void 0 || value === null) return null;
322
+ const soft = params?.soft;
323
+ const message = params?.message;
324
+ if (typeof value === "number" && value >= 0) {
325
+ return createError(
326
+ context,
327
+ "NOT_NEGATIVE",
328
+ message || "Value must be negative",
329
+ soft
330
+ );
331
+ }
332
+ return null;
333
+ }
334
+ };
335
+ var customValidators = /* @__PURE__ */ new Map();
336
+ function registerValidator(name, validator) {
337
+ customValidators.set(name, validator);
338
+ }
339
+ function getValidator(name) {
340
+ return ruleValidators[name] ?? customValidators.get(name);
341
+ }
342
+ function getTypeValidator(type) {
343
+ return typeValidators[type];
344
+ }
345
+
346
+ // src/core/engine.ts
347
+ function validateField(fieldDef, value, context) {
348
+ const errors = [];
349
+ const typeValidator = getTypeValidator(fieldDef.type);
350
+ if (typeValidator) {
351
+ const typeError = typeValidator(value, void 0, context);
352
+ if (typeError) {
353
+ errors.push(typeError);
354
+ return errors;
355
+ }
356
+ }
357
+ if (fieldDef.required) {
358
+ const requiredValidator = getValidator("required");
359
+ if (requiredValidator) {
360
+ const error = requiredValidator(value, void 0, context);
361
+ if (error) {
362
+ errors.push(error);
363
+ return errors;
364
+ }
365
+ }
366
+ } else if (value === void 0 || value === null || value === "") {
367
+ return errors;
368
+ }
369
+ for (const rule of fieldDef.rules) {
370
+ const validator = getValidator(rule.type);
371
+ if (!validator) {
372
+ console.warn(`Unknown validator: ${rule.type}`);
373
+ continue;
374
+ }
375
+ const params = {
376
+ ...rule.params,
377
+ soft: rule.soft,
378
+ message: rule.message
379
+ };
380
+ const error = validator(value, params, context);
381
+ if (error) {
382
+ errors.push(error);
383
+ }
384
+ }
385
+ if (fieldDef.type === "object" && fieldDef.schema && value !== null && value !== void 0) {
386
+ const nestedResult = validateSchema(fieldDef.schema, value, context.path, context.root);
387
+ errors.push(...nestedResult.hardErrors, ...nestedResult.softErrors);
388
+ }
389
+ if (fieldDef.type === "array" && fieldDef.items && Array.isArray(value)) {
390
+ for (let i = 0; i < value.length; i++) {
391
+ const itemContext = {
392
+ path: `${context.path}[${i}]`,
393
+ root: context.root,
394
+ parent: value
395
+ };
396
+ const itemErrors = validateField(fieldDef.items, value[i], itemContext);
397
+ errors.push(...itemErrors);
398
+ }
399
+ }
400
+ return errors;
401
+ }
402
+ function validateSchema(schema, data, basePath = "", root) {
403
+ const hardErrors = [];
404
+ const softErrors = [];
405
+ const rootData = root ?? data;
406
+ for (const [fieldName, fieldDef] of Object.entries(schema.fields)) {
407
+ const value = data[fieldName];
408
+ const path = basePath ? `${basePath}.${fieldName}` : fieldName;
409
+ const context = {
410
+ path,
411
+ root: rootData,
412
+ parent: data
413
+ };
414
+ const errors = validateField(fieldDef, value, context);
415
+ for (const error of errors) {
416
+ if (error.severity === "soft") {
417
+ softErrors.push(error);
418
+ } else {
419
+ hardErrors.push(error);
420
+ }
421
+ }
422
+ }
423
+ return {
424
+ valid: hardErrors.length === 0,
425
+ hardErrors,
426
+ softErrors
427
+ };
428
+ }
429
+ function validate(schema, data) {
430
+ return validateSchema(schema, data);
431
+ }
432
+ function isValid(schema, data) {
433
+ return validate(schema, data).valid;
434
+ }
435
+ function assertValid(schema, data) {
436
+ const result = validate(schema, data);
437
+ if (!result.valid) {
438
+ const error = new Error("Validation failed");
439
+ error.errors = result.hardErrors;
440
+ throw error;
441
+ }
442
+ return data;
443
+ }
444
+ function mergeResults(...results) {
445
+ const hardErrors = [];
446
+ const softErrors = [];
447
+ for (const result of results) {
448
+ hardErrors.push(...result.hardErrors);
449
+ softErrors.push(...result.softErrors);
450
+ }
451
+ return {
452
+ valid: hardErrors.length === 0,
453
+ hardErrors,
454
+ softErrors
455
+ };
456
+ }
457
+ function validResult() {
458
+ return {
459
+ valid: true,
460
+ hardErrors: [],
461
+ softErrors: []
462
+ };
463
+ }
464
+ function errorResult(field, code, message, soft = false) {
465
+ const error = {
466
+ field,
467
+ code,
468
+ message,
469
+ severity: soft ? "soft" : "hard"
470
+ };
471
+ return {
472
+ valid: soft,
473
+ hardErrors: soft ? [] : [error],
474
+ softErrors: soft ? [error] : []
475
+ };
476
+ }
477
+
478
+ export { assertValid, errorResult, getTypeValidator, getValidator, isValid, mergeResults, registerValidator, ruleValidators, typeValidators, validResult, validate, validateSchema };