kanun 0.1.4 → 0.1.6

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_js = require("dayjs/plugin/customParseFormat.js");
30
+ dayjs_plugin_customParseFormat_js = __toESM(dayjs_plugin_customParseFormat_js);
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_js.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
@@ -193,14 +193,18 @@ interface ReplaceAttributeInterface {
193
193
  replaceAfterOrEqual: (payload: replaceAttributePayload) => string;
194
194
  replaceBetween: (payload: replaceAttributePayload) => string;
195
195
  replaceDateEquals: (payload: replaceAttributePayload) => string;
196
+ replaceDatetime: (payload: replaceAttributePayload) => string;
196
197
  replaceDeclinedIf: (payload: replaceAttributePayload) => string;
197
198
  replaceDigits: (payload: replaceAttributePayload) => string;
198
199
  replaceDigitsBetween: (payload: replaceAttributePayload) => string;
199
200
  replaceDifferent: (payload: replaceAttributePayload) => string;
200
201
  replaceEndsWith: (payload: replaceAttributePayload) => string;
202
+ replaceExists: (payload: replaceAttributePayload) => string;
201
203
  replaceIn: (payload: replaceAttributePayload) => string;
204
+ replaceIncludes: (payload: replaceAttributePayload) => string;
202
205
  replaceMin: (payload: replaceAttributePayload) => string;
203
206
  replaceMax: (payload: replaceAttributePayload) => string;
207
+ replaceNotIncludes: (payload: replaceAttributePayload) => string;
204
208
  replaceRequiredWith: (payload: replaceAttributePayload) => string;
205
209
  replaceRequiredWithAll: (payload: replaceAttributePayload) => string;
206
210
  replaceRequiredWithout: (payload: replaceAttributePayload) => string;
@@ -214,6 +218,7 @@ interface ReplaceAttributeInterface {
214
218
  replaceRequiredUnless: (payload: replaceAttributePayload) => string;
215
219
  replaceSame: (payload: replaceAttributePayload) => string;
216
220
  replaceSize: (payload: replaceAttributePayload) => string;
221
+ replaceUnique: (payload: replaceAttributePayload) => string;
217
222
  }
218
223
  type ValidationCallback = (value: any, fail: (message: string) => void, attribute: string) => void;
219
224
  //#endregion
package/dist/index.js CHANGED
@@ -1,3 +1,6 @@
1
+ import customParseFormat from "dayjs/plugin/customParseFormat.js";
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.4",
3
+ "version": "0.1.6",
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",