@zipbul/baker 2.1.0 → 3.0.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 (91) hide show
  1. package/CHANGELOG.md +256 -0
  2. package/MIGRATION-3.0.md +104 -0
  3. package/README.md +121 -75
  4. package/dist/index.d.ts +8 -7
  5. package/dist/index.js +10 -229
  6. package/dist/src/collect.d.ts +13 -10
  7. package/dist/src/collect.js +26 -0
  8. package/dist/src/configure.d.ts +8 -11
  9. package/dist/src/configure.js +43 -0
  10. package/dist/src/create-rule.d.ts +1 -1
  11. package/dist/src/create-rule.js +41 -0
  12. package/dist/src/decorators/field.d.ts +22 -18
  13. package/dist/src/decorators/field.js +268 -0
  14. package/dist/src/decorators/index.d.ts +1 -0
  15. package/dist/src/decorators/index.js +2 -2
  16. package/dist/src/decorators/recipe.d.ts +17 -0
  17. package/dist/src/decorators/recipe.js +23 -0
  18. package/dist/src/errors.d.ts +28 -17
  19. package/dist/src/errors.js +52 -0
  20. package/dist/src/functions/check-call-options.d.ts +8 -0
  21. package/dist/src/functions/check-call-options.js +51 -0
  22. package/dist/src/functions/deserialize.d.ts +14 -6
  23. package/dist/src/functions/deserialize.js +57 -0
  24. package/dist/src/functions/serialize.d.ts +10 -3
  25. package/dist/src/functions/serialize.js +52 -0
  26. package/dist/src/functions/validate.d.ts +13 -8
  27. package/dist/src/functions/validate.js +49 -0
  28. package/dist/src/interfaces.d.ts +1 -1
  29. package/dist/src/interfaces.js +4 -0
  30. package/dist/src/meta-access.d.ts +19 -0
  31. package/dist/src/meta-access.js +75 -0
  32. package/dist/src/registry.js +8 -0
  33. package/dist/src/rule-metadata.d.ts +11 -0
  34. package/dist/src/rule-metadata.js +17 -0
  35. package/dist/src/rule-plan.d.ts +29 -0
  36. package/dist/src/rule-plan.js +117 -0
  37. package/dist/src/rules/array.d.ts +7 -6
  38. package/dist/src/rules/array.js +96 -0
  39. package/dist/src/rules/common.d.ts +2 -2
  40. package/dist/src/rules/common.js +77 -0
  41. package/dist/src/rules/date.js +35 -0
  42. package/dist/src/rules/index.d.ts +2 -4
  43. package/dist/src/rules/index.js +8 -11
  44. package/dist/src/rules/locales.d.ts +5 -4
  45. package/dist/src/rules/locales.js +249 -0
  46. package/dist/src/rules/number.d.ts +2 -2
  47. package/dist/src/rules/number.js +79 -0
  48. package/dist/src/rules/object.d.ts +1 -1
  49. package/dist/src/rules/object.js +49 -0
  50. package/dist/src/rules/string.d.ts +83 -80
  51. package/dist/src/rules/string.js +1998 -0
  52. package/dist/src/rules/typechecker.d.ts +6 -6
  53. package/dist/src/rules/typechecker.js +143 -0
  54. package/dist/src/seal/circular-analyzer.js +63 -0
  55. package/dist/src/seal/codegen-utils.d.ts +7 -0
  56. package/dist/src/seal/codegen-utils.js +18 -0
  57. package/dist/src/seal/deserialize-builder.d.ts +8 -3
  58. package/dist/src/seal/deserialize-builder.js +1546 -0
  59. package/dist/src/seal/expose-validator.d.ts +3 -2
  60. package/dist/src/seal/expose-validator.js +65 -0
  61. package/dist/src/seal/seal-state.d.ts +10 -0
  62. package/dist/src/seal/seal-state.js +18 -0
  63. package/dist/src/seal/seal.d.ts +22 -21
  64. package/dist/src/seal/seal.js +431 -0
  65. package/dist/src/seal/serialize-builder.d.ts +3 -2
  66. package/dist/src/seal/serialize-builder.js +374 -0
  67. package/dist/src/seal/validate-meta.d.ts +13 -0
  68. package/dist/src/seal/validate-meta.js +61 -0
  69. package/dist/src/symbols.d.ts +1 -1
  70. package/dist/src/symbols.js +13 -2
  71. package/dist/src/transformers/collection.transformer.js +25 -0
  72. package/dist/src/transformers/date.transformer.js +18 -0
  73. package/dist/src/transformers/index.js +6 -2
  74. package/dist/src/transformers/luxon.transformer.d.ts +4 -2
  75. package/dist/src/transformers/luxon.transformer.js +34 -0
  76. package/dist/src/transformers/moment.transformer.d.ts +4 -2
  77. package/dist/src/transformers/moment.transformer.js +32 -0
  78. package/dist/src/transformers/number.transformer.js +8 -0
  79. package/dist/src/transformers/string.transformer.js +12 -0
  80. package/dist/src/types.d.ts +68 -28
  81. package/dist/src/types.js +1 -0
  82. package/dist/src/utils.d.ts +4 -2
  83. package/dist/src/utils.js +10 -0
  84. package/package.json +80 -67
  85. package/dist/index-fnv35wrf.js +0 -3
  86. package/dist/index-k3d659ad.js +0 -3
  87. package/dist/index-s0n74vx1.js +0 -3
  88. package/dist/index-xdn55cz3.js +0 -1
  89. package/dist/src/functions/_run-sealed.d.ts +0 -7
  90. package/dist/src/functions/index.d.ts +0 -3
  91. package/dist/src/seal/index.d.ts +0 -5
@@ -0,0 +1,249 @@
1
+ import { BakerError } from '../errors.js';
2
+ import { makeRule } from '../rule-plan.js';
3
+ // ─────────────────────────────────────────────────────────────────────────────
4
+ // Locale-specific Validators
5
+ // ─────────────────────────────────────────────────────────────────────────────
6
+ // ─── isMobilePhone ────────────────────────────────────────────────────────────
7
+ const MOBILE_PHONE_REGEXES = {
8
+ 'ko-KR': /^(\+?82|0)1[016789]\d{7,8}$/,
9
+ 'en-US': /^\+?1?[2-9]\d{2}[2-9]\d{6}$/,
10
+ 'zh-CN': /^(\+?86)?1[3-9]\d{9}$/,
11
+ 'zh-TW': /^(\+?886)?9\d{8}$/,
12
+ 'ja-JP': /^(\+?81)?0?[789]0[0-9]{8}$/,
13
+ 'de-DE': /^(\+?49)?1(5\d|6[0-9]|7[0-9])\d{8}$/,
14
+ 'fr-FR': /^(\+?33)?[67]\d{8}$/,
15
+ 'en-GB': /^(\+?44)?7[1-9]\d{8}$/,
16
+ 'ru-RU': /^(\+?7)?9\d{9}$/,
17
+ 'pt-BR': /^(\+?55)?[1-9]{2}9?\d{8}$/,
18
+ 'in-IN': /^(\+?91)?[6-9]\d{9}$/,
19
+ 'ar-SA': /^(\+?966)?5\d{8}$/,
20
+ 'ar-EG': /^(\+?20)?1[0125]\d{8}$/,
21
+ 'vi-VN': /^(\+?84)?[35789]\d{8}$/,
22
+ 'th-TH': /^(\+?66)?[689]\d{8}$/,
23
+ 'id-ID': /^(\+?62)?8\d{9,11}$/,
24
+ 'ms-MY': /^(\+?60)?1\d{8,9}$/,
25
+ 'nl-NL': /^(\+?31)?6\d{8}$/,
26
+ 'it-IT': /^(\+?39)?3\d{9}$/,
27
+ 'es-ES': /^(\+?34)?[67]\d{8}$/,
28
+ 'pl-PL': /^(\+?48)?[45789]\d{8}$/,
29
+ };
30
+ function isMobilePhone(locale) {
31
+ return makeLocaleRegexRule('isMobilePhone', locale, MOBILE_PHONE_REGEXES);
32
+ }
33
+ // ─── isPostalCode ─────────────────────────────────────────────────────────────
34
+ const POSTAL_CODE_REGEXES = {
35
+ AD: /^AD\d{3}$/,
36
+ AT: /^\d{4}$/,
37
+ AU: /^\d{4}$/,
38
+ AZ: /^\d{4}$/,
39
+ BE: /^\d{4}$/,
40
+ BG: /^\d{4}$/,
41
+ BR: /^\d{5}-?\d{3}$/,
42
+ BY: /^\d{6}$/,
43
+ CA: /^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJ-NPRSTV-Z] ?\d[ABCEGHJ-NPRSTV-Z]\d$/i,
44
+ CH: /^\d{4}$/,
45
+ CN: /^\d{6}$/,
46
+ CZ: /^\d{3} ?\d{2}$/,
47
+ DE: /^\d{5}$/,
48
+ DK: /^\d{4}$/,
49
+ EE: /^\d{5}$/,
50
+ ES: /^\d{5}$/,
51
+ FI: /^\d{5}$/,
52
+ FR: /^\d{2} ?\d{3}$/,
53
+ GB: /^(GIR ?0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]([0-9ABEHMNPRV-Y])?)|[0-9][A-HJKPSTUW]) ?[0-9][ABD-HJLNP-UW-Z]{2})$/i,
54
+ GR: /^\d{3} ?\d{2}$/,
55
+ HR: /^\d{5}$/,
56
+ HU: /^\d{4}$/,
57
+ ID: /^\d{5}$/,
58
+ IL: /^\d{5}(\d{2})?$/,
59
+ IN: /^\d{6}$/,
60
+ IS: /^\d{3}$/,
61
+ IT: /^\d{5}$/,
62
+ JP: /^\d{3}-?\d{4}$/,
63
+ KR: /^\d{5}$/,
64
+ LI: /^(948[5-9]|949[0-7])$/,
65
+ LT: /^LT-\d{5}$/,
66
+ LU: /^\d{4}$/,
67
+ LV: /^LV-\d{4}$/,
68
+ MX: /^\d{5}$/,
69
+ MT: /^[A-Z]{3} ?\d{4}$/i,
70
+ MZ: /^\d{4}$/,
71
+ NL: /^\d{4} ?[A-Z]{2}$/i,
72
+ NO: /^\d{4}$/,
73
+ NP: /^\d{5}$/,
74
+ NZ: /^\d{4}$/,
75
+ PH: /^\d{4}$/,
76
+ PK: /^\d{5}$/,
77
+ PL: /^\d{2}-\d{3}$/,
78
+ PR: /^009\d{2}([ -]\d{4})?$/,
79
+ PT: /^\d{4}-\d{3}$/,
80
+ RO: /^\d{6}$/,
81
+ RU: /^\d{6}$/,
82
+ SE: /^\d{3} ?\d{2}$/,
83
+ SG: /^\d{6}$/,
84
+ SI: /^\d{4}$/,
85
+ SK: /^\d{3} ?\d{2}$/,
86
+ TH: /^\d{5}$/,
87
+ TN: /^\d{4}$/,
88
+ TW: /^\d{3}(\d{2})?$/,
89
+ UA: /^\d{5}$/,
90
+ US: /^\d{5}(-\d{4})?$/,
91
+ ZA: /^\d{4}$/,
92
+ ZM: /^\d{5}$/,
93
+ };
94
+ function isPostalCode(locale) {
95
+ return makeLocaleRegexRule('isPostalCode', locale, POSTAL_CODE_REGEXES);
96
+ }
97
+ // ─── isIdentityCard ───────────────────────────────────────────────────────────
98
+ const IDENTITY_CARD_REGEXES = {
99
+ AF: /^\d{8}$/,
100
+ AL: /^[A-Z]\d{8}[A-Z]$/i,
101
+ AR: /^\d{7,8}$/,
102
+ AZ: /^AZE\d{8}$/,
103
+ BE: /^\d{11}$/,
104
+ BG: /^\d{10}$/,
105
+ BR: /^\d{9}$/,
106
+ BY: /^[A-Z]{2}\d{7}$/i,
107
+ CA: /^\d{9}$/,
108
+ CH: /^756\d{10}$/,
109
+ CN: /^\d{15}(\d{2}[0-9xX])?$/,
110
+ CY: /^\d{7}[A-Z]$/i,
111
+ CZ: /^\d{9,10}$/,
112
+ DE: /^[LITOUAEVBMNPRSZDFGHCK]{9}$/i,
113
+ DK: /^\d{10}$/,
114
+ EE: /^\d{11}$/,
115
+ ES: /^[0-9X-Z]\d{7}[TRWAGMYFPDXBNJZSQVHLCKE]$/i,
116
+ FI: /^\d{6}[+-A]\d{3}[0-9A-FHJ-NPR-Y]$/,
117
+ FR: /^\d{8,9}[0-9Á-ÿ]{1}$/i,
118
+ GB: /^[A-Z]{2}\d{6}[A-Z]$/i,
119
+ GR: /^[A-Z]{2}\d{6}$/i,
120
+ HR: /^\d{11}$/,
121
+ HU: /^\d{8}[A-Z]{2}$/i,
122
+ ID: /^\d{16}$/,
123
+ IE: /^\d{7}[A-W][A-W]?$/,
124
+ IL: /^\d{9}$/,
125
+ IN: /^\d{12}$/,
126
+ IR: /^\d{10}$/,
127
+ IS: /^\d{10}$/,
128
+ IT: /^[A-Z]{6}\d{2}[A-Z]\d{2}[A-Z]\d{3}[A-Z]$/i,
129
+ JP: /^\d{12}$/,
130
+ KR: /^\d{6}-\d{7}$/,
131
+ LT: /^\d{11}$/,
132
+ LU: /^\d{13}$/,
133
+ LV: /^\d{6}-\d{5}$/,
134
+ MK: /^\d{13}$/,
135
+ MX: /^[A-Z]{4}\d{6}[HM][A-Z]{2}[B-DF-HJ-NP-TV-Z]{3}[A-Z0-9]\d$/i,
136
+ MT: /^\d{7}[A-Z]$/i,
137
+ NL: /^\d{9}$/,
138
+ NO: /^\d{11}$/,
139
+ PL: /^\d{11}$/,
140
+ PT: /^[1-9]\d{7}[0-9TV]$/i,
141
+ RO: /^\d{13}$/,
142
+ RS: /^\d{13}$/,
143
+ RU: /^\d{10}$/,
144
+ SE: /^\d{10,12}$/,
145
+ SI: /^\d{13}$/,
146
+ SK: /^\d{9,10}$/,
147
+ TH: /^\d{13}$/,
148
+ TR: /^\d{11}$/,
149
+ TW: /^[A-Z]\d{9}$/i,
150
+ UA: /^\d{9}$/,
151
+ US: /^\d{3}-\d{2}-\d{4}$/,
152
+ ZA: /^\d{13}$/,
153
+ };
154
+ function isIdentityCard(locale) {
155
+ return makeLocaleRegexRule('isIdentityCard', locale, IDENTITY_CARD_REGEXES);
156
+ }
157
+ // ─── isPassportNumber ─────────────────────────────────────────────────────────
158
+ const PASSPORT_REGEXES = {
159
+ AM: /^[A-Z]{2}\d{7}$/i,
160
+ AR: /^[A-Z]{3}\d{6}$/i,
161
+ AT: /^[A-Z]\d{7}$/i,
162
+ AU: /^[A-Z]\d{7}$/i,
163
+ AZ: /^[Aa]\d{8}$/,
164
+ BE: /^[A-Z]{2}\d{6}$/i,
165
+ BG: /^\d{9}$/,
166
+ BH: /^[A-Z]{2}\d{6}$/i,
167
+ BR: /^[A-Z]{2}\d{6}$/i,
168
+ BY: /^[A-Z]{2}\d{7}$/i,
169
+ CA: /^[A-Z]{2}\d{6}$/i,
170
+ CH: /^[A-Z]\d{7}$/i,
171
+ CN: /^G\d{8}$/,
172
+ CY: /^[A-Z](\d{6}|\d{8})$/i,
173
+ CZ: /^\d{8}$/,
174
+ DE: /^[CFGHJKLMNPRTVWXYZ0-9]{9}$/i,
175
+ DK: /^\d{9}$/,
176
+ EE: /^([A-Z]\d{7}|[A-Z]{2}\d{7})$/i,
177
+ ES: /^[A-Z0-9]{2}([A-Z0-9]?)\d{6}$/i,
178
+ FI: /^[A-Z]{2}\d{7}$/i,
179
+ FR: /^[A-Z0-9]{9}$/i,
180
+ GB: /^\d{9}$/,
181
+ GR: /^[A-Z]{2}\d{7}$/i,
182
+ HR: /^\d{9}$/,
183
+ HU: /^[A-Z]{2}(\d{6}|\d{7})$/i,
184
+ ID: /^[A-C]\d{7}$/i,
185
+ IE: /^[A-Z0-9]{2}\d{7}$/i,
186
+ IL: /^\d{9}$/,
187
+ IN: /^[A-Z]\d{7}$/i,
188
+ IR: /^[A-Z]\d{8}$/i,
189
+ IS: /^(A)\d{7}$/i,
190
+ IT: /^[A-Z0-9]{9}$/i,
191
+ JO: /^[A-Z]{2}\d{7}$/i,
192
+ JP: /^[A-Z]{2}\d{7}$/i,
193
+ KR: /^[A-Z][A-Z0-9]\d{7}$/i,
194
+ KW: /^\d{8}$/,
195
+ KZ: /^[A-Z]\d{8}$/i,
196
+ LI: /^[A-Z]\d{6}X$/i,
197
+ LT: /^[A-Z0-9]{8}$/i,
198
+ LU: /^[A-Z0-9]{8}$/i,
199
+ LV: /^[A-Z0-9]{2}\d{7}$/i,
200
+ LY: /^[A-Z]{2}\d{7}$/i,
201
+ MA: /^[A-Z0-9]{2}\d{7}$/i,
202
+ MD: /^[A-Z]{2}\d{7}$/i,
203
+ ME: /^[A-Z]{2}\d{7}$/i,
204
+ MK: /^[A-Z]\d{7}$/i,
205
+ MT: /^\d{7}$/,
206
+ MX: /^[A-Z]\d{8}$/i,
207
+ MY: /^[AHK]\d{8}[A-Z]$/i,
208
+ NL: /^[A-NP-Z]{2}[A-NP-Z0-9]{6}\d$/i,
209
+ NO: /^\d{9}$/,
210
+ NZ: /^[A-Z]{2}\d{6}$/i,
211
+ PH: /^[A-Z]\d{7}[A-Z]$/i,
212
+ PK: /^[A-Z]{2}\d{7}$/i,
213
+ PL: /^[A-Z]{2}\d{7}$/i,
214
+ PT: /^[A-Z]\d{6}$/i,
215
+ RO: /^\d{8}$/,
216
+ RS: /^\d{9}$/,
217
+ RU: /^\d{9}$/,
218
+ SA: /^[A-Z]\d{8}$/i,
219
+ SE: /^\d{8}$/,
220
+ SL: /^(P)[A-Z]\d{7}$/i,
221
+ SK: /^[0-9A-Z]\d{7}$/i,
222
+ TH: /^[A-Z]{1,2}\d{6,7}$/i,
223
+ TN: /^\d{8}$/,
224
+ TR: /^[A-Z]\d{8}$/i,
225
+ TW: /^[A-Z]\d{9}$/i,
226
+ UA: /^[A-Z]{2}\d{6}$/i,
227
+ US: /^\d{9}$/,
228
+ ZA: /^[A-Z]\d{8}$/i,
229
+ };
230
+ function isPassportNumber(locale) {
231
+ return makeLocaleRegexRule('isPassportNumber', locale, PASSPORT_REGEXES);
232
+ }
233
+ function makeLocaleRegexRule(name, locale, registry) {
234
+ const re = registry[locale];
235
+ if (!re) {
236
+ throw new BakerError(`Unsupported locale: "${locale}" for ${name}`);
237
+ }
238
+ return makeRule({
239
+ name,
240
+ requiresType: 'string',
241
+ constraints: { locale },
242
+ validate: value => typeof value === 'string' && re.test(value),
243
+ emit: (varName, ctx) => {
244
+ const i = ctx.addRegex(re);
245
+ return `if (!re[${i}].test(${varName})) ${ctx.fail(name)};`;
246
+ },
247
+ });
248
+ }
249
+ export { isMobilePhone, isPostalCode, isIdentityCard, isPassportNumber };
@@ -5,6 +5,6 @@ export declare function min(n: number, opts?: {
5
5
  export declare function max(n: number, opts?: {
6
6
  exclusive?: boolean;
7
7
  }): EmittableRule;
8
- export declare const isPositive: EmittableRule;
9
- export declare const isNegative: EmittableRule;
8
+ export declare const isPositive: import("../types").InternalRule;
9
+ export declare const isNegative: import("../types").InternalRule;
10
10
  export declare function isDivisibleBy(n: number): EmittableRule;
@@ -0,0 +1,79 @@
1
+ import { BakerError } from '../errors.js';
2
+ import { makePlannedRule, makeRule, planCompare, planLiteral, planOr, planValue } from '../rule-plan.js';
3
+ // ─────────────────────────────────────────────────────────────────────────────
4
+ // min — v >= n check. requiresType='number' (§4.7, §4.8 A)
5
+ // ─────────────────────────────────────────────────────────────────────────────
6
+ export function min(n, opts) {
7
+ if (!Number.isFinite(n)) {
8
+ throw new BakerError(`min: bound must be a finite number, got ${n}`);
9
+ }
10
+ const exclusive = opts?.exclusive ?? false;
11
+ const plan = {
12
+ failure: planOr(planCompare(planValue(), '!==', planValue()), planCompare(planValue(), exclusive ? '<=' : '<', planLiteral(n))),
13
+ };
14
+ return makePlannedRule({
15
+ name: 'min',
16
+ requiresType: 'number',
17
+ constraints: exclusive ? { min: n, exclusive: true } : { min: n },
18
+ plan,
19
+ validate: exclusive ? value => typeof value === 'number' && value > n : value => typeof value === 'number' && value >= n,
20
+ });
21
+ }
22
+ // ─────────────────────────────────────────────────────────────────────────────
23
+ // max — v <= n check. requiresType='number' (§4.7, §4.8 A)
24
+ // ─────────────────────────────────────────────────────────────────────────────
25
+ export function max(n, opts) {
26
+ if (!Number.isFinite(n)) {
27
+ throw new BakerError(`max: bound must be a finite number, got ${n}`);
28
+ }
29
+ const exclusive = opts?.exclusive ?? false;
30
+ const plan = {
31
+ failure: planOr(planCompare(planValue(), '!==', planValue()), planCompare(planValue(), exclusive ? '>=' : '>', planLiteral(n))),
32
+ };
33
+ return makePlannedRule({
34
+ name: 'max',
35
+ requiresType: 'number',
36
+ constraints: exclusive ? { max: n, exclusive: true } : { max: n },
37
+ plan,
38
+ validate: exclusive ? value => typeof value === 'number' && value < n : value => typeof value === 'number' && value <= n,
39
+ });
40
+ }
41
+ // ─────────────────────────────────────────────────────────────────────────────
42
+ // isPositive — v > 0 (0 not included). requiresType='number' (§4.8 A)
43
+ // ─────────────────────────────────────────────────────────────────────────────
44
+ export const isPositive = makePlannedRule({
45
+ name: 'isPositive',
46
+ requiresType: 'number',
47
+ constraints: { min: 0, exclusive: true },
48
+ plan: {
49
+ failure: planOr(planCompare(planValue(), '!==', planValue()), planCompare(planValue(), '<=', planLiteral(0))),
50
+ },
51
+ validate: value => typeof value === 'number' && value > 0,
52
+ });
53
+ // ─────────────────────────────────────────────────────────────────────────────
54
+ // isNegative — v < 0 (0 not included). requiresType='number' (§4.8 A)
55
+ // ─────────────────────────────────────────────────────────────────────────────
56
+ export const isNegative = makePlannedRule({
57
+ name: 'isNegative',
58
+ requiresType: 'number',
59
+ constraints: { max: 0, exclusive: true },
60
+ plan: {
61
+ failure: planOr(planCompare(planValue(), '!==', planValue()), planCompare(planValue(), '>=', planLiteral(0))),
62
+ },
63
+ validate: value => typeof value === 'number' && value < 0,
64
+ });
65
+ // ─────────────────────────────────────────────────────────────────────────────
66
+ // isDivisibleBy — v % n === 0 check. requiresType='number' (§4.8 A)
67
+ // ─────────────────────────────────────────────────────────────────────────────
68
+ export function isDivisibleBy(n) {
69
+ if (n === 0) {
70
+ throw new BakerError('isDivisibleBy: divisor must not be zero');
71
+ }
72
+ return makeRule({
73
+ name: 'isDivisibleBy',
74
+ requiresType: 'number',
75
+ constraints: { divisor: n },
76
+ validate: value => typeof value === 'number' && value % n === 0,
77
+ emit: (varName, ctx) => `if (${varName} % ${n} !== 0) ${ctx.fail('isDivisibleBy')};`,
78
+ });
79
+ }
@@ -4,4 +4,4 @@ export interface IsNotEmptyObjectOptions {
4
4
  nullable?: boolean;
5
5
  }
6
6
  export declare function isNotEmptyObject(options?: IsNotEmptyObjectOptions): EmittableRule;
7
- export declare function isInstance(targetType: new (...args: any[]) => any): EmittableRule;
7
+ export declare function isInstance(targetType: new (...args: never[]) => object): EmittableRule;
@@ -0,0 +1,49 @@
1
+ import { makeRule } from '../rule-plan.js';
2
+ export function isNotEmptyObject(options) {
3
+ const validate = (value) => {
4
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
5
+ return false;
6
+ }
7
+ const obj = value;
8
+ if (options?.nullable) {
9
+ for (const k in obj) {
10
+ if (obj[k] != null) {
11
+ return true;
12
+ }
13
+ }
14
+ return false;
15
+ }
16
+ for (const _k in obj) {
17
+ return true;
18
+ }
19
+ return false;
20
+ };
21
+ return makeRule({
22
+ name: 'isNotEmptyObject',
23
+ requiresType: 'object',
24
+ constraints: { nullable: options?.nullable },
25
+ validate,
26
+ // Codegen: for-in with break — measured ~1 ns faster than Object.keys allocation
27
+ // (Bun 1.3.13 / i7-13700K). The generated body is not subject to source-lint rules.
28
+ emit: (varName, ctx) => {
29
+ if (options?.nullable) {
30
+ return `{var __ne=false;for(var __k in ${varName}){if(${varName}[__k]!=null){__ne=true;break;}}if(!__ne) ${ctx.fail('isNotEmptyObject')};}`;
31
+ }
32
+ return `{var __ne=false;for(var __k in ${varName}){__ne=true;break;}if(!__ne) ${ctx.fail('isNotEmptyObject')};}`;
33
+ },
34
+ });
35
+ }
36
+ // ─────────────────────────────────────────────────────────────────────────────
37
+ // isInstance(targetType) — checks if value is an instance of a specific class
38
+ // ─────────────────────────────────────────────────────────────────────────────
39
+ export function isInstance(targetType) {
40
+ return makeRule({
41
+ name: 'isInstance',
42
+ constraints: { type: targetType.name },
43
+ validate: value => value instanceof targetType,
44
+ emit: (varName, ctx) => {
45
+ const i = ctx.addRef(targetType);
46
+ return `if (!(${varName} instanceof refs[${i}])) ${ctx.fail('isInstance')};`;
47
+ },
48
+ });
49
+ }
@@ -1,105 +1,108 @@
1
1
  import type { EmittableRule } from '../types';
2
- export declare function minLength(min: number): EmittableRule;
3
- export declare function maxLength(max: number): EmittableRule;
4
- export declare function length(minLen: number, maxLen: number): EmittableRule;
5
- export declare function contains(seed: string): EmittableRule;
6
- export declare function notContains(seed: string): EmittableRule;
7
- export declare function matches(pattern: string | RegExp, modifiers?: string): EmittableRule;
8
- export declare const isLowercase: EmittableRule;
9
- export declare const isUppercase: EmittableRule;
10
- export declare const isAscii: EmittableRule;
11
- export declare const isAlpha: EmittableRule;
12
- export declare const isAlphanumeric: EmittableRule;
13
- export declare const isBooleanString: EmittableRule;
14
- export interface IsNumberStringOptions {
2
+ declare function minLength(min: number): EmittableRule;
3
+ declare function maxLength(max: number): EmittableRule;
4
+ declare function length(minLen: number, maxLen: number): EmittableRule;
5
+ declare function contains(seed: string): EmittableRule;
6
+ declare function notContains(seed: string): EmittableRule;
7
+ declare function matches(pattern: string | RegExp, modifiers?: string): EmittableRule;
8
+ declare const isLowercase: import("../types").InternalRule;
9
+ declare const isUppercase: import("../types").InternalRule;
10
+ declare const isAscii: EmittableRule;
11
+ declare const isAlpha: EmittableRule;
12
+ declare const isAlphanumeric: EmittableRule;
13
+ declare const isHttpToken: EmittableRule;
14
+ declare const isBooleanString: import("../types").InternalRule;
15
+ interface IsNumberStringOptions {
15
16
  no_symbols?: boolean;
16
17
  }
17
- export declare function isNumberString(options?: IsNumberStringOptions): EmittableRule;
18
- export declare function isDecimal(): EmittableRule;
19
- export declare const isFullWidth: EmittableRule;
20
- export declare const isHalfWidth: EmittableRule;
21
- export declare const isVariableWidth: EmittableRule;
22
- export declare const isMultibyte: EmittableRule;
23
- export declare const isSurrogatePair: EmittableRule;
24
- export declare const isHexadecimal: EmittableRule;
25
- export declare const isOctal: EmittableRule;
26
- export declare function isEmail(): EmittableRule;
27
- export interface IsURLOptions {
18
+ declare function isNumberString(options?: IsNumberStringOptions): EmittableRule;
19
+ declare function isDecimal(): EmittableRule;
20
+ declare const isFullWidth: EmittableRule;
21
+ declare const isHalfWidth: EmittableRule;
22
+ declare const isVariableWidth: EmittableRule;
23
+ declare const isMultibyte: EmittableRule;
24
+ declare const isSurrogatePair: EmittableRule;
25
+ declare const isHexadecimal: EmittableRule;
26
+ declare const isOctal: EmittableRule;
27
+ declare function isEmail(): EmittableRule;
28
+ interface IsURLOptions {
28
29
  protocols?: string[];
29
30
  }
30
- export declare function isURL(options?: IsURLOptions): EmittableRule;
31
- export declare function isUUID(version?: 1 | 2 | 3 | 4 | 5 | 'all'): EmittableRule;
32
- export declare function isIP(version?: 4 | 6): EmittableRule;
33
- export declare const isHexColor: EmittableRule;
34
- export declare function isRgbColor(includePercentValues?: boolean): EmittableRule;
35
- export declare const isHSL: EmittableRule;
36
- export interface IsMACAddressOptions {
31
+ declare function isURL(options?: IsURLOptions): EmittableRule;
32
+ declare function isUUID(version?: 1 | 2 | 3 | 4 | 5 | 'all'): EmittableRule;
33
+ declare function isIP(version?: 4 | 6): EmittableRule;
34
+ declare const isHexColor: EmittableRule;
35
+ declare function isRgbColor(includePercentValues?: boolean): EmittableRule;
36
+ declare const isHSL: EmittableRule;
37
+ interface IsMACAddressOptions {
37
38
  no_separators?: boolean;
38
39
  }
39
- export declare function isMACAddress(options?: IsMACAddressOptions): EmittableRule;
40
- export declare function isISBN(version?: 10 | 13): EmittableRule;
41
- export declare const isISIN: EmittableRule;
42
- export interface IsISO8601Options {
40
+ declare function isMACAddress(options?: IsMACAddressOptions): EmittableRule;
41
+ declare function isISBN(version?: 10 | 13): EmittableRule;
42
+ declare const isISIN: EmittableRule;
43
+ interface IsISO8601Options {
43
44
  strict?: boolean;
44
45
  }
45
- export declare function isISO8601(options?: IsISO8601Options): EmittableRule;
46
- export declare const isISRC: EmittableRule;
47
- export interface IsISSNOptions {
46
+ declare function isISO8601(options?: IsISO8601Options): EmittableRule;
47
+ declare const isISRC: EmittableRule;
48
+ interface IsISSNOptions {
48
49
  requireHyphen?: boolean;
49
50
  }
50
- export declare function isISSN(options?: IsISSNOptions): EmittableRule;
51
- export declare const isJWT: EmittableRule;
52
- export declare function isLatLong(): EmittableRule;
53
- export declare const isLocale: EmittableRule;
54
- export declare const isDataURI: EmittableRule;
55
- export interface IsFQDNOptions {
51
+ declare function isISSN(options?: IsISSNOptions): EmittableRule;
52
+ declare const isJWT: EmittableRule;
53
+ declare function isLatLong(): EmittableRule;
54
+ declare const isLocale: EmittableRule;
55
+ declare const isDataURI: EmittableRule;
56
+ interface IsFQDNOptions {
56
57
  require_tld?: boolean;
57
58
  allow_underscores?: boolean;
58
59
  allow_trailing_dot?: boolean;
59
60
  }
60
- export declare function isFQDN(options?: IsFQDNOptions): EmittableRule;
61
- export declare const isPort: EmittableRule;
62
- export declare const isEAN: EmittableRule;
63
- export declare const isISO31661Alpha2: EmittableRule;
64
- export declare const isISO31661Alpha3: EmittableRule;
65
- export declare const isBIC: EmittableRule;
66
- export declare const isFirebasePushId: EmittableRule;
67
- export declare const isSemVer: EmittableRule;
68
- export declare const isMongoId: EmittableRule;
69
- export declare const isJSON: EmittableRule;
70
- export declare function isBase32(): EmittableRule;
71
- export declare const isBase58: EmittableRule;
72
- export interface IsBase64Options {
61
+ declare function isFQDN(options?: IsFQDNOptions): EmittableRule;
62
+ declare const isPort: EmittableRule;
63
+ declare const isEAN: EmittableRule;
64
+ declare const isISO31661Alpha2: import("../types").InternalRule;
65
+ declare const isISO31661Alpha3: import("../types").InternalRule;
66
+ declare const isBIC: EmittableRule;
67
+ declare const isFirebasePushId: EmittableRule;
68
+ declare const isSemVer: EmittableRule;
69
+ declare const isMongoId: EmittableRule;
70
+ declare const isJSON: import("../types").InternalRule;
71
+ declare function isBase32(): EmittableRule;
72
+ declare const isBase58: EmittableRule;
73
+ interface IsBase64Options {
73
74
  urlSafe?: boolean;
74
75
  }
75
- export declare function isBase64(options?: IsBase64Options): EmittableRule;
76
- export declare function isDateString(): EmittableRule;
77
- export declare const isMimeType: EmittableRule;
78
- export declare function isCurrency(): EmittableRule;
79
- export declare const isMagnetURI: EmittableRule;
80
- export declare const isCreditCard: EmittableRule;
81
- export interface IsIBANOptions {
76
+ declare function isBase64(options?: IsBase64Options): EmittableRule;
77
+ declare function isDateString(): EmittableRule;
78
+ declare const isMimeType: EmittableRule;
79
+ declare function isCurrency(): EmittableRule;
80
+ declare const isMagnetURI: EmittableRule;
81
+ declare const isCreditCard: import("../types").InternalRule;
82
+ interface IsIBANOptions {
82
83
  allowSpaces?: boolean;
83
84
  }
84
- export declare function isIBAN(options?: IsIBANOptions): EmittableRule;
85
- export declare function isByteLength(min: number, max?: number): EmittableRule;
86
- export declare function isHash(algorithm: string): EmittableRule;
87
- export declare const isRFC3339: EmittableRule;
88
- export declare const isMilitaryTime: EmittableRule;
89
- export declare const isLatitude: EmittableRule;
90
- export declare const isLongitude: EmittableRule;
91
- export declare const isEthereumAddress: EmittableRule;
92
- export declare const isBtcAddress: EmittableRule;
93
- export declare const isISO4217CurrencyCode: EmittableRule;
94
- export declare const isPhoneNumber: EmittableRule;
95
- export interface IsStrongPasswordOptions {
85
+ declare function isIBAN(options?: IsIBANOptions): EmittableRule;
86
+ declare function isByteLength(min: number, max?: number): EmittableRule;
87
+ declare function isHash(algorithm: string): EmittableRule;
88
+ declare const isRFC3339: EmittableRule;
89
+ declare const isMilitaryTime: EmittableRule;
90
+ declare const isLatitude: import("../types").InternalRule;
91
+ declare const isLongitude: import("../types").InternalRule;
92
+ declare const isEthereumAddress: EmittableRule;
93
+ declare const isBtcAddress: EmittableRule;
94
+ declare const isISO4217CurrencyCode: EmittableRule;
95
+ declare const isPhoneNumber: EmittableRule;
96
+ interface IsStrongPasswordOptions {
96
97
  minLength?: number;
97
98
  minLowercase?: number;
98
99
  minUppercase?: number;
99
100
  minNumbers?: number;
100
101
  minSymbols?: number;
101
102
  }
102
- export declare function isStrongPassword(options?: IsStrongPasswordOptions): EmittableRule;
103
- export declare function isTaxId(locale: string): EmittableRule;
104
- export declare function isULID(): EmittableRule;
105
- export declare function isCUID2(): EmittableRule;
103
+ declare function isStrongPassword(options?: IsStrongPasswordOptions): EmittableRule;
104
+ declare function isTaxId(locale: string): EmittableRule;
105
+ declare function isULID(): EmittableRule;
106
+ declare function isCUID2(): EmittableRule;
107
+ export { minLength, maxLength, length, contains, notContains, matches, isLowercase, isUppercase, isAscii, isAlpha, isAlphanumeric, isHttpToken, isBooleanString, isNumberString, isDecimal, isFullWidth, isHalfWidth, isVariableWidth, isMultibyte, isSurrogatePair, isHexadecimal, isOctal, isEmail, isURL, isUUID, isIP, isHexColor, isRgbColor, isHSL, isMACAddress, isISBN, isISIN, isISO8601, isISRC, isISSN, isJWT, isLatLong, isLocale, isDataURI, isFQDN, isPort, isEAN, isISO31661Alpha2, isISO31661Alpha3, isBIC, isFirebasePushId, isSemVer, isMongoId, isJSON, isBase32, isBase58, isBase64, isDateString, isMimeType, isCurrency, isMagnetURI, isCreditCard, isIBAN, isByteLength, isHash, isRFC3339, isMilitaryTime, isLatitude, isLongitude, isEthereumAddress, isBtcAddress, isISO4217CurrencyCode, isPhoneNumber, isStrongPassword, isTaxId, isULID, isCUID2, };
108
+ export type { IsNumberStringOptions, IsURLOptions, IsMACAddressOptions, IsISO8601Options, IsISSNOptions, IsFQDNOptions, IsBase64Options, IsIBANOptions, IsStrongPasswordOptions, };