kanun 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Toneflix, LLC. and Arcstack Contributors
3
+ Copyright (c) 2025 Toneflix, LLC. and Arkstack Contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -148,11 +148,11 @@ const validator = new Validator(
148
148
  );
149
149
  ```
150
150
 
151
- For the complete guide and API reference, visit the docs site: https://arcstack-hq.github.io/kanun
151
+ For the complete guide and API reference, visit the docs site: https://arkstack-hq.github.io/kanun
152
152
 
153
153
  ## Code of Conduct
154
154
 
155
- In order to ensure that the Kanun community is welcoming to all, please review and abide by the [Code of Conduct](https://arcstack-hq.github.io/code-of-conduct).
155
+ In order to ensure that the Kanun community is welcoming to all, please review and abide by the [Code of Conduct](https://arkstack-hq.github.io/code-of-conduct).
156
156
 
157
157
  ## Security Vulnerabilities
158
158
 
@@ -160,12 +160,12 @@ If you discover a security vulnerability within Kanun, please send an e-mail to
160
160
 
161
161
  ## License
162
162
 
163
- Kanun and all Arcstack packages are open source and licensed under the [MIT license](LICENSE).
163
+ Kanun and all Arkstack packages are open source and licensed under the [MIT license](LICENSE).
164
164
 
165
165
  [i1]: https://img.shields.io/npm/v/kanun?style=flat-square&label=kanun&color=%230970ce
166
166
  [l1]: https://www.npmjs.com/package/kanun
167
167
  [d1]: https://img.shields.io/npm/dt/kanun?style=flat-square&label=Downloads&link=https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fkanun
168
- [linl]: https://github.com/arcstack-hq/kanun/blob/main/LICENSE
169
- [lini]: https://img.shields.io/github/license/arcstack-hq/kanun
170
- [tel]: https://github.com/arcstack-hq/kanun/actions/workflows/ci.yml
171
- [tei]: https://github.com/arcstack-hq/kanun/actions/workflows/ci.yml/badge.svg
168
+ [linl]: https://github.com/arkstack-hq/kanun/blob/main/LICENSE
169
+ [lini]: https://img.shields.io/github/license/arkstack-hq/kanun
170
+ [tel]: https://github.com/arkstack-hq/kanun/actions/workflows/ci.yml
171
+ [tei]: https://github.com/arkstack-hq/kanun/actions/workflows/ci.yml/badge.svg
package/dist/index.cjs CHANGED
@@ -1,4 +1,35 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
+ key = keys[i];
13
+ if (!__hasOwnProp.call(to, key) && key !== except) {
14
+ __defProp(to, key, {
15
+ get: ((k) => from[k]).bind(null, key),
16
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
17
+ });
18
+ }
19
+ }
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
24
+ value: mod,
25
+ enumerable: true
26
+ }) : target, mod));
27
+
28
+ //#endregion
29
+ let dayjs_plugin_customParseFormat = require("dayjs/plugin/customParseFormat");
30
+ dayjs_plugin_customParseFormat = __toESM(dayjs_plugin_customParseFormat);
31
+ let dayjs = require("dayjs");
32
+ dayjs = __toESM(dayjs);
2
33
 
3
34
  //#region src/Rules/baseRule.ts
4
35
  var BaseRule = class {};
@@ -26,6 +57,7 @@ var en_default = {
26
57
  boolean: "The :attribute field must be true or false.",
27
58
  confirmed: "The :attribute confirmation does not match.",
28
59
  date: "The :attribute is not a valid date.",
60
+ datetime: "The :attribute must be a valid date matching the format :format.",
29
61
  date_equals: "The :attribute must be a date equal to :date.",
30
62
  declined: "The :attribute must be declined.",
31
63
  declined_if: "The :attribute must be declined when :other is :value.",
@@ -34,6 +66,7 @@ var en_default = {
34
66
  digits_between: "The :attribute must be between :min and :max digits.",
35
67
  email: "The :attribute must be a valid email address.",
36
68
  ends_with: "The :attribute must end with one of the following: :values.",
69
+ exists: ":value is not a valid :attribute.",
37
70
  gt: {
38
71
  number: "The :attribute must be greater than :value.",
39
72
  string: "The :attribute must be greater than :value characters.",
@@ -46,7 +79,9 @@ var en_default = {
46
79
  array: "The :attribute must have :value items or more.",
47
80
  object: "The :attribute must have :value items or more."
48
81
  },
82
+ hex: "The :attribute must be a valid hexadecimal color.",
49
83
  in: "The :attribute must be one of the following :values.",
84
+ includes: "The :attribute must include one of the following values: :values.",
50
85
  integer: "The :attribute must be an integer.",
51
86
  json: "The :attribute must be a valid JSON string.",
52
87
  lt: {
@@ -75,6 +110,7 @@ var en_default = {
75
110
  },
76
111
  not_in: "The selected :attribute is invalid.",
77
112
  not_regex: "The :attribute format is invalid.",
113
+ not_includes: "The :attribute must not include any of the following values: :values.",
78
114
  numeric: "The :attribute must be a number.",
79
115
  object: "The :attribute must be an object.",
80
116
  password: {
@@ -107,6 +143,7 @@ var en_default = {
107
143
  object: "The :attribute must contain :size items."
108
144
  },
109
145
  string: "The :attribute must be a string.",
146
+ unique: "The :attribute has already been taken.",
110
147
  url: "The :attribute must have a valid URL format."
111
148
  };
112
149
 
@@ -132,6 +169,7 @@ var ar_default = {
132
169
  boolean: "يجب أن تكون قيمة الحقل :attribute إما true أو false",
133
170
  confirmed: "حقل التأكيد غير مُطابق للحقل :attribute",
134
171
  date: "الحقل :attribute ليس تاريخًا صحيحًا",
172
+ datetime: "الحقل :attribute يجب أن يكون تاريخًا صالحًا يطابق الصيغة :format.",
135
173
  date_equals: "لا يساوي الحقل :attribute مع :date.",
136
174
  declined: "يجب رفض الحقل :attribute",
137
175
  declined_if: "الحقل :attribute مرفوض في حال ما إذا كان :other يساوي :value.",
@@ -140,6 +178,7 @@ var ar_default = {
140
178
  digits_between: "يجب أن يحتوي الحقل :attribute بين :min و :max رقمًا/أرقام",
141
179
  email: "يجب أن يكون :attribute عنوان بريد إلكتروني صحيح البُنية",
142
180
  ends_with: "حقل :attribute يجب ان ينتهي بأحد القيم التالية :value.",
181
+ exists: ":value غير صالح :attribute.",
143
182
  gt: {
144
183
  number: "حقل :attribute يجب ان يكون اكبر من :value.",
145
184
  string: "حقل :attribute يجب ان يكون اكبر من :value حروفٍ/حرفًا.",
@@ -152,7 +191,9 @@ var ar_default = {
152
191
  array: "حقل :attribute يجب ان يحتوي علي :value عناصر/عنصر او اكثر.",
153
192
  object: "حقل :attribute يجب ان يحتوي علي :value عناصر/عنصر او اكثر."
154
193
  },
194
+ hex: "الحقل :attribute يجب أن يكون لونًا سداسيًا صالحًا.",
155
195
  in: "الحقل :attribute غير صالح",
196
+ includes: "الحقل :attribute يجب أن يحتوي على أحد القيم التالية: :values.",
156
197
  integer: "يجب أن يكون الحقل :attribute عددًا صحيحًا",
157
198
  json: "يجب أن يكون الحقل :attribute نصا من نوع JSON.",
158
199
  lt: {
@@ -181,6 +222,7 @@ var ar_default = {
181
222
  },
182
223
  not_in: "الحقل :attribute غير صالح",
183
224
  not_regex: "الحقل :attribute نوعه غير صالح",
225
+ not_includes: "الحقل :attribute يجب ألا يحتوي على أي من القيم التالية: :values.",
184
226
  numeric: "يجب على الحقل :attribute أن يكون رقمًا",
185
227
  object: "الحقل :attribute يجب ان يكون من نوع object.",
186
228
  password: {
@@ -213,6 +255,7 @@ var ar_default = {
213
255
  object: "يجب أن يحتوي الحقل :attribute على :size عنصرٍ/عناصر بالظبط"
214
256
  },
215
257
  string: "يجب أن يكون الحقل :attribute نصآ.",
258
+ unique: "الحقل :attribute مستخدم بالفعل.",
216
259
  url: "صيغة الرابط :attribute غير صحيحة"
217
260
  };
218
261
 
@@ -1077,6 +1120,9 @@ const replaceAttributes = {
1077
1120
  replaceDateEquals: function(payload) {
1078
1121
  return this.replaceBefore(payload);
1079
1122
  },
1123
+ replaceDatetime: function({ message, parameters }) {
1124
+ return message.replace(":format", parameters[0]);
1125
+ },
1080
1126
  replaceDeclinedIf: function({ message, parameters, data, getDisplayableAttribute }) {
1081
1127
  const [other] = parameters;
1082
1128
  const result = deepFind(data, other);
@@ -1098,9 +1144,15 @@ const replaceAttributes = {
1098
1144
  replaceEndsWith: function({ message, parameters }) {
1099
1145
  return message.replace(":values", parameters.join(", "));
1100
1146
  },
1147
+ replaceExists: function({ message, parameters, data }) {
1148
+ return message.replace(":value", data[parameters[1]]);
1149
+ },
1101
1150
  replaceIn: function({ message, parameters }) {
1102
1151
  return message.replace(":values", parameters.join(", "));
1103
1152
  },
1153
+ replaceIncludes: function({ message, parameters }) {
1154
+ return message.replace(":values", parameters.join(", "));
1155
+ },
1104
1156
  replaceStartsWith: function({ message, parameters }) {
1105
1157
  return message.replace(":values", parameters.join(", "));
1106
1158
  },
@@ -1110,6 +1162,9 @@ const replaceAttributes = {
1110
1162
  replaceMax: function({ message, parameters }) {
1111
1163
  return message.replace(":max", parameters[0]);
1112
1164
  },
1165
+ replaceNotIncludes: function({ message, parameters }) {
1166
+ return message.replace(":values", parameters.join(", "));
1167
+ },
1113
1168
  replaceRequiredWith: function({ message, parameters, getDisplayableAttribute }) {
1114
1169
  return message.replace(":values", parameters.map((attribute) => getDisplayableAttribute(attribute)).join(", "));
1115
1170
  },
@@ -1159,6 +1214,9 @@ const replaceAttributes = {
1159
1214
  },
1160
1215
  replaceSize: function({ message, parameters }) {
1161
1216
  return message.replace(":size", parameters[0]);
1217
+ },
1218
+ replaceUnique: function({ message, parameters, data }) {
1219
+ return message.replace(":value", data[parameters[1]]);
1162
1220
  }
1163
1221
  };
1164
1222
 
@@ -2393,6 +2451,7 @@ var ValidationRule = class extends IRuleContract {
2393
2451
 
2394
2452
  //#endregion
2395
2453
  //#region src/Rules/ExtendedRules.ts
2454
+ dayjs.default.extend(dayjs_plugin_customParseFormat.default);
2396
2455
  var ExtendedRules = class extends ValidationRule {
2397
2456
  /**
2398
2457
  * The validator instance.
@@ -2449,9 +2508,9 @@ var ExtendedRules = class extends ValidationRule {
2449
2508
  const [format] = parameters;
2450
2509
  if (!format) return !isNaN(Date.parse(value));
2451
2510
  try {
2452
- return new Date(value).toISOString() === new Date(format).toISOString();
2511
+ return (0, dayjs.default)(value, format, true).isValid();
2453
2512
  } catch {
2454
- return !isNaN(Date.parse(value));
2513
+ return false;
2455
2514
  }
2456
2515
  },
2457
2516
  message: "The :attribute must be a valid date matching the format :format."
package/dist/index.d.ts CHANGED
@@ -73,17 +73,20 @@ declare class replaceAttributePayload {
73
73
  //#region src/Contracts/BaseContract.d.ts
74
74
  type InitialRule = string | ValidationCallback | IRuleContract | BaseRule;
75
75
  type TRule = string | IRuleContract;
76
- interface InitialRules extends GenericObject {
77
- [key: string]: InitialRule | InitialRule[];
78
- }
79
- interface Rules extends GenericObject {
80
- [key: string]: TRule[];
81
- }
76
+ type NestedStringMap = {
77
+ [key: string]: string | NestedStringMap;
78
+ };
79
+ type RuleLeaf = InitialRule | InitialRule[];
80
+ type KnownRulePaths<X extends GenericObject, Prefix extends string = ''> = { [K in keyof X & string]: X[K] extends (infer A)[] ? `${Prefix}${K}` | `${Prefix}${K}.*` | (A extends GenericObject ? `${Prefix}${K}.*.${KnownRulePaths<A>}` : never) : X[K] extends GenericObject ? `${Prefix}${K}` | `${Prefix}${K}.${KnownRulePaths<X[K]>}` : `${Prefix}${K}` }[keyof X & string];
81
+ type LooseNestedRulePaths<X extends GenericObject> = { [K in keyof X & string]: X[K] extends (infer _A)[] ? `${K}.*.${string}` : X[K] extends GenericObject ? `${K}.${string}` : never }[keyof X & string];
82
+ type ScopedInitialRules<X extends GenericObject> = Partial<Record<KnownRulePaths<X> | LooseNestedRulePaths<X>, RuleLeaf>> & { [K in keyof X & string]?: X[K] extends (infer A)[] ? RuleLeaf | (A extends GenericObject ? ScopedInitialRules<A> : never) : X[K] extends GenericObject ? RuleLeaf | ScopedInitialRules<X[K]> : RuleLeaf };
83
+ type InitialRules<X extends GenericObject = GenericObject> = ScopedInitialRules<keyof X extends never ? GenericObject : X>;
84
+ type Rules<X extends GenericObject = GenericObject> = Partial<Record<Extract<keyof X, string>, TRule[]>> & Record<string, TRule[]>;
82
85
  interface ImplicitAttributes {
83
86
  [key: string]: string[];
84
87
  }
85
- type CustomMessages = GenericObject & {};
86
- type CustomAttributes = GenericObject & {};
88
+ type CustomMessages<_X extends GenericObject = GenericObject> = GenericObject;
89
+ type CustomAttributes<_X extends GenericObject = GenericObject> = GenericObject;
87
90
  interface ErrorMessage {
88
91
  error_type?: string;
89
92
  message: string;
@@ -190,14 +193,18 @@ interface ReplaceAttributeInterface {
190
193
  replaceAfterOrEqual: (payload: replaceAttributePayload) => string;
191
194
  replaceBetween: (payload: replaceAttributePayload) => string;
192
195
  replaceDateEquals: (payload: replaceAttributePayload) => string;
196
+ replaceDatetime: (payload: replaceAttributePayload) => string;
193
197
  replaceDeclinedIf: (payload: replaceAttributePayload) => string;
194
198
  replaceDigits: (payload: replaceAttributePayload) => string;
195
199
  replaceDigitsBetween: (payload: replaceAttributePayload) => string;
196
200
  replaceDifferent: (payload: replaceAttributePayload) => string;
197
201
  replaceEndsWith: (payload: replaceAttributePayload) => string;
202
+ replaceExists: (payload: replaceAttributePayload) => string;
198
203
  replaceIn: (payload: replaceAttributePayload) => string;
204
+ replaceIncludes: (payload: replaceAttributePayload) => string;
199
205
  replaceMin: (payload: replaceAttributePayload) => string;
200
206
  replaceMax: (payload: replaceAttributePayload) => string;
207
+ replaceNotIncludes: (payload: replaceAttributePayload) => string;
201
208
  replaceRequiredWith: (payload: replaceAttributePayload) => string;
202
209
  replaceRequiredWithAll: (payload: replaceAttributePayload) => string;
203
210
  replaceRequiredWithout: (payload: replaceAttributePayload) => string;
@@ -211,6 +218,7 @@ interface ReplaceAttributeInterface {
211
218
  replaceRequiredUnless: (payload: replaceAttributePayload) => string;
212
219
  replaceSame: (payload: replaceAttributePayload) => string;
213
220
  replaceSize: (payload: replaceAttributePayload) => string;
221
+ replaceUnique: (payload: replaceAttributePayload) => string;
214
222
  }
215
223
  type ValidationCallback = (value: any, fail: (message: string) => void, attribute: string) => void;
216
224
  //#endregion
@@ -272,7 +280,7 @@ declare class ErrorBag {
272
280
  }
273
281
  //#endregion
274
282
  //#region src/BaseValidator.d.ts
275
- declare class BaseValidator {
283
+ declare class BaseValidator<D extends GenericObject = GenericObject> {
276
284
  /**
277
285
  * The lang used to return error messages
278
286
  */
@@ -308,18 +316,18 @@ declare class BaseValidator {
308
316
  /**
309
317
  * Custom messages returned based on the error
310
318
  */
311
- customMessages: CustomMessages;
319
+ customMessages: CustomMessages<D>;
312
320
  /**
313
321
  * Object of custom attribute name;
314
322
  */
315
- customAttributes: CustomAttributes;
316
- constructor(data: object, rules: InitialRules, customMessages?: CustomMessages, customAttributes?: CustomAttributes);
317
- setData(data: object): this;
318
- setRules(rules: InitialRules): this;
323
+ customAttributes: CustomAttributes<D>;
324
+ constructor(data: D, rules: InitialRules<D>, customMessages?: CustomMessages<D>, customAttributes?: CustomAttributes<D>);
325
+ setData<ND extends GenericObject>(data: ND): BaseValidator<ND>;
326
+ setRules(rules: InitialRules<D>): this;
319
327
  setLang(lang: string): this;
320
328
  getLang(): string;
321
- setCustomMessages(customMessages?: CustomMessages): this;
322
- setCustomAttributes(customAttributes?: CustomAttributes): this;
329
+ setCustomMessages(customMessages?: CustomMessages<D>): this;
330
+ setCustomAttributes(customAttributes?: CustomAttributes<D>): this;
323
331
  stopOnFirstFailure(stopOnFirstFailure?: boolean): this;
324
332
  errors(): ErrorBag;
325
333
  clearErrors(keys?: string[]): ErrorBag;
@@ -660,6 +668,7 @@ type ValidationRuleSet = RuleName | RuleName[] | `${ValidationRuleName}${string
660
668
  * Parse rule names from rule string or string[] definitions
661
669
  */
662
670
  type ExtractRules<R> = R extends string ? R extends `${infer Head}|${infer Tail}` ? Head extends `${infer Rule}:${string}` ? Rule | ExtractRules<Tail> : Head | ExtractRules<Tail> : R extends `${infer Rule}:${string}` ? Rule : R : R extends string[] ? ExtractRules<R[number]> : never;
671
+ type ValidatedByRules<D extends Record<string, any>, R extends RulesForData<D>> = { [K in Extract<keyof R, keyof D>]: D[K] };
663
672
  /**
664
673
  * Flatten data structure into dot-notation keys
665
674
  * including wildcards (*) for arrays.
@@ -699,13 +708,13 @@ declare class IValidator<D extends Record<string, any> = any, R extends RulesFor
699
708
  *
700
709
  * @throws ValidationException if validation fails
701
710
  */
702
- validate(): Promise<Record<string, any>>;
711
+ validate(): Promise<ValidatedByRules<D, R>>;
703
712
  /**
704
713
  * Run the validator's rules against its data.
705
714
  * @param bagName
706
715
  * @returns
707
716
  */
708
- validateWithBag(bagName: string): Promise<Record<string, any>>;
717
+ validateWithBag(bagName: string): Promise<ValidatedByRules<D, R>>;
709
718
  /**
710
719
  * Stop validation on first failure.
711
720
  */
@@ -713,7 +722,7 @@ declare class IValidator<D extends Record<string, any> = any, R extends RulesFor
713
722
  /**
714
723
  * Get the data that passed validation.
715
724
  */
716
- validatedData(): Record<string, any>;
725
+ validatedData(): ValidatedByRules<D, R>;
717
726
  /**
718
727
  * Return all validated input.
719
728
  */
@@ -759,7 +768,7 @@ declare class IValidator<D extends Record<string, any> = any, R extends RulesFor
759
768
  /**
760
769
  * Get current data.
761
770
  */
762
- getData(): Record<string, any>;
771
+ getData(): ValidatedByRules<D, R>;
763
772
  /**
764
773
  * Get current rules.
765
774
  */
@@ -869,7 +878,7 @@ declare function notRegex(value: RegExp): Regex;
869
878
  //#endregion
870
879
  //#region src/Core.d.ts
871
880
  declare class Password extends Password$1 {}
872
- declare function make(data?: GenericObject, rules?: InitialRules, customMessages?: CustomMessages, customAttributes?: CustomAttributes): BaseValidator;
881
+ declare function make<D extends GenericObject = GenericObject>(data?: D, rules?: InitialRules<D>, customMessages?: CustomMessages<D>, customAttributes?: CustomAttributes<D>): BaseValidator<D>;
873
882
  //#endregion
874
883
  //#region src/Rules/IImplicitRule.d.ts
875
884
  declare class IImplicitRule extends IRuleContract {
@@ -1030,13 +1039,13 @@ declare class Validator<D extends Record<string, any> = any, R extends RulesForD
1030
1039
  *
1031
1040
  * @throws ValidationException if validation fails
1032
1041
  */
1033
- validate(): Promise<Record<string, any>>;
1042
+ validate(): Promise<ValidatedByRules<D, R>>;
1034
1043
  /**
1035
1044
  * Run the validator's rules against its data.
1036
1045
  * @param bagName
1037
1046
  * @returns
1038
1047
  */
1039
- validateWithBag(bagName: string): Promise<Record<string, any>>;
1048
+ validateWithBag(bagName: string): Promise<ValidatedByRules<D, R>>;
1040
1049
  /**
1041
1050
  * Stop validation on first failure.
1042
1051
  */
@@ -1044,7 +1053,7 @@ declare class Validator<D extends Record<string, any> = any, R extends RulesForD
1044
1053
  /**
1045
1054
  * Get the data that passed validation.
1046
1055
  */
1047
- validatedData(): Record<string, any>;
1056
+ validatedData(): ValidatedByRules<D, R>;
1048
1057
  /**
1049
1058
  * Return all validated input.
1050
1059
  */
@@ -1090,7 +1099,7 @@ declare class Validator<D extends Record<string, any> = any, R extends RulesForD
1090
1099
  /**
1091
1100
  * Get current data.
1092
1101
  */
1093
- getData(): Record<string, any>;
1102
+ getData(): ValidatedByRules<D, R>;
1094
1103
  /**
1095
1104
  * Get current rules.
1096
1105
  */
@@ -1432,4 +1441,4 @@ declare class ValidationException extends Error {
1432
1441
  getResponse(): any;
1433
1442
  }
1434
1443
  //#endregion
1435
- export { BaseValidationRuleClass, BaseValidator, CustomAttributes, CustomErrors, CustomMessages, CustomValidationRules, DotPaths, ErrorBag, ErrorMessage, Errors, ExtendedRules, ExtractRules, FieldMessages, GenericCallable, GenericObject, IDatabaseDriver, IMessageBag, IValidationRule, IValidator, ImplicitAttributes, ImplicitRule, InitialRule, InitialRules, Lang, MessageBag, Messages, MessagesForRules, ParamableValidationRuleName, Password, PlainRuleName, ReplaceAttributeInterface, Rules, RulesForData, TRule, ValidationCallback, ValidationDataInterface, ValidationDatabaseExistsInput, ValidationException, ValidationMessageProvider, ValidationRule, ValidationRuleCallable, ValidationRuleName, ValidationRuleParserInterface, ValidationRuleSet, ValidationServiceProvider, Validator, addImplicitRule, buildValidationMethodName, compare, convertValuesToBoolean, convertValuesToNull, convertValuesToNumber, deepEqual, deepFind, deepSet, dotify, getFormattedAttribute, getKeyCombinations, getMessage, getNumericRules, getSize, isArrayOfRules, isImplicitRule, isInteger, isNumericRule, isObject, isRule, isSizeRule, make, mergeDeep, notRegex, plural, regex, register, registerImplicit, requiredIf, ruleIn, ruleNotIn, sameType, toDate, toSnakeCase };
1444
+ export { BaseValidationRuleClass, BaseValidator, CustomAttributes, CustomErrors, CustomMessages, CustomValidationRules, DotPaths, ErrorBag, ErrorMessage, Errors, ExtendedRules, ExtractRules, FieldMessages, GenericCallable, GenericObject, IDatabaseDriver, IMessageBag, IValidationRule, IValidator, ImplicitAttributes, ImplicitRule, InitialRule, InitialRules, Lang, MessageBag, Messages, MessagesForRules, NestedStringMap, ParamableValidationRuleName, Password, PlainRuleName, ReplaceAttributeInterface, Rules, RulesForData, TRule, ValidatedByRules, ValidationCallback, ValidationDataInterface, ValidationDatabaseExistsInput, ValidationException, ValidationMessageProvider, ValidationRule, ValidationRuleCallable, ValidationRuleName, ValidationRuleParserInterface, ValidationRuleSet, ValidationServiceProvider, Validator, addImplicitRule, buildValidationMethodName, compare, convertValuesToBoolean, convertValuesToNull, convertValuesToNumber, deepEqual, deepFind, deepSet, dotify, getFormattedAttribute, getKeyCombinations, getMessage, getNumericRules, getSize, isArrayOfRules, isImplicitRule, isInteger, isNumericRule, isObject, isRule, isSizeRule, make, mergeDeep, notRegex, plural, regex, register, registerImplicit, requiredIf, ruleIn, ruleNotIn, sameType, toDate, toSnakeCase };
package/dist/index.js CHANGED
@@ -1,3 +1,6 @@
1
+ import customParseFormat from "dayjs/plugin/customParseFormat";
2
+ import dayjs from "dayjs";
3
+
1
4
  //#region src/Rules/baseRule.ts
2
5
  var BaseRule = class {};
3
6
 
@@ -24,6 +27,7 @@ var en_default = {
24
27
  boolean: "The :attribute field must be true or false.",
25
28
  confirmed: "The :attribute confirmation does not match.",
26
29
  date: "The :attribute is not a valid date.",
30
+ datetime: "The :attribute must be a valid date matching the format :format.",
27
31
  date_equals: "The :attribute must be a date equal to :date.",
28
32
  declined: "The :attribute must be declined.",
29
33
  declined_if: "The :attribute must be declined when :other is :value.",
@@ -32,6 +36,7 @@ var en_default = {
32
36
  digits_between: "The :attribute must be between :min and :max digits.",
33
37
  email: "The :attribute must be a valid email address.",
34
38
  ends_with: "The :attribute must end with one of the following: :values.",
39
+ exists: ":value is not a valid :attribute.",
35
40
  gt: {
36
41
  number: "The :attribute must be greater than :value.",
37
42
  string: "The :attribute must be greater than :value characters.",
@@ -44,7 +49,9 @@ var en_default = {
44
49
  array: "The :attribute must have :value items or more.",
45
50
  object: "The :attribute must have :value items or more."
46
51
  },
52
+ hex: "The :attribute must be a valid hexadecimal color.",
47
53
  in: "The :attribute must be one of the following :values.",
54
+ includes: "The :attribute must include one of the following values: :values.",
48
55
  integer: "The :attribute must be an integer.",
49
56
  json: "The :attribute must be a valid JSON string.",
50
57
  lt: {
@@ -73,6 +80,7 @@ var en_default = {
73
80
  },
74
81
  not_in: "The selected :attribute is invalid.",
75
82
  not_regex: "The :attribute format is invalid.",
83
+ not_includes: "The :attribute must not include any of the following values: :values.",
76
84
  numeric: "The :attribute must be a number.",
77
85
  object: "The :attribute must be an object.",
78
86
  password: {
@@ -105,6 +113,7 @@ var en_default = {
105
113
  object: "The :attribute must contain :size items."
106
114
  },
107
115
  string: "The :attribute must be a string.",
116
+ unique: "The :attribute has already been taken.",
108
117
  url: "The :attribute must have a valid URL format."
109
118
  };
110
119
 
@@ -130,6 +139,7 @@ var ar_default = {
130
139
  boolean: "يجب أن تكون قيمة الحقل :attribute إما true أو false",
131
140
  confirmed: "حقل التأكيد غير مُطابق للحقل :attribute",
132
141
  date: "الحقل :attribute ليس تاريخًا صحيحًا",
142
+ datetime: "الحقل :attribute يجب أن يكون تاريخًا صالحًا يطابق الصيغة :format.",
133
143
  date_equals: "لا يساوي الحقل :attribute مع :date.",
134
144
  declined: "يجب رفض الحقل :attribute",
135
145
  declined_if: "الحقل :attribute مرفوض في حال ما إذا كان :other يساوي :value.",
@@ -138,6 +148,7 @@ var ar_default = {
138
148
  digits_between: "يجب أن يحتوي الحقل :attribute بين :min و :max رقمًا/أرقام",
139
149
  email: "يجب أن يكون :attribute عنوان بريد إلكتروني صحيح البُنية",
140
150
  ends_with: "حقل :attribute يجب ان ينتهي بأحد القيم التالية :value.",
151
+ exists: ":value غير صالح :attribute.",
141
152
  gt: {
142
153
  number: "حقل :attribute يجب ان يكون اكبر من :value.",
143
154
  string: "حقل :attribute يجب ان يكون اكبر من :value حروفٍ/حرفًا.",
@@ -150,7 +161,9 @@ var ar_default = {
150
161
  array: "حقل :attribute يجب ان يحتوي علي :value عناصر/عنصر او اكثر.",
151
162
  object: "حقل :attribute يجب ان يحتوي علي :value عناصر/عنصر او اكثر."
152
163
  },
164
+ hex: "الحقل :attribute يجب أن يكون لونًا سداسيًا صالحًا.",
153
165
  in: "الحقل :attribute غير صالح",
166
+ includes: "الحقل :attribute يجب أن يحتوي على أحد القيم التالية: :values.",
154
167
  integer: "يجب أن يكون الحقل :attribute عددًا صحيحًا",
155
168
  json: "يجب أن يكون الحقل :attribute نصا من نوع JSON.",
156
169
  lt: {
@@ -179,6 +192,7 @@ var ar_default = {
179
192
  },
180
193
  not_in: "الحقل :attribute غير صالح",
181
194
  not_regex: "الحقل :attribute نوعه غير صالح",
195
+ not_includes: "الحقل :attribute يجب ألا يحتوي على أي من القيم التالية: :values.",
182
196
  numeric: "يجب على الحقل :attribute أن يكون رقمًا",
183
197
  object: "الحقل :attribute يجب ان يكون من نوع object.",
184
198
  password: {
@@ -211,6 +225,7 @@ var ar_default = {
211
225
  object: "يجب أن يحتوي الحقل :attribute على :size عنصرٍ/عناصر بالظبط"
212
226
  },
213
227
  string: "يجب أن يكون الحقل :attribute نصآ.",
228
+ unique: "الحقل :attribute مستخدم بالفعل.",
214
229
  url: "صيغة الرابط :attribute غير صحيحة"
215
230
  };
216
231
 
@@ -1075,6 +1090,9 @@ const replaceAttributes = {
1075
1090
  replaceDateEquals: function(payload) {
1076
1091
  return this.replaceBefore(payload);
1077
1092
  },
1093
+ replaceDatetime: function({ message, parameters }) {
1094
+ return message.replace(":format", parameters[0]);
1095
+ },
1078
1096
  replaceDeclinedIf: function({ message, parameters, data, getDisplayableAttribute }) {
1079
1097
  const [other] = parameters;
1080
1098
  const result = deepFind(data, other);
@@ -1096,9 +1114,15 @@ const replaceAttributes = {
1096
1114
  replaceEndsWith: function({ message, parameters }) {
1097
1115
  return message.replace(":values", parameters.join(", "));
1098
1116
  },
1117
+ replaceExists: function({ message, parameters, data }) {
1118
+ return message.replace(":value", data[parameters[1]]);
1119
+ },
1099
1120
  replaceIn: function({ message, parameters }) {
1100
1121
  return message.replace(":values", parameters.join(", "));
1101
1122
  },
1123
+ replaceIncludes: function({ message, parameters }) {
1124
+ return message.replace(":values", parameters.join(", "));
1125
+ },
1102
1126
  replaceStartsWith: function({ message, parameters }) {
1103
1127
  return message.replace(":values", parameters.join(", "));
1104
1128
  },
@@ -1108,6 +1132,9 @@ const replaceAttributes = {
1108
1132
  replaceMax: function({ message, parameters }) {
1109
1133
  return message.replace(":max", parameters[0]);
1110
1134
  },
1135
+ replaceNotIncludes: function({ message, parameters }) {
1136
+ return message.replace(":values", parameters.join(", "));
1137
+ },
1111
1138
  replaceRequiredWith: function({ message, parameters, getDisplayableAttribute }) {
1112
1139
  return message.replace(":values", parameters.map((attribute) => getDisplayableAttribute(attribute)).join(", "));
1113
1140
  },
@@ -1157,6 +1184,9 @@ const replaceAttributes = {
1157
1184
  },
1158
1185
  replaceSize: function({ message, parameters }) {
1159
1186
  return message.replace(":size", parameters[0]);
1187
+ },
1188
+ replaceUnique: function({ message, parameters, data }) {
1189
+ return message.replace(":value", data[parameters[1]]);
1160
1190
  }
1161
1191
  };
1162
1192
 
@@ -2391,6 +2421,7 @@ var ValidationRule = class extends IRuleContract {
2391
2421
 
2392
2422
  //#endregion
2393
2423
  //#region src/Rules/ExtendedRules.ts
2424
+ dayjs.extend(customParseFormat);
2394
2425
  var ExtendedRules = class extends ValidationRule {
2395
2426
  /**
2396
2427
  * The validator instance.
@@ -2447,9 +2478,9 @@ var ExtendedRules = class extends ValidationRule {
2447
2478
  const [format] = parameters;
2448
2479
  if (!format) return !isNaN(Date.parse(value));
2449
2480
  try {
2450
- return new Date(value).toISOString() === new Date(format).toISOString();
2481
+ return dayjs(value, format, true).isValid();
2451
2482
  } catch {
2452
- return !isNaN(Date.parse(value));
2483
+ return false;
2453
2484
  }
2454
2485
  },
2455
2486
  message: "The :attribute must be a valid date matching the format :format."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kanun",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Framework-agnostic TypeScript-first validation library.",
5
5
  "type": "module",
6
6
  "files": [
@@ -16,17 +16,17 @@
16
16
  },
17
17
  "./package.json": "./package.json"
18
18
  },
19
- "homepage": "https://arcstack-hq.github.io/kanun",
19
+ "homepage": "https://arkstack-hq.github.io/kanun",
20
20
  "repository": {
21
21
  "type": "git",
22
- "url": "git+https://github.com/arcstack-hq/kanun.git",
22
+ "url": "git+https://github.com/arkstack-hq/kanun.git",
23
23
  "directory": "packages/validation"
24
24
  },
25
25
  "keywords": [
26
- "arcstack",
26
+ "arkstack",
27
27
  "modern",
28
28
  "web",
29
- "Arcstack",
29
+ "Arkstack",
30
30
  "framework",
31
31
  "nodejs",
32
32
  "typescript",
@@ -50,6 +50,9 @@
50
50
  "vitepress": "2.0.0-alpha.16",
51
51
  "vitest": "^4.0.18"
52
52
  },
53
+ "dependencies": {
54
+ "dayjs": "^1.11.20"
55
+ },
53
56
  "scripts": {
54
57
  "lint": "eslint",
55
58
  "test": "vitest",