semola 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (273) hide show
  1. package/README.md +75 -20
  2. package/dist/api/core/index.cjs +206 -0
  3. package/dist/api/core/index.d.cts +21 -0
  4. package/dist/api/core/index.d.cts.map +1 -0
  5. package/dist/api/core/index.d.mts +21 -0
  6. package/dist/api/core/index.d.mts.map +1 -0
  7. package/dist/api/core/index.mjs +208 -0
  8. package/dist/api/core/index.mjs.map +1 -0
  9. package/dist/api/core/types.d.cts +107 -0
  10. package/dist/api/core/types.d.cts.map +1 -0
  11. package/dist/api/core/types.d.mts +107 -0
  12. package/dist/api/core/types.d.mts.map +1 -0
  13. package/dist/api/middleware/index.cjs +8 -0
  14. package/dist/api/middleware/index.d.cts +11 -0
  15. package/dist/api/middleware/index.d.cts.map +1 -0
  16. package/dist/api/middleware/index.d.mts +11 -0
  17. package/dist/api/middleware/index.d.mts.map +1 -0
  18. package/dist/api/middleware/index.mjs +10 -0
  19. package/dist/api/middleware/index.mjs.map +1 -0
  20. package/dist/api/middleware/types.d.cts +16 -0
  21. package/dist/api/middleware/types.d.cts.map +1 -0
  22. package/dist/api/middleware/types.d.mts +16 -0
  23. package/dist/api/middleware/types.d.mts.map +1 -0
  24. package/dist/api/openapi/index.cjs +254 -0
  25. package/dist/api/openapi/index.mjs +256 -0
  26. package/dist/api/openapi/index.mjs.map +1 -0
  27. package/dist/api/openapi/types.d.cts +60 -0
  28. package/dist/api/openapi/types.d.cts.map +1 -0
  29. package/dist/api/openapi/types.d.mts +60 -0
  30. package/dist/api/openapi/types.d.mts.map +1 -0
  31. package/dist/api/validation/index.cjs +64 -0
  32. package/dist/api/validation/index.mjs +61 -0
  33. package/dist/api/validation/index.mjs.map +1 -0
  34. package/dist/cache/types.d.cts +17 -0
  35. package/dist/cache/types.d.cts.map +1 -0
  36. package/dist/cache/types.d.mts +17 -0
  37. package/dist/cache/types.d.mts.map +1 -0
  38. package/dist/cron/scanner.cjs +237 -0
  39. package/dist/cron/scanner.mjs +238 -0
  40. package/dist/cron/scanner.mjs.map +1 -0
  41. package/dist/cron/types.d.cts +11 -0
  42. package/dist/cron/types.d.cts.map +1 -0
  43. package/dist/cron/types.d.mts +11 -0
  44. package/dist/cron/types.d.mts.map +1 -0
  45. package/dist/errors/types.d.cts +5 -0
  46. package/dist/errors/types.d.cts.map +1 -0
  47. package/dist/errors/types.d.mts +5 -0
  48. package/dist/errors/types.d.mts.map +1 -0
  49. package/dist/i18n/types.d.cts +13 -0
  50. package/dist/i18n/types.d.cts.map +1 -0
  51. package/dist/i18n/types.d.mts +13 -0
  52. package/dist/i18n/types.d.mts.map +1 -0
  53. package/dist/lib/api/index.cjs +5 -0
  54. package/dist/lib/api/index.d.cts +5 -0
  55. package/dist/lib/api/index.d.mts +5 -0
  56. package/dist/lib/api/index.mjs +3 -0
  57. package/dist/lib/cache/index.cjs +74 -0
  58. package/dist/lib/cache/index.d.cts +36 -0
  59. package/dist/lib/cache/index.d.cts.map +1 -0
  60. package/dist/lib/cache/index.d.mts +36 -0
  61. package/dist/lib/cache/index.d.mts.map +1 -0
  62. package/dist/lib/cache/index.mjs +75 -0
  63. package/dist/lib/cache/index.mjs.map +1 -0
  64. package/dist/lib/cron/index.cjs +276 -0
  65. package/dist/lib/cron/index.d.cts +39 -0
  66. package/dist/lib/cron/index.d.cts.map +1 -0
  67. package/dist/lib/cron/index.d.mts +39 -0
  68. package/dist/lib/cron/index.d.mts.map +1 -0
  69. package/dist/lib/cron/index.mjs +277 -0
  70. package/dist/lib/cron/index.mjs.map +1 -0
  71. package/dist/lib/errors/index.cjs +30 -0
  72. package/dist/lib/errors/index.d.cts +13 -0
  73. package/dist/lib/errors/index.d.cts.map +1 -0
  74. package/dist/lib/errors/index.d.mts +13 -0
  75. package/dist/lib/errors/index.d.mts.map +1 -0
  76. package/dist/lib/errors/index.mjs +28 -0
  77. package/dist/lib/errors/index.mjs.map +1 -0
  78. package/dist/lib/i18n/index.cjs +37 -0
  79. package/dist/lib/i18n/index.d.cts +20 -0
  80. package/dist/lib/i18n/index.d.cts.map +1 -0
  81. package/dist/lib/i18n/index.d.mts +20 -0
  82. package/dist/lib/i18n/index.d.mts.map +1 -0
  83. package/dist/lib/i18n/index.mjs +38 -0
  84. package/dist/lib/i18n/index.mjs.map +1 -0
  85. package/dist/lib/policy/index.cjs +99 -0
  86. package/dist/lib/policy/index.d.cts +21 -0
  87. package/dist/lib/policy/index.d.cts.map +1 -0
  88. package/dist/lib/policy/index.d.mts +21 -0
  89. package/dist/lib/policy/index.d.mts.map +1 -0
  90. package/dist/lib/policy/index.mjs +81 -0
  91. package/dist/lib/policy/index.mjs.map +1 -0
  92. package/dist/lib/prompts/index.cjs +409 -0
  93. package/dist/lib/prompts/index.d.cts +31 -0
  94. package/dist/lib/prompts/index.d.cts.map +1 -0
  95. package/dist/lib/prompts/index.d.mts +31 -0
  96. package/dist/lib/prompts/index.d.mts.map +1 -0
  97. package/dist/lib/prompts/index.mjs +405 -0
  98. package/dist/lib/prompts/index.mjs.map +1 -0
  99. package/dist/lib/pubsub/index.cjs +48 -0
  100. package/dist/lib/pubsub/index.d.cts +27 -0
  101. package/dist/lib/pubsub/index.d.cts.map +1 -0
  102. package/dist/lib/pubsub/index.d.mts +27 -0
  103. package/dist/lib/pubsub/index.d.mts.map +1 -0
  104. package/dist/lib/pubsub/index.mjs +49 -0
  105. package/dist/lib/pubsub/index.mjs.map +1 -0
  106. package/dist/lib/queue/index.cjs +182 -0
  107. package/dist/lib/queue/index.d.cts +32 -0
  108. package/dist/lib/queue/index.d.cts.map +1 -0
  109. package/dist/lib/queue/index.d.mts +32 -0
  110. package/dist/lib/queue/index.d.mts.map +1 -0
  111. package/dist/lib/queue/index.mjs +183 -0
  112. package/dist/lib/queue/index.mjs.map +1 -0
  113. package/dist/node_modules/@standard-schema/spec/dist/index.d.cts +80 -0
  114. package/dist/node_modules/@standard-schema/spec/dist/index.d.cts.map +1 -0
  115. package/dist/node_modules/@standard-schema/spec/dist/index.d.mts +80 -0
  116. package/dist/node_modules/@standard-schema/spec/dist/index.d.mts.map +1 -0
  117. package/dist/policy/helpers.cjs +206 -0
  118. package/dist/policy/helpers.d.cts +50 -0
  119. package/dist/policy/helpers.d.cts.map +1 -0
  120. package/dist/policy/helpers.d.mts +50 -0
  121. package/dist/policy/helpers.d.mts.map +1 -0
  122. package/dist/policy/helpers.mjs +190 -0
  123. package/dist/policy/helpers.mjs.map +1 -0
  124. package/dist/policy/types.d.cts +16 -0
  125. package/dist/policy/types.d.cts.map +1 -0
  126. package/dist/policy/types.d.mts +16 -0
  127. package/dist/policy/types.d.mts.map +1 -0
  128. package/dist/prompts/core/keys.cjs +165 -0
  129. package/dist/prompts/core/keys.mjs +167 -0
  130. package/dist/prompts/core/keys.mjs.map +1 -0
  131. package/dist/prompts/core/runtime.cjs +104 -0
  132. package/dist/prompts/core/runtime.mjs +106 -0
  133. package/dist/prompts/core/runtime.mjs.map +1 -0
  134. package/dist/prompts/core/session.cjs +98 -0
  135. package/dist/prompts/core/session.mjs +100 -0
  136. package/dist/prompts/core/session.mjs.map +1 -0
  137. package/dist/prompts/core/types.d.cts +21 -0
  138. package/dist/prompts/core/types.d.cts.map +1 -0
  139. package/dist/prompts/core/types.d.mts +21 -0
  140. package/dist/prompts/core/types.d.mts.map +1 -0
  141. package/dist/prompts/types.d.cts +52 -0
  142. package/dist/prompts/types.d.cts.map +1 -0
  143. package/dist/prompts/types.d.mts +52 -0
  144. package/dist/prompts/types.d.mts.map +1 -0
  145. package/dist/pubsub/types.d.cts +10 -0
  146. package/dist/pubsub/types.d.cts.map +1 -0
  147. package/dist/pubsub/types.d.mts +10 -0
  148. package/dist/pubsub/types.d.mts.map +1 -0
  149. package/dist/queue/types.d.cts +47 -0
  150. package/dist/queue/types.d.cts.map +1 -0
  151. package/dist/queue/types.d.mts +47 -0
  152. package/dist/queue/types.d.mts.map +1 -0
  153. package/package.json +86 -16
  154. package/dist/lib/api/core/index.d.ts +0 -15
  155. package/dist/lib/api/core/index.d.ts.map +0 -1
  156. package/dist/lib/api/core/index.js +0 -166
  157. package/dist/lib/api/core/index.js.map +0 -1
  158. package/dist/lib/api/core/index.test.d.ts +0 -2
  159. package/dist/lib/api/core/index.test.d.ts.map +0 -1
  160. package/dist/lib/api/core/index.test.js +0 -219
  161. package/dist/lib/api/core/index.test.js.map +0 -1
  162. package/dist/lib/api/core/types.d.ts +0 -102
  163. package/dist/lib/api/core/types.d.ts.map +0 -1
  164. package/dist/lib/api/core/types.js +0 -2
  165. package/dist/lib/api/core/types.js.map +0 -1
  166. package/dist/lib/api/index.d.ts +0 -5
  167. package/dist/lib/api/index.d.ts.map +0 -1
  168. package/dist/lib/api/index.js +0 -3
  169. package/dist/lib/api/index.js.map +0 -1
  170. package/dist/lib/api/middleware/index.d.ts +0 -7
  171. package/dist/lib/api/middleware/index.d.ts.map +0 -1
  172. package/dist/lib/api/middleware/index.js +0 -7
  173. package/dist/lib/api/middleware/index.js.map +0 -1
  174. package/dist/lib/api/middleware/index.test.d.ts +0 -2
  175. package/dist/lib/api/middleware/index.test.d.ts.map +0 -1
  176. package/dist/lib/api/middleware/index.test.js +0 -67
  177. package/dist/lib/api/middleware/index.test.js.map +0 -1
  178. package/dist/lib/api/middleware/types.d.ts +0 -12
  179. package/dist/lib/api/middleware/types.d.ts.map +0 -1
  180. package/dist/lib/api/middleware/types.js +0 -2
  181. package/dist/lib/api/middleware/types.js.map +0 -1
  182. package/dist/lib/api/openapi/index.d.ts +0 -31
  183. package/dist/lib/api/openapi/index.d.ts.map +0 -1
  184. package/dist/lib/api/openapi/index.js +0 -328
  185. package/dist/lib/api/openapi/index.js.map +0 -1
  186. package/dist/lib/api/openapi/index.test.d.ts +0 -2
  187. package/dist/lib/api/openapi/index.test.d.ts.map +0 -1
  188. package/dist/lib/api/openapi/index.test.js +0 -359
  189. package/dist/lib/api/openapi/index.test.js.map +0 -1
  190. package/dist/lib/api/openapi/types.d.ts +0 -57
  191. package/dist/lib/api/openapi/types.d.ts.map +0 -1
  192. package/dist/lib/api/openapi/types.js +0 -5
  193. package/dist/lib/api/openapi/types.js.map +0 -1
  194. package/dist/lib/api/validation/index.d.ts +0 -33
  195. package/dist/lib/api/validation/index.d.ts.map +0 -1
  196. package/dist/lib/api/validation/index.js +0 -81
  197. package/dist/lib/api/validation/index.js.map +0 -1
  198. package/dist/lib/api/validation/index.test.d.ts +0 -2
  199. package/dist/lib/api/validation/index.test.d.ts.map +0 -1
  200. package/dist/lib/api/validation/index.test.js +0 -135
  201. package/dist/lib/api/validation/index.test.js.map +0 -1
  202. package/dist/lib/cache/index.d.ts +0 -25
  203. package/dist/lib/cache/index.d.ts.map +0 -1
  204. package/dist/lib/cache/index.js +0 -62
  205. package/dist/lib/cache/index.js.map +0 -1
  206. package/dist/lib/cache/index.test.d.ts +0 -2
  207. package/dist/lib/cache/index.test.d.ts.map +0 -1
  208. package/dist/lib/cache/index.test.js +0 -314
  209. package/dist/lib/cache/index.test.js.map +0 -1
  210. package/dist/lib/cache/types.d.ts +0 -5
  211. package/dist/lib/cache/types.d.ts.map +0 -1
  212. package/dist/lib/cache/types.js +0 -2
  213. package/dist/lib/cache/types.js.map +0 -1
  214. package/dist/lib/errors/index.d.ts +0 -9
  215. package/dist/lib/errors/index.d.ts.map +0 -1
  216. package/dist/lib/errors/index.js +0 -25
  217. package/dist/lib/errors/index.js.map +0 -1
  218. package/dist/lib/errors/index.test.d.ts +0 -2
  219. package/dist/lib/errors/index.test.d.ts.map +0 -1
  220. package/dist/lib/errors/index.test.js +0 -197
  221. package/dist/lib/errors/index.test.js.map +0 -1
  222. package/dist/lib/errors/types.d.ts +0 -2
  223. package/dist/lib/errors/types.d.ts.map +0 -1
  224. package/dist/lib/errors/types.js +0 -2
  225. package/dist/lib/errors/types.js.map +0 -1
  226. package/dist/lib/i18n/index.d.ts +0 -18
  227. package/dist/lib/i18n/index.d.ts.map +0 -1
  228. package/dist/lib/i18n/index.js +0 -38
  229. package/dist/lib/i18n/index.js.map +0 -1
  230. package/dist/lib/i18n/index.test.d.ts +0 -2
  231. package/dist/lib/i18n/index.test.d.ts.map +0 -1
  232. package/dist/lib/i18n/index.test.js +0 -402
  233. package/dist/lib/i18n/index.test.js.map +0 -1
  234. package/dist/lib/i18n/types.d.ts +0 -15
  235. package/dist/lib/i18n/types.d.ts.map +0 -1
  236. package/dist/lib/i18n/types.js +0 -2
  237. package/dist/lib/i18n/types.js.map +0 -1
  238. package/dist/lib/policy/index.d.ts +0 -9
  239. package/dist/lib/policy/index.d.ts.map +0 -1
  240. package/dist/lib/policy/index.js +0 -51
  241. package/dist/lib/policy/index.js.map +0 -1
  242. package/dist/lib/policy/index.test.d.ts +0 -2
  243. package/dist/lib/policy/index.test.d.ts.map +0 -1
  244. package/dist/lib/policy/index.test.js +0 -328
  245. package/dist/lib/policy/index.test.js.map +0 -1
  246. package/dist/lib/policy/types.d.ts +0 -27
  247. package/dist/lib/policy/types.d.ts.map +0 -1
  248. package/dist/lib/policy/types.js +0 -2
  249. package/dist/lib/policy/types.js.map +0 -1
  250. package/dist/lib/pubsub/index.d.ts +0 -23
  251. package/dist/lib/pubsub/index.d.ts.map +0 -1
  252. package/dist/lib/pubsub/index.js +0 -55
  253. package/dist/lib/pubsub/index.js.map +0 -1
  254. package/dist/lib/pubsub/index.test.d.ts +0 -2
  255. package/dist/lib/pubsub/index.test.d.ts.map +0 -1
  256. package/dist/lib/pubsub/index.test.js +0 -550
  257. package/dist/lib/pubsub/index.test.js.map +0 -1
  258. package/dist/lib/pubsub/types.d.ts +0 -7
  259. package/dist/lib/pubsub/types.d.ts.map +0 -1
  260. package/dist/lib/pubsub/types.js +0 -2
  261. package/dist/lib/pubsub/types.js.map +0 -1
  262. package/dist/lib/queue/index.d.ts +0 -28
  263. package/dist/lib/queue/index.d.ts.map +0 -1
  264. package/dist/lib/queue/index.js +0 -211
  265. package/dist/lib/queue/index.js.map +0 -1
  266. package/dist/lib/queue/index.test.d.ts +0 -2
  267. package/dist/lib/queue/index.test.d.ts.map +0 -1
  268. package/dist/lib/queue/index.test.js +0 -740
  269. package/dist/lib/queue/index.test.js.map +0 -1
  270. package/dist/lib/queue/types.d.ts +0 -52
  271. package/dist/lib/queue/types.d.ts.map +0 -1
  272. package/dist/lib/queue/types.js +0 -2
  273. package/dist/lib/queue/types.js.map +0 -1
@@ -0,0 +1,277 @@
1
+ import { err, mightThrow, ok } from "../errors/index.mjs";
2
+ import { FieldAmount, Scanner } from "../../cron/scanner.mjs";
3
+ //#region src/lib/cron/index.ts
4
+ const RETRY_DELAY_MS = 3600 * 1e3;
5
+ const ALIASES = {
6
+ "@yearly": "0 0 1 1 *",
7
+ "@monthly": "0 0 1 * *",
8
+ "@weekly": "0 0 * * 0",
9
+ "@daily": "0 0 * * *",
10
+ "@hourly": "0 * * * *",
11
+ "@minutely": "* * * * *"
12
+ };
13
+ const CronSecondRange = {
14
+ min: 0,
15
+ max: 59
16
+ };
17
+ const CronMinuteRange = {
18
+ min: 0,
19
+ max: 59
20
+ };
21
+ const CronHourRange = {
22
+ min: 0,
23
+ max: 23
24
+ };
25
+ const CronDayRange = {
26
+ min: 1,
27
+ max: 31
28
+ };
29
+ const CronMonthRange = {
30
+ min: 1,
31
+ max: 12
32
+ };
33
+ const CronDayOfWeekRange = {
34
+ min: 0,
35
+ max: 6
36
+ };
37
+ var Cron = class {
38
+ options;
39
+ status = "idle";
40
+ timeoutId = null;
41
+ second = Array(CronSecondRange.max + 1).fill(0);
42
+ minute = Array(CronMinuteRange.max + 1).fill(0);
43
+ hour = Array(CronHourRange.max + 1).fill(0);
44
+ day = Array(CronDayRange.max + 1).fill(0);
45
+ month = Array(CronMonthRange.max + 1).fill(0);
46
+ dayOfWeek = Array(CronDayOfWeekRange.max + 1).fill(0);
47
+ hasSeconds;
48
+ _dayWildcard = false;
49
+ _dowWildcard = false;
50
+ fillRange(values, min, max) {
51
+ for (let i = min; i <= max; i++) values[i] = 1;
52
+ }
53
+ handleStep(part, values, min, max) {
54
+ const [rangePart, stepStr] = part.split("/");
55
+ if (!rangePart) return err("InvalidValueError", `'${rangePart}' is empty`);
56
+ if (!stepStr) return err("InvalidValueError", `'${stepStr}' is empty`);
57
+ const step = Number(stepStr);
58
+ if (!Number.isInteger(step)) return err("InvalidValueError", `'${step}' is not a valid number`);
59
+ if (step <= 0) return err("OutOfBoundError", `Expected ${step} > 0`);
60
+ if (rangePart === "*") {
61
+ for (let i = min; i <= max; i += step) values[i] = 1;
62
+ return ok(true);
63
+ }
64
+ if (rangePart.includes("-")) return this.handleStepRange(rangePart, step, values, min, max);
65
+ return this.handleStepSingle(rangePart, step, values, min, max);
66
+ }
67
+ handleStepRange(range, step, values, min, max) {
68
+ const [startStr, endStr] = range.split("-");
69
+ if (!endStr) return err("InvalidValueError", `'${endStr}' is empty`);
70
+ let start = min;
71
+ if (startStr && startStr.length > 0) start = Number(startStr);
72
+ const end = Number(endStr);
73
+ if (!Number.isInteger(start)) return err("InvalidValueError", `'${start}' is not a valid number`);
74
+ if (!Number.isInteger(end)) return err("InvalidValueError", `'${end}' is not a valid number`);
75
+ if (start < min) return err("OutOfBoundError", `Expected ${start} >= ${min}`);
76
+ if (end > max) return err("OutOfBoundError", `Expected ${end} <= ${max}`);
77
+ if (start > end) return err("OutOfBoundError", `Expected ${start} <= ${end}`);
78
+ for (let i = start; i <= end; i += step) values[i] = 1;
79
+ return ok(true);
80
+ }
81
+ handleStepSingle(value, step, values, min, max) {
82
+ const start = Number(value);
83
+ if (!Number.isInteger(start)) return err("InvalidValueError", `'${start}' is not a valid number`);
84
+ if (start < min) return err("OutOfBoundError", `Expected ${start} >= ${min}`);
85
+ if (start > max) return err("OutOfBoundError", `Expected ${start} <= ${max}`);
86
+ for (let i = start; i <= max; i += step) values[i] = 1;
87
+ return ok(true);
88
+ }
89
+ handleRange(part, values, min, max) {
90
+ const [startStr, endStr] = part.split("-");
91
+ if (!startStr) return err("InvalidValueError", `'${startStr}' is empty`);
92
+ if (!endStr) return err("InvalidValueError", `'${endStr}' is empty`);
93
+ const start = Number(startStr);
94
+ const end = Number(endStr);
95
+ if (!Number.isInteger(start)) return err("InvalidValueError", `'${start}' is not a valid number`);
96
+ if (!Number.isInteger(end)) return err("InvalidValueError", `'${end}' is not a valid number`);
97
+ if (start < min) return err("OutOfBoundError", `Expected ${start} >= ${min}`);
98
+ if (end > max) return err("OutOfBoundError", `Expected ${end} <= ${max}`);
99
+ if (start > end) return err("OutOfBoundError", `Expected ${start} <= ${end}`);
100
+ for (let i = start; i <= end; i++) values[i] = 1;
101
+ return ok(true);
102
+ }
103
+ handleNumber(value, values, min, max) {
104
+ const n = Number(value);
105
+ if (!Number.isInteger(n)) return err("InvalidValueError", `'${value}' is not a valid number`);
106
+ if (n < min) return err("OutOfBoundError", `Expected ${n} >= ${min}`);
107
+ if (n > max) return err("OutOfBoundError", `Expected ${n} <= ${max}`);
108
+ values[n] = 1;
109
+ return ok(true);
110
+ }
111
+ constructor(options) {
112
+ this.options = options;
113
+ const expr = this.resolveAlias(options.schedule);
114
+ const [error, tokens] = new Scanner(expr).scan();
115
+ if (error) throw new Error(`${error.type}: ${error.message}`);
116
+ this.hasSeconds = expr.trim().split(/\s+/).length === FieldAmount.max;
117
+ const [parsingError, _] = this.parse(tokens);
118
+ if (parsingError) throw new Error(`${parsingError.type}: ${parsingError.message}`);
119
+ }
120
+ resolveAlias(schedule) {
121
+ return ALIASES[schedule] || schedule;
122
+ }
123
+ parse(tokens) {
124
+ for (let i = 0; i < tokens.length; i++) {
125
+ const token = tokens[i];
126
+ if (!token) return err("InvalidValueError", "Undefined token");
127
+ const tokenType = token.getTokenType();
128
+ switch (token.getField()) {
129
+ case "second": {
130
+ const [error, _] = this.handleField(token, this.second, CronSecondRange.min, CronSecondRange.max);
131
+ if (error) return err(error.type, `${error.message} in field '${token.getField()}'`);
132
+ break;
133
+ }
134
+ case "minute": {
135
+ const [error, _] = this.handleField(token, this.minute, CronMinuteRange.min, CronMinuteRange.max);
136
+ if (error) return err(error.type, `${error.message} in field '${token.getField()}'`);
137
+ break;
138
+ }
139
+ case "hour": {
140
+ const [error, _] = this.handleField(token, this.hour, CronHourRange.min, CronHourRange.max);
141
+ if (error) return err(error.type, `${error.message} in field '${token.getField()}'`);
142
+ break;
143
+ }
144
+ case "day": {
145
+ if (tokenType === "any") this._dayWildcard = true;
146
+ const [error, _] = this.handleField(token, this.day, CronDayRange.min, CronDayRange.max);
147
+ if (error) return err(error.type, `${error.message} in field '${token.getField()}'`);
148
+ break;
149
+ }
150
+ case "month": {
151
+ const [error, _] = this.handleField(token, this.month, CronMonthRange.min, CronMonthRange.max);
152
+ if (error) return err(error.type, `${error.message} in field '${token.getField()}'`);
153
+ break;
154
+ }
155
+ case "weekday": {
156
+ if (tokenType === "any") this._dowWildcard = true;
157
+ const [error, _] = this.handleField(token, this.dayOfWeek, CronDayOfWeekRange.min, CronDayOfWeekRange.max);
158
+ if (error) return err(error.type, `${error.message} in field '${token.getField()}'`);
159
+ break;
160
+ }
161
+ default: return err("InvalidValueError", `Invalid field '${token.getField()}'`);
162
+ }
163
+ }
164
+ return ok(true);
165
+ }
166
+ handleField(token, field, min, max) {
167
+ switch (token.getTokenType()) {
168
+ case "any":
169
+ this.fillRange(field, min, max);
170
+ break;
171
+ case "number": {
172
+ const [error, _] = this.handleNumber(token.getComponent(), field, min, max);
173
+ if (error) return err(error.type, error.message);
174
+ break;
175
+ }
176
+ case "range": {
177
+ const component = token.getComponent();
178
+ const [error, _] = this.handleRange(component, field, min, max);
179
+ if (error) return err(error.type, error.message);
180
+ break;
181
+ }
182
+ case "step": {
183
+ const component = token.getComponent();
184
+ const [error, _] = this.handleStep(component, field, min, max);
185
+ if (error) return err(error.type, error.message);
186
+ break;
187
+ }
188
+ default: return err("InvalidValueError", `Invalid token type '${token.getTokenType()}'`);
189
+ }
190
+ return ok(true);
191
+ }
192
+ matches(date) {
193
+ const s = date.getSeconds();
194
+ const m = date.getMinutes();
195
+ const h = date.getHours();
196
+ const d = date.getDate();
197
+ const mon = date.getMonth();
198
+ const dow = date.getDay();
199
+ const isSecondMatch = this.hasSeconds ? this.second[s] === 1 : true;
200
+ const isMinuteMatch = this.minute[m] === 1;
201
+ const isHourMatch = this.hour[h] === 1;
202
+ const isMonthMatch = this.month[mon + 1] === 1;
203
+ let isDayOrDowMatch;
204
+ if (!this._dayWildcard && !this._dowWildcard) isDayOrDowMatch = this.day[d] === 1 || this.dayOfWeek[dow] === 1;
205
+ else isDayOrDowMatch = this.day[d] === 1 && this.dayOfWeek[dow] === 1;
206
+ return isSecondMatch && isMinuteMatch && isHourMatch && isDayOrDowMatch && isMonthMatch;
207
+ }
208
+ getNextRun() {
209
+ const date = /* @__PURE__ */ new Date(/* @__PURE__ */ new Date());
210
+ if (this.hasSeconds) {
211
+ date.setMilliseconds(0);
212
+ date.setSeconds(date.getSeconds() + 1);
213
+ } else {
214
+ date.setSeconds(0, 0);
215
+ date.setMinutes(date.getMinutes() + 1);
216
+ }
217
+ const maxIterations = this.hasSeconds ? 366 * 4 * 24 * 3600 : 366 * 4 * 24 * 60;
218
+ for (let i = 0; i < maxIterations; i++) {
219
+ if (this.matches(date)) {
220
+ if (date > /* @__PURE__ */ new Date()) return new Date(date);
221
+ }
222
+ if (this.hasSeconds) date.setSeconds(date.getSeconds() + 1);
223
+ else date.setMinutes(date.getMinutes() + 1);
224
+ }
225
+ return null;
226
+ }
227
+ start() {
228
+ if (this.status !== "idle") return;
229
+ this.status = "running";
230
+ this.next();
231
+ }
232
+ stop() {
233
+ this.status = "idle";
234
+ if (this.timeoutId) {
235
+ clearTimeout(this.timeoutId);
236
+ this.timeoutId = null;
237
+ }
238
+ }
239
+ pause() {
240
+ if (this.status !== "running") return;
241
+ this.status = "paused";
242
+ if (this.timeoutId) {
243
+ clearTimeout(this.timeoutId);
244
+ this.timeoutId = null;
245
+ }
246
+ }
247
+ resume() {
248
+ if (this.status !== "paused") return;
249
+ this.status = "running";
250
+ this.next();
251
+ }
252
+ getStatus() {
253
+ return this.status;
254
+ }
255
+ next() {
256
+ if (this.status !== "running") return;
257
+ const nextRun = this.getNextRun();
258
+ if (!nextRun) {
259
+ this.timeoutId = setTimeout(() => this.next(), RETRY_DELAY_MS);
260
+ return;
261
+ }
262
+ const delay = nextRun.getTime() - Date.now();
263
+ this.timeoutId = setTimeout(() => {
264
+ this.run();
265
+ }, Math.max(0, delay));
266
+ }
267
+ async run() {
268
+ if (this.status !== "running") return;
269
+ const handlerResult = this.options.handler();
270
+ await mightThrow(Promise.resolve(handlerResult));
271
+ if (this.status === "running") this.next();
272
+ }
273
+ };
274
+ //#endregion
275
+ export { Cron };
276
+
277
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/lib/cron/index.ts"],"sourcesContent":["import { err, mightThrow, ok } from \"../errors/index.js\";\nimport { FieldAmount, Scanner, type Token } from \"./scanner.js\";\nimport type { CronOptions, CronParsingError, CronStatus } from \"./types.js\";\n\nconst RETRY_DELAY_MS = 60 * 60 * 1000; // 1 hour\n\nconst ALIASES: Record<string, string> = {\n \"@yearly\": \"0 0 1 1 *\",\n \"@monthly\": \"0 0 1 * *\",\n \"@weekly\": \"0 0 * * 0\",\n \"@daily\": \"0 0 * * *\",\n \"@hourly\": \"0 * * * *\",\n \"@minutely\": \"* * * * *\",\n};\n\nconst CronSecondRange = {\n min: 0,\n max: 59,\n} as const;\n\nconst CronMinuteRange = {\n min: 0,\n max: 59,\n} as const;\n\nconst CronHourRange = {\n min: 0,\n max: 23,\n} as const;\n\nconst CronDayRange = {\n min: 1,\n max: 31,\n} as const;\n\nconst CronMonthRange = {\n min: 1,\n max: 12,\n} as const;\n\nconst CronDayOfWeekRange = {\n min: 0,\n max: 6,\n} as const;\n\nexport class Cron {\n private options: CronOptions;\n private status: CronStatus = \"idle\";\n private timeoutId: NodeJS.Timeout | null = null;\n\n // Array-based storage using 1-indexed slots (0 = don't run, 1 = run)\n private second = Array<number>(CronSecondRange.max + 1).fill(0); // 0-59\n private minute = Array<number>(CronMinuteRange.max + 1).fill(0); // 0-59\n private hour = Array<number>(CronHourRange.max + 1).fill(0); // 0-23\n private day = Array<number>(CronDayRange.max + 1).fill(0); // indices 1-31 (0 unused)\n private month = Array<number>(CronMonthRange.max + 1).fill(0); // indices 1-12 (0 unused)\n private dayOfWeek = Array<number>(CronDayOfWeekRange.max + 1).fill(0); // 0-6\n private hasSeconds;\n private _dayWildcard = false;\n private _dowWildcard = false;\n\n // Fill all values from min to max with 1\n private fillRange(values: number[], min: number, max: number) {\n for (let i = min; i <= max; i++) {\n values[i] = 1;\n }\n }\n\n private handleStep(part: string, values: number[], min: number, max: number) {\n // Split step format into range and step components\n const [rangePart, stepStr] = part.split(\"/\");\n\n if (!rangePart) {\n return err<CronParsingError>(\n \"InvalidValueError\",\n `'${rangePart}' is empty`,\n );\n }\n\n if (!stepStr) {\n return err<CronParsingError>(\n \"InvalidValueError\",\n `'${stepStr}' is empty`,\n );\n }\n\n const step = Number(stepStr);\n\n // Validate step is a positive integer\n if (!Number.isInteger(step)) {\n return err<CronParsingError>(\n \"InvalidValueError\",\n `'${step}' is not a valid number`,\n );\n }\n\n if (step <= 0) {\n return err<CronParsingError>(\"OutOfBoundError\", `Expected ${step} > 0`);\n }\n\n if (rangePart === \"*\") {\n // Wildcard with step: apply step across entire range\n for (let i = min; i <= max; i += step) {\n values[i] = 1;\n }\n\n return ok(true);\n }\n\n if (rangePart.includes(\"-\")) {\n // Range with step: delegate to specialized handler\n return this.handleStepRange(rangePart, step, values, min, max);\n }\n\n // Single value with step: delegate to specialized handler\n return this.handleStepSingle(rangePart, step, values, min, max);\n }\n\n private handleStepRange(\n range: string,\n step: number,\n values: number[],\n min: number,\n max: number,\n ) {\n // Split range into start and end values\n const [startStr, endStr] = range.split(\"-\");\n\n if (!endStr) {\n return err<CronParsingError>(\"InvalidValueError\", `'${endStr}' is empty`);\n }\n\n let start = min;\n if (startStr && startStr.length > 0) {\n start = Number(startStr);\n }\n\n const end = Number(endStr);\n\n // Validate range boundaries are integers within bounds\n if (!Number.isInteger(start)) {\n return err<CronParsingError>(\n \"InvalidValueError\",\n `'${start}' is not a valid number`,\n );\n }\n\n if (!Number.isInteger(end)) {\n return err<CronParsingError>(\n \"InvalidValueError\",\n `'${end}' is not a valid number`,\n );\n }\n\n if (start < min) {\n return err<CronParsingError>(\n \"OutOfBoundError\",\n `Expected ${start} >= ${min}`,\n );\n }\n\n if (end > max) {\n return err<CronParsingError>(\n \"OutOfBoundError\",\n `Expected ${end} <= ${max}`,\n );\n }\n\n if (start > end) {\n return err<CronParsingError>(\n \"OutOfBoundError\",\n `Expected ${start} <= ${end}`,\n );\n }\n\n // Apply step through range\n for (let i = start; i <= end; i += step) {\n values[i] = 1;\n }\n\n return ok(true);\n }\n\n private handleStepSingle(\n value: string,\n step: number,\n values: number[],\n min: number,\n max: number,\n ) {\n const start = Number(value);\n\n // Validate starting value is an integer within bounds\n if (!Number.isInteger(start)) {\n return err<CronParsingError>(\n \"InvalidValueError\",\n `'${start}' is not a valid number`,\n );\n }\n\n if (start < min) {\n return err<CronParsingError>(\n \"OutOfBoundError\",\n `Expected ${start} >= ${min}`,\n );\n }\n\n if (start > max) {\n return err<CronParsingError>(\n \"OutOfBoundError\",\n `Expected ${start} <= ${max}`,\n );\n }\n\n // Apply step from start to end of range\n for (let i = start; i <= max; i += step) {\n values[i] = 1;\n }\n\n return ok(true);\n }\n\n private handleRange(\n part: string,\n values: number[],\n min: number,\n max: number,\n ) {\n // Split range into start and end values\n const [startStr, endStr] = part.split(\"-\");\n\n if (!startStr) {\n return err<CronParsingError>(\n \"InvalidValueError\",\n `'${startStr}' is empty`,\n );\n }\n\n if (!endStr) {\n return err<CronParsingError>(\"InvalidValueError\", `'${endStr}' is empty`);\n }\n\n const start = Number(startStr);\n const end = Number(endStr);\n\n // Validate range boundaries are integers within bounds\n if (!Number.isInteger(start)) {\n return err<CronParsingError>(\n \"InvalidValueError\",\n `'${start}' is not a valid number`,\n );\n }\n\n if (!Number.isInteger(end)) {\n return err<CronParsingError>(\n \"InvalidValueError\",\n `'${end}' is not a valid number`,\n );\n }\n\n if (start < min) {\n return err<CronParsingError>(\n \"OutOfBoundError\",\n `Expected ${start} >= ${min}`,\n );\n }\n\n if (end > max) {\n return err<CronParsingError>(\n \"OutOfBoundError\",\n `Expected ${end} <= ${max}`,\n );\n }\n\n if (start > end) {\n return err<CronParsingError>(\n \"OutOfBoundError\",\n `Expected ${start} <= ${end}`,\n );\n }\n\n // Mark all values in the range\n for (let i = start; i <= end; i++) {\n values[i] = 1;\n }\n\n return ok(true);\n }\n\n private handleNumber(\n value: string,\n values: number[],\n min: number,\n max: number,\n ) {\n const n = Number(value);\n\n // Validate value is an integer within bounds\n if (!Number.isInteger(n)) {\n return err<CronParsingError>(\n \"InvalidValueError\",\n `'${value}' is not a valid number`,\n );\n }\n\n if (n < min) {\n return err<CronParsingError>(\n \"OutOfBoundError\",\n `Expected ${n} >= ${min}`,\n );\n }\n if (n > max) {\n return err<CronParsingError>(\n \"OutOfBoundError\",\n `Expected ${n} <= ${max}`,\n );\n }\n\n values[n] = 1;\n\n return ok(true);\n }\n\n public constructor(options: CronOptions) {\n this.options = options;\n\n // Resolve alias or use raw expression\n const expr = this.resolveAlias(options.schedule);\n const [error, tokens] = new Scanner(expr).scan();\n if (error) throw new Error(`${error.type}: ${error.message}`);\n\n const fields = expr.trim().split(/\\s+/);\n this.hasSeconds = fields.length === FieldAmount.max;\n\n // Parse and validate the cron expression\n const [parsingError, _] = this.parse(tokens);\n\n if (parsingError) {\n throw new Error(`${parsingError.type}: ${parsingError.message}`);\n }\n }\n\n // Map alias to standard cron expression if present\n private resolveAlias(schedule: string) {\n return ALIASES[schedule] || schedule;\n }\n\n private parse(tokens: Token[]) {\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n\n if (!token) {\n return err<CronParsingError>(\"InvalidValueError\", \"Undefined token\");\n }\n\n const tokenType = token.getTokenType();\n\n switch (token.getField()) {\n case \"second\": {\n const [error, _] = this.handleField(\n token,\n this.second,\n CronSecondRange.min,\n CronSecondRange.max,\n );\n\n if (error) {\n return err<CronParsingError>(\n error.type,\n `${error.message} in field '${token.getField()}'`,\n );\n }\n\n break;\n }\n case \"minute\": {\n const [error, _] = this.handleField(\n token,\n this.minute,\n CronMinuteRange.min,\n CronMinuteRange.max,\n );\n\n if (error) {\n return err<CronParsingError>(\n error.type,\n `${error.message} in field '${token.getField()}'`,\n );\n }\n\n break;\n }\n case \"hour\": {\n const [error, _] = this.handleField(\n token,\n this.hour,\n CronHourRange.min,\n CronHourRange.max,\n );\n\n if (error) {\n return err<CronParsingError>(\n error.type,\n `${error.message} in field '${token.getField()}'`,\n );\n }\n\n break;\n }\n case \"day\": {\n if (tokenType === \"any\") {\n this._dayWildcard = true;\n }\n\n const [error, _] = this.handleField(\n token,\n this.day,\n CronDayRange.min,\n CronDayRange.max,\n );\n\n if (error) {\n return err<CronParsingError>(\n error.type,\n `${error.message} in field '${token.getField()}'`,\n );\n }\n\n break;\n }\n case \"month\": {\n const [error, _] = this.handleField(\n token,\n this.month,\n CronMonthRange.min,\n CronMonthRange.max,\n );\n\n if (error) {\n return err<CronParsingError>(\n error.type,\n `${error.message} in field '${token.getField()}'`,\n );\n }\n\n break;\n }\n case \"weekday\": {\n if (tokenType === \"any\") {\n this._dowWildcard = true;\n }\n\n const [error, _] = this.handleField(\n token,\n this.dayOfWeek,\n CronDayOfWeekRange.min,\n CronDayOfWeekRange.max,\n );\n\n if (error) {\n return err<CronParsingError>(\n error.type,\n `${error.message} in field '${token.getField()}'`,\n );\n }\n\n break;\n }\n default:\n return err<CronParsingError>(\n \"InvalidValueError\",\n `Invalid field '${token.getField()}'`,\n );\n }\n }\n\n return ok(true);\n }\n\n private handleField(token: Token, field: number[], min: number, max: number) {\n switch (token.getTokenType()) {\n case \"any\": {\n this.fillRange(field, min, max);\n break;\n }\n case \"number\": {\n const [error, _] = this.handleNumber(\n token.getComponent(),\n field,\n min,\n max,\n );\n if (error) return err<CronParsingError>(error.type, error.message);\n\n break;\n }\n case \"range\": {\n const component = token.getComponent();\n const [error, _] = this.handleRange(component, field, min, max);\n if (error) return err<CronParsingError>(error.type, error.message);\n\n break;\n }\n case \"step\": {\n const component = token.getComponent();\n const [error, _] = this.handleStep(component, field, min, max);\n if (error) return err<CronParsingError>(error.type, error.message);\n\n break;\n }\n default:\n return err<CronParsingError>(\n \"InvalidValueError\",\n `Invalid token type '${token.getTokenType()}'`,\n );\n }\n\n return ok(true);\n }\n\n public matches(date: Date) {\n // Extract date/time components\n const s = date.getSeconds();\n const m = date.getMinutes();\n const h = date.getHours();\n const d = date.getDate();\n const mon = date.getMonth();\n const dow = date.getDay();\n\n // Check each component against configured values\n const isSecondMatch = this.hasSeconds ? this.second[s] === 1 : true;\n const isMinuteMatch = this.minute[m] === 1;\n const isHourMatch = this.hour[h] === 1;\n const isMonthMatch = this.month[mon + 1] === 1;\n\n // Standard cron: when both day-of-month and day-of-week are restricted (not *),\n // fire if EITHER matches. When at least one is *, use AND (the wildcard is always 1).\n let isDayOrDowMatch: boolean;\n\n if (!this._dayWildcard && !this._dowWildcard) {\n isDayOrDowMatch = this.day[d] === 1 || this.dayOfWeek[dow] === 1;\n } else {\n isDayOrDowMatch = this.day[d] === 1 && this.dayOfWeek[dow] === 1;\n }\n\n return (\n isSecondMatch &&\n isMinuteMatch &&\n isHourMatch &&\n isDayOrDowMatch &&\n isMonthMatch\n );\n }\n\n public getNextRun() {\n const now = new Date();\n const date = new Date(now);\n\n // Start from next minute/second\n if (this.hasSeconds) {\n date.setMilliseconds(0);\n date.setSeconds(date.getSeconds() + 1);\n } else {\n date.setSeconds(0, 0);\n date.setMinutes(date.getMinutes() + 1);\n }\n\n // Search up to 4 years to cover leap-day schedules (next Feb 29 can be ~4 years away)\n const maxIterations = this.hasSeconds\n ? 366 * 4 * 24 * 3600\n : 366 * 4 * 24 * 60;\n\n for (let i = 0; i < maxIterations; i++) {\n if (this.matches(date)) {\n const freshNow = new Date();\n\n // Ensure match is still in the future\n if (date > freshNow) {\n return new Date(date);\n }\n }\n\n // Increment time\n if (this.hasSeconds) {\n date.setSeconds(date.getSeconds() + 1);\n } else {\n date.setMinutes(date.getMinutes() + 1);\n }\n }\n\n return null;\n }\n\n public start() {\n if (this.status !== \"idle\") return;\n\n this.status = \"running\";\n this.next();\n }\n\n public stop() {\n this.status = \"idle\";\n\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n this.timeoutId = null;\n }\n }\n\n public pause() {\n if (this.status !== \"running\") return;\n\n this.status = \"paused\";\n\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n this.timeoutId = null;\n }\n }\n\n public resume() {\n if (this.status !== \"paused\") return;\n\n this.status = \"running\";\n this.next();\n }\n\n public getStatus() {\n return this.status;\n }\n\n private next() {\n if (this.status !== \"running\") return;\n\n const nextRun = this.getNextRun();\n\n if (!nextRun) {\n this.timeoutId = setTimeout(() => this.next(), RETRY_DELAY_MS);\n return;\n }\n\n const delay = nextRun.getTime() - Date.now();\n\n const actualDelay = Math.max(0, delay);\n\n this.timeoutId = setTimeout(() => {\n this.run();\n }, actualDelay);\n }\n\n private async run() {\n if (this.status !== \"running\") return;\n\n const handlerResult = this.options.handler();\n await mightThrow(Promise.resolve(handlerResult));\n\n if (this.status === \"running\") {\n this.next();\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/lib/errors/index.ts
3
+ const ok = (data) => {
4
+ return [null, data];
5
+ };
6
+ const err = (type, message) => {
7
+ return [{
8
+ type,
9
+ message
10
+ }, null];
11
+ };
12
+ const mightThrowSync = (fn) => {
13
+ try {
14
+ return [null, fn()];
15
+ } catch (error) {
16
+ return [error, null];
17
+ }
18
+ };
19
+ const mightThrow = async (promise) => {
20
+ try {
21
+ return [null, await promise];
22
+ } catch (error) {
23
+ return [error, null];
24
+ }
25
+ };
26
+ //#endregion
27
+ exports.err = err;
28
+ exports.mightThrow = mightThrow;
29
+ exports.mightThrowSync = mightThrowSync;
30
+ exports.ok = ok;
@@ -0,0 +1,13 @@
1
+ import { CommonError } from "../../errors/types.cjs";
2
+
3
+ //#region src/lib/errors/index.d.ts
4
+ declare const ok: <T>(data: T) => readonly [null, T];
5
+ declare const err: <T extends CommonError>(type: T, message: string) => readonly [{
6
+ readonly type: T;
7
+ readonly message: string;
8
+ }, null];
9
+ declare const mightThrowSync: <T>(fn: () => T) => readonly [unknown, null] | readonly [null, T];
10
+ declare const mightThrow: <T>(promise: Promise<T>) => Promise<readonly [null, Awaited<T>] | readonly [unknown, null]>;
11
+ //#endregion
12
+ export { err, mightThrow, mightThrowSync, ok };
13
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../../src/lib/errors/index.ts"],"mappings":";;;cAEa,EAAA,MAAS,IAAA,EAAM,CAAA,qBAAC,CAAA;AAAA,cAIhB,GAAA,aAAiB,WAAA,EAAa,IAAA,EAAM,CAAA,EAAG,OAAA;EAAA;;;cAIvC,cAAA,MAAqB,EAAA,QAAU,CAAA,gDAAC,CAAA;AAAA,cAShC,UAAA,MAAuB,OAAA,EAAS,OAAA,CAAQ,CAAA,MAAE,OAAA,iBAAA,OAAA,CAAA,CAAA"}
@@ -0,0 +1,13 @@
1
+ import { CommonError } from "../../errors/types.mjs";
2
+
3
+ //#region src/lib/errors/index.d.ts
4
+ declare const ok: <T>(data: T) => readonly [null, T];
5
+ declare const err: <T extends CommonError>(type: T, message: string) => readonly [{
6
+ readonly type: T;
7
+ readonly message: string;
8
+ }, null];
9
+ declare const mightThrowSync: <T>(fn: () => T) => readonly [unknown, null] | readonly [null, T];
10
+ declare const mightThrow: <T>(promise: Promise<T>) => Promise<readonly [null, Awaited<T>] | readonly [unknown, null]>;
11
+ //#endregion
12
+ export { err, mightThrow, mightThrowSync, ok };
13
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/lib/errors/index.ts"],"mappings":";;;cAEa,EAAA,MAAS,IAAA,EAAM,CAAA,qBAAC,CAAA;AAAA,cAIhB,GAAA,aAAiB,WAAA,EAAa,IAAA,EAAM,CAAA,EAAG,OAAA;EAAA;;;cAIvC,cAAA,MAAqB,EAAA,QAAU,CAAA,gDAAC,CAAA;AAAA,cAShC,UAAA,MAAuB,OAAA,EAAS,OAAA,CAAQ,CAAA,MAAE,OAAA,iBAAA,OAAA,CAAA,CAAA"}
@@ -0,0 +1,28 @@
1
+ //#region src/lib/errors/index.ts
2
+ const ok = (data) => {
3
+ return [null, data];
4
+ };
5
+ const err = (type, message) => {
6
+ return [{
7
+ type,
8
+ message
9
+ }, null];
10
+ };
11
+ const mightThrowSync = (fn) => {
12
+ try {
13
+ return [null, fn()];
14
+ } catch (error) {
15
+ return [error, null];
16
+ }
17
+ };
18
+ const mightThrow = async (promise) => {
19
+ try {
20
+ return [null, await promise];
21
+ } catch (error) {
22
+ return [error, null];
23
+ }
24
+ };
25
+ //#endregion
26
+ export { err, mightThrow, mightThrowSync, ok };
27
+
28
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/lib/errors/index.ts"],"sourcesContent":["import type { CommonError } from \"./types.js\";\n\nexport const ok = <T>(data: T) => {\n return [null, data] as const;\n};\n\nexport const err = <T extends CommonError>(type: T, message: string) => {\n return [{ type, message }, null] as const;\n};\n\nexport const mightThrowSync = <T>(fn: () => T) => {\n try {\n const result = fn();\n return [null, result] as const;\n } catch (error) {\n return [error, null] as const;\n }\n};\n\nexport const mightThrow = async <T>(promise: Promise<T>) => {\n try {\n const data = await promise;\n return [null, data] as const;\n } catch (error) {\n return [error, null] as const;\n }\n};\n"],"mappings":";AAEA,MAAa,MAAS,SAAY;AAChC,QAAO,CAAC,MAAM,KAAK;;AAGrB,MAAa,OAA8B,MAAS,YAAoB;AACtE,QAAO,CAAC;EAAE;EAAM;EAAS,EAAE,KAAK;;AAGlC,MAAa,kBAAqB,OAAgB;AAChD,KAAI;AAEF,SAAO,CAAC,MADO,IAAI,CACE;UACd,OAAO;AACd,SAAO,CAAC,OAAO,KAAK;;;AAIxB,MAAa,aAAa,OAAU,YAAwB;AAC1D,KAAI;AAEF,SAAO,CAAC,MADK,MAAM,QACA;UACZ,OAAO;AACd,SAAO,CAAC,OAAO,KAAK"}
@@ -0,0 +1,37 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/lib/i18n/index.ts
3
+ var I18n = class {
4
+ locales;
5
+ currentLocale;
6
+ defaultLocale;
7
+ constructor(config) {
8
+ this.defaultLocale = config.defaultLocale;
9
+ this.currentLocale = config.defaultLocale;
10
+ this.locales = config.locales;
11
+ }
12
+ setLocale(locale) {
13
+ this.currentLocale = locale;
14
+ }
15
+ getLocale() {
16
+ return this.currentLocale;
17
+ }
18
+ translate(key, ...params) {
19
+ const currentTranslations = this.locales[this.currentLocale];
20
+ const defaultTranslations = this.locales[this.defaultLocale];
21
+ const translation = this.getNestedValue(currentTranslations, key) ?? this.getNestedValue(defaultTranslations, key);
22
+ if (!translation) return key;
23
+ const paramObj = params[0];
24
+ return this.substituteParams(translation, paramObj);
25
+ }
26
+ getNestedValue(obj, path) {
27
+ return path.split(".").reduce((current, key) => current?.[key], obj);
28
+ }
29
+ substituteParams(template, params) {
30
+ if (!params) return template;
31
+ return template.replace(/\{(\w+):(\w+)\}/g, (_match, name) => {
32
+ return String(params[name]);
33
+ });
34
+ }
35
+ };
36
+ //#endregion
37
+ exports.I18n = I18n;
@@ -0,0 +1,20 @@
1
+ import { BuildParamObject, GetNestedValue, NestedKeyOf } from "../../i18n/types.cjs";
2
+
3
+ //#region src/lib/i18n/index.d.ts
4
+ declare class I18n<const TLocales extends Record<string, Record<string, unknown>>, TDefaultLocale extends keyof TLocales> {
5
+ private locales;
6
+ private currentLocale;
7
+ private defaultLocale;
8
+ constructor(config: {
9
+ defaultLocale: TDefaultLocale;
10
+ locales: TLocales;
11
+ });
12
+ setLocale(locale: keyof TLocales): void;
13
+ getLocale(): keyof TLocales;
14
+ translate<TKey extends NestedKeyOf<TLocales[TDefaultLocale]>>(key: TKey, ...params: BuildParamObject<GetNestedValue<TLocales[TDefaultLocale], TKey> extends string ? GetNestedValue<TLocales[TDefaultLocale], TKey> : never> extends Record<string, never> ? [] : [BuildParamObject<GetNestedValue<TLocales[TDefaultLocale], TKey> extends string ? GetNestedValue<TLocales[TDefaultLocale], TKey> : never>]): string;
15
+ private getNestedValue;
16
+ private substituteParams;
17
+ }
18
+ //#endregion
19
+ export { I18n };
20
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../../src/lib/i18n/index.ts"],"mappings":";;;cAEa,IAAA,wBACY,MAAA,SAAe,MAAA,iDACT,QAAA;EAAA,QAErB,OAAA;EAAA,QACA,aAAA;EAAA,QACA,aAAA;cAEW,MAAA;IACjB,aAAA,EAAe,cAAA;IACf,OAAA,EAAS,QAAA;EAAA;EAOJ,SAAA,CAAU,MAAA,QAAc,QAAA;EAIxB,SAAA,CAAA,SAAS,QAAA;EAIT,SAAA,cAAuB,WAAA,CAAY,QAAA,CAAS,cAAA,GAAA,CACjD,GAAA,EAAK,IAAA,KACF,MAAA,EAAQ,gBAAA,CACT,cAAA,CAAe,QAAA,CAAS,cAAA,GAAiB,IAAA,mBACrC,cAAA,CAAe,QAAA,CAAS,cAAA,GAAiB,IAAA,mBAErC,MAAA,wBAGJ,gBAAA,CACE,cAAA,CAAe,QAAA,CAAS,cAAA,GAAiB,IAAA,mBACrC,cAAA,CAAe,QAAA,CAAS,cAAA,GAAiB,IAAA;EAAA,QAoB/C,cAAA;EAAA,QAOA,gBAAA;AAAA"}
@@ -0,0 +1,20 @@
1
+ import { BuildParamObject, GetNestedValue, NestedKeyOf } from "../../i18n/types.mjs";
2
+
3
+ //#region src/lib/i18n/index.d.ts
4
+ declare class I18n<const TLocales extends Record<string, Record<string, unknown>>, TDefaultLocale extends keyof TLocales> {
5
+ private locales;
6
+ private currentLocale;
7
+ private defaultLocale;
8
+ constructor(config: {
9
+ defaultLocale: TDefaultLocale;
10
+ locales: TLocales;
11
+ });
12
+ setLocale(locale: keyof TLocales): void;
13
+ getLocale(): keyof TLocales;
14
+ translate<TKey extends NestedKeyOf<TLocales[TDefaultLocale]>>(key: TKey, ...params: BuildParamObject<GetNestedValue<TLocales[TDefaultLocale], TKey> extends string ? GetNestedValue<TLocales[TDefaultLocale], TKey> : never> extends Record<string, never> ? [] : [BuildParamObject<GetNestedValue<TLocales[TDefaultLocale], TKey> extends string ? GetNestedValue<TLocales[TDefaultLocale], TKey> : never>]): string;
15
+ private getNestedValue;
16
+ private substituteParams;
17
+ }
18
+ //#endregion
19
+ export { I18n };
20
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/lib/i18n/index.ts"],"mappings":";;;cAEa,IAAA,wBACY,MAAA,SAAe,MAAA,iDACT,QAAA;EAAA,QAErB,OAAA;EAAA,QACA,aAAA;EAAA,QACA,aAAA;cAEW,MAAA;IACjB,aAAA,EAAe,cAAA;IACf,OAAA,EAAS,QAAA;EAAA;EAOJ,SAAA,CAAU,MAAA,QAAc,QAAA;EAIxB,SAAA,CAAA,SAAS,QAAA;EAIT,SAAA,cAAuB,WAAA,CAAY,QAAA,CAAS,cAAA,GAAA,CACjD,GAAA,EAAK,IAAA,KACF,MAAA,EAAQ,gBAAA,CACT,cAAA,CAAe,QAAA,CAAS,cAAA,GAAiB,IAAA,mBACrC,cAAA,CAAe,QAAA,CAAS,cAAA,GAAiB,IAAA,mBAErC,MAAA,wBAGJ,gBAAA,CACE,cAAA,CAAe,QAAA,CAAS,cAAA,GAAiB,IAAA,mBACrC,cAAA,CAAe,QAAA,CAAS,cAAA,GAAiB,IAAA;EAAA,QAoB/C,cAAA;EAAA,QAOA,gBAAA;AAAA"}
@@ -0,0 +1,38 @@
1
+ //#region src/lib/i18n/index.ts
2
+ var I18n = class {
3
+ locales;
4
+ currentLocale;
5
+ defaultLocale;
6
+ constructor(config) {
7
+ this.defaultLocale = config.defaultLocale;
8
+ this.currentLocale = config.defaultLocale;
9
+ this.locales = config.locales;
10
+ }
11
+ setLocale(locale) {
12
+ this.currentLocale = locale;
13
+ }
14
+ getLocale() {
15
+ return this.currentLocale;
16
+ }
17
+ translate(key, ...params) {
18
+ const currentTranslations = this.locales[this.currentLocale];
19
+ const defaultTranslations = this.locales[this.defaultLocale];
20
+ const translation = this.getNestedValue(currentTranslations, key) ?? this.getNestedValue(defaultTranslations, key);
21
+ if (!translation) return key;
22
+ const paramObj = params[0];
23
+ return this.substituteParams(translation, paramObj);
24
+ }
25
+ getNestedValue(obj, path) {
26
+ return path.split(".").reduce((current, key) => current?.[key], obj);
27
+ }
28
+ substituteParams(template, params) {
29
+ if (!params) return template;
30
+ return template.replace(/\{(\w+):(\w+)\}/g, (_match, name) => {
31
+ return String(params[name]);
32
+ });
33
+ }
34
+ };
35
+ //#endregion
36
+ export { I18n };
37
+
38
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/lib/i18n/index.ts"],"sourcesContent":["import type { BuildParamObject, GetNestedValue, NestedKeyOf } from \"./types.js\";\n\nexport class I18n<\n const TLocales extends Record<string, Record<string, unknown>>,\n TDefaultLocale extends keyof TLocales,\n> {\n private locales: TLocales;\n private currentLocale: keyof TLocales;\n private defaultLocale: TDefaultLocale;\n\n public constructor(config: {\n defaultLocale: TDefaultLocale;\n locales: TLocales;\n }) {\n this.defaultLocale = config.defaultLocale;\n this.currentLocale = config.defaultLocale;\n this.locales = config.locales;\n }\n\n public setLocale(locale: keyof TLocales) {\n this.currentLocale = locale;\n }\n\n public getLocale() {\n return this.currentLocale;\n }\n\n public translate<TKey extends NestedKeyOf<TLocales[TDefaultLocale]>>(\n key: TKey,\n ...params: BuildParamObject<\n GetNestedValue<TLocales[TDefaultLocale], TKey> extends string\n ? GetNestedValue<TLocales[TDefaultLocale], TKey>\n : never\n > extends Record<string, never>\n ? []\n : [\n BuildParamObject<\n GetNestedValue<TLocales[TDefaultLocale], TKey> extends string\n ? GetNestedValue<TLocales[TDefaultLocale], TKey>\n : never\n >,\n ]\n ) {\n const currentTranslations = this.locales[this.currentLocale];\n const defaultTranslations = this.locales[this.defaultLocale];\n\n const translation =\n this.getNestedValue(currentTranslations, key) ??\n this.getNestedValue(defaultTranslations, key);\n\n if (!translation) {\n return key;\n }\n\n const paramObj = params[0] as Record<string, unknown> | undefined;\n return this.substituteParams(translation, paramObj);\n }\n\n private getNestedValue(\n obj: Record<string, unknown> | undefined,\n path: string,\n ) {\n return path.split(\".\").reduce((current: any, key) => current?.[key], obj);\n }\n\n private substituteParams(template: string, params?: Record<string, unknown>) {\n if (!params) return template;\n\n return template.replace(/\\{(\\w+):(\\w+)\\}/g, (_match, name) => {\n return String(params[name]);\n });\n }\n}\n"],"mappings":";AAEA,IAAa,OAAb,MAGE;CACA;CACA;CACA;CAEA,YAAmB,QAGhB;AACD,OAAK,gBAAgB,OAAO;AAC5B,OAAK,gBAAgB,OAAO;AAC5B,OAAK,UAAU,OAAO;;CAGxB,UAAiB,QAAwB;AACvC,OAAK,gBAAgB;;CAGvB,YAAmB;AACjB,SAAO,KAAK;;CAGd,UACE,KACA,GAAG,QAaH;EACA,MAAM,sBAAsB,KAAK,QAAQ,KAAK;EAC9C,MAAM,sBAAsB,KAAK,QAAQ,KAAK;EAE9C,MAAM,cACJ,KAAK,eAAe,qBAAqB,IAAI,IAC7C,KAAK,eAAe,qBAAqB,IAAI;AAE/C,MAAI,CAAC,YACH,QAAO;EAGT,MAAM,WAAW,OAAO;AACxB,SAAO,KAAK,iBAAiB,aAAa,SAAS;;CAGrD,eACE,KACA,MACA;AACA,SAAO,KAAK,MAAM,IAAI,CAAC,QAAQ,SAAc,QAAQ,UAAU,MAAM,IAAI;;CAG3E,iBAAyB,UAAkB,QAAkC;AAC3E,MAAI,CAAC,OAAQ,QAAO;AAEpB,SAAO,SAAS,QAAQ,qBAAqB,QAAQ,SAAS;AAC5D,UAAO,OAAO,OAAO,MAAM;IAC3B"}