@orieljs/validation 0.1.0-alpha.3 → 0.1.0-alpha.4

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/dist/index.d.ts CHANGED
@@ -11,6 +11,16 @@ declare class ValidationErrorImpl extends Error implements ValidationError {
11
11
  readonly name = "ValidationError";
12
12
  constructor(errors: Record<string, string[]>, errorBag?: string, redirectTo?: string | undefined);
13
13
  }
14
+ /**
15
+ * Laravel's ValidationException, for failing a request by hand:
16
+ * `throw ValidationException.withMessages({ email: __('auth.failed') })`. Rendered like any validation error: 422 JSON,
17
+ * or a redirect back with the errors.
18
+ */
19
+ declare class ValidationException extends ValidationErrorImpl {
20
+ /** Messages per field, each a string or a list. */
21
+ static withMessages(messages: Record<string, string | readonly string[]>): ValidationException;
22
+ constructor(errors: Record<string, string[]>, errorBag?: string, redirectTo?: string);
23
+ }
14
24
  declare class AuthorizationErrorImpl extends Error implements OrielError {
15
25
  readonly kind: "Authorization";
16
26
  readonly status = 403;
@@ -89,6 +99,8 @@ interface BuiltinRule {
89
99
  replacements?(ctx: RuleContext): Record<string, string>;
90
100
  /** Used when messageKey() isn't in DEFAULT_MESSAGES (e.g. an extend()ed rule with a custom message). */
91
101
  defaultMessage?: string;
102
+ /** An extend()ed rule's own message: it wins over the default lines, as Laravel's fallback messages do. */
103
+ message?: string;
92
104
  /** Runs even when the value is missing, blank, or null under nullable (the required* family, and accepted); a failure stops the field. */
93
105
  implicit?: boolean;
94
106
  }
@@ -123,6 +135,36 @@ declare function expandWildcardKeys(pattern: string, data: Record<string, unknow
123
135
  /** Every built-in rule, merged. Later tasks (database rules) add their own spread here. */
124
136
  declare const builtinRules: Record<string, BuiltinRule>;
125
137
 
138
+ /**
139
+ * Laravel's Illuminate\Validation\Rules\Password: a string of at least `min` characters (8 by default), plus the
140
+ * checks you add: letters(), mixedCase(), numbers(), symbols(), max(). Every failing check adds its own message.
141
+ * Rule.password() returns the application default (PasswordRule.defaults()). (Laravel's uncompromised() is not
142
+ * ported: it calls an outside service.)
143
+ */
144
+ declare class PasswordRule implements ValidationRule {
145
+ #private;
146
+ constructor(min?: number);
147
+ /** A password rule of at least `size` characters: PasswordRule.min(12).mixedCase(). */
148
+ static min(size: number): PasswordRule;
149
+ /**
150
+ * With an argument, sets the default (Laravel's Password::defaults(fn () => ...), in a provider's boot());
151
+ * `null` resets it. Without one, returns a copy of the default: PasswordRule.min(8) unless set.
152
+ */
153
+ static defaults(): PasswordRule;
154
+ static defaults(rule: PasswordRule | (() => PasswordRule) | null): void;
155
+ min(size: number): this;
156
+ max(size: number): this;
157
+ /** At least one letter. */
158
+ letters(): this;
159
+ /** At least one uppercase and one lowercase letter. */
160
+ mixedCase(): this;
161
+ /** At least one number. */
162
+ numbers(): this;
163
+ /** At least one symbol (punctuation, a symbol or a space). */
164
+ symbols(): this;
165
+ validate(attribute: string, value: unknown, fail: (message: string) => void): void;
166
+ }
167
+
126
168
  /**
127
169
  * Base for the fluent builders. Each one reports under a built-in rule name (`in`, `unique`, `exists`), so when it
128
170
  * runs inside a Validator its failure goes through exactly the same lookup as the string rule: custom messages
@@ -169,6 +211,8 @@ declare const Rule: {
169
211
  in: (values: readonly unknown[]) => InRule;
170
212
  unique: (table: string, column?: string) => UniqueRule;
171
213
  exists: (table: string, column?: string) => ExistsRule;
214
+ /** Laravel's Password::defaults(): the application's password rule (at least 8 characters unless PasswordRule.defaults() changed it). */
215
+ password: () => PasswordRule;
172
216
  };
173
217
 
174
218
  /** See Task 9's writeup in the plan for exactly what this does and doesn't infer. */
@@ -239,4 +283,4 @@ declare class ValidationServiceProvider extends ServiceProvider {
239
283
  register(): void;
240
284
  }
241
285
 
242
- export { AuthorizationErrorImpl, type BuiltinRule, BuiltinRuleObject, DEFAULT_MESSAGES, FormRequest, type InferRuleType, type InferValidatedType, InvalidRuleParameterError, MessageBagImpl, type ParsedRule, Rule, type RuleContext, UnknownValidationRuleError, ValidationErrorImpl, ValidationFactoryImpl, ValidationServiceProvider, Validator, ValidatorImpl, applyReplacements, builtinRules, defaultAttributeName, expandWildcardKeys, isEmptyValue, isUploadedFileLike, parseRuleSpec };
286
+ export { AuthorizationErrorImpl, type BuiltinRule, BuiltinRuleObject, DEFAULT_MESSAGES, FormRequest, type InferRuleType, type InferValidatedType, InvalidRuleParameterError, MessageBagImpl, type ParsedRule, PasswordRule, Rule, type RuleContext, UnknownValidationRuleError, ValidationErrorImpl, ValidationException, ValidationFactoryImpl, ValidationServiceProvider, Validator, ValidatorImpl, applyReplacements, builtinRules, defaultAttributeName, expandWildcardKeys, isEmptyValue, isUploadedFileLike, parseRuleSpec };
package/dist/index.js CHANGED
@@ -13,6 +13,23 @@ var ValidationErrorImpl = class extends Error {
13
13
  status = 422;
14
14
  name = "ValidationError";
15
15
  };
16
+ var ValidationException = class _ValidationException extends ValidationErrorImpl {
17
+ /** Messages per field, each a string or a list. */
18
+ static withMessages(messages) {
19
+ const errors = Object.fromEntries(Object.entries(messages).map(([field, list]) => [field, typeof list === "string" ? [list] : [...list]]));
20
+ return new _ValidationException(errors);
21
+ }
22
+ constructor(errors, errorBag = "default", redirectTo) {
23
+ super(errors, errorBag, redirectTo);
24
+ this.message = summarize(errors);
25
+ }
26
+ };
27
+ function summarize(errors) {
28
+ const messages = Object.values(errors).flat();
29
+ if (messages.length === 0) return "The given data was invalid.";
30
+ const more = messages.length - 1;
31
+ return more === 0 ? messages[0] : `${messages[0]} (and ${more} more ${more === 1 ? "error" : "errors"})`;
32
+ }
16
33
  var AuthorizationErrorImpl = class extends Error {
17
34
  kind = "Authorization";
18
35
  status = 403;
@@ -95,6 +112,13 @@ var DEFAULT_MESSAGES = {
95
112
  alpha_num: "The :attribute field must only contain letters and numbers.",
96
113
  alpha_dash: "The :attribute field must only contain letters, numbers, dashes and underscores.",
97
114
  regex: "The :attribute field format is invalid.",
115
+ lowercase: "The :attribute field must be lowercase.",
116
+ uppercase: "The :attribute field must be uppercase.",
117
+ current_password: "The password is incorrect.",
118
+ "password.letters": "The :attribute field must contain at least one letter.",
119
+ "password.mixed": "The :attribute field must contain at least one uppercase and one lowercase letter.",
120
+ "password.numbers": "The :attribute field must contain at least one number.",
121
+ "password.symbols": "The :attribute field must contain at least one symbol.",
98
122
  confirmed: "The :attribute field confirmation does not match.",
99
123
  same: "The :attribute field must match :other.",
100
124
  different: "The :attribute field must be different from :other.",
@@ -163,9 +187,24 @@ var MessageBagImpl = class {
163
187
  }
164
188
  };
165
189
 
190
+ // rules/auth.ts
191
+ import { AuthFactory, Hasher } from "@orieljs/contracts";
192
+ import { inject as inject2 } from "@orieljs/container";
193
+ var authRules = {
194
+ current_password: {
195
+ validate: async (ctx) => {
196
+ const guard = inject2(AuthFactory).guard(ctx.parameters[0]);
197
+ if (await guard.guest()) return false;
198
+ const user = await guard.user();
199
+ return user !== void 0 && typeof ctx.value === "string" && inject2(Hasher).check(ctx.value, user.getAuthPassword());
200
+ },
201
+ messageKey: () => "current_password"
202
+ }
203
+ };
204
+
166
205
  // rules/database.ts
167
206
  import { DatabaseManager } from "@orieljs/contracts";
168
- import { inject as inject2 } from "@orieljs/container";
207
+ import { inject as inject3 } from "@orieljs/container";
169
208
  function guessColumn(attribute, expandedFromWildcard = false) {
170
209
  if (!expandedFromWildcard) return attribute;
171
210
  return attribute.split(".").filter((segment) => !/^\d+$/.test(segment)).at(-1) ?? attribute;
@@ -174,7 +213,7 @@ function isNoExcept(except) {
174
213
  return except === void 0 || except === null || except === "" || except === "NULL";
175
214
  }
176
215
  async function matchingRecordExists(table, column, value, except, idColumn = "id") {
177
- const db = inject2(DatabaseManager);
216
+ const db = inject3(DatabaseManager);
178
217
  let query = db.connection().table(table).where(column, value);
179
218
  if (!isNoExcept(except)) query = query.where(idColumn, "!=", except);
180
219
  return query.exists();
@@ -394,6 +433,14 @@ var formatRules = {
394
433
  validate: (ctx) => typeof ctx.value === "string" && ALPHA_DASH_RE.test(ctx.value),
395
434
  messageKey: () => "alpha_dash"
396
435
  },
436
+ lowercase: {
437
+ validate: (ctx) => (typeof ctx.value === "string" || typeof ctx.value === "number") && String(ctx.value).toLowerCase() === String(ctx.value),
438
+ messageKey: () => "lowercase"
439
+ },
440
+ uppercase: {
441
+ validate: (ctx) => (typeof ctx.value === "string" || typeof ctx.value === "number") && String(ctx.value).toUpperCase() === String(ctx.value),
442
+ messageKey: () => "uppercase"
443
+ },
397
444
  regex: {
398
445
  validate: (ctx) => typeof ctx.value === "string" && compileRegex(ctx.parameters[0] ?? "").test(ctx.value),
399
446
  messageKey: () => "regex"
@@ -584,7 +631,83 @@ var builtinRules = {
584
631
  ...formatRules,
585
632
  ...sizeRules,
586
633
  ...fileRules,
587
- ...databaseRules
634
+ ...databaseRules,
635
+ ...authRules
636
+ };
637
+
638
+ // rules/password.ts
639
+ var defaultRule;
640
+ var PasswordRule = class _PasswordRule {
641
+ #min;
642
+ #max;
643
+ #letters = false;
644
+ #mixedCase = false;
645
+ #numbers = false;
646
+ #symbols = false;
647
+ constructor(min = 8) {
648
+ this.#min = Math.max(1, min);
649
+ }
650
+ /** A password rule of at least `size` characters: PasswordRule.min(12).mixedCase(). */
651
+ static min(size) {
652
+ return new _PasswordRule(size);
653
+ }
654
+ static defaults(rule) {
655
+ if (rule !== void 0) {
656
+ defaultRule = rule ?? void 0;
657
+ return;
658
+ }
659
+ const resolved = typeof defaultRule === "function" ? defaultRule() : defaultRule;
660
+ return resolved === void 0 ? new _PasswordRule(8) : resolved.#copy();
661
+ }
662
+ min(size) {
663
+ this.#min = Math.max(1, size);
664
+ return this;
665
+ }
666
+ max(size) {
667
+ this.#max = size;
668
+ return this;
669
+ }
670
+ /** At least one letter. */
671
+ letters() {
672
+ this.#letters = true;
673
+ return this;
674
+ }
675
+ /** At least one uppercase and one lowercase letter. */
676
+ mixedCase() {
677
+ this.#mixedCase = true;
678
+ return this;
679
+ }
680
+ /** At least one number. */
681
+ numbers() {
682
+ this.#numbers = true;
683
+ return this;
684
+ }
685
+ /** At least one symbol (punctuation, a symbol or a space). */
686
+ symbols() {
687
+ this.#symbols = true;
688
+ return this;
689
+ }
690
+ validate(attribute, value, fail) {
691
+ const name = defaultAttributeName(attribute);
692
+ const say = (key, replacements = {}) => fail(applyReplacements(DEFAULT_MESSAGES[key], { attribute: name, ...replacements }));
693
+ if (typeof value !== "string") return say("string");
694
+ const length = [...value].length;
695
+ if (length < this.#min) say("min.string", { min: String(this.#min) });
696
+ if (this.#max !== void 0 && length > this.#max) say("max.string", { max: String(this.#max) });
697
+ if (this.#mixedCase && !/(\p{Ll}+.*\p{Lu})|(\p{Lu}+.*\p{Ll})/u.test(value)) say("password.mixed");
698
+ if (this.#letters && !/\p{L}/u.test(value)) say("password.letters");
699
+ if (this.#symbols && !/\p{Z}|\p{S}|\p{P}/u.test(value)) say("password.symbols");
700
+ if (this.#numbers && !/\p{N}/u.test(value)) say("password.numbers");
701
+ }
702
+ #copy() {
703
+ const copy = new _PasswordRule(this.#min);
704
+ copy.#max = this.#max;
705
+ copy.#letters = this.#letters;
706
+ copy.#mixedCase = this.#mixedCase;
707
+ copy.#numbers = this.#numbers;
708
+ copy.#symbols = this.#symbols;
709
+ return copy;
710
+ }
588
711
  };
589
712
 
590
713
  // Rule.ts
@@ -659,7 +782,9 @@ var ExistsRule = class extends BuiltinRuleObject {
659
782
  var Rule = {
660
783
  in: (values) => new InRule(values),
661
784
  unique: (table, column) => new UniqueRule(table, column),
662
- exists: (table, column) => new ExistsRule(table, column)
785
+ exists: (table, column) => new ExistsRule(table, column),
786
+ /** Laravel's Password::defaults(): the application's password rule (at least 8 characters unless PasswordRule.defaults() changed it). */
787
+ password: () => PasswordRule.defaults()
663
788
  };
664
789
 
665
790
  // Validator.ts
@@ -777,9 +902,9 @@ var ValidatorImpl = class {
777
902
  const implicit = rule.kind === "named" && (this.registry[rule.name]?.implicit ?? false);
778
903
  if (!implicit && (!present || isBlank)) continue;
779
904
  if (!implicit && nullable && isNull) continue;
780
- const message = await this.runRule(rule, field, pattern, value, names);
781
- if (message !== void 0) {
782
- this.bag.add(field, message);
905
+ const messages = await this.runRule(rule, field, pattern, value, names);
906
+ if (messages.length > 0) {
907
+ for (const message of messages) this.bag.add(field, message);
783
908
  if (bail || implicit) break;
784
909
  }
785
910
  }
@@ -792,26 +917,24 @@ var ValidatorImpl = class {
792
917
  const expanded = pattern.includes("*");
793
918
  if (rule.kind === "object") {
794
919
  if (rule.rule instanceof BuiltinRuleObject) {
795
- if (await rule.rule.passes(field, value, this.data, expanded)) return void 0;
920
+ if (await rule.rule.passes(field, value, this.data, expanded)) return [];
796
921
  const ctx2 = { attribute: field, expandedFromWildcard: expanded, value, parameters: [], data: this.data, ruleNames };
797
- return this.failureMessage(rule.rule.ruleName, this.registry[rule.rule.ruleName], ctx2, pattern);
922
+ return [this.failureMessage(rule.rule.ruleName, this.registry[rule.rule.ruleName], ctx2, pattern)];
798
923
  }
799
- let failure;
800
- await rule.rule.validate(field, value, (message) => {
801
- failure = message;
802
- }, this.data);
803
- return failure;
924
+ const failures = [];
925
+ await rule.rule.validate(field, value, (message) => void failures.push(message), this.data);
926
+ return failures;
804
927
  }
805
928
  const builtin = this.registry[rule.name];
806
929
  if (!builtin) throw new UnknownValidationRuleError(rule.name);
807
930
  const ctx = { attribute: field, expandedFromWildcard: expanded, value, parameters: rule.parameters, data: this.data, ruleNames };
808
- if (await builtin.validate(ctx)) return void 0;
809
- return this.failureMessage(rule.name, builtin, ctx, pattern);
931
+ if (await builtin.validate(ctx)) return [];
932
+ return [this.failureMessage(rule.name, builtin, ctx, pattern)];
810
933
  }
811
934
  /** Custom message (concrete field, then wildcard pattern, then rule name) or the default, with :attribute filled. */
812
935
  failureMessage(name, builtin, ctx, pattern) {
813
936
  const field = ctx.attribute;
814
- const template = this.customMessages[`${field}.${name}`] ?? this.customMessages[`${pattern}.${name}`] ?? this.customMessages[name] ?? DEFAULT_MESSAGES[builtin?.messageKey(ctx) ?? name] ?? builtin?.defaultMessage ?? "The :attribute field is invalid.";
937
+ const template = this.customMessages[`${field}.${name}`] ?? this.customMessages[`${pattern}.${name}`] ?? this.customMessages[name] ?? builtin?.message ?? DEFAULT_MESSAGES[builtin?.messageKey(ctx) ?? name] ?? builtin?.defaultMessage ?? "The :attribute field is invalid.";
815
938
  const display = this.customAttributes[field] ?? this.customAttributes[pattern] ?? defaultAttributeName(field);
816
939
  return applyReplacements(template, { attribute: display, ...builtin?.replacements?.(ctx) ?? {} });
817
940
  }
@@ -827,6 +950,7 @@ var ValidationFactoryImpl = class {
827
950
  this.extended[name] = {
828
951
  validate: (ctx) => callback(ctx.attribute, ctx.value, ctx.parameters, ctx.data),
829
952
  messageKey: () => name,
953
+ ...message === void 0 ? {} : { message },
830
954
  defaultMessage: message ?? "The :attribute field is invalid."
831
955
  };
832
956
  }
@@ -852,9 +976,11 @@ export {
852
976
  FormRequest,
853
977
  InvalidRuleParameterError,
854
978
  MessageBagImpl,
979
+ PasswordRule,
855
980
  Rule,
856
981
  UnknownValidationRuleError,
857
982
  ValidationErrorImpl,
983
+ ValidationException,
858
984
  ValidationFactoryImpl,
859
985
  ValidationServiceProvider,
860
986
  Validator,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../errors.ts","../FormRequest.ts","../messages.ts","../MessageBag.ts","../rules/database.ts","../parse.ts","../rules/file.ts","../rules/format.ts","../rules/presence.ts","../rules/type.ts","../rules/size.ts","../registry.ts","../Rule.ts","../Validator.ts","../ValidationFactory.ts","../facade.ts","../ValidationServiceProvider.ts"],"sourcesContent":["import type { OrielError, ValidationError } from '@orieljs/contracts'\n\nexport class ValidationErrorImpl extends Error implements ValidationError {\n readonly kind = 'Validation' as const\n readonly status = 422\n override readonly name = 'ValidationError'\n constructor(\n readonly errors: Record<string, string[]>,\n readonly errorBag = 'default',\n readonly redirectTo?: string,\n ) {\n super('The given data was invalid.')\n }\n}\n\nexport class AuthorizationErrorImpl extends Error implements OrielError {\n readonly kind = 'Authorization' as const\n readonly status = 403\n override readonly name = 'AuthorizationError'\n constructor(message = 'This action is unauthorized.') {\n super(message)\n }\n}\n\nexport class UnknownValidationRuleError extends Error implements OrielError {\n readonly kind = 'Server' as const\n readonly status = 500\n override readonly name = 'UnknownValidationRuleError'\n constructor(name: string) {\n super(`Validation rule \"${name}\" is not registered. Register it with ValidationFactory.extend() first.`)\n }\n}\n\n/** A rule was written with a parameter it can't use (a bad regex, an unparseable date). A developer error, not a user one. */\nexport class InvalidRuleParameterError extends Error implements OrielError {\n readonly kind = 'Server' as const\n readonly status = 500\n override readonly name = 'InvalidRuleParameterError'\n constructor(rule: string, parameter: string, reason: string) {\n super(`Validation rule \"${rule}\" has an invalid parameter \"${parameter}\": ${reason}`)\n }\n}\n","import type { Rules } from '@orieljs/contracts'\nimport { HttpRequest, ValidationFactory } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport { AuthorizationErrorImpl } from './errors'\n\n/**\n * Mirrors Illuminate\\Foundation\\Http\\FormRequest, minus dependency injection by type (Oriel resolves the current\n * request and the ValidationFactory through inject(), never through constructor parameters — see spec §3 rule 5).\n * A subclass only has to implement rules(); authorize()/messages()/attributes() default to Laravel's own defaults.\n */\nexport abstract class FormRequest {\n abstract rules(): Rules\n\n authorize(): boolean | Promise<boolean> {\n return true\n }\n\n messages(): Record<string, string> {\n return {}\n }\n\n attributes(): Record<string, string> {\n return {}\n }\n\n /**\n * `const data = await StorePostRequest.validate()` (spec §4.3). Resolves the current request and the\n * ValidationFactory from the active container, runs authorize() first (throwing AuthorizationErrorImpl if it\n * returns false), then validates request.all() against rules()/messages()/attributes() and returns the typed\n * validated data (or throws the 422 ValidationError — see ValidatorImpl.validated()).\n */\n static async validate<T = Record<string, unknown>>(this: new () => FormRequest): Promise<T> {\n const instance = new this()\n if (!(await instance.authorize())) throw new AuthorizationErrorImpl()\n\n const request = inject(HttpRequest)\n const factory = inject(ValidationFactory)\n const validator = factory.make(request.all(), instance.rules(), instance.messages(), instance.attributes())\n return validator.validated<T>()\n }\n}\n","import { Str } from '@orieljs/support'\n\n/** Humanizes a (possibly dotted) attribute key, e.g. \"items.0.product_name\" -> \"items.0.product name\". */\nexport function defaultAttributeName(key: string): string {\n return key\n .split('.')\n .map((segment) => Str.snake(segment).replace(/_/g, ' '))\n .join('.')\n}\n\nexport function applyReplacements(template: string, replacements: Record<string, string>): string {\n return Object.entries(replacements).reduce((message, [key, value]) => message.replaceAll(`:${key}`, value), template)\n}\n\n/** Laravel's English lang/en/validation.php, reproduced as closely as possible (see plan Notes/assumptions). */\nexport const DEFAULT_MESSAGES: Record<string, string> = {\n required: 'The :attribute field is required.',\n required_if: 'The :attribute field is required when :other is :value.',\n required_unless: 'The :attribute field is required unless :other is in :values.',\n required_with: 'The :attribute field is required when :values is present.',\n required_with_all: 'The :attribute field is required when :values are present.',\n required_without: 'The :attribute field is required when :values is not present.',\n required_without_all: 'The :attribute field is required when none of :values are present.',\n string: 'The :attribute field must be a string.',\n integer: 'The :attribute field must be an integer.',\n numeric: 'The :attribute field must be a number.',\n boolean: 'The :attribute field must be true or false.',\n array: 'The :attribute field must be an array.',\n email: 'The :attribute field must be a valid email address.',\n url: 'The :attribute field must be a valid URL.',\n uuid: 'The :attribute field must be a valid UUID.',\n alpha: 'The :attribute field must only contain letters.',\n alpha_num: 'The :attribute field must only contain letters and numbers.',\n alpha_dash: 'The :attribute field must only contain letters, numbers, dashes and underscores.',\n regex: 'The :attribute field format is invalid.',\n confirmed: 'The :attribute field confirmation does not match.',\n same: 'The :attribute field must match :other.',\n different: 'The :attribute field must be different from :other.',\n accepted: 'The :attribute field must be accepted.',\n digits: 'The :attribute field must be :digits digits.',\n date: 'The :attribute field must be a valid date.',\n before: 'The :attribute field must be a date before :date.',\n after: 'The :attribute field must be a date after :date.',\n in: 'The selected :attribute is invalid.',\n not_in: 'The selected :attribute is invalid.',\n unique: 'The :attribute has already been taken.',\n exists: 'The selected :attribute is invalid.',\n file: 'The :attribute field must be a file.',\n image: 'The :attribute field must be an image.',\n mimes: 'The :attribute field must be a file of type: :values.',\n 'max.string': 'The :attribute field must not be greater than :max characters.',\n 'max.numeric': 'The :attribute field must not be greater than :max.',\n 'max.array': 'The :attribute field must not have more than :max items.',\n 'max.file': 'The :attribute field must not be greater than :max kilobytes.',\n 'min.string': 'The :attribute field must be at least :min characters.',\n 'min.numeric': 'The :attribute field must be at least :min.',\n 'min.array': 'The :attribute field must have at least :min items.',\n 'min.file': 'The :attribute field must be at least :min kilobytes.',\n 'between.string': 'The :attribute field must be between :min and :max characters.',\n 'between.numeric': 'The :attribute field must be between :min and :max.',\n 'between.array': 'The :attribute field must have between :min and :max items.',\n 'between.file': 'The :attribute field must be between :min and :max kilobytes.',\n 'size.string': 'The :attribute field must be :size characters.',\n 'size.numeric': 'The :attribute field must be :size.',\n 'size.array': 'The :attribute field must contain :size items.',\n 'size.file': 'The :attribute field must be :size kilobytes.',\n}\n","import type { MessageBag } from '@orieljs/contracts'\n\nexport class MessageBagImpl implements MessageBag {\n private readonly items: Record<string, string[]> = {}\n\n /** Not part of the MessageBag contract — used internally by ValidatorImpl and by after() hooks. */\n add(key: string, message: string): void {\n ;(this.items[key] ??= []).push(message)\n }\n\n has(key: string): boolean {\n return (this.items[key]?.length ?? 0) > 0\n }\n\n first(key?: string): string | undefined {\n if (key !== undefined) return this.items[key]?.[0]\n for (const messages of Object.values(this.items)) {\n if (messages[0] !== undefined) return messages[0]\n }\n return undefined\n }\n\n get(key: string): string[] {\n return this.items[key] ?? []\n }\n\n all(): string[] {\n return Object.values(this.items).flat()\n }\n\n isEmpty(): boolean {\n return Object.keys(this.items).length === 0\n }\n\n count(): number {\n return this.all().length\n }\n\n toObject(): Record<string, string[]> {\n return structuredClone(this.items)\n }\n}\n","import { DatabaseManager } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport type { BuiltinRule } from '../parse'\n\n/**\n * The column to query when a unique/exists rule doesn't name one: the attribute itself, except for a\n * wildcard-expanded field like \"items.0.email\", which checks the last non-numeric segment (\"email\") rather than a\n * column literally named after the path (Laravel's guessColumnForQuery).\n */\nexport function guessColumn(attribute: string, expandedFromWildcard = false): string {\n if (!expandedFromWildcard) return attribute\n return attribute.split('.').filter((segment) => !/^\\d+$/.test(segment)).at(-1) ?? attribute\n}\n\n/** Laravel's idiom `unique:users,email,NULL,id` (and an empty or null ignore) means \"exclude nothing\". */\nfunction isNoExcept(except: unknown): boolean {\n return except === undefined || except === null || except === '' || except === 'NULL'\n}\n\n/**\n * Shared query shape behind both `unique`/`exists` string rules and `Rule.unique()`/`Rule.exists()` (Review Focus\n * #2): resolve DatabaseManager, filter table/column on value, optionally exclude a record by idColumn/except, and\n * report whether any row matches. Kept in one place so a future fix to this path can't miss one of the two callers.\n */\nexport async function matchingRecordExists(\n table: string,\n column: string,\n value: unknown,\n except?: unknown,\n idColumn = 'id',\n): Promise<boolean> {\n const db = inject(DatabaseManager)\n let query = db.connection().table(table).where(column, value)\n if (!isNoExcept(except)) query = query.where(idColumn, '!=', except)\n return query.exists()\n}\n\nexport const databaseRules: Record<string, BuiltinRule> = {\n unique: {\n validate: async (ctx) => {\n const [table, column, except, idColumn] = ctx.parameters\n return !(await matchingRecordExists(table!, column || guessColumn(ctx.attribute, ctx.expandedFromWildcard), ctx.value, except, idColumn || 'id'))\n },\n messageKey: () => 'unique',\n },\n exists: {\n validate: async (ctx) => {\n const [table, column] = ctx.parameters\n return matchingRecordExists(table!, column || guessColumn(ctx.attribute, ctx.expandedFromWildcard), ctx.value)\n },\n messageKey: () => 'exists',\n },\n}\n","import type { ValidationRule } from '@orieljs/contracts'\nimport { Arr } from '@orieljs/support'\n\n/** Everything a single rule needs to validate one concrete field. */\nexport interface RuleContext {\n /** The concrete, wildcard-expanded field path, e.g. \"items.1.name\". */\n attribute: string\n /** True when `attribute` came from expanding a wildcard pattern such as \"items.*.email\". */\n expandedFromWildcard?: boolean\n value: unknown\n parameters: string[]\n data: Record<string, unknown>\n /** Every named rule attached to this field (for size-type resolution: numeric/array/file/string). */\n ruleNames: string[]\n}\n\nexport interface BuiltinRule {\n validate(ctx: RuleContext): boolean | Promise<boolean>\n /** Which DEFAULT_MESSAGES key to use, e.g. `max.${sizeType}`. Most rules return a constant name. */\n messageKey(ctx: RuleContext): string\n /** Extra :placeholder substitutions beyond :attribute (e.g. :max, :other, :values). */\n replacements?(ctx: RuleContext): Record<string, string>\n /** Used when messageKey() isn't in DEFAULT_MESSAGES (e.g. an extend()ed rule with a custom message). */\n defaultMessage?: string\n /** Runs even when the value is missing, blank, or null under nullable (the required* family, and accepted); a failure stops the field. */\n implicit?: boolean\n}\n\nexport type ParsedRule =\n | { kind: 'named'; name: string; parameters: string[] }\n | { kind: 'object'; rule: ValidationRule }\n\nfunction splitParameters(name: string, raw: string): string[] {\n // regex/not_regex parameters are never comma-split, so a pattern containing a comma survives intact.\n return name === 'regex' || name === 'not_regex' ? [raw] : raw.split(',')\n}\n\nfunction splitOnce(value: string, separator: string): [string, string | undefined] {\n const index = value.indexOf(separator)\n return index === -1 ? [value, undefined] : [value.slice(0, index), value.slice(index + 1)]\n}\n\nexport function parseRuleSpec(spec: string | ReadonlyArray<string | ValidationRule>): ParsedRule[] {\n const items = typeof spec === 'string' ? spec.split('|') : spec\n return items\n .filter((item) => item !== '')\n .map((item): ParsedRule => {\n if (typeof item !== 'string') return { kind: 'object', rule: item }\n const [name, raw] = splitOnce(item, ':')\n return { kind: 'named', name, parameters: raw === undefined ? [] : splitParameters(name, raw) }\n })\n}\n\n/** Laravel's definition of \"empty\" for the required family: null, undefined, '' and []. false and 0 are NOT empty. */\nexport function isEmptyValue(value: unknown): boolean {\n if (value === null || value === undefined) return true\n if (typeof value === 'string') return value === ''\n if (Array.isArray(value)) return value.length === 0\n return false\n}\n\n/** Duck-types Contracts/Http's UploadedFile without importing @orieljs/http. */\nexport function isUploadedFileLike(value: unknown): value is {\n clientName: string\n mimeType: string\n size: number\n extension(): string\n arrayBuffer(): Promise<ArrayBuffer>\n} {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Record<string, unknown>).clientName === 'string' &&\n typeof (value as Record<string, unknown>).arrayBuffer === 'function'\n )\n}\n\n/**\n * Keys that must never be followed or written when walking user input: assigning through them reaches\n * Object.prototype (or a constructor) instead of a plain data slot. Mirrors the guard in Arr.set.\n */\nexport const UNSAFE_KEYS: ReadonlySet<string> = new Set(['__proto__', 'prototype', 'constructor'])\n\n/**\n * Expands a `*`-wildcard rule pattern (e.g. \"items.*.name\") into every concrete path present in `data`\n * (e.g. [\"items.0.name\", \"items.1.name\"]). A pattern with no `*` is returned unchanged. A `*` segment whose\n * container is missing, not an array and not a plain object expands to nothing for that branch (Review Focus #4:\n * every reported error is keyed by a concrete path, never the literal pattern). Object keys in UNSAFE_KEYS are\n * treated as absent, so a JSON body like {\"items\":{\"__proto__\":{...}}} never yields a path through the prototype.\n */\nexport function expandWildcardKeys(pattern: string, data: Record<string, unknown>): string[] {\n const segments = pattern.split('.')\n let paths = ['']\n for (const segment of segments) {\n const next: string[] = []\n for (const base of paths) {\n const prefix = base === '' ? '' : `${base}.`\n if (segment !== '*') {\n next.push(`${prefix}${segment}`)\n continue\n }\n const container = Arr.get<unknown>(data, base === '' ? undefined : base)\n if (Array.isArray(container)) {\n container.forEach((_, index) => next.push(`${prefix}${index}`))\n } else if (container !== null && typeof container === 'object') {\n Object.keys(container)\n .filter((key) => !UNSAFE_KEYS.has(key))\n .forEach((key) => next.push(`${prefix}${key}`))\n }\n }\n paths = next\n }\n return paths\n}\n","import type { BuiltinRule } from '../parse'\nimport { isUploadedFileLike } from '../parse'\n\nconst IMAGE_EXTENSIONS = new Set(['jpg', 'jpeg', 'png', 'bmp', 'gif', 'svg', 'webp'])\n\nexport const fileRules: Record<string, BuiltinRule> = {\n file: { validate: (ctx) => isUploadedFileLike(ctx.value), messageKey: () => 'file' },\n image: {\n validate: (ctx) => {\n if (!isUploadedFileLike(ctx.value)) return false\n if (ctx.value.mimeType.startsWith('image/')) return true\n return IMAGE_EXTENSIONS.has(ctx.value.extension().toLowerCase())\n },\n messageKey: () => 'image',\n },\n mimes: {\n validate: (ctx) => {\n if (!isUploadedFileLike(ctx.value)) return false\n const allowed = ctx.parameters.map((p) => p.toLowerCase())\n return allowed.includes(ctx.value.extension().toLowerCase())\n },\n messageKey: () => 'mimes',\n replacements: (ctx) => ({ values: ctx.parameters.join(', ') }),\n },\n}\n","import { Arr } from '@orieljs/support'\nimport type { BuiltinRule, RuleContext } from '../parse'\nimport { InvalidRuleParameterError } from '../errors'\nimport { defaultAttributeName } from '../messages'\n\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\nconst ALPHA_RE = /^[A-Za-z]+$/\nconst ALPHA_NUM_RE = /^[A-Za-z0-9]+$/\nconst ALPHA_DASH_RE = /^[A-Za-z0-9_-]+$/\nconst ACCEPTED_VALUES: unknown[] = ['yes', 'on', 1, '1', true, 'true']\n\nfunction compileRegex(raw: string): RegExp {\n const match = /^\\/(.*)\\/([a-z]*)$/.exec(raw)\n try {\n return match ? new RegExp(match[1]!, match[2]) : new RegExp(raw)\n } catch (error) {\n throw new InvalidRuleParameterError('regex', raw, error instanceof Error ? error.message : String(error))\n }\n}\n\n/**\n * Shapes a string must have before it counts as a date. Date.parse alone is far too lenient (V8 reads \"1\" as the\n * year 2001), so a value needs an ISO date, a slashed/dotted/dashed day-month-year, or a month name with a number.\n */\nconst DATE_SHAPES = [\n /^\\d{4}-\\d{1,2}-\\d{1,2}(?:[T\\s].*)?$/,\n /^\\d{1,2}[/.-]\\d{1,2}[/.-]\\d{2,4}(?:\\s.*)?$/,\n /^(?=.*\\d).*\\b(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]*\\b/i,\n]\nconst DATE_ONLY_RE = /^(\\d{4})-(\\d{2})-(\\d{2})$/\n\n/**\n * Parses a user-supplied date string to epoch milliseconds, or NaN. A bare YYYY-MM-DD means local midnight, like\n * PHP's strtotime, so it compares sensibly against `today`/`tomorrow`.\n */\nfunction parseDate(value: string): number {\n const trimmed = value.trim()\n if (!DATE_SHAPES.some((shape) => shape.test(trimmed))) return Number.NaN\n const dateOnly = DATE_ONLY_RE.exec(trimmed)\n if (dateOnly) {\n const [, y, m, d] = dateOnly.map(Number) as [number, number, number, number]\n const local = new Date(y, m - 1, d)\n return local.getMonth() === m - 1 && local.getDate() === d ? local.getTime() : Number.NaN\n }\n return Date.parse(trimmed)\n}\n\nfunction startOfDay(offsetDays: number): number {\n const date = new Date()\n date.setHours(0, 0, 0, 0)\n date.setDate(date.getDate() + offsetDays)\n return date.getTime()\n}\n\nconst RELATIVE_RE = /^([+-]\\d+)\\s*(second|minute|hour|day|week|month|year)s?$/i\n\n/** strtotime's keywords (today, tomorrow, yesterday, now) and \"+N unit\"/\"-N unit\" offsets from now, or undefined. */\nfunction relativeDate(param: string): number | undefined {\n switch (param.trim().toLowerCase()) {\n case 'now':\n return Date.now()\n case 'today':\n return startOfDay(0)\n case 'tomorrow':\n return startOfDay(1)\n case 'yesterday':\n return startOfDay(-1)\n }\n const match = RELATIVE_RE.exec(param.trim())\n if (!match) return undefined\n const amount = Number(match[1])\n const date = new Date()\n switch (match[2]!.toLowerCase()) {\n case 'second':\n date.setSeconds(date.getSeconds() + amount)\n break\n case 'minute':\n date.setMinutes(date.getMinutes() + amount)\n break\n case 'hour':\n date.setHours(date.getHours() + amount)\n break\n case 'day':\n date.setDate(date.getDate() + amount)\n break\n case 'week':\n date.setDate(date.getDate() + amount * 7)\n break\n case 'month':\n date.setMonth(date.getMonth() + amount)\n break\n case 'year':\n date.setFullYear(date.getFullYear() + amount)\n break\n }\n return date.getTime()\n}\n\n/** An attribute path such as \"starts_at\" or \"event.starts_at\". */\nconst FIELD_REFERENCE_RE = /^[A-Za-z_][\\w-]*(?:\\.[\\w-]+)*$/\n\n/**\n * Resolves a before/after parameter, in order: another field's date value, a relative keyword/offset, a literal\n * date. A parameter shaped like a field name whose field is missing or not a date gives NaN (the user's value\n * fails). Anything else that can't be parsed is a mistake in the rule itself, so it throws a 'Server' error\n * instead of blaming the user's input.\n */\nfunction resolveDateParam(rule: string, param: string, data: Record<string, unknown>): number {\n const fieldValue = Arr.get<unknown>(data, param)\n if (typeof fieldValue === 'string') {\n const parsed = parseDate(fieldValue)\n if (!Number.isNaN(parsed)) return parsed\n }\n const relative = relativeDate(param)\n if (relative !== undefined) return relative\n const literal = parseDate(param)\n if (!Number.isNaN(literal)) return literal\n if (FIELD_REFERENCE_RE.test(param)) return Number.NaN\n throw new InvalidRuleParameterError(rule, param, 'expected a date, today/tomorrow/yesterday/now, \"+N unit\", or a field name')\n}\n\nfunction compareDate(ctx: RuleContext, rule: 'before' | 'after'): boolean {\n const target = resolveDateParam(rule, ctx.parameters[0] ?? '', ctx.data)\n if (typeof ctx.value !== 'string') return false\n const value = parseDate(ctx.value)\n if (Number.isNaN(value) || Number.isNaN(target)) return false\n return rule === 'before' ? value < target : value > target\n}\n\nexport const formatRules: Record<string, BuiltinRule> = {\n email: { validate: (ctx) => typeof ctx.value === 'string' && EMAIL_RE.test(ctx.value), messageKey: () => 'email' },\n url: {\n validate: (ctx) => {\n if (typeof ctx.value !== 'string') return false\n try {\n new URL(ctx.value)\n return true\n } catch {\n return false\n }\n },\n messageKey: () => 'url',\n },\n uuid: { validate: (ctx) => typeof ctx.value === 'string' && UUID_RE.test(ctx.value), messageKey: () => 'uuid' },\n alpha: { validate: (ctx) => typeof ctx.value === 'string' && ALPHA_RE.test(ctx.value), messageKey: () => 'alpha' },\n alpha_num: {\n validate: (ctx) => typeof ctx.value === 'string' && ALPHA_NUM_RE.test(ctx.value),\n messageKey: () => 'alpha_num',\n },\n alpha_dash: {\n validate: (ctx) => typeof ctx.value === 'string' && ALPHA_DASH_RE.test(ctx.value),\n messageKey: () => 'alpha_dash',\n },\n regex: {\n validate: (ctx) => typeof ctx.value === 'string' && compileRegex(ctx.parameters[0] ?? '').test(ctx.value),\n messageKey: () => 'regex',\n },\n confirmed: {\n validate: (ctx: RuleContext) => ctx.value === Arr.get(ctx.data, `${ctx.attribute}_confirmation`),\n messageKey: () => 'confirmed',\n },\n same: {\n validate: (ctx) => ctx.value === Arr.get(ctx.data, ctx.parameters[0] ?? ''),\n messageKey: () => 'same',\n replacements: (ctx) => ({ other: defaultAttributeName(ctx.parameters[0] ?? '') }),\n },\n different: {\n validate: (ctx) => ctx.value !== Arr.get(ctx.data, ctx.parameters[0] ?? ''),\n messageKey: () => 'different',\n replacements: (ctx) => ({ other: defaultAttributeName(ctx.parameters[0] ?? '') }),\n },\n accepted: { implicit: true, validate: (ctx) => ACCEPTED_VALUES.includes(ctx.value), messageKey: () => 'accepted' },\n digits: {\n validate: (ctx) =>\n typeof ctx.value !== 'object' && new RegExp(`^\\\\d{${ctx.parameters[0]}}$`).test(String(ctx.value)),\n messageKey: () => 'digits',\n replacements: (ctx) => ({ digits: ctx.parameters[0] ?? '' }),\n },\n date: {\n validate: (ctx) => typeof ctx.value === 'string' && !Number.isNaN(parseDate(ctx.value)),\n messageKey: () => 'date',\n },\n before: {\n validate: (ctx) => compareDate(ctx, 'before'),\n messageKey: () => 'before',\n replacements: (ctx) => ({ date: ctx.parameters[0] ?? '' }),\n },\n after: {\n validate: (ctx) => compareDate(ctx, 'after'),\n messageKey: () => 'after',\n replacements: (ctx) => ({ date: ctx.parameters[0] ?? '' }),\n },\n}\n","import { Arr } from '@orieljs/support'\nimport type { BuiltinRule, RuleContext } from '../parse'\nimport { isEmptyValue } from '../parse'\n\nfunction isFieldPresent(field: string, data: Record<string, unknown>): boolean {\n return Arr.has(data, field) && !isEmptyValue(Arr.get(data, field))\n}\n\nfunction anyPresent(fields: string[], data: Record<string, unknown>): boolean {\n return fields.some((field) => isFieldPresent(field, data))\n}\n\nfunction allPresent(fields: string[], data: Record<string, unknown>): boolean {\n return fields.every((field) => isFieldPresent(field, data))\n}\n\nexport const presenceRules: Record<string, BuiltinRule> = {\n required: {\n implicit: true,\n validate: (ctx: RuleContext) => !isEmptyValue(ctx.value),\n messageKey: () => 'required',\n },\n required_if: {\n implicit: true,\n validate: (ctx: RuleContext) => {\n const [other, ...values] = ctx.parameters\n const applies = values.includes(String(Arr.get(ctx.data, other)))\n return !applies || !isEmptyValue(ctx.value)\n },\n messageKey: () => 'required_if',\n replacements: (ctx) => ({ other: ctx.parameters[0] ?? '', value: ctx.parameters.slice(1).join(', ') }),\n },\n required_unless: {\n implicit: true,\n validate: (ctx: RuleContext) => {\n const [other, ...values] = ctx.parameters\n const applies = !values.includes(String(Arr.get(ctx.data, other)))\n return !applies || !isEmptyValue(ctx.value)\n },\n messageKey: () => 'required_unless',\n replacements: (ctx) => ({ other: ctx.parameters[0] ?? '', values: ctx.parameters.slice(1).join(', ') }),\n },\n required_with: {\n implicit: true,\n validate: (ctx: RuleContext) => !anyPresent(ctx.parameters, ctx.data) || !isEmptyValue(ctx.value),\n messageKey: () => 'required_with',\n replacements: (ctx) => ({ values: ctx.parameters.join(' / ') }),\n },\n required_with_all: {\n implicit: true,\n validate: (ctx: RuleContext) => !allPresent(ctx.parameters, ctx.data) || !isEmptyValue(ctx.value),\n messageKey: () => 'required_with_all',\n replacements: (ctx) => ({ values: ctx.parameters.join(' / ') }),\n },\n required_without: {\n implicit: true,\n validate: (ctx: RuleContext) => ctx.parameters.every((f) => isFieldPresent(f, ctx.data)) || !isEmptyValue(ctx.value),\n messageKey: () => 'required_without',\n replacements: (ctx) => ({ values: ctx.parameters.join(' / ') }),\n },\n required_without_all: {\n implicit: true,\n validate: (ctx: RuleContext) => anyPresent(ctx.parameters, ctx.data) || !isEmptyValue(ctx.value),\n messageKey: () => 'required_without_all',\n replacements: (ctx) => ({ values: ctx.parameters.join(' / ') }),\n },\n}\n","import type { BuiltinRule } from '../parse'\n\nconst BOOLEAN_VALUES: unknown[] = [true, false, 0, 1, '0', '1']\n\n/** PHP's is_numeric for strings: optional surrounding whitespace and sign, decimal digits, optional exponent. */\nconst NUMERIC_STRING_RE = /^\\s*[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?\\s*$/\n\n/**\n * Laravel's `numeric` (PHP is_numeric): a finite number, or a decimal string. Unlike `Number()`, it rejects\n * \"Infinity\", hex/binary/octal literals (\"0x1F\", \"0b101\", \"0o7\") and the empty string.\n */\nexport function isNumeric(value: unknown): boolean {\n if (typeof value === 'number') return Number.isFinite(value)\n return typeof value === 'string' && NUMERIC_STRING_RE.test(value)\n}\n\nexport const typeRules: Record<string, BuiltinRule> = {\n string: { validate: (ctx) => typeof ctx.value === 'string', messageKey: () => 'string' },\n integer: {\n validate: (ctx) => typeof ctx.value !== 'object' && /^-?\\d+$/.test(String(ctx.value).trim()),\n messageKey: () => 'integer',\n },\n numeric: {\n validate: (ctx) => isNumeric(ctx.value),\n messageKey: () => 'numeric',\n },\n boolean: { validate: (ctx) => BOOLEAN_VALUES.includes(ctx.value), messageKey: () => 'boolean' },\n array: { validate: (ctx) => Array.isArray(ctx.value), messageKey: () => 'array' },\n}\n","import type { BuiltinRule, RuleContext } from '../parse'\nimport { isUploadedFileLike } from '../parse'\nimport { isNumeric } from './type'\n\ntype SizeType = 'numeric' | 'array' | 'file' | 'string'\n\nfunction hasAny(ctx: RuleContext, names: string[]): boolean {\n return names.some((name) => ctx.ruleNames.includes(name))\n}\n\n/** A JSON object is a PHP associative array, so it's counted like one. */\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null) return false\n const proto: unknown = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n}\n\n/**\n * What a size rule measures and which message family it reports, decided in one place so the check and the\n * message always agree (Laravel's getSize + getAttributeType):\n * - numeric/integer rule: the number itself (a non-numeric value falls back to its string length, which the\n * numeric rule rejects anyway);\n * - an array (or plain object): its item count;\n * - an uploaded file: its size in fractional kilobytes;\n * - a file/image rule on something that isn't a file: NaN, so every size comparison fails;\n * - anything else: the length of its string form (a number without a numeric rule counts its digits).\n */\nfunction measure(ctx: RuleContext): { type: SizeType; size: number } {\n const { value } = ctx\n if (hasAny(ctx, ['numeric', 'integer'])) {\n return { type: 'numeric', size: isNumeric(value) ? Number(value) : stringLength(value) }\n }\n if (Array.isArray(value)) return { type: 'array', size: value.length }\n if (isUploadedFileLike(value)) return { type: 'file', size: value.size / 1024 }\n if (hasAny(ctx, ['file', 'image'])) return { type: 'file', size: Number.NaN }\n if (isPlainObject(value)) return { type: 'array', size: Object.keys(value).length }\n if (hasAny(ctx, ['array'])) return { type: 'array', size: stringLength(value) }\n return { type: 'string', size: stringLength(value) }\n}\n\nfunction stringLength(value: unknown): number {\n if (value === null || value === undefined) return 0\n return [...String(value)].length\n}\n\nfunction sizeOf(ctx: RuleContext): number {\n return measure(ctx).size\n}\n\nfunction sizeType(ctx: RuleContext): SizeType {\n return measure(ctx).type\n}\n\nexport const sizeRules: Record<string, BuiltinRule> = {\n max: {\n validate: (ctx) => sizeOf(ctx) <= Number(ctx.parameters[0]),\n messageKey: (ctx) => `max.${sizeType(ctx)}`,\n replacements: (ctx) => ({ max: ctx.parameters[0] ?? '' }),\n },\n min: {\n validate: (ctx) => sizeOf(ctx) >= Number(ctx.parameters[0]),\n messageKey: (ctx) => `min.${sizeType(ctx)}`,\n replacements: (ctx) => ({ min: ctx.parameters[0] ?? '' }),\n },\n between: {\n validate: (ctx) => {\n const size = sizeOf(ctx)\n return size >= Number(ctx.parameters[0]) && size <= Number(ctx.parameters[1])\n },\n messageKey: (ctx) => `between.${sizeType(ctx)}`,\n replacements: (ctx) => ({ min: ctx.parameters[0] ?? '', max: ctx.parameters[1] ?? '' }),\n },\n size: {\n validate: (ctx) => sizeOf(ctx) === Number(ctx.parameters[0]),\n messageKey: (ctx) => `size.${sizeType(ctx)}`,\n replacements: (ctx) => ({ size: ctx.parameters[0] ?? '' }),\n },\n in: { validate: (ctx) => ctx.parameters.includes(String(ctx.value)), messageKey: () => 'in' },\n not_in: { validate: (ctx) => !ctx.parameters.includes(String(ctx.value)), messageKey: () => 'not_in' },\n}\n","import type { BuiltinRule } from './parse'\nimport { databaseRules } from './rules/database'\nimport { fileRules } from './rules/file'\nimport { formatRules } from './rules/format'\nimport { presenceRules } from './rules/presence'\nimport { sizeRules } from './rules/size'\nimport { typeRules } from './rules/type'\n\n/** Every built-in rule, merged. Later tasks (database rules) add their own spread here. */\nexport const builtinRules: Record<string, BuiltinRule> = {\n ...presenceRules,\n ...typeRules,\n ...formatRules,\n ...sizeRules,\n ...fileRules,\n ...databaseRules,\n}\n","import type { ValidationRule } from '@orieljs/contracts'\nimport { applyReplacements, DEFAULT_MESSAGES, defaultAttributeName } from './messages'\nimport { guessColumn, matchingRecordExists } from './rules/database'\n\n/**\n * Base for the fluent builders. Each one reports under a built-in rule name (`in`, `unique`, `exists`), so when it\n * runs inside a Validator its failure goes through exactly the same lookup as the string rule: custom messages\n * (\"email.unique\", \"items.*.email.unique\", \"unique\"), custom attributes, then the default text. Called directly\n * as a plain ValidationRule, validate() fails with the default English message.\n */\nexport abstract class BuiltinRuleObject implements ValidationRule {\n abstract readonly ruleName: string\n\n abstract passes(attribute: string, value: unknown, data: Record<string, unknown>, expandedFromWildcard?: boolean): boolean | Promise<boolean>\n\n // Declares all 4 contract parameters so a subclass's inferred type (from `Rule.in(...)` etc.) still accepts a\n // call with the full 4-arg ValidationRule.validate signature, as Rule.test.ts makes.\n async validate(attribute: string, value: unknown, fail: (message: string) => void, data: Record<string, unknown>, expandedFromWildcard = false): Promise<void> {\n if (await this.passes(attribute, value, data, expandedFromWildcard)) return\n fail(applyReplacements(DEFAULT_MESSAGES[this.ruleName]!, { attribute: defaultAttributeName(attribute) }))\n }\n}\n\nclass InRule extends BuiltinRuleObject {\n readonly ruleName = 'in'\n\n constructor(private readonly values: readonly unknown[]) {\n super()\n }\n\n passes(_attribute: string, value: unknown): boolean {\n return this.values.map(String).includes(String(value))\n }\n}\n\n/** Structural shape of Database's Model — duck-typed so this package never imports `@orieljs/database` (B27). */\ninterface ModelInstanceLike {\n getKey(): unknown\n getKeyName(): string\n}\n\nfunction isModelInstance(value: unknown): value is ModelInstanceLike {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as ModelInstanceLike).getKey === 'function' &&\n typeof (value as ModelInstanceLike).getKeyName === 'function'\n )\n}\n\nclass UniqueRule extends BuiltinRuleObject {\n readonly ruleName = 'unique'\n private exceptId: unknown\n private idColumnName: string | undefined\n\n constructor(\n private readonly table: string,\n private readonly column?: string,\n ) {\n super()\n }\n\n /**\n * Excludes the current record from the uniqueness check. Laravel's `Rule::unique('users')->ignore($user)` accepts\n * a model directly (the common case: \"update your profile without changing your email\"), so a model instance is\n * bound by its key (`getKey()`/`getKeyName()`), not the object itself — the object would reach the query builder\n * as an opaque value and either be rejected by the driver or stringified (B27). A plain id still works as before;\n * null (or \"NULL\") excludes nothing.\n */\n ignore(id: unknown, idColumn?: string): this {\n if (isModelInstance(id)) {\n this.exceptId = id.getKey()\n this.idColumnName = idColumn ?? id.getKeyName()\n } else {\n this.exceptId = id\n this.idColumnName = idColumn ?? 'id'\n }\n return this\n }\n\n async passes(attribute: string, value: unknown, _data?: Record<string, unknown>, expandedFromWildcard = false): Promise<boolean> {\n const column = this.column ?? guessColumn(attribute, expandedFromWildcard)\n return !(await matchingRecordExists(this.table, column, value, this.exceptId, this.idColumnName ?? 'id'))\n }\n}\n\nclass ExistsRule extends BuiltinRuleObject {\n readonly ruleName = 'exists'\n\n constructor(\n private readonly table: string,\n private readonly column?: string,\n ) {\n super()\n }\n\n passes(attribute: string, value: unknown, _data?: Record<string, unknown>, expandedFromWildcard = false): Promise<boolean> {\n return matchingRecordExists(this.table, this.column ?? guessColumn(attribute, expandedFromWildcard), value)\n }\n}\n\n/** Fluent rule-object builders, for when a plain string rule can't express what's needed (e.g. .ignore()). */\nexport const Rule = {\n in: (values: readonly unknown[]): InRule => new InRule(values),\n unique: (table: string, column?: string): UniqueRule => new UniqueRule(table, column),\n exists: (table: string, column?: string): ExistsRule => new ExistsRule(table, column),\n}\n","import type { Rules, Validator } from '@orieljs/contracts'\nimport { Arr } from '@orieljs/support'\nimport { UnknownValidationRuleError, ValidationErrorImpl } from './errors'\nimport { MessageBagImpl } from './MessageBag'\nimport { BuiltinRuleObject } from './Rule'\nimport { applyReplacements, DEFAULT_MESSAGES, defaultAttributeName } from './messages'\nimport type { BuiltinRule, ParsedRule, RuleContext } from './parse'\nimport { expandWildcardKeys, parseRuleSpec, UNSAFE_KEYS } from './parse'\n\nconst SKIPPED_MODIFIERS = new Set(['bail', 'nullable', 'sometimes'])\n\n/**\n * Rebuilds a nested structure from flat dot-paths, the way Laravel's validated() does for wildcard fields.\n * `Arr.undot` (from @orieljs/support) always builds plain objects; it can't know \"items.0\"/\"items.1\" should\n * become an array. This walks the same way, then promotes any container it created itself whose keys are exactly\n * \"0\", \"1\", \"2\", … in order into a real array. Leaf values copied from the input (a Date, an uploaded file, an\n * object that happens to have \"0\"/\"1\" keys) are returned untouched, by identity. A path with a segment in\n * UNSAFE_KEYS is dropped, so nothing can be written through to Object.prototype. The input is never mutated.\n */\nfunction buildNested(flat: Record<string, unknown>): Record<string, unknown> {\n const root: Record<string, unknown> = {}\n const created = new Set<object>([root])\n for (const [path, value] of Object.entries(flat)) {\n const parts = path.split('.')\n if (parts.some((part) => UNSAFE_KEYS.has(part))) continue\n let current = root\n for (const part of parts.slice(0, -1)) {\n const existing = Object.hasOwn(current, part) ? current[part] : undefined\n if (typeof existing === 'object' && existing !== null && created.has(existing)) {\n current = existing as Record<string, unknown>\n continue\n }\n const container = cloneContainer(existing)\n created.add(container)\n current[part] = container\n current = container\n }\n current[parts.at(-1)!] = value\n }\n return arrayify(root, created) as Record<string, unknown>\n}\n\nfunction isPlainContainer(value: unknown): value is Record<string, unknown> {\n if (Array.isArray(value)) return true\n if (typeof value !== 'object' || value === null) return false\n const proto: unknown = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n}\n\n/**\n * A fresh container to write a child path into. When a parent key was already copied from the input (rules on both\n * \"user\" and \"user.name\"), its plain contents are kept (Laravel returns the whole parent) but copied, so the input\n * is never mutated. Anything else (missing, a scalar, a class instance) starts empty.\n */\nfunction cloneContainer(existing: unknown): Record<string, unknown> {\n const container: Record<string, unknown> = {}\n if (!isPlainContainer(existing)) return container\n for (const [key, value] of Object.entries(existing)) {\n if (!UNSAFE_KEYS.has(key)) container[key] = value\n }\n return container\n}\n\nfunction arrayify(node: unknown, created: ReadonlySet<object>): unknown {\n if (node === null || typeof node !== 'object' || !created.has(node)) return node\n const entries = Object.entries(node as Record<string, unknown>).map(([k, v]) => [k, arrayify(v, created)] as const)\n const keys = entries.map(([k]) => k)\n const isArrayLike = keys.length > 0 && keys.every((k, i) => k === String(i))\n return isArrayLike ? entries.map(([, v]) => v) : Object.fromEntries(entries)\n}\n\n/**\n * Runs each field's rules the way Laravel's Validator does:\n * - a missing key, or a string that is blank after trimming, only runs implicit rules (the required* family and\n * accepted); every other rule, including ValidationRule objects, is skipped for it;\n * - an explicit null runs every rule unless the field is `nullable` (then only implicit rules run), so\n * `{ age: null }` still fails `integer`;\n * - `sometimes` skips a missing field entirely;\n * - a field stops validating after its first failure under `bail`, or after any implicit rule fails.\n */\nexport class ValidatorImpl implements Validator {\n private bag: MessageBagImpl | undefined\n private ranPromise: Promise<boolean> | undefined\n private readonly afterCallbacks: Array<(validator: Validator) => void | Promise<void>> = []\n\n constructor(\n private readonly data: Record<string, unknown>,\n private readonly rules: Rules,\n private readonly customMessages: Record<string, string>,\n private readonly customAttributes: Record<string, string>,\n private readonly registry: Record<string, BuiltinRule>,\n private readonly errorBagName = 'default',\n ) {}\n\n after(callback: (validator: Validator) => void | Promise<void>): this {\n this.afterCallbacks.push(callback)\n return this\n }\n\n /** Not part of the Validator contract — lets an after() hook add a failure (MessageBag itself is read-only). */\n fail(field: string, message: string): void {\n this.bag ??= new MessageBagImpl()\n this.bag.add(field, message)\n }\n\n async passes(): Promise<boolean> {\n this.ranPromise ??= this.run()\n return this.ranPromise\n }\n\n async fails(): Promise<boolean> {\n return !(await this.passes())\n }\n\n errors(): MessageBagImpl {\n return this.bag ?? new MessageBagImpl()\n }\n\n async validated<T = Record<string, unknown>>(): Promise<T> {\n if (!(await this.passes())) throw new ValidationErrorImpl(this.bag!.toObject(), this.errorBagName)\n const flat: Record<string, unknown> = {}\n for (const pattern of Object.keys(this.rules)) {\n for (const field of this.fieldsFor(pattern)) {\n if (Arr.has(this.data, field)) flat[field] = Arr.get(this.data, field)\n }\n }\n return buildNested(flat) as T\n }\n\n private fieldsFor(pattern: string): string[] {\n return pattern.includes('*') ? expandWildcardKeys(pattern, this.data) : [pattern]\n }\n\n private async run(): Promise<boolean> {\n this.bag = new MessageBagImpl()\n\n for (const [pattern, spec] of Object.entries(this.rules)) {\n const parsed = parseRuleSpec(spec)\n const names = parsed.filter((r): r is Extract<ParsedRule, { kind: 'named' }> => r.kind === 'named').map((r) => r.name)\n const bail = names.includes('bail')\n const nullable = names.includes('nullable')\n const sometimes = names.includes('sometimes')\n\n for (const field of this.fieldsFor(pattern)) {\n const present = Arr.has(this.data, field)\n if (sometimes && !present) continue\n\n const value = Arr.get(this.data, field)\n const isNull = value === null || value === undefined\n const isBlank = typeof value === 'string' && value.trim() === ''\n\n for (const rule of parsed) {\n if (rule.kind === 'named' && SKIPPED_MODIFIERS.has(rule.name)) continue\n const implicit = rule.kind === 'named' && (this.registry[rule.name]?.implicit ?? false)\n // Laravel's presentOrRuleIsImplicit: a missing key or a blank string only runs implicit rules.\n if (!implicit && (!present || isBlank)) continue\n // Laravel's isNotNullIfMarkedAsNullable: nullable + null only runs implicit rules.\n if (!implicit && nullable && isNull) continue\n\n const message = await this.runRule(rule, field, pattern, value, names)\n if (message !== undefined) {\n this.bag.add(field, message)\n // Laravel's shouldStopValidating: bail stops at the first failure; a failed implicit rule always stops.\n if (bail || implicit) break\n }\n }\n }\n }\n\n for (const callback of this.afterCallbacks) await callback(this)\n return this.bag.isEmpty()\n }\n\n private async runRule(\n rule: ParsedRule,\n field: string,\n pattern: string,\n value: unknown,\n ruleNames: string[],\n ): Promise<string | undefined> {\n const expanded = pattern.includes('*')\n if (rule.kind === 'object') {\n if (rule.rule instanceof BuiltinRuleObject) {\n if (await rule.rule.passes(field, value, this.data, expanded)) return undefined\n const ctx = { attribute: field, expandedFromWildcard: expanded, value, parameters: [], data: this.data, ruleNames }\n return this.failureMessage(rule.rule.ruleName, this.registry[rule.rule.ruleName], ctx, pattern)\n }\n let failure: string | undefined\n await rule.rule.validate(field, value, (message) => { failure = message }, this.data)\n return failure\n }\n\n const builtin = this.registry[rule.name]\n if (!builtin) throw new UnknownValidationRuleError(rule.name)\n\n const ctx = { attribute: field, expandedFromWildcard: expanded, value, parameters: rule.parameters, data: this.data, ruleNames }\n if (await builtin.validate(ctx)) return undefined\n return this.failureMessage(rule.name, builtin, ctx, pattern)\n }\n\n /** Custom message (concrete field, then wildcard pattern, then rule name) or the default, with :attribute filled. */\n private failureMessage(name: string, builtin: BuiltinRule | undefined, ctx: RuleContext, pattern: string): string {\n const field = ctx.attribute\n const template =\n this.customMessages[`${field}.${name}`] ??\n this.customMessages[`${pattern}.${name}`] ??\n this.customMessages[name] ??\n DEFAULT_MESSAGES[builtin?.messageKey(ctx) ?? name] ??\n builtin?.defaultMessage ??\n 'The :attribute field is invalid.'\n\n const display = this.customAttributes[field] ?? this.customAttributes[pattern] ?? defaultAttributeName(field)\n return applyReplacements(template, { attribute: display, ...(builtin?.replacements?.(ctx) ?? {}) })\n }\n}\n","import type { RuleCallback, Rules, ValidationFactory } from '@orieljs/contracts'\nimport type { BuiltinRule } from './parse'\nimport { builtinRules } from './registry'\nimport { ValidatorImpl } from './Validator'\n\nexport class ValidationFactoryImpl implements ValidationFactory {\n private readonly extended: Record<string, BuiltinRule> = {}\n\n make(\n data: Record<string, unknown>,\n rules: Rules,\n messages: Record<string, string> = {},\n attributes: Record<string, string> = {},\n ): ValidatorImpl {\n return new ValidatorImpl(data, rules, messages, attributes, { ...builtinRules, ...this.extended })\n }\n\n extend(name: string, callback: RuleCallback, message?: string): void {\n this.extended[name] = {\n validate: (ctx) => callback(ctx.attribute, ctx.value, ctx.parameters, ctx.data),\n messageKey: () => name,\n defaultMessage: message ?? 'The :attribute field is invalid.',\n }\n }\n}\n","import type { ValidationFactory } from '@orieljs/contracts'\nimport { ValidationFactory as ValidationFactoryToken } from '@orieljs/contracts'\nimport { facade } from '@orieljs/support'\n\n/** Laravel's Validator facade: Validator.make(...)/Validator.extend(...), proxied to the resolved ValidationFactory. */\nexport const Validator = facade<ValidationFactory>(ValidationFactoryToken)\n","import { ValidationFactory as ValidationFactoryToken } from '@orieljs/contracts'\nimport { ServiceProvider } from '@orieljs/support'\nimport { ValidationFactoryImpl } from './ValidationFactory'\n\nexport class ValidationServiceProvider extends ServiceProvider {\n override register(): void {\n this.app.singleton(ValidationFactoryToken, () => new ValidationFactoryImpl())\n }\n}\n"],"mappings":"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","names":["inject","Arr","Arr","Arr","Arr","Arr","Arr","ctx","ValidationFactoryToken","ValidationFactoryToken"]}
1
+ {"version":3,"sources":["../errors.ts","../FormRequest.ts","../messages.ts","../MessageBag.ts","../rules/auth.ts","../rules/database.ts","../parse.ts","../rules/file.ts","../rules/format.ts","../rules/presence.ts","../rules/type.ts","../rules/size.ts","../registry.ts","../rules/password.ts","../Rule.ts","../Validator.ts","../ValidationFactory.ts","../facade.ts","../ValidationServiceProvider.ts"],"sourcesContent":["import type { OrielError, ValidationError } from '@orieljs/contracts'\n\nexport class ValidationErrorImpl extends Error implements ValidationError {\n readonly kind = 'Validation' as const\n readonly status = 422\n override readonly name = 'ValidationError'\n constructor(\n readonly errors: Record<string, string[]>,\n readonly errorBag = 'default',\n readonly redirectTo?: string,\n ) {\n super('The given data was invalid.')\n }\n}\n\n/**\n * Laravel's ValidationException, for failing a request by hand:\n * `throw ValidationException.withMessages({ email: __('auth.failed') })`. Rendered like any validation error: 422 JSON,\n * or a redirect back with the errors.\n */\nexport class ValidationException extends ValidationErrorImpl {\n /** Messages per field, each a string or a list. */\n static withMessages(messages: Record<string, string | readonly string[]>): ValidationException {\n const errors = Object.fromEntries(Object.entries(messages).map(([field, list]) => [field, typeof list === 'string' ? [list] : [...list]]))\n return new ValidationException(errors)\n }\n\n constructor(errors: Record<string, string[]>, errorBag = 'default', redirectTo?: string) {\n super(errors, errorBag, redirectTo)\n this.message = summarize(errors)\n }\n}\n\n/** \"The first message. (and 2 more errors)\" (Laravel's ValidationException::summarize()). */\nfunction summarize(errors: Record<string, string[]>): string {\n const messages = Object.values(errors).flat()\n if (messages.length === 0) return 'The given data was invalid.'\n const more = messages.length - 1\n return more === 0 ? messages[0]! : `${messages[0]!} (and ${more} more ${more === 1 ? 'error' : 'errors'})`\n}\n\nexport class AuthorizationErrorImpl extends Error implements OrielError {\n readonly kind = 'Authorization' as const\n readonly status = 403\n override readonly name = 'AuthorizationError'\n constructor(message = 'This action is unauthorized.') {\n super(message)\n }\n}\n\nexport class UnknownValidationRuleError extends Error implements OrielError {\n readonly kind = 'Server' as const\n readonly status = 500\n override readonly name = 'UnknownValidationRuleError'\n constructor(name: string) {\n super(`Validation rule \"${name}\" is not registered. Register it with ValidationFactory.extend() first.`)\n }\n}\n\n/** A rule was written with a parameter it can't use (a bad regex, an unparseable date). A developer error, not a user one. */\nexport class InvalidRuleParameterError extends Error implements OrielError {\n readonly kind = 'Server' as const\n readonly status = 500\n override readonly name = 'InvalidRuleParameterError'\n constructor(rule: string, parameter: string, reason: string) {\n super(`Validation rule \"${rule}\" has an invalid parameter \"${parameter}\": ${reason}`)\n }\n}\n","import type { Rules } from '@orieljs/contracts'\nimport { HttpRequest, ValidationFactory } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport { AuthorizationErrorImpl } from './errors'\n\n/**\n * Mirrors Illuminate\\Foundation\\Http\\FormRequest, minus dependency injection by type (Oriel resolves the current\n * request and the ValidationFactory through inject(), never through constructor parameters — see spec §3 rule 5).\n * A subclass only has to implement rules(); authorize()/messages()/attributes() default to Laravel's own defaults.\n */\nexport abstract class FormRequest {\n abstract rules(): Rules\n\n authorize(): boolean | Promise<boolean> {\n return true\n }\n\n messages(): Record<string, string> {\n return {}\n }\n\n attributes(): Record<string, string> {\n return {}\n }\n\n /**\n * `const data = await StorePostRequest.validate()` (spec §4.3). Resolves the current request and the\n * ValidationFactory from the active container, runs authorize() first (throwing AuthorizationErrorImpl if it\n * returns false), then validates request.all() against rules()/messages()/attributes() and returns the typed\n * validated data (or throws the 422 ValidationError — see ValidatorImpl.validated()).\n */\n static async validate<T = Record<string, unknown>>(this: new () => FormRequest): Promise<T> {\n const instance = new this()\n if (!(await instance.authorize())) throw new AuthorizationErrorImpl()\n\n const request = inject(HttpRequest)\n const factory = inject(ValidationFactory)\n const validator = factory.make(request.all(), instance.rules(), instance.messages(), instance.attributes())\n return validator.validated<T>()\n }\n}\n","import { Str } from '@orieljs/support'\n\n/** Humanizes a (possibly dotted) attribute key, e.g. \"items.0.product_name\" -> \"items.0.product name\". */\nexport function defaultAttributeName(key: string): string {\n return key\n .split('.')\n .map((segment) => Str.snake(segment).replace(/_/g, ' '))\n .join('.')\n}\n\nexport function applyReplacements(template: string, replacements: Record<string, string>): string {\n return Object.entries(replacements).reduce((message, [key, value]) => message.replaceAll(`:${key}`, value), template)\n}\n\n/** Laravel's English lang/en/validation.php, reproduced as closely as possible (see plan Notes/assumptions). */\nexport const DEFAULT_MESSAGES: Record<string, string> = {\n required: 'The :attribute field is required.',\n required_if: 'The :attribute field is required when :other is :value.',\n required_unless: 'The :attribute field is required unless :other is in :values.',\n required_with: 'The :attribute field is required when :values is present.',\n required_with_all: 'The :attribute field is required when :values are present.',\n required_without: 'The :attribute field is required when :values is not present.',\n required_without_all: 'The :attribute field is required when none of :values are present.',\n string: 'The :attribute field must be a string.',\n integer: 'The :attribute field must be an integer.',\n numeric: 'The :attribute field must be a number.',\n boolean: 'The :attribute field must be true or false.',\n array: 'The :attribute field must be an array.',\n email: 'The :attribute field must be a valid email address.',\n url: 'The :attribute field must be a valid URL.',\n uuid: 'The :attribute field must be a valid UUID.',\n alpha: 'The :attribute field must only contain letters.',\n alpha_num: 'The :attribute field must only contain letters and numbers.',\n alpha_dash: 'The :attribute field must only contain letters, numbers, dashes and underscores.',\n regex: 'The :attribute field format is invalid.',\n lowercase: 'The :attribute field must be lowercase.',\n uppercase: 'The :attribute field must be uppercase.',\n current_password: 'The password is incorrect.',\n 'password.letters': 'The :attribute field must contain at least one letter.',\n 'password.mixed': 'The :attribute field must contain at least one uppercase and one lowercase letter.',\n 'password.numbers': 'The :attribute field must contain at least one number.',\n 'password.symbols': 'The :attribute field must contain at least one symbol.',\n confirmed: 'The :attribute field confirmation does not match.',\n same: 'The :attribute field must match :other.',\n different: 'The :attribute field must be different from :other.',\n accepted: 'The :attribute field must be accepted.',\n digits: 'The :attribute field must be :digits digits.',\n date: 'The :attribute field must be a valid date.',\n before: 'The :attribute field must be a date before :date.',\n after: 'The :attribute field must be a date after :date.',\n in: 'The selected :attribute is invalid.',\n not_in: 'The selected :attribute is invalid.',\n unique: 'The :attribute has already been taken.',\n exists: 'The selected :attribute is invalid.',\n file: 'The :attribute field must be a file.',\n image: 'The :attribute field must be an image.',\n mimes: 'The :attribute field must be a file of type: :values.',\n 'max.string': 'The :attribute field must not be greater than :max characters.',\n 'max.numeric': 'The :attribute field must not be greater than :max.',\n 'max.array': 'The :attribute field must not have more than :max items.',\n 'max.file': 'The :attribute field must not be greater than :max kilobytes.',\n 'min.string': 'The :attribute field must be at least :min characters.',\n 'min.numeric': 'The :attribute field must be at least :min.',\n 'min.array': 'The :attribute field must have at least :min items.',\n 'min.file': 'The :attribute field must be at least :min kilobytes.',\n 'between.string': 'The :attribute field must be between :min and :max characters.',\n 'between.numeric': 'The :attribute field must be between :min and :max.',\n 'between.array': 'The :attribute field must have between :min and :max items.',\n 'between.file': 'The :attribute field must be between :min and :max kilobytes.',\n 'size.string': 'The :attribute field must be :size characters.',\n 'size.numeric': 'The :attribute field must be :size.',\n 'size.array': 'The :attribute field must contain :size items.',\n 'size.file': 'The :attribute field must be :size kilobytes.',\n}\n","import type { MessageBag } from '@orieljs/contracts'\n\nexport class MessageBagImpl implements MessageBag {\n private readonly items: Record<string, string[]> = {}\n\n /** Not part of the MessageBag contract — used internally by ValidatorImpl and by after() hooks. */\n add(key: string, message: string): void {\n ;(this.items[key] ??= []).push(message)\n }\n\n has(key: string): boolean {\n return (this.items[key]?.length ?? 0) > 0\n }\n\n first(key?: string): string | undefined {\n if (key !== undefined) return this.items[key]?.[0]\n for (const messages of Object.values(this.items)) {\n if (messages[0] !== undefined) return messages[0]\n }\n return undefined\n }\n\n get(key: string): string[] {\n return this.items[key] ?? []\n }\n\n all(): string[] {\n return Object.values(this.items).flat()\n }\n\n isEmpty(): boolean {\n return Object.keys(this.items).length === 0\n }\n\n count(): number {\n return this.all().length\n }\n\n toObject(): Record<string, string[]> {\n return structuredClone(this.items)\n }\n}\n","import { AuthFactory, Hasher } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport type { BuiltinRule } from '../parse'\n\n/** `current_password` / `current_password:<guard>`: the value is the signed-in user's password (Laravel). */\nexport const authRules: Record<string, BuiltinRule> = {\n current_password: {\n validate: async (ctx) => {\n const guard = inject(AuthFactory).guard(ctx.parameters[0])\n if (await guard.guest()) return false\n const user = await guard.user()\n return user !== undefined && typeof ctx.value === 'string' && inject(Hasher).check(ctx.value, user.getAuthPassword())\n },\n messageKey: () => 'current_password',\n },\n}\n","import { DatabaseManager } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport type { BuiltinRule } from '../parse'\n\n/**\n * The column to query when a unique/exists rule doesn't name one: the attribute itself, except for a\n * wildcard-expanded field like \"items.0.email\", which checks the last non-numeric segment (\"email\") rather than a\n * column literally named after the path (Laravel's guessColumnForQuery).\n */\nexport function guessColumn(attribute: string, expandedFromWildcard = false): string {\n if (!expandedFromWildcard) return attribute\n return attribute.split('.').filter((segment) => !/^\\d+$/.test(segment)).at(-1) ?? attribute\n}\n\n/** Laravel's idiom `unique:users,email,NULL,id` (and an empty or null ignore) means \"exclude nothing\". */\nfunction isNoExcept(except: unknown): boolean {\n return except === undefined || except === null || except === '' || except === 'NULL'\n}\n\n/**\n * Shared query shape behind both `unique`/`exists` string rules and `Rule.unique()`/`Rule.exists()` (Review Focus\n * #2): resolve DatabaseManager, filter table/column on value, optionally exclude a record by idColumn/except, and\n * report whether any row matches. Kept in one place so a future fix to this path can't miss one of the two callers.\n */\nexport async function matchingRecordExists(\n table: string,\n column: string,\n value: unknown,\n except?: unknown,\n idColumn = 'id',\n): Promise<boolean> {\n const db = inject(DatabaseManager)\n let query = db.connection().table(table).where(column, value)\n if (!isNoExcept(except)) query = query.where(idColumn, '!=', except)\n return query.exists()\n}\n\nexport const databaseRules: Record<string, BuiltinRule> = {\n unique: {\n validate: async (ctx) => {\n const [table, column, except, idColumn] = ctx.parameters\n return !(await matchingRecordExists(table!, column || guessColumn(ctx.attribute, ctx.expandedFromWildcard), ctx.value, except, idColumn || 'id'))\n },\n messageKey: () => 'unique',\n },\n exists: {\n validate: async (ctx) => {\n const [table, column] = ctx.parameters\n return matchingRecordExists(table!, column || guessColumn(ctx.attribute, ctx.expandedFromWildcard), ctx.value)\n },\n messageKey: () => 'exists',\n },\n}\n","import type { ValidationRule } from '@orieljs/contracts'\nimport { Arr } from '@orieljs/support'\n\n/** Everything a single rule needs to validate one concrete field. */\nexport interface RuleContext {\n /** The concrete, wildcard-expanded field path, e.g. \"items.1.name\". */\n attribute: string\n /** True when `attribute` came from expanding a wildcard pattern such as \"items.*.email\". */\n expandedFromWildcard?: boolean\n value: unknown\n parameters: string[]\n data: Record<string, unknown>\n /** Every named rule attached to this field (for size-type resolution: numeric/array/file/string). */\n ruleNames: string[]\n}\n\nexport interface BuiltinRule {\n validate(ctx: RuleContext): boolean | Promise<boolean>\n /** Which DEFAULT_MESSAGES key to use, e.g. `max.${sizeType}`. Most rules return a constant name. */\n messageKey(ctx: RuleContext): string\n /** Extra :placeholder substitutions beyond :attribute (e.g. :max, :other, :values). */\n replacements?(ctx: RuleContext): Record<string, string>\n /** Used when messageKey() isn't in DEFAULT_MESSAGES (e.g. an extend()ed rule with a custom message). */\n defaultMessage?: string\n /** An extend()ed rule's own message: it wins over the default lines, as Laravel's fallback messages do. */\n message?: string\n /** Runs even when the value is missing, blank, or null under nullable (the required* family, and accepted); a failure stops the field. */\n implicit?: boolean\n}\n\nexport type ParsedRule =\n | { kind: 'named'; name: string; parameters: string[] }\n | { kind: 'object'; rule: ValidationRule }\n\nfunction splitParameters(name: string, raw: string): string[] {\n // regex/not_regex parameters are never comma-split, so a pattern containing a comma survives intact.\n return name === 'regex' || name === 'not_regex' ? [raw] : raw.split(',')\n}\n\nfunction splitOnce(value: string, separator: string): [string, string | undefined] {\n const index = value.indexOf(separator)\n return index === -1 ? [value, undefined] : [value.slice(0, index), value.slice(index + 1)]\n}\n\nexport function parseRuleSpec(spec: string | ReadonlyArray<string | ValidationRule>): ParsedRule[] {\n const items = typeof spec === 'string' ? spec.split('|') : spec\n return items\n .filter((item) => item !== '')\n .map((item): ParsedRule => {\n if (typeof item !== 'string') return { kind: 'object', rule: item }\n const [name, raw] = splitOnce(item, ':')\n return { kind: 'named', name, parameters: raw === undefined ? [] : splitParameters(name, raw) }\n })\n}\n\n/** Laravel's definition of \"empty\" for the required family: null, undefined, '' and []. false and 0 are NOT empty. */\nexport function isEmptyValue(value: unknown): boolean {\n if (value === null || value === undefined) return true\n if (typeof value === 'string') return value === ''\n if (Array.isArray(value)) return value.length === 0\n return false\n}\n\n/** Duck-types Contracts/Http's UploadedFile without importing @orieljs/http. */\nexport function isUploadedFileLike(value: unknown): value is {\n clientName: string\n mimeType: string\n size: number\n extension(): string\n arrayBuffer(): Promise<ArrayBuffer>\n} {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Record<string, unknown>).clientName === 'string' &&\n typeof (value as Record<string, unknown>).arrayBuffer === 'function'\n )\n}\n\n/**\n * Keys that must never be followed or written when walking user input: assigning through them reaches\n * Object.prototype (or a constructor) instead of a plain data slot. Mirrors the guard in Arr.set.\n */\nexport const UNSAFE_KEYS: ReadonlySet<string> = new Set(['__proto__', 'prototype', 'constructor'])\n\n/**\n * Expands a `*`-wildcard rule pattern (e.g. \"items.*.name\") into every concrete path present in `data`\n * (e.g. [\"items.0.name\", \"items.1.name\"]). A pattern with no `*` is returned unchanged. A `*` segment whose\n * container is missing, not an array and not a plain object expands to nothing for that branch (Review Focus #4:\n * every reported error is keyed by a concrete path, never the literal pattern). Object keys in UNSAFE_KEYS are\n * treated as absent, so a JSON body like {\"items\":{\"__proto__\":{...}}} never yields a path through the prototype.\n */\nexport function expandWildcardKeys(pattern: string, data: Record<string, unknown>): string[] {\n const segments = pattern.split('.')\n let paths = ['']\n for (const segment of segments) {\n const next: string[] = []\n for (const base of paths) {\n const prefix = base === '' ? '' : `${base}.`\n if (segment !== '*') {\n next.push(`${prefix}${segment}`)\n continue\n }\n const container = Arr.get<unknown>(data, base === '' ? undefined : base)\n if (Array.isArray(container)) {\n container.forEach((_, index) => next.push(`${prefix}${index}`))\n } else if (container !== null && typeof container === 'object') {\n Object.keys(container)\n .filter((key) => !UNSAFE_KEYS.has(key))\n .forEach((key) => next.push(`${prefix}${key}`))\n }\n }\n paths = next\n }\n return paths\n}\n","import type { BuiltinRule } from '../parse'\nimport { isUploadedFileLike } from '../parse'\n\nconst IMAGE_EXTENSIONS = new Set(['jpg', 'jpeg', 'png', 'bmp', 'gif', 'svg', 'webp'])\n\nexport const fileRules: Record<string, BuiltinRule> = {\n file: { validate: (ctx) => isUploadedFileLike(ctx.value), messageKey: () => 'file' },\n image: {\n validate: (ctx) => {\n if (!isUploadedFileLike(ctx.value)) return false\n if (ctx.value.mimeType.startsWith('image/')) return true\n return IMAGE_EXTENSIONS.has(ctx.value.extension().toLowerCase())\n },\n messageKey: () => 'image',\n },\n mimes: {\n validate: (ctx) => {\n if (!isUploadedFileLike(ctx.value)) return false\n const allowed = ctx.parameters.map((p) => p.toLowerCase())\n return allowed.includes(ctx.value.extension().toLowerCase())\n },\n messageKey: () => 'mimes',\n replacements: (ctx) => ({ values: ctx.parameters.join(', ') }),\n },\n}\n","import { Arr } from '@orieljs/support'\nimport type { BuiltinRule, RuleContext } from '../parse'\nimport { InvalidRuleParameterError } from '../errors'\nimport { defaultAttributeName } from '../messages'\n\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\nconst ALPHA_RE = /^[A-Za-z]+$/\nconst ALPHA_NUM_RE = /^[A-Za-z0-9]+$/\nconst ALPHA_DASH_RE = /^[A-Za-z0-9_-]+$/\nconst ACCEPTED_VALUES: unknown[] = ['yes', 'on', 1, '1', true, 'true']\n\nfunction compileRegex(raw: string): RegExp {\n const match = /^\\/(.*)\\/([a-z]*)$/.exec(raw)\n try {\n return match ? new RegExp(match[1]!, match[2]) : new RegExp(raw)\n } catch (error) {\n throw new InvalidRuleParameterError('regex', raw, error instanceof Error ? error.message : String(error))\n }\n}\n\n/**\n * Shapes a string must have before it counts as a date. Date.parse alone is far too lenient (V8 reads \"1\" as the\n * year 2001), so a value needs an ISO date, a slashed/dotted/dashed day-month-year, or a month name with a number.\n */\nconst DATE_SHAPES = [\n /^\\d{4}-\\d{1,2}-\\d{1,2}(?:[T\\s].*)?$/,\n /^\\d{1,2}[/.-]\\d{1,2}[/.-]\\d{2,4}(?:\\s.*)?$/,\n /^(?=.*\\d).*\\b(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]*\\b/i,\n]\nconst DATE_ONLY_RE = /^(\\d{4})-(\\d{2})-(\\d{2})$/\n\n/**\n * Parses a user-supplied date string to epoch milliseconds, or NaN. A bare YYYY-MM-DD means local midnight, like\n * PHP's strtotime, so it compares sensibly against `today`/`tomorrow`.\n */\nfunction parseDate(value: string): number {\n const trimmed = value.trim()\n if (!DATE_SHAPES.some((shape) => shape.test(trimmed))) return Number.NaN\n const dateOnly = DATE_ONLY_RE.exec(trimmed)\n if (dateOnly) {\n const [, y, m, d] = dateOnly.map(Number) as [number, number, number, number]\n const local = new Date(y, m - 1, d)\n return local.getMonth() === m - 1 && local.getDate() === d ? local.getTime() : Number.NaN\n }\n return Date.parse(trimmed)\n}\n\nfunction startOfDay(offsetDays: number): number {\n const date = new Date()\n date.setHours(0, 0, 0, 0)\n date.setDate(date.getDate() + offsetDays)\n return date.getTime()\n}\n\nconst RELATIVE_RE = /^([+-]\\d+)\\s*(second|minute|hour|day|week|month|year)s?$/i\n\n/** strtotime's keywords (today, tomorrow, yesterday, now) and \"+N unit\"/\"-N unit\" offsets from now, or undefined. */\nfunction relativeDate(param: string): number | undefined {\n switch (param.trim().toLowerCase()) {\n case 'now':\n return Date.now()\n case 'today':\n return startOfDay(0)\n case 'tomorrow':\n return startOfDay(1)\n case 'yesterday':\n return startOfDay(-1)\n }\n const match = RELATIVE_RE.exec(param.trim())\n if (!match) return undefined\n const amount = Number(match[1])\n const date = new Date()\n switch (match[2]!.toLowerCase()) {\n case 'second':\n date.setSeconds(date.getSeconds() + amount)\n break\n case 'minute':\n date.setMinutes(date.getMinutes() + amount)\n break\n case 'hour':\n date.setHours(date.getHours() + amount)\n break\n case 'day':\n date.setDate(date.getDate() + amount)\n break\n case 'week':\n date.setDate(date.getDate() + amount * 7)\n break\n case 'month':\n date.setMonth(date.getMonth() + amount)\n break\n case 'year':\n date.setFullYear(date.getFullYear() + amount)\n break\n }\n return date.getTime()\n}\n\n/** An attribute path such as \"starts_at\" or \"event.starts_at\". */\nconst FIELD_REFERENCE_RE = /^[A-Za-z_][\\w-]*(?:\\.[\\w-]+)*$/\n\n/**\n * Resolves a before/after parameter, in order: another field's date value, a relative keyword/offset, a literal\n * date. A parameter shaped like a field name whose field is missing or not a date gives NaN (the user's value\n * fails). Anything else that can't be parsed is a mistake in the rule itself, so it throws a 'Server' error\n * instead of blaming the user's input.\n */\nfunction resolveDateParam(rule: string, param: string, data: Record<string, unknown>): number {\n const fieldValue = Arr.get<unknown>(data, param)\n if (typeof fieldValue === 'string') {\n const parsed = parseDate(fieldValue)\n if (!Number.isNaN(parsed)) return parsed\n }\n const relative = relativeDate(param)\n if (relative !== undefined) return relative\n const literal = parseDate(param)\n if (!Number.isNaN(literal)) return literal\n if (FIELD_REFERENCE_RE.test(param)) return Number.NaN\n throw new InvalidRuleParameterError(rule, param, 'expected a date, today/tomorrow/yesterday/now, \"+N unit\", or a field name')\n}\n\nfunction compareDate(ctx: RuleContext, rule: 'before' | 'after'): boolean {\n const target = resolveDateParam(rule, ctx.parameters[0] ?? '', ctx.data)\n if (typeof ctx.value !== 'string') return false\n const value = parseDate(ctx.value)\n if (Number.isNaN(value) || Number.isNaN(target)) return false\n return rule === 'before' ? value < target : value > target\n}\n\nexport const formatRules: Record<string, BuiltinRule> = {\n email: { validate: (ctx) => typeof ctx.value === 'string' && EMAIL_RE.test(ctx.value), messageKey: () => 'email' },\n url: {\n validate: (ctx) => {\n if (typeof ctx.value !== 'string') return false\n try {\n new URL(ctx.value)\n return true\n } catch {\n return false\n }\n },\n messageKey: () => 'url',\n },\n uuid: { validate: (ctx) => typeof ctx.value === 'string' && UUID_RE.test(ctx.value), messageKey: () => 'uuid' },\n alpha: { validate: (ctx) => typeof ctx.value === 'string' && ALPHA_RE.test(ctx.value), messageKey: () => 'alpha' },\n alpha_num: {\n validate: (ctx) => typeof ctx.value === 'string' && ALPHA_NUM_RE.test(ctx.value),\n messageKey: () => 'alpha_num',\n },\n alpha_dash: {\n validate: (ctx) => typeof ctx.value === 'string' && ALPHA_DASH_RE.test(ctx.value),\n messageKey: () => 'alpha_dash',\n },\n lowercase: {\n validate: (ctx) => (typeof ctx.value === 'string' || typeof ctx.value === 'number') && String(ctx.value).toLowerCase() === String(ctx.value),\n messageKey: () => 'lowercase',\n },\n uppercase: {\n validate: (ctx) => (typeof ctx.value === 'string' || typeof ctx.value === 'number') && String(ctx.value).toUpperCase() === String(ctx.value),\n messageKey: () => 'uppercase',\n },\n regex: {\n validate: (ctx) => typeof ctx.value === 'string' && compileRegex(ctx.parameters[0] ?? '').test(ctx.value),\n messageKey: () => 'regex',\n },\n confirmed: {\n validate: (ctx: RuleContext) => ctx.value === Arr.get(ctx.data, `${ctx.attribute}_confirmation`),\n messageKey: () => 'confirmed',\n },\n same: {\n validate: (ctx) => ctx.value === Arr.get(ctx.data, ctx.parameters[0] ?? ''),\n messageKey: () => 'same',\n replacements: (ctx) => ({ other: defaultAttributeName(ctx.parameters[0] ?? '') }),\n },\n different: {\n validate: (ctx) => ctx.value !== Arr.get(ctx.data, ctx.parameters[0] ?? ''),\n messageKey: () => 'different',\n replacements: (ctx) => ({ other: defaultAttributeName(ctx.parameters[0] ?? '') }),\n },\n accepted: { implicit: true, validate: (ctx) => ACCEPTED_VALUES.includes(ctx.value), messageKey: () => 'accepted' },\n digits: {\n validate: (ctx) =>\n typeof ctx.value !== 'object' && new RegExp(`^\\\\d{${ctx.parameters[0]}}$`).test(String(ctx.value)),\n messageKey: () => 'digits',\n replacements: (ctx) => ({ digits: ctx.parameters[0] ?? '' }),\n },\n date: {\n validate: (ctx) => typeof ctx.value === 'string' && !Number.isNaN(parseDate(ctx.value)),\n messageKey: () => 'date',\n },\n before: {\n validate: (ctx) => compareDate(ctx, 'before'),\n messageKey: () => 'before',\n replacements: (ctx) => ({ date: ctx.parameters[0] ?? '' }),\n },\n after: {\n validate: (ctx) => compareDate(ctx, 'after'),\n messageKey: () => 'after',\n replacements: (ctx) => ({ date: ctx.parameters[0] ?? '' }),\n },\n}\n","import { Arr } from '@orieljs/support'\nimport type { BuiltinRule, RuleContext } from '../parse'\nimport { isEmptyValue } from '../parse'\n\nfunction isFieldPresent(field: string, data: Record<string, unknown>): boolean {\n return Arr.has(data, field) && !isEmptyValue(Arr.get(data, field))\n}\n\nfunction anyPresent(fields: string[], data: Record<string, unknown>): boolean {\n return fields.some((field) => isFieldPresent(field, data))\n}\n\nfunction allPresent(fields: string[], data: Record<string, unknown>): boolean {\n return fields.every((field) => isFieldPresent(field, data))\n}\n\nexport const presenceRules: Record<string, BuiltinRule> = {\n required: {\n implicit: true,\n validate: (ctx: RuleContext) => !isEmptyValue(ctx.value),\n messageKey: () => 'required',\n },\n required_if: {\n implicit: true,\n validate: (ctx: RuleContext) => {\n const [other, ...values] = ctx.parameters\n const applies = values.includes(String(Arr.get(ctx.data, other)))\n return !applies || !isEmptyValue(ctx.value)\n },\n messageKey: () => 'required_if',\n replacements: (ctx) => ({ other: ctx.parameters[0] ?? '', value: ctx.parameters.slice(1).join(', ') }),\n },\n required_unless: {\n implicit: true,\n validate: (ctx: RuleContext) => {\n const [other, ...values] = ctx.parameters\n const applies = !values.includes(String(Arr.get(ctx.data, other)))\n return !applies || !isEmptyValue(ctx.value)\n },\n messageKey: () => 'required_unless',\n replacements: (ctx) => ({ other: ctx.parameters[0] ?? '', values: ctx.parameters.slice(1).join(', ') }),\n },\n required_with: {\n implicit: true,\n validate: (ctx: RuleContext) => !anyPresent(ctx.parameters, ctx.data) || !isEmptyValue(ctx.value),\n messageKey: () => 'required_with',\n replacements: (ctx) => ({ values: ctx.parameters.join(' / ') }),\n },\n required_with_all: {\n implicit: true,\n validate: (ctx: RuleContext) => !allPresent(ctx.parameters, ctx.data) || !isEmptyValue(ctx.value),\n messageKey: () => 'required_with_all',\n replacements: (ctx) => ({ values: ctx.parameters.join(' / ') }),\n },\n required_without: {\n implicit: true,\n validate: (ctx: RuleContext) => ctx.parameters.every((f) => isFieldPresent(f, ctx.data)) || !isEmptyValue(ctx.value),\n messageKey: () => 'required_without',\n replacements: (ctx) => ({ values: ctx.parameters.join(' / ') }),\n },\n required_without_all: {\n implicit: true,\n validate: (ctx: RuleContext) => anyPresent(ctx.parameters, ctx.data) || !isEmptyValue(ctx.value),\n messageKey: () => 'required_without_all',\n replacements: (ctx) => ({ values: ctx.parameters.join(' / ') }),\n },\n}\n","import type { BuiltinRule } from '../parse'\n\nconst BOOLEAN_VALUES: unknown[] = [true, false, 0, 1, '0', '1']\n\n/** PHP's is_numeric for strings: optional surrounding whitespace and sign, decimal digits, optional exponent. */\nconst NUMERIC_STRING_RE = /^\\s*[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?\\s*$/\n\n/**\n * Laravel's `numeric` (PHP is_numeric): a finite number, or a decimal string. Unlike `Number()`, it rejects\n * \"Infinity\", hex/binary/octal literals (\"0x1F\", \"0b101\", \"0o7\") and the empty string.\n */\nexport function isNumeric(value: unknown): boolean {\n if (typeof value === 'number') return Number.isFinite(value)\n return typeof value === 'string' && NUMERIC_STRING_RE.test(value)\n}\n\nexport const typeRules: Record<string, BuiltinRule> = {\n string: { validate: (ctx) => typeof ctx.value === 'string', messageKey: () => 'string' },\n integer: {\n validate: (ctx) => typeof ctx.value !== 'object' && /^-?\\d+$/.test(String(ctx.value).trim()),\n messageKey: () => 'integer',\n },\n numeric: {\n validate: (ctx) => isNumeric(ctx.value),\n messageKey: () => 'numeric',\n },\n boolean: { validate: (ctx) => BOOLEAN_VALUES.includes(ctx.value), messageKey: () => 'boolean' },\n array: { validate: (ctx) => Array.isArray(ctx.value), messageKey: () => 'array' },\n}\n","import type { BuiltinRule, RuleContext } from '../parse'\nimport { isUploadedFileLike } from '../parse'\nimport { isNumeric } from './type'\n\ntype SizeType = 'numeric' | 'array' | 'file' | 'string'\n\nfunction hasAny(ctx: RuleContext, names: string[]): boolean {\n return names.some((name) => ctx.ruleNames.includes(name))\n}\n\n/** A JSON object is a PHP associative array, so it's counted like one. */\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null) return false\n const proto: unknown = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n}\n\n/**\n * What a size rule measures and which message family it reports, decided in one place so the check and the\n * message always agree (Laravel's getSize + getAttributeType):\n * - numeric/integer rule: the number itself (a non-numeric value falls back to its string length, which the\n * numeric rule rejects anyway);\n * - an array (or plain object): its item count;\n * - an uploaded file: its size in fractional kilobytes;\n * - a file/image rule on something that isn't a file: NaN, so every size comparison fails;\n * - anything else: the length of its string form (a number without a numeric rule counts its digits).\n */\nfunction measure(ctx: RuleContext): { type: SizeType; size: number } {\n const { value } = ctx\n if (hasAny(ctx, ['numeric', 'integer'])) {\n return { type: 'numeric', size: isNumeric(value) ? Number(value) : stringLength(value) }\n }\n if (Array.isArray(value)) return { type: 'array', size: value.length }\n if (isUploadedFileLike(value)) return { type: 'file', size: value.size / 1024 }\n if (hasAny(ctx, ['file', 'image'])) return { type: 'file', size: Number.NaN }\n if (isPlainObject(value)) return { type: 'array', size: Object.keys(value).length }\n if (hasAny(ctx, ['array'])) return { type: 'array', size: stringLength(value) }\n return { type: 'string', size: stringLength(value) }\n}\n\nfunction stringLength(value: unknown): number {\n if (value === null || value === undefined) return 0\n return [...String(value)].length\n}\n\nfunction sizeOf(ctx: RuleContext): number {\n return measure(ctx).size\n}\n\nfunction sizeType(ctx: RuleContext): SizeType {\n return measure(ctx).type\n}\n\nexport const sizeRules: Record<string, BuiltinRule> = {\n max: {\n validate: (ctx) => sizeOf(ctx) <= Number(ctx.parameters[0]),\n messageKey: (ctx) => `max.${sizeType(ctx)}`,\n replacements: (ctx) => ({ max: ctx.parameters[0] ?? '' }),\n },\n min: {\n validate: (ctx) => sizeOf(ctx) >= Number(ctx.parameters[0]),\n messageKey: (ctx) => `min.${sizeType(ctx)}`,\n replacements: (ctx) => ({ min: ctx.parameters[0] ?? '' }),\n },\n between: {\n validate: (ctx) => {\n const size = sizeOf(ctx)\n return size >= Number(ctx.parameters[0]) && size <= Number(ctx.parameters[1])\n },\n messageKey: (ctx) => `between.${sizeType(ctx)}`,\n replacements: (ctx) => ({ min: ctx.parameters[0] ?? '', max: ctx.parameters[1] ?? '' }),\n },\n size: {\n validate: (ctx) => sizeOf(ctx) === Number(ctx.parameters[0]),\n messageKey: (ctx) => `size.${sizeType(ctx)}`,\n replacements: (ctx) => ({ size: ctx.parameters[0] ?? '' }),\n },\n in: { validate: (ctx) => ctx.parameters.includes(String(ctx.value)), messageKey: () => 'in' },\n not_in: { validate: (ctx) => !ctx.parameters.includes(String(ctx.value)), messageKey: () => 'not_in' },\n}\n","import type { BuiltinRule } from './parse'\nimport { authRules } from './rules/auth'\nimport { databaseRules } from './rules/database'\nimport { fileRules } from './rules/file'\nimport { formatRules } from './rules/format'\nimport { presenceRules } from './rules/presence'\nimport { sizeRules } from './rules/size'\nimport { typeRules } from './rules/type'\n\n/** Every built-in rule, merged. Later tasks (database rules) add their own spread here. */\nexport const builtinRules: Record<string, BuiltinRule> = {\n ...presenceRules,\n ...typeRules,\n ...formatRules,\n ...sizeRules,\n ...fileRules,\n ...databaseRules,\n ...authRules,\n}\n","import type { ValidationRule } from '@orieljs/contracts'\nimport { applyReplacements, DEFAULT_MESSAGES, defaultAttributeName } from '../messages'\n\nlet defaultRule: PasswordRule | (() => PasswordRule) | undefined\n\n/**\n * Laravel's Illuminate\\Validation\\Rules\\Password: a string of at least `min` characters (8 by default), plus the\n * checks you add: letters(), mixedCase(), numbers(), symbols(), max(). Every failing check adds its own message.\n * Rule.password() returns the application default (PasswordRule.defaults()). (Laravel's uncompromised() is not\n * ported: it calls an outside service.)\n */\nexport class PasswordRule implements ValidationRule {\n #min: number\n #max: number | undefined\n #letters = false\n #mixedCase = false\n #numbers = false\n #symbols = false\n\n constructor(min = 8) {\n this.#min = Math.max(1, min)\n }\n\n /** A password rule of at least `size` characters: PasswordRule.min(12).mixedCase(). */\n static min(size: number): PasswordRule {\n return new PasswordRule(size)\n }\n\n /**\n * With an argument, sets the default (Laravel's Password::defaults(fn () => ...), in a provider's boot());\n * `null` resets it. Without one, returns a copy of the default: PasswordRule.min(8) unless set.\n */\n static defaults(): PasswordRule\n static defaults(rule: PasswordRule | (() => PasswordRule) | null): void\n static defaults(rule?: PasswordRule | (() => PasswordRule) | null): PasswordRule | void {\n if (rule !== undefined) {\n defaultRule = rule ?? undefined\n return\n }\n const resolved = typeof defaultRule === 'function' ? defaultRule() : defaultRule\n return resolved === undefined ? new PasswordRule(8) : resolved.#copy()\n }\n\n min(size: number): this {\n this.#min = Math.max(1, size)\n return this\n }\n\n max(size: number): this {\n this.#max = size\n return this\n }\n\n /** At least one letter. */\n letters(): this {\n this.#letters = true\n return this\n }\n\n /** At least one uppercase and one lowercase letter. */\n mixedCase(): this {\n this.#mixedCase = true\n return this\n }\n\n /** At least one number. */\n numbers(): this {\n this.#numbers = true\n return this\n }\n\n /** At least one symbol (punctuation, a symbol or a space). */\n symbols(): this {\n this.#symbols = true\n return this\n }\n\n validate(attribute: string, value: unknown, fail: (message: string) => void): void {\n const name = defaultAttributeName(attribute)\n const say = (key: string, replacements: Record<string, string> = {}) =>\n fail(applyReplacements(DEFAULT_MESSAGES[key]!, { attribute: name, ...replacements }))\n if (typeof value !== 'string') return say('string')\n const length = [...value].length\n if (length < this.#min) say('min.string', { min: String(this.#min) })\n if (this.#max !== undefined && length > this.#max) say('max.string', { max: String(this.#max) })\n // Laravel's order and patterns.\n if (this.#mixedCase && !/(\\p{Ll}+.*\\p{Lu})|(\\p{Lu}+.*\\p{Ll})/u.test(value)) say('password.mixed')\n if (this.#letters && !/\\p{L}/u.test(value)) say('password.letters')\n if (this.#symbols && !/\\p{Z}|\\p{S}|\\p{P}/u.test(value)) say('password.symbols')\n if (this.#numbers && !/\\p{N}/u.test(value)) say('password.numbers')\n }\n\n #copy(): PasswordRule {\n const copy = new PasswordRule(this.#min)\n copy.#max = this.#max\n copy.#letters = this.#letters\n copy.#mixedCase = this.#mixedCase\n copy.#numbers = this.#numbers\n copy.#symbols = this.#symbols\n return copy\n }\n}\n","import type { ValidationRule } from '@orieljs/contracts'\nimport { applyReplacements, DEFAULT_MESSAGES, defaultAttributeName } from './messages'\nimport { guessColumn, matchingRecordExists } from './rules/database'\nimport { PasswordRule } from './rules/password'\n\n/**\n * Base for the fluent builders. Each one reports under a built-in rule name (`in`, `unique`, `exists`), so when it\n * runs inside a Validator its failure goes through exactly the same lookup as the string rule: custom messages\n * (\"email.unique\", \"items.*.email.unique\", \"unique\"), custom attributes, then the default text. Called directly\n * as a plain ValidationRule, validate() fails with the default English message.\n */\nexport abstract class BuiltinRuleObject implements ValidationRule {\n abstract readonly ruleName: string\n\n abstract passes(attribute: string, value: unknown, data: Record<string, unknown>, expandedFromWildcard?: boolean): boolean | Promise<boolean>\n\n // Declares all 4 contract parameters so a subclass's inferred type (from `Rule.in(...)` etc.) still accepts a\n // call with the full 4-arg ValidationRule.validate signature, as Rule.test.ts makes.\n async validate(attribute: string, value: unknown, fail: (message: string) => void, data: Record<string, unknown>, expandedFromWildcard = false): Promise<void> {\n if (await this.passes(attribute, value, data, expandedFromWildcard)) return\n fail(applyReplacements(DEFAULT_MESSAGES[this.ruleName]!, { attribute: defaultAttributeName(attribute) }))\n }\n}\n\nclass InRule extends BuiltinRuleObject {\n readonly ruleName = 'in'\n\n constructor(private readonly values: readonly unknown[]) {\n super()\n }\n\n passes(_attribute: string, value: unknown): boolean {\n return this.values.map(String).includes(String(value))\n }\n}\n\n/** Structural shape of Database's Model — duck-typed so this package never imports `@orieljs/database` (B27). */\ninterface ModelInstanceLike {\n getKey(): unknown\n getKeyName(): string\n}\n\nfunction isModelInstance(value: unknown): value is ModelInstanceLike {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as ModelInstanceLike).getKey === 'function' &&\n typeof (value as ModelInstanceLike).getKeyName === 'function'\n )\n}\n\nclass UniqueRule extends BuiltinRuleObject {\n readonly ruleName = 'unique'\n private exceptId: unknown\n private idColumnName: string | undefined\n\n constructor(\n private readonly table: string,\n private readonly column?: string,\n ) {\n super()\n }\n\n /**\n * Excludes the current record from the uniqueness check. Laravel's `Rule::unique('users')->ignore($user)` accepts\n * a model directly (the common case: \"update your profile without changing your email\"), so a model instance is\n * bound by its key (`getKey()`/`getKeyName()`), not the object itself — the object would reach the query builder\n * as an opaque value and either be rejected by the driver or stringified (B27). A plain id still works as before;\n * null (or \"NULL\") excludes nothing.\n */\n ignore(id: unknown, idColumn?: string): this {\n if (isModelInstance(id)) {\n this.exceptId = id.getKey()\n this.idColumnName = idColumn ?? id.getKeyName()\n } else {\n this.exceptId = id\n this.idColumnName = idColumn ?? 'id'\n }\n return this\n }\n\n async passes(attribute: string, value: unknown, _data?: Record<string, unknown>, expandedFromWildcard = false): Promise<boolean> {\n const column = this.column ?? guessColumn(attribute, expandedFromWildcard)\n return !(await matchingRecordExists(this.table, column, value, this.exceptId, this.idColumnName ?? 'id'))\n }\n}\n\nclass ExistsRule extends BuiltinRuleObject {\n readonly ruleName = 'exists'\n\n constructor(\n private readonly table: string,\n private readonly column?: string,\n ) {\n super()\n }\n\n passes(attribute: string, value: unknown, _data?: Record<string, unknown>, expandedFromWildcard = false): Promise<boolean> {\n return matchingRecordExists(this.table, this.column ?? guessColumn(attribute, expandedFromWildcard), value)\n }\n}\n\n/** Fluent rule-object builders, for when a plain string rule can't express what's needed (e.g. .ignore()). */\nexport const Rule = {\n in: (values: readonly unknown[]): InRule => new InRule(values),\n unique: (table: string, column?: string): UniqueRule => new UniqueRule(table, column),\n exists: (table: string, column?: string): ExistsRule => new ExistsRule(table, column),\n /** Laravel's Password::defaults(): the application's password rule (at least 8 characters unless PasswordRule.defaults() changed it). */\n password: (): PasswordRule => PasswordRule.defaults(),\n}\n","import type { Rules, Validator } from '@orieljs/contracts'\nimport { Arr } from '@orieljs/support'\nimport { UnknownValidationRuleError, ValidationErrorImpl } from './errors'\nimport { MessageBagImpl } from './MessageBag'\nimport { BuiltinRuleObject } from './Rule'\nimport { applyReplacements, DEFAULT_MESSAGES, defaultAttributeName } from './messages'\nimport type { BuiltinRule, ParsedRule, RuleContext } from './parse'\nimport { expandWildcardKeys, parseRuleSpec, UNSAFE_KEYS } from './parse'\n\nconst SKIPPED_MODIFIERS = new Set(['bail', 'nullable', 'sometimes'])\n\n/**\n * Rebuilds a nested structure from flat dot-paths, the way Laravel's validated() does for wildcard fields.\n * `Arr.undot` (from @orieljs/support) always builds plain objects; it can't know \"items.0\"/\"items.1\" should\n * become an array. This walks the same way, then promotes any container it created itself whose keys are exactly\n * \"0\", \"1\", \"2\", … in order into a real array. Leaf values copied from the input (a Date, an uploaded file, an\n * object that happens to have \"0\"/\"1\" keys) are returned untouched, by identity. A path with a segment in\n * UNSAFE_KEYS is dropped, so nothing can be written through to Object.prototype. The input is never mutated.\n */\nfunction buildNested(flat: Record<string, unknown>): Record<string, unknown> {\n const root: Record<string, unknown> = {}\n const created = new Set<object>([root])\n for (const [path, value] of Object.entries(flat)) {\n const parts = path.split('.')\n if (parts.some((part) => UNSAFE_KEYS.has(part))) continue\n let current = root\n for (const part of parts.slice(0, -1)) {\n const existing = Object.hasOwn(current, part) ? current[part] : undefined\n if (typeof existing === 'object' && existing !== null && created.has(existing)) {\n current = existing as Record<string, unknown>\n continue\n }\n const container = cloneContainer(existing)\n created.add(container)\n current[part] = container\n current = container\n }\n current[parts.at(-1)!] = value\n }\n return arrayify(root, created) as Record<string, unknown>\n}\n\nfunction isPlainContainer(value: unknown): value is Record<string, unknown> {\n if (Array.isArray(value)) return true\n if (typeof value !== 'object' || value === null) return false\n const proto: unknown = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n}\n\n/**\n * A fresh container to write a child path into. When a parent key was already copied from the input (rules on both\n * \"user\" and \"user.name\"), its plain contents are kept (Laravel returns the whole parent) but copied, so the input\n * is never mutated. Anything else (missing, a scalar, a class instance) starts empty.\n */\nfunction cloneContainer(existing: unknown): Record<string, unknown> {\n const container: Record<string, unknown> = {}\n if (!isPlainContainer(existing)) return container\n for (const [key, value] of Object.entries(existing)) {\n if (!UNSAFE_KEYS.has(key)) container[key] = value\n }\n return container\n}\n\nfunction arrayify(node: unknown, created: ReadonlySet<object>): unknown {\n if (node === null || typeof node !== 'object' || !created.has(node)) return node\n const entries = Object.entries(node as Record<string, unknown>).map(([k, v]) => [k, arrayify(v, created)] as const)\n const keys = entries.map(([k]) => k)\n const isArrayLike = keys.length > 0 && keys.every((k, i) => k === String(i))\n return isArrayLike ? entries.map(([, v]) => v) : Object.fromEntries(entries)\n}\n\n/**\n * Runs each field's rules the way Laravel's Validator does:\n * - a missing key, or a string that is blank after trimming, only runs implicit rules (the required* family and\n * accepted); every other rule, including ValidationRule objects, is skipped for it;\n * - an explicit null runs every rule unless the field is `nullable` (then only implicit rules run), so\n * `{ age: null }` still fails `integer`;\n * - `sometimes` skips a missing field entirely;\n * - a field stops validating after its first failure under `bail`, or after any implicit rule fails.\n */\nexport class ValidatorImpl implements Validator {\n private bag: MessageBagImpl | undefined\n private ranPromise: Promise<boolean> | undefined\n private readonly afterCallbacks: Array<(validator: Validator) => void | Promise<void>> = []\n\n constructor(\n private readonly data: Record<string, unknown>,\n private readonly rules: Rules,\n private readonly customMessages: Record<string, string>,\n private readonly customAttributes: Record<string, string>,\n private readonly registry: Record<string, BuiltinRule>,\n private readonly errorBagName = 'default',\n ) {}\n\n after(callback: (validator: Validator) => void | Promise<void>): this {\n this.afterCallbacks.push(callback)\n return this\n }\n\n /** Not part of the Validator contract — lets an after() hook add a failure (MessageBag itself is read-only). */\n fail(field: string, message: string): void {\n this.bag ??= new MessageBagImpl()\n this.bag.add(field, message)\n }\n\n async passes(): Promise<boolean> {\n this.ranPromise ??= this.run()\n return this.ranPromise\n }\n\n async fails(): Promise<boolean> {\n return !(await this.passes())\n }\n\n errors(): MessageBagImpl {\n return this.bag ?? new MessageBagImpl()\n }\n\n async validated<T = Record<string, unknown>>(): Promise<T> {\n if (!(await this.passes())) throw new ValidationErrorImpl(this.bag!.toObject(), this.errorBagName)\n const flat: Record<string, unknown> = {}\n for (const pattern of Object.keys(this.rules)) {\n for (const field of this.fieldsFor(pattern)) {\n if (Arr.has(this.data, field)) flat[field] = Arr.get(this.data, field)\n }\n }\n return buildNested(flat) as T\n }\n\n private fieldsFor(pattern: string): string[] {\n return pattern.includes('*') ? expandWildcardKeys(pattern, this.data) : [pattern]\n }\n\n private async run(): Promise<boolean> {\n this.bag = new MessageBagImpl()\n\n for (const [pattern, spec] of Object.entries(this.rules)) {\n const parsed = parseRuleSpec(spec)\n const names = parsed.filter((r): r is Extract<ParsedRule, { kind: 'named' }> => r.kind === 'named').map((r) => r.name)\n const bail = names.includes('bail')\n const nullable = names.includes('nullable')\n const sometimes = names.includes('sometimes')\n\n for (const field of this.fieldsFor(pattern)) {\n const present = Arr.has(this.data, field)\n if (sometimes && !present) continue\n\n const value = Arr.get(this.data, field)\n const isNull = value === null || value === undefined\n const isBlank = typeof value === 'string' && value.trim() === ''\n\n for (const rule of parsed) {\n if (rule.kind === 'named' && SKIPPED_MODIFIERS.has(rule.name)) continue\n const implicit = rule.kind === 'named' && (this.registry[rule.name]?.implicit ?? false)\n // Laravel's presentOrRuleIsImplicit: a missing key or a blank string only runs implicit rules.\n if (!implicit && (!present || isBlank)) continue\n // Laravel's isNotNullIfMarkedAsNullable: nullable + null only runs implicit rules.\n if (!implicit && nullable && isNull) continue\n\n const messages = await this.runRule(rule, field, pattern, value, names)\n if (messages.length > 0) {\n for (const message of messages) this.bag.add(field, message)\n // Laravel's shouldStopValidating: bail stops at the first failure; a failed implicit rule always stops.\n if (bail || implicit) break\n }\n }\n }\n }\n\n for (const callback of this.afterCallbacks) await callback(this)\n return this.bag.isEmpty()\n }\n\n private async runRule(\n rule: ParsedRule,\n field: string,\n pattern: string,\n value: unknown,\n ruleNames: string[],\n ): Promise<string[]> {\n const expanded = pattern.includes('*')\n if (rule.kind === 'object') {\n if (rule.rule instanceof BuiltinRuleObject) {\n if (await rule.rule.passes(field, value, this.data, expanded)) return []\n const ctx = { attribute: field, expandedFromWildcard: expanded, value, parameters: [], data: this.data, ruleNames }\n return [this.failureMessage(rule.rule.ruleName, this.registry[rule.rule.ruleName], ctx, pattern)]\n }\n // Every fail() call is a message, as with Laravel's invokable rules (Rule.password() reports each failed check).\n const failures: string[] = []\n await rule.rule.validate(field, value, (message) => void failures.push(message), this.data)\n return failures\n }\n\n const builtin = this.registry[rule.name]\n if (!builtin) throw new UnknownValidationRuleError(rule.name)\n\n const ctx = { attribute: field, expandedFromWildcard: expanded, value, parameters: rule.parameters, data: this.data, ruleNames }\n if (await builtin.validate(ctx)) return []\n return [this.failureMessage(rule.name, builtin, ctx, pattern)]\n }\n\n /** Custom message (concrete field, then wildcard pattern, then rule name) or the default, with :attribute filled. */\n private failureMessage(name: string, builtin: BuiltinRule | undefined, ctx: RuleContext, pattern: string): string {\n const field = ctx.attribute\n const template =\n this.customMessages[`${field}.${name}`] ??\n this.customMessages[`${pattern}.${name}`] ??\n this.customMessages[name] ??\n builtin?.message ??\n DEFAULT_MESSAGES[builtin?.messageKey(ctx) ?? name] ??\n builtin?.defaultMessage ??\n 'The :attribute field is invalid.'\n\n const display = this.customAttributes[field] ?? this.customAttributes[pattern] ?? defaultAttributeName(field)\n return applyReplacements(template, { attribute: display, ...(builtin?.replacements?.(ctx) ?? {}) })\n }\n}\n","import type { RuleCallback, Rules, ValidationFactory } from '@orieljs/contracts'\nimport type { BuiltinRule } from './parse'\nimport { builtinRules } from './registry'\nimport { ValidatorImpl } from './Validator'\n\nexport class ValidationFactoryImpl implements ValidationFactory {\n private readonly extended: Record<string, BuiltinRule> = {}\n\n make(\n data: Record<string, unknown>,\n rules: Rules,\n messages: Record<string, string> = {},\n attributes: Record<string, string> = {},\n ): ValidatorImpl {\n return new ValidatorImpl(data, rules, messages, attributes, { ...builtinRules, ...this.extended })\n }\n\n extend(name: string, callback: RuleCallback, message?: string): void {\n this.extended[name] = {\n validate: (ctx) => callback(ctx.attribute, ctx.value, ctx.parameters, ctx.data),\n messageKey: () => name,\n ...(message === undefined ? {} : { message }),\n defaultMessage: message ?? 'The :attribute field is invalid.',\n }\n }\n}\n","import type { ValidationFactory } from '@orieljs/contracts'\nimport { ValidationFactory as ValidationFactoryToken } from '@orieljs/contracts'\nimport { facade } from '@orieljs/support'\n\n/** Laravel's Validator facade: Validator.make(...)/Validator.extend(...), proxied to the resolved ValidationFactory. */\nexport const Validator = facade<ValidationFactory>(ValidationFactoryToken)\n","import { ValidationFactory as ValidationFactoryToken } from '@orieljs/contracts'\nimport { ServiceProvider } from '@orieljs/support'\nimport { ValidationFactoryImpl } from './ValidationFactory'\n\nexport class ValidationServiceProvider extends ServiceProvider {\n override register(): void {\n this.app.singleton(ValidationFactoryToken, () => new ValidationFactoryImpl())\n }\n}\n"],"mappings":"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","names":["inject","inject","Arr","Arr","Arr","Arr","Arr","Arr","ctx","ValidationFactoryToken","ValidationFactoryToken"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orieljs/validation",
3
- "version": "0.1.0-alpha.3",
3
+ "version": "0.1.0-alpha.4",
4
4
  "description": "The Oriel Validation component.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -30,9 +30,9 @@
30
30
  "NOTICE"
31
31
  ],
32
32
  "dependencies": {
33
- "@orieljs/contracts": "0.1.0-alpha.3",
34
- "@orieljs/support": "0.1.0-alpha.3",
35
- "@orieljs/container": "0.1.0-alpha.3"
33
+ "@orieljs/contracts": "0.1.0-alpha.4",
34
+ "@orieljs/container": "0.1.0-alpha.4",
35
+ "@orieljs/support": "0.1.0-alpha.4"
36
36
  },
37
37
  "scripts": {
38
38
  "build": "tsup && node ../../../scripts/copy-license.mjs"