unischema 1.1.0 → 1.2.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 (65) hide show
  1. package/README.md +151 -2
  2. package/dist/adapters/backend/index.d.mts +2 -2
  3. package/dist/adapters/backend/index.d.ts +2 -2
  4. package/dist/adapters/backend/index.js +11 -11
  5. package/dist/adapters/backend/index.mjs +8 -8
  6. package/dist/adapters/frontend/index.d.mts +2 -2
  7. package/dist/adapters/frontend/index.d.ts +2 -2
  8. package/dist/adapters/frontend/index.js +10 -10
  9. package/dist/adapters/frontend/index.mjs +8 -8
  10. package/dist/{chunk-XGTUU27F.mjs → chunk-5A4ITJVD.mjs} +1 -1
  11. package/dist/{chunk-ASKTY6EG.js → chunk-66RFUBVU.js} +20 -20
  12. package/dist/{chunk-KHHJD6QK.mjs → chunk-75YSYC4K.mjs} +1 -1
  13. package/dist/{chunk-BNIB23NQ.js → chunk-76BBWQDH.js} +13 -13
  14. package/dist/{chunk-ELL7U7IC.mjs → chunk-7XES4A3M.mjs} +1 -1
  15. package/dist/{chunk-FRBZHN4K.mjs → chunk-COMVAVFU.mjs} +1 -1
  16. package/dist/chunk-DT2TQZU7.js +796 -0
  17. package/dist/{chunk-2JYFKT3R.js → chunk-FPCCH55A.js} +14 -14
  18. package/dist/{chunk-3FANCMEF.js → chunk-IUXRLMET.js} +34 -34
  19. package/dist/{chunk-CQYXR2LZ.js → chunk-JEW6U6CB.js} +65 -65
  20. package/dist/{chunk-XC4DKEXP.mjs → chunk-KZCV5IW4.mjs} +1 -1
  21. package/dist/{chunk-FKDWSZIV.mjs → chunk-KZZ7NVU3.mjs} +4 -2
  22. package/dist/{chunk-3TS35CVJ.mjs → chunk-MFEBMQAU.mjs} +341 -40
  23. package/dist/{chunk-NUW55QTO.js → chunk-OIYG5D2I.js} +4 -2
  24. package/dist/{chunk-VWP24NYS.mjs → chunk-RW6HDA5H.mjs} +1 -1
  25. package/dist/{chunk-FZ7K2PC7.js → chunk-TXT36BCE.js} +35 -35
  26. package/dist/index-C17xs-fU.d.mts +140 -0
  27. package/dist/index-C17xs-fU.d.ts +140 -0
  28. package/dist/index.d.mts +26 -8
  29. package/dist/index.d.ts +26 -8
  30. package/dist/index.js +262 -25
  31. package/dist/index.mjs +228 -14
  32. package/dist/{schema-DYU1zGVm.d.mts → schema-DYE8Wz8X.d.mts} +84 -2
  33. package/dist/{schema-CpAjXgEF.d.ts → schema-Dtp-joeT.d.ts} +84 -2
  34. package/dist/validators/array.d.mts +1 -1
  35. package/dist/validators/array.d.ts +1 -1
  36. package/dist/validators/array.js +8 -8
  37. package/dist/validators/array.mjs +2 -2
  38. package/dist/validators/common.d.mts +1 -1
  39. package/dist/validators/common.d.ts +1 -1
  40. package/dist/validators/common.js +7 -7
  41. package/dist/validators/common.mjs +2 -2
  42. package/dist/validators/date.d.mts +1 -1
  43. package/dist/validators/date.d.ts +1 -1
  44. package/dist/validators/date.js +12 -12
  45. package/dist/validators/date.mjs +2 -2
  46. package/dist/validators/index.d.mts +2 -2
  47. package/dist/validators/index.d.ts +2 -2
  48. package/dist/validators/index.js +68 -68
  49. package/dist/validators/index.mjs +7 -7
  50. package/dist/validators/number.d.mts +1 -1
  51. package/dist/validators/number.d.ts +1 -1
  52. package/dist/validators/number.js +13 -13
  53. package/dist/validators/number.mjs +2 -2
  54. package/dist/validators/object.d.mts +1 -1
  55. package/dist/validators/object.d.ts +1 -1
  56. package/dist/validators/object.js +6 -6
  57. package/dist/validators/object.mjs +2 -2
  58. package/dist/validators/string.d.mts +1 -1
  59. package/dist/validators/string.d.ts +1 -1
  60. package/dist/validators/string.js +19 -19
  61. package/dist/validators/string.mjs +2 -2
  62. package/package.json +47 -5
  63. package/dist/chunk-BJLVOIAP.js +0 -491
  64. package/dist/index-BQR7OrY7.d.mts +0 -80
  65. package/dist/index-BQR7OrY7.d.ts +0 -80
package/dist/index.js CHANGED
@@ -1,14 +1,14 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkBVRXGZLS_js = require('./chunk-BVRXGZLS.js');
4
- var chunkBJLVOIAP_js = require('./chunk-BJLVOIAP.js');
5
- require('./chunk-BNIB23NQ.js');
6
- require('./chunk-2JYFKT3R.js');
7
- require('./chunk-CQYXR2LZ.js');
8
- require('./chunk-3FANCMEF.js');
9
- require('./chunk-FZ7K2PC7.js');
10
- require('./chunk-ASKTY6EG.js');
11
- require('./chunk-NUW55QTO.js');
4
+ var chunkDT2TQZU7_js = require('./chunk-DT2TQZU7.js');
5
+ require('./chunk-76BBWQDH.js');
6
+ require('./chunk-FPCCH55A.js');
7
+ require('./chunk-JEW6U6CB.js');
8
+ require('./chunk-IUXRLMET.js');
9
+ require('./chunk-TXT36BCE.js');
10
+ require('./chunk-66RFUBVU.js');
11
+ require('./chunk-OIYG5D2I.js');
12
12
 
13
13
  // src/schema/field.ts
14
14
  var BaseFieldBuilder = class {
@@ -16,6 +16,9 @@ var BaseFieldBuilder = class {
16
16
  this._rules = [];
17
17
  this._required = false;
18
18
  this._meta = {};
19
+ this._transforms = [];
20
+ this._nullable = false;
21
+ this._nullish = false;
19
22
  this._type = type;
20
23
  }
21
24
  /**
@@ -65,6 +68,59 @@ var BaseFieldBuilder = class {
65
68
  });
66
69
  return this;
67
70
  }
71
+ /**
72
+ * Add async custom validation
73
+ */
74
+ refineAsync(validate2, options) {
75
+ const opts = typeof options === "string" ? { message: options } : options || {};
76
+ this._rules.push({
77
+ type: "refineAsync",
78
+ params: { validate: validate2 },
79
+ message: opts.message,
80
+ soft: opts.soft,
81
+ async: true,
82
+ debounce: opts.debounce,
83
+ timeout: opts.timeout || 5e3
84
+ });
85
+ return this;
86
+ }
87
+ /**
88
+ * Add async soft validation (warning only)
89
+ */
90
+ refineAsyncSoft(validate2, options) {
91
+ const opts = typeof options === "string" ? { message: options } : options || {};
92
+ return this.refineAsync(validate2, { ...opts, soft: true });
93
+ }
94
+ /**
95
+ * Transform value before validation (applied after preprocessing)
96
+ */
97
+ transform(transformer) {
98
+ this._transforms.push(transformer);
99
+ return this;
100
+ }
101
+ /**
102
+ * Preprocess value before transformations and validation
103
+ * Useful for handling null/undefined values
104
+ */
105
+ preprocess(preprocessor) {
106
+ this._preprocess = preprocessor;
107
+ return this;
108
+ }
109
+ /**
110
+ * Allow null values
111
+ */
112
+ nullable() {
113
+ this._nullable = true;
114
+ return this;
115
+ }
116
+ /**
117
+ * Allow null or undefined values
118
+ */
119
+ nullish() {
120
+ this._nullish = true;
121
+ this._nullable = true;
122
+ return this;
123
+ }
68
124
  /**
69
125
  * Add field metadata
70
126
  */
@@ -125,7 +181,11 @@ var BaseFieldBuilder = class {
125
181
  rules: [...this._rules],
126
182
  required: this._required,
127
183
  defaultValue: this._defaultValue,
128
- meta: Object.keys(this._meta).length > 0 ? this._meta : void 0
184
+ meta: Object.keys(this._meta).length > 0 ? this._meta : void 0,
185
+ transforms: this._transforms.length > 0 ? [...this._transforms] : void 0,
186
+ preprocess: this._preprocess,
187
+ nullable: this._nullable || void 0,
188
+ nullish: this._nullish || void 0
129
189
  };
130
190
  }
131
191
  };
@@ -400,11 +460,11 @@ var StringFieldBuilder = class extends BaseFieldBuilder {
400
460
  }
401
461
  };
402
462
  var EnumFieldBuilder = class extends BaseFieldBuilder {
403
- constructor(values, rules = [], required = false, meta = {}) {
463
+ constructor(values, rules = [], required2 = false, meta = {}) {
404
464
  super("string");
405
465
  this._values = values;
406
466
  this._rules = [...rules];
407
- this._required = required;
467
+ this._required = required2;
408
468
  this._meta = { ...meta };
409
469
  }
410
470
  /**
@@ -996,7 +1056,11 @@ var ArrayFieldBuilder = class extends BaseFieldBuilder {
996
1056
  required: this._required,
997
1057
  defaultValue: this._defaultValue,
998
1058
  items: this._itemDef,
999
- meta: Object.keys(this._meta).length > 0 ? this._meta : void 0
1059
+ meta: Object.keys(this._meta).length > 0 ? this._meta : void 0,
1060
+ transforms: this._transforms.length > 0 ? [...this._transforms] : void 0,
1061
+ preprocess: this._preprocess,
1062
+ nullable: this._nullable || void 0,
1063
+ nullish: this._nullish || void 0
1000
1064
  };
1001
1065
  }
1002
1066
  };
@@ -1016,10 +1080,80 @@ var ObjectFieldBuilder = class extends BaseFieldBuilder {
1016
1080
  required: this._required,
1017
1081
  defaultValue: this._defaultValue,
1018
1082
  schema: this._schema,
1019
- meta: Object.keys(this._meta).length > 0 ? this._meta : void 0
1083
+ meta: Object.keys(this._meta).length > 0 ? this._meta : void 0,
1084
+ transforms: this._transforms.length > 0 ? [...this._transforms] : void 0,
1085
+ preprocess: this._preprocess,
1086
+ nullable: this._nullable || void 0,
1087
+ nullish: this._nullish || void 0
1020
1088
  };
1021
1089
  }
1022
1090
  };
1091
+ var coerce = {
1092
+ /**
1093
+ * Coerce value to string
1094
+ */
1095
+ string() {
1096
+ return new StringFieldBuilder().preprocess((value) => {
1097
+ if (value === null || value === void 0) return value;
1098
+ return String(value);
1099
+ });
1100
+ },
1101
+ /**
1102
+ * Coerce value to number
1103
+ */
1104
+ number() {
1105
+ return new NumberFieldBuilder().preprocess((value) => {
1106
+ if (value === null || value === void 0) return value;
1107
+ if (typeof value === "number") return value;
1108
+ if (typeof value === "string") {
1109
+ const parsed = parseFloat(value);
1110
+ return isNaN(parsed) ? value : parsed;
1111
+ }
1112
+ if (typeof value === "boolean") return value ? 1 : 0;
1113
+ return value;
1114
+ });
1115
+ },
1116
+ /**
1117
+ * Coerce value to boolean
1118
+ */
1119
+ boolean() {
1120
+ return new BooleanFieldBuilder().preprocess((value) => {
1121
+ if (value === null || value === void 0) return value;
1122
+ if (typeof value === "boolean") return value;
1123
+ if (typeof value === "string") {
1124
+ const lower = value.toLowerCase().trim();
1125
+ if (lower === "true" || lower === "1" || lower === "yes" || lower === "on") return true;
1126
+ if (lower === "false" || lower === "0" || lower === "no" || lower === "off") return false;
1127
+ }
1128
+ if (typeof value === "number") return value !== 0;
1129
+ return value;
1130
+ });
1131
+ },
1132
+ /**
1133
+ * Coerce value to date
1134
+ */
1135
+ date() {
1136
+ return new DateFieldBuilder().preprocess((value) => {
1137
+ if (value === null || value === void 0) return value;
1138
+ if (value instanceof Date) return value;
1139
+ if (typeof value === "string" || typeof value === "number") {
1140
+ const date = new Date(value);
1141
+ return isNaN(date.getTime()) ? value : date;
1142
+ }
1143
+ return value;
1144
+ });
1145
+ },
1146
+ /**
1147
+ * Coerce value to array
1148
+ */
1149
+ array(itemBuilder) {
1150
+ return new ArrayFieldBuilder(itemBuilder).preprocess((value) => {
1151
+ if (value === null || value === void 0) return value;
1152
+ if (Array.isArray(value)) return value;
1153
+ return [value];
1154
+ });
1155
+ }
1156
+ };
1023
1157
 
1024
1158
  // src/schema/schema.ts
1025
1159
  function schema(fields) {
@@ -1070,6 +1204,86 @@ function partial(baseSchema) {
1070
1204
  }
1071
1205
  return schema(partialFields);
1072
1206
  }
1207
+ function deepPartial(baseSchema) {
1208
+ const deepPartialFields = {};
1209
+ for (const [key, builder] of Object.entries(baseSchema._fields)) {
1210
+ const clonedBuilder = Object.create(Object.getPrototypeOf(builder));
1211
+ Object.assign(clonedBuilder, builder);
1212
+ clonedBuilder._required = false;
1213
+ if (builder instanceof ObjectFieldBuilder) {
1214
+ const fieldDef = builder.build();
1215
+ if (fieldDef.schema) {
1216
+ const nestedFields = {};
1217
+ for (const [nestedKey, nestedDef] of Object.entries(fieldDef.schema.fields)) {
1218
+ const nestedBuilder = Object.create(BaseFieldBuilder.prototype);
1219
+ Object.assign(nestedBuilder, {
1220
+ _type: nestedDef.type,
1221
+ _rules: nestedDef.rules || [],
1222
+ _required: false,
1223
+ // Make optional
1224
+ _defaultValue: nestedDef.defaultValue,
1225
+ _meta: nestedDef.meta || {},
1226
+ _transforms: nestedDef.transforms || [],
1227
+ _preprocess: nestedDef.preprocess,
1228
+ _nullable: nestedDef.nullable || false,
1229
+ _nullish: nestedDef.nullish || false
1230
+ });
1231
+ nestedFields[nestedKey] = nestedBuilder;
1232
+ }
1233
+ const nestedSchema = schema(nestedFields);
1234
+ const deepNestedSchema = deepPartial(nestedSchema);
1235
+ clonedBuilder._schema = deepNestedSchema.definition;
1236
+ }
1237
+ }
1238
+ deepPartialFields[key] = clonedBuilder;
1239
+ }
1240
+ return schema(deepPartialFields);
1241
+ }
1242
+ function passthrough(baseSchema) {
1243
+ const result = schema(baseSchema._fields);
1244
+ result.definition.passthrough = true;
1245
+ return result;
1246
+ }
1247
+ function strict(baseSchema) {
1248
+ const result = schema(baseSchema._fields);
1249
+ result.definition.strict = true;
1250
+ return result;
1251
+ }
1252
+ function catchall(baseSchema, fieldBuilder) {
1253
+ const result = schema(baseSchema._fields);
1254
+ result.definition.catchall = fieldBuilder.build();
1255
+ return result;
1256
+ }
1257
+ function required(baseSchema, keys) {
1258
+ const keySet = new Set(keys);
1259
+ const newFields = {};
1260
+ for (const [key, builder] of Object.entries(baseSchema._fields)) {
1261
+ if (keySet.has(key)) {
1262
+ const clonedBuilder = Object.create(Object.getPrototypeOf(builder));
1263
+ Object.assign(clonedBuilder, builder);
1264
+ clonedBuilder._required = true;
1265
+ newFields[key] = clonedBuilder;
1266
+ } else {
1267
+ newFields[key] = builder;
1268
+ }
1269
+ }
1270
+ return schema(newFields);
1271
+ }
1272
+ function optional(baseSchema, keys) {
1273
+ const keySet = new Set(keys);
1274
+ const newFields = {};
1275
+ for (const [key, builder] of Object.entries(baseSchema._fields)) {
1276
+ if (keySet.has(key)) {
1277
+ const clonedBuilder = Object.create(Object.getPrototypeOf(builder));
1278
+ Object.assign(clonedBuilder, builder);
1279
+ clonedBuilder._required = false;
1280
+ newFields[key] = clonedBuilder;
1281
+ } else {
1282
+ newFields[key] = builder;
1283
+ }
1284
+ }
1285
+ return schema(newFields);
1286
+ }
1073
1287
  function merge(schema1, schema2) {
1074
1288
  return schema({
1075
1289
  ...schema1._fields,
@@ -1133,51 +1347,67 @@ Object.defineProperty(exports, "toEnterpriseResponse", {
1133
1347
  });
1134
1348
  Object.defineProperty(exports, "assertValid", {
1135
1349
  enumerable: true,
1136
- get: function () { return chunkBJLVOIAP_js.assertValid; }
1350
+ get: function () { return chunkDT2TQZU7_js.assertValid; }
1351
+ });
1352
+ Object.defineProperty(exports, "assertValidAsync", {
1353
+ enumerable: true,
1354
+ get: function () { return chunkDT2TQZU7_js.assertValidAsync; }
1137
1355
  });
1138
1356
  Object.defineProperty(exports, "errorResult", {
1139
1357
  enumerable: true,
1140
- get: function () { return chunkBJLVOIAP_js.errorResult; }
1358
+ get: function () { return chunkDT2TQZU7_js.errorResult; }
1141
1359
  });
1142
1360
  Object.defineProperty(exports, "getTypeValidator", {
1143
1361
  enumerable: true,
1144
- get: function () { return chunkBJLVOIAP_js.getTypeValidator; }
1362
+ get: function () { return chunkDT2TQZU7_js.getTypeValidator; }
1145
1363
  });
1146
1364
  Object.defineProperty(exports, "getValidator", {
1147
1365
  enumerable: true,
1148
- get: function () { return chunkBJLVOIAP_js.getValidator; }
1366
+ get: function () { return chunkDT2TQZU7_js.getValidator; }
1149
1367
  });
1150
1368
  Object.defineProperty(exports, "isValid", {
1151
1369
  enumerable: true,
1152
- get: function () { return chunkBJLVOIAP_js.isValid; }
1370
+ get: function () { return chunkDT2TQZU7_js.isValid; }
1371
+ });
1372
+ Object.defineProperty(exports, "isValidAsync", {
1373
+ enumerable: true,
1374
+ get: function () { return chunkDT2TQZU7_js.isValidAsync; }
1153
1375
  });
1154
1376
  Object.defineProperty(exports, "mergeResults", {
1155
1377
  enumerable: true,
1156
- get: function () { return chunkBJLVOIAP_js.mergeResults; }
1378
+ get: function () { return chunkDT2TQZU7_js.mergeResults; }
1157
1379
  });
1158
1380
  Object.defineProperty(exports, "registerValidator", {
1159
1381
  enumerable: true,
1160
- get: function () { return chunkBJLVOIAP_js.registerValidator; }
1382
+ get: function () { return chunkDT2TQZU7_js.registerValidator; }
1161
1383
  });
1162
1384
  Object.defineProperty(exports, "ruleValidators", {
1163
1385
  enumerable: true,
1164
- get: function () { return chunkBJLVOIAP_js.ruleValidators; }
1386
+ get: function () { return chunkDT2TQZU7_js.ruleValidators; }
1165
1387
  });
1166
1388
  Object.defineProperty(exports, "typeValidators", {
1167
1389
  enumerable: true,
1168
- get: function () { return chunkBJLVOIAP_js.typeValidators; }
1390
+ get: function () { return chunkDT2TQZU7_js.typeValidators; }
1169
1391
  });
1170
1392
  Object.defineProperty(exports, "validResult", {
1171
1393
  enumerable: true,
1172
- get: function () { return chunkBJLVOIAP_js.validResult; }
1394
+ get: function () { return chunkDT2TQZU7_js.validResult; }
1173
1395
  });
1174
1396
  Object.defineProperty(exports, "validate", {
1175
1397
  enumerable: true,
1176
- get: function () { return chunkBJLVOIAP_js.validate; }
1398
+ get: function () { return chunkDT2TQZU7_js.validate; }
1399
+ });
1400
+ Object.defineProperty(exports, "validateAsync", {
1401
+ enumerable: true,
1402
+ get: function () { return chunkDT2TQZU7_js.validateAsync; }
1177
1403
  });
1178
1404
  Object.defineProperty(exports, "validateSchema", {
1179
1405
  enumerable: true,
1180
- get: function () { return chunkBJLVOIAP_js.validateSchema; }
1406
+ get: function () { return chunkDT2TQZU7_js.validateSchema; }
1407
+ });
1408
+ Object.defineProperty(exports, "validateSchemaAsync", {
1409
+ enumerable: true,
1410
+ get: function () { return chunkDT2TQZU7_js.validateSchemaAsync; }
1181
1411
  });
1182
1412
  exports.ArrayFieldBuilder = ArrayFieldBuilder;
1183
1413
  exports.BaseFieldBuilder = BaseFieldBuilder;
@@ -1187,10 +1417,17 @@ exports.EnumFieldBuilder = EnumFieldBuilder;
1187
1417
  exports.NumberFieldBuilder = NumberFieldBuilder;
1188
1418
  exports.ObjectFieldBuilder = ObjectFieldBuilder;
1189
1419
  exports.StringFieldBuilder = StringFieldBuilder;
1420
+ exports.catchall = catchall;
1421
+ exports.coerce = coerce;
1422
+ exports.deepPartial = deepPartial;
1190
1423
  exports.extend = extend;
1191
1424
  exports.field = field;
1192
1425
  exports.merge = merge;
1193
1426
  exports.omit = omit;
1427
+ exports.optional = optional;
1194
1428
  exports.partial = partial;
1429
+ exports.passthrough = passthrough;
1195
1430
  exports.pick = pick;
1431
+ exports.required = required;
1196
1432
  exports.schema = schema;
1433
+ exports.strict = strict;
package/dist/index.mjs CHANGED
@@ -1,12 +1,12 @@
1
1
  export { toEnterpriseResponse } from './chunk-TTK77YBI.mjs';
2
- export { assertValid, errorResult, getTypeValidator, getValidator, isValid, mergeResults, registerValidator, ruleValidators, typeValidators, validResult, validate, validateSchema } from './chunk-3TS35CVJ.mjs';
3
- import './chunk-KHHJD6QK.mjs';
4
- import './chunk-XC4DKEXP.mjs';
5
- import './chunk-FRBZHN4K.mjs';
6
- import './chunk-VWP24NYS.mjs';
7
- import './chunk-ELL7U7IC.mjs';
8
- import './chunk-XGTUU27F.mjs';
9
- import './chunk-FKDWSZIV.mjs';
2
+ export { assertValid, assertValidAsync, errorResult, getTypeValidator, getValidator, isValid, isValidAsync, mergeResults, registerValidator, ruleValidators, typeValidators, validResult, validate, validateAsync, validateSchema, validateSchemaAsync } from './chunk-MFEBMQAU.mjs';
3
+ import './chunk-75YSYC4K.mjs';
4
+ import './chunk-KZCV5IW4.mjs';
5
+ import './chunk-COMVAVFU.mjs';
6
+ import './chunk-RW6HDA5H.mjs';
7
+ import './chunk-7XES4A3M.mjs';
8
+ import './chunk-5A4ITJVD.mjs';
9
+ import './chunk-KZZ7NVU3.mjs';
10
10
 
11
11
  // src/schema/field.ts
12
12
  var BaseFieldBuilder = class {
@@ -14,6 +14,9 @@ var BaseFieldBuilder = class {
14
14
  this._rules = [];
15
15
  this._required = false;
16
16
  this._meta = {};
17
+ this._transforms = [];
18
+ this._nullable = false;
19
+ this._nullish = false;
17
20
  this._type = type;
18
21
  }
19
22
  /**
@@ -63,6 +66,59 @@ var BaseFieldBuilder = class {
63
66
  });
64
67
  return this;
65
68
  }
69
+ /**
70
+ * Add async custom validation
71
+ */
72
+ refineAsync(validate2, options) {
73
+ const opts = typeof options === "string" ? { message: options } : options || {};
74
+ this._rules.push({
75
+ type: "refineAsync",
76
+ params: { validate: validate2 },
77
+ message: opts.message,
78
+ soft: opts.soft,
79
+ async: true,
80
+ debounce: opts.debounce,
81
+ timeout: opts.timeout || 5e3
82
+ });
83
+ return this;
84
+ }
85
+ /**
86
+ * Add async soft validation (warning only)
87
+ */
88
+ refineAsyncSoft(validate2, options) {
89
+ const opts = typeof options === "string" ? { message: options } : options || {};
90
+ return this.refineAsync(validate2, { ...opts, soft: true });
91
+ }
92
+ /**
93
+ * Transform value before validation (applied after preprocessing)
94
+ */
95
+ transform(transformer) {
96
+ this._transforms.push(transformer);
97
+ return this;
98
+ }
99
+ /**
100
+ * Preprocess value before transformations and validation
101
+ * Useful for handling null/undefined values
102
+ */
103
+ preprocess(preprocessor) {
104
+ this._preprocess = preprocessor;
105
+ return this;
106
+ }
107
+ /**
108
+ * Allow null values
109
+ */
110
+ nullable() {
111
+ this._nullable = true;
112
+ return this;
113
+ }
114
+ /**
115
+ * Allow null or undefined values
116
+ */
117
+ nullish() {
118
+ this._nullish = true;
119
+ this._nullable = true;
120
+ return this;
121
+ }
66
122
  /**
67
123
  * Add field metadata
68
124
  */
@@ -123,7 +179,11 @@ var BaseFieldBuilder = class {
123
179
  rules: [...this._rules],
124
180
  required: this._required,
125
181
  defaultValue: this._defaultValue,
126
- meta: Object.keys(this._meta).length > 0 ? this._meta : void 0
182
+ meta: Object.keys(this._meta).length > 0 ? this._meta : void 0,
183
+ transforms: this._transforms.length > 0 ? [...this._transforms] : void 0,
184
+ preprocess: this._preprocess,
185
+ nullable: this._nullable || void 0,
186
+ nullish: this._nullish || void 0
127
187
  };
128
188
  }
129
189
  };
@@ -398,11 +458,11 @@ var StringFieldBuilder = class extends BaseFieldBuilder {
398
458
  }
399
459
  };
400
460
  var EnumFieldBuilder = class extends BaseFieldBuilder {
401
- constructor(values, rules = [], required = false, meta = {}) {
461
+ constructor(values, rules = [], required2 = false, meta = {}) {
402
462
  super("string");
403
463
  this._values = values;
404
464
  this._rules = [...rules];
405
- this._required = required;
465
+ this._required = required2;
406
466
  this._meta = { ...meta };
407
467
  }
408
468
  /**
@@ -994,7 +1054,11 @@ var ArrayFieldBuilder = class extends BaseFieldBuilder {
994
1054
  required: this._required,
995
1055
  defaultValue: this._defaultValue,
996
1056
  items: this._itemDef,
997
- meta: Object.keys(this._meta).length > 0 ? this._meta : void 0
1057
+ meta: Object.keys(this._meta).length > 0 ? this._meta : void 0,
1058
+ transforms: this._transforms.length > 0 ? [...this._transforms] : void 0,
1059
+ preprocess: this._preprocess,
1060
+ nullable: this._nullable || void 0,
1061
+ nullish: this._nullish || void 0
998
1062
  };
999
1063
  }
1000
1064
  };
@@ -1014,10 +1078,80 @@ var ObjectFieldBuilder = class extends BaseFieldBuilder {
1014
1078
  required: this._required,
1015
1079
  defaultValue: this._defaultValue,
1016
1080
  schema: this._schema,
1017
- meta: Object.keys(this._meta).length > 0 ? this._meta : void 0
1081
+ meta: Object.keys(this._meta).length > 0 ? this._meta : void 0,
1082
+ transforms: this._transforms.length > 0 ? [...this._transforms] : void 0,
1083
+ preprocess: this._preprocess,
1084
+ nullable: this._nullable || void 0,
1085
+ nullish: this._nullish || void 0
1018
1086
  };
1019
1087
  }
1020
1088
  };
1089
+ var coerce = {
1090
+ /**
1091
+ * Coerce value to string
1092
+ */
1093
+ string() {
1094
+ return new StringFieldBuilder().preprocess((value) => {
1095
+ if (value === null || value === void 0) return value;
1096
+ return String(value);
1097
+ });
1098
+ },
1099
+ /**
1100
+ * Coerce value to number
1101
+ */
1102
+ number() {
1103
+ return new NumberFieldBuilder().preprocess((value) => {
1104
+ if (value === null || value === void 0) return value;
1105
+ if (typeof value === "number") return value;
1106
+ if (typeof value === "string") {
1107
+ const parsed = parseFloat(value);
1108
+ return isNaN(parsed) ? value : parsed;
1109
+ }
1110
+ if (typeof value === "boolean") return value ? 1 : 0;
1111
+ return value;
1112
+ });
1113
+ },
1114
+ /**
1115
+ * Coerce value to boolean
1116
+ */
1117
+ boolean() {
1118
+ return new BooleanFieldBuilder().preprocess((value) => {
1119
+ if (value === null || value === void 0) return value;
1120
+ if (typeof value === "boolean") return value;
1121
+ if (typeof value === "string") {
1122
+ const lower = value.toLowerCase().trim();
1123
+ if (lower === "true" || lower === "1" || lower === "yes" || lower === "on") return true;
1124
+ if (lower === "false" || lower === "0" || lower === "no" || lower === "off") return false;
1125
+ }
1126
+ if (typeof value === "number") return value !== 0;
1127
+ return value;
1128
+ });
1129
+ },
1130
+ /**
1131
+ * Coerce value to date
1132
+ */
1133
+ date() {
1134
+ return new DateFieldBuilder().preprocess((value) => {
1135
+ if (value === null || value === void 0) return value;
1136
+ if (value instanceof Date) return value;
1137
+ if (typeof value === "string" || typeof value === "number") {
1138
+ const date = new Date(value);
1139
+ return isNaN(date.getTime()) ? value : date;
1140
+ }
1141
+ return value;
1142
+ });
1143
+ },
1144
+ /**
1145
+ * Coerce value to array
1146
+ */
1147
+ array(itemBuilder) {
1148
+ return new ArrayFieldBuilder(itemBuilder).preprocess((value) => {
1149
+ if (value === null || value === void 0) return value;
1150
+ if (Array.isArray(value)) return value;
1151
+ return [value];
1152
+ });
1153
+ }
1154
+ };
1021
1155
 
1022
1156
  // src/schema/schema.ts
1023
1157
  function schema(fields) {
@@ -1068,6 +1202,86 @@ function partial(baseSchema) {
1068
1202
  }
1069
1203
  return schema(partialFields);
1070
1204
  }
1205
+ function deepPartial(baseSchema) {
1206
+ const deepPartialFields = {};
1207
+ for (const [key, builder] of Object.entries(baseSchema._fields)) {
1208
+ const clonedBuilder = Object.create(Object.getPrototypeOf(builder));
1209
+ Object.assign(clonedBuilder, builder);
1210
+ clonedBuilder._required = false;
1211
+ if (builder instanceof ObjectFieldBuilder) {
1212
+ const fieldDef = builder.build();
1213
+ if (fieldDef.schema) {
1214
+ const nestedFields = {};
1215
+ for (const [nestedKey, nestedDef] of Object.entries(fieldDef.schema.fields)) {
1216
+ const nestedBuilder = Object.create(BaseFieldBuilder.prototype);
1217
+ Object.assign(nestedBuilder, {
1218
+ _type: nestedDef.type,
1219
+ _rules: nestedDef.rules || [],
1220
+ _required: false,
1221
+ // Make optional
1222
+ _defaultValue: nestedDef.defaultValue,
1223
+ _meta: nestedDef.meta || {},
1224
+ _transforms: nestedDef.transforms || [],
1225
+ _preprocess: nestedDef.preprocess,
1226
+ _nullable: nestedDef.nullable || false,
1227
+ _nullish: nestedDef.nullish || false
1228
+ });
1229
+ nestedFields[nestedKey] = nestedBuilder;
1230
+ }
1231
+ const nestedSchema = schema(nestedFields);
1232
+ const deepNestedSchema = deepPartial(nestedSchema);
1233
+ clonedBuilder._schema = deepNestedSchema.definition;
1234
+ }
1235
+ }
1236
+ deepPartialFields[key] = clonedBuilder;
1237
+ }
1238
+ return schema(deepPartialFields);
1239
+ }
1240
+ function passthrough(baseSchema) {
1241
+ const result = schema(baseSchema._fields);
1242
+ result.definition.passthrough = true;
1243
+ return result;
1244
+ }
1245
+ function strict(baseSchema) {
1246
+ const result = schema(baseSchema._fields);
1247
+ result.definition.strict = true;
1248
+ return result;
1249
+ }
1250
+ function catchall(baseSchema, fieldBuilder) {
1251
+ const result = schema(baseSchema._fields);
1252
+ result.definition.catchall = fieldBuilder.build();
1253
+ return result;
1254
+ }
1255
+ function required(baseSchema, keys) {
1256
+ const keySet = new Set(keys);
1257
+ const newFields = {};
1258
+ for (const [key, builder] of Object.entries(baseSchema._fields)) {
1259
+ if (keySet.has(key)) {
1260
+ const clonedBuilder = Object.create(Object.getPrototypeOf(builder));
1261
+ Object.assign(clonedBuilder, builder);
1262
+ clonedBuilder._required = true;
1263
+ newFields[key] = clonedBuilder;
1264
+ } else {
1265
+ newFields[key] = builder;
1266
+ }
1267
+ }
1268
+ return schema(newFields);
1269
+ }
1270
+ function optional(baseSchema, keys) {
1271
+ const keySet = new Set(keys);
1272
+ const newFields = {};
1273
+ for (const [key, builder] of Object.entries(baseSchema._fields)) {
1274
+ if (keySet.has(key)) {
1275
+ const clonedBuilder = Object.create(Object.getPrototypeOf(builder));
1276
+ Object.assign(clonedBuilder, builder);
1277
+ clonedBuilder._required = false;
1278
+ newFields[key] = clonedBuilder;
1279
+ } else {
1280
+ newFields[key] = builder;
1281
+ }
1282
+ }
1283
+ return schema(newFields);
1284
+ }
1071
1285
  function merge(schema1, schema2) {
1072
1286
  return schema({
1073
1287
  ...schema1._fields,
@@ -1125,4 +1339,4 @@ var field = {
1125
1339
  }
1126
1340
  };
1127
1341
 
1128
- export { ArrayFieldBuilder, BaseFieldBuilder, BooleanFieldBuilder, DateFieldBuilder, EnumFieldBuilder, NumberFieldBuilder, ObjectFieldBuilder, StringFieldBuilder, extend, field, merge, omit, partial, pick, schema };
1342
+ export { ArrayFieldBuilder, BaseFieldBuilder, BooleanFieldBuilder, DateFieldBuilder, EnumFieldBuilder, NumberFieldBuilder, ObjectFieldBuilder, StringFieldBuilder, catchall, coerce, deepPartial, extend, field, merge, omit, optional, partial, passthrough, pick, required, schema, strict };