@sonamu-kit/tasks 0.0.1

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 (280) hide show
  1. package/.swcrc +17 -0
  2. package/README.md +7 -0
  3. package/dist/backend.d.ts +107 -0
  4. package/dist/backend.d.ts.map +1 -0
  5. package/dist/backend.js +3 -0
  6. package/dist/backend.js.map +1 -0
  7. package/dist/chaos.test.d.ts +2 -0
  8. package/dist/chaos.test.d.ts.map +1 -0
  9. package/dist/chaos.test.js +92 -0
  10. package/dist/chaos.test.js.map +1 -0
  11. package/dist/client.d.ts +178 -0
  12. package/dist/client.d.ts.map +1 -0
  13. package/dist/client.js +223 -0
  14. package/dist/client.js.map +1 -0
  15. package/dist/client.test.d.ts +2 -0
  16. package/dist/client.test.d.ts.map +1 -0
  17. package/dist/client.test.js +339 -0
  18. package/dist/client.test.js.map +1 -0
  19. package/dist/config.d.ts +22 -0
  20. package/dist/config.d.ts.map +1 -0
  21. package/dist/config.js +23 -0
  22. package/dist/config.js.map +1 -0
  23. package/dist/config.test.d.ts +2 -0
  24. package/dist/config.test.d.ts.map +1 -0
  25. package/dist/config.test.js +24 -0
  26. package/dist/config.test.js.map +1 -0
  27. package/dist/core/duration.d.ts +22 -0
  28. package/dist/core/duration.d.ts.map +1 -0
  29. package/dist/core/duration.js +64 -0
  30. package/dist/core/duration.js.map +1 -0
  31. package/dist/core/duration.test.d.ts +2 -0
  32. package/dist/core/duration.test.d.ts.map +1 -0
  33. package/dist/core/duration.test.js +265 -0
  34. package/dist/core/duration.test.js.map +1 -0
  35. package/dist/core/error.d.ts +15 -0
  36. package/dist/core/error.d.ts.map +1 -0
  37. package/dist/core/error.js +25 -0
  38. package/dist/core/error.js.map +1 -0
  39. package/dist/core/error.test.d.ts +2 -0
  40. package/dist/core/error.test.d.ts.map +1 -0
  41. package/dist/core/error.test.js +63 -0
  42. package/dist/core/error.test.js.map +1 -0
  43. package/dist/core/json.d.ts +5 -0
  44. package/dist/core/json.d.ts.map +1 -0
  45. package/dist/core/json.js +3 -0
  46. package/dist/core/json.js.map +1 -0
  47. package/dist/core/result.d.ts +22 -0
  48. package/dist/core/result.d.ts.map +1 -0
  49. package/dist/core/result.js +22 -0
  50. package/dist/core/result.js.map +1 -0
  51. package/dist/core/result.test.d.ts +2 -0
  52. package/dist/core/result.test.d.ts.map +1 -0
  53. package/dist/core/result.test.js +19 -0
  54. package/dist/core/result.test.js.map +1 -0
  55. package/dist/core/retry.d.ts +21 -0
  56. package/dist/core/retry.d.ts.map +1 -0
  57. package/dist/core/retry.js +25 -0
  58. package/dist/core/retry.js.map +1 -0
  59. package/dist/core/retry.test.d.ts +2 -0
  60. package/dist/core/retry.test.d.ts.map +1 -0
  61. package/dist/core/retry.test.js +37 -0
  62. package/dist/core/retry.test.js.map +1 -0
  63. package/dist/core/schema.d.ts +57 -0
  64. package/dist/core/schema.d.ts.map +1 -0
  65. package/dist/core/schema.js +4 -0
  66. package/dist/core/schema.js.map +1 -0
  67. package/dist/core/step.d.ts +96 -0
  68. package/dist/core/step.d.ts.map +1 -0
  69. package/dist/core/step.js +78 -0
  70. package/dist/core/step.js.map +1 -0
  71. package/dist/core/step.test.d.ts +2 -0
  72. package/dist/core/step.test.d.ts.map +1 -0
  73. package/dist/core/step.test.js +356 -0
  74. package/dist/core/step.test.js.map +1 -0
  75. package/dist/core/workflow.d.ts +78 -0
  76. package/dist/core/workflow.d.ts.map +1 -0
  77. package/dist/core/workflow.js +46 -0
  78. package/dist/core/workflow.js.map +1 -0
  79. package/dist/core/workflow.test.d.ts +2 -0
  80. package/dist/core/workflow.test.d.ts.map +1 -0
  81. package/dist/core/workflow.test.js +172 -0
  82. package/dist/core/workflow.test.js.map +1 -0
  83. package/dist/database/backend.d.ts +60 -0
  84. package/dist/database/backend.d.ts.map +1 -0
  85. package/dist/database/backend.js +387 -0
  86. package/dist/database/backend.js.map +1 -0
  87. package/dist/database/backend.test.d.ts +2 -0
  88. package/dist/database/backend.test.d.ts.map +1 -0
  89. package/dist/database/backend.test.js +17 -0
  90. package/dist/database/backend.test.js.map +1 -0
  91. package/dist/database/backend.testsuite.d.ts +20 -0
  92. package/dist/database/backend.testsuite.d.ts.map +1 -0
  93. package/dist/database/backend.testsuite.js +1174 -0
  94. package/dist/database/backend.testsuite.js.map +1 -0
  95. package/dist/database/base.d.ts +12 -0
  96. package/dist/database/base.d.ts.map +1 -0
  97. package/dist/database/base.js +19 -0
  98. package/dist/database/base.js.map +1 -0
  99. package/dist/database/migrations/20251212000000_0_init.js +9 -0
  100. package/dist/database/migrations/20251212000000_0_init.js.map +1 -0
  101. package/dist/database/migrations/20251212000000_1_tables.js +88 -0
  102. package/dist/database/migrations/20251212000000_1_tables.js.map +1 -0
  103. package/dist/database/migrations/20251212000000_2_fk.js +48 -0
  104. package/dist/database/migrations/20251212000000_2_fk.js.map +1 -0
  105. package/dist/database/migrations/20251212000000_3_indexes.js +107 -0
  106. package/dist/database/migrations/20251212000000_3_indexes.js.map +1 -0
  107. package/dist/database/pubsub.d.ts +17 -0
  108. package/dist/database/pubsub.d.ts.map +1 -0
  109. package/dist/database/pubsub.js +70 -0
  110. package/dist/database/pubsub.js.map +1 -0
  111. package/dist/database/pubsub.test.d.ts +2 -0
  112. package/dist/database/pubsub.test.d.ts.map +1 -0
  113. package/dist/database/pubsub.test.js +86 -0
  114. package/dist/database/pubsub.test.js.map +1 -0
  115. package/dist/errors.d.ts +8 -0
  116. package/dist/errors.d.ts.map +1 -0
  117. package/dist/errors.js +21 -0
  118. package/dist/errors.js.map +1 -0
  119. package/dist/execution.d.ts +82 -0
  120. package/dist/execution.d.ts.map +1 -0
  121. package/dist/execution.js +182 -0
  122. package/dist/execution.js.map +1 -0
  123. package/dist/execution.test.d.ts +2 -0
  124. package/dist/execution.test.d.ts.map +1 -0
  125. package/dist/execution.test.js +556 -0
  126. package/dist/execution.test.js.map +1 -0
  127. package/dist/index.d.ts +8 -0
  128. package/dist/index.d.ts.map +1 -0
  129. package/dist/index.js +6 -0
  130. package/dist/index.js.map +1 -0
  131. package/dist/internal.d.ts +12 -0
  132. package/dist/internal.d.ts.map +1 -0
  133. package/dist/internal.js +5 -0
  134. package/dist/internal.js.map +1 -0
  135. package/dist/practices/01-remote-workflow.d.ts +2 -0
  136. package/dist/practices/01-remote-workflow.d.ts.map +1 -0
  137. package/dist/practices/01-remote-workflow.js +69 -0
  138. package/dist/practices/01-remote-workflow.js.map +1 -0
  139. package/dist/practices/01-remote.d.ts +2 -0
  140. package/dist/practices/01-remote.d.ts.map +1 -0
  141. package/dist/practices/01-remote.js +87 -0
  142. package/dist/practices/01-remote.js.map +1 -0
  143. package/dist/practices/02-local.d.ts +2 -0
  144. package/dist/practices/02-local.d.ts.map +1 -0
  145. package/dist/practices/02-local.js +84 -0
  146. package/dist/practices/02-local.js.map +1 -0
  147. package/dist/practices/03-local-retry.d.ts +2 -0
  148. package/dist/practices/03-local-retry.d.ts.map +1 -0
  149. package/dist/practices/03-local-retry.js +85 -0
  150. package/dist/practices/03-local-retry.js.map +1 -0
  151. package/dist/practices/04-scheduler-dispose.d.ts +2 -0
  152. package/dist/practices/04-scheduler-dispose.d.ts.map +1 -0
  153. package/dist/practices/04-scheduler-dispose.js +65 -0
  154. package/dist/practices/04-scheduler-dispose.js.map +1 -0
  155. package/dist/practices/05-router.d.ts +2 -0
  156. package/dist/practices/05-router.d.ts.map +1 -0
  157. package/dist/practices/05-router.js +80 -0
  158. package/dist/practices/05-router.js.map +1 -0
  159. package/dist/registry.d.ts +33 -0
  160. package/dist/registry.d.ts.map +1 -0
  161. package/dist/registry.js +54 -0
  162. package/dist/registry.js.map +1 -0
  163. package/dist/registry.test.d.ts +2 -0
  164. package/dist/registry.test.d.ts.map +1 -0
  165. package/dist/registry.test.js +95 -0
  166. package/dist/registry.test.js.map +1 -0
  167. package/dist/scheduler.d.ts +22 -0
  168. package/dist/scheduler.d.ts.map +1 -0
  169. package/dist/scheduler.js +117 -0
  170. package/dist/scheduler.js.map +1 -0
  171. package/dist/tasks/index.d.ts +4 -0
  172. package/dist/tasks/index.d.ts.map +1 -0
  173. package/dist/tasks/index.js +5 -0
  174. package/dist/tasks/index.js.map +1 -0
  175. package/dist/tasks/local-task.d.ts +6 -0
  176. package/dist/tasks/local-task.d.ts.map +1 -0
  177. package/dist/tasks/local-task.js +95 -0
  178. package/dist/tasks/local-task.js.map +1 -0
  179. package/dist/tasks/remote-task.d.ts +11 -0
  180. package/dist/tasks/remote-task.d.ts.map +1 -0
  181. package/dist/tasks/remote-task.js +213 -0
  182. package/dist/tasks/remote-task.js.map +1 -0
  183. package/dist/tasks/shared.d.ts +8 -0
  184. package/dist/tasks/shared.d.ts.map +1 -0
  185. package/dist/tasks/shared.js +41 -0
  186. package/dist/tasks/shared.js.map +1 -0
  187. package/dist/testing/connection.d.ts +7 -0
  188. package/dist/testing/connection.d.ts.map +1 -0
  189. package/dist/testing/connection.js +38 -0
  190. package/dist/testing/connection.js.map +1 -0
  191. package/dist/types/config.d.ts +44 -0
  192. package/dist/types/config.d.ts.map +1 -0
  193. package/dist/types/config.js +3 -0
  194. package/dist/types/config.js.map +1 -0
  195. package/dist/types/context.d.ts +18 -0
  196. package/dist/types/context.d.ts.map +1 -0
  197. package/dist/types/context.js +4 -0
  198. package/dist/types/context.js.map +1 -0
  199. package/dist/types/events.d.ts +43 -0
  200. package/dist/types/events.d.ts.map +1 -0
  201. package/dist/types/events.js +3 -0
  202. package/dist/types/events.js.map +1 -0
  203. package/dist/types/index.d.ts +6 -0
  204. package/dist/types/index.d.ts.map +1 -0
  205. package/dist/types/index.js +3 -0
  206. package/dist/types/index.js.map +1 -0
  207. package/dist/types/task-items.d.ts +12 -0
  208. package/dist/types/task-items.d.ts.map +1 -0
  209. package/dist/types/task-items.js +3 -0
  210. package/dist/types/task-items.js.map +1 -0
  211. package/dist/types/utils.d.ts +4 -0
  212. package/dist/types/utils.d.ts.map +1 -0
  213. package/dist/types/utils.js +8 -0
  214. package/dist/types/utils.js.map +1 -0
  215. package/dist/worker.d.ts +61 -0
  216. package/dist/worker.d.ts.map +1 -0
  217. package/dist/worker.js +206 -0
  218. package/dist/worker.js.map +1 -0
  219. package/dist/worker.test.d.ts +2 -0
  220. package/dist/worker.test.d.ts.map +1 -0
  221. package/dist/worker.test.js +1163 -0
  222. package/dist/worker.test.js.map +1 -0
  223. package/dist/workflow.d.ts +44 -0
  224. package/dist/workflow.d.ts.map +1 -0
  225. package/dist/workflow.js +21 -0
  226. package/dist/workflow.js.map +1 -0
  227. package/dist/workflow.test.d.ts +2 -0
  228. package/dist/workflow.test.d.ts.map +1 -0
  229. package/dist/workflow.test.js +73 -0
  230. package/dist/workflow.test.js.map +1 -0
  231. package/nodemon.json +6 -0
  232. package/package.json +63 -0
  233. package/scripts/migrate.ts +11 -0
  234. package/src/backend.ts +133 -0
  235. package/src/chaos.test.ts +108 -0
  236. package/src/client.test.ts +297 -0
  237. package/src/client.ts +331 -0
  238. package/src/config.test.ts +23 -0
  239. package/src/config.ts +35 -0
  240. package/src/core/duration.test.ts +326 -0
  241. package/src/core/duration.ts +86 -0
  242. package/src/core/error.test.ts +77 -0
  243. package/src/core/error.ts +30 -0
  244. package/src/core/json.ts +2 -0
  245. package/src/core/result.test.ts +13 -0
  246. package/src/core/result.ts +29 -0
  247. package/src/core/retry.test.ts +41 -0
  248. package/src/core/retry.ts +29 -0
  249. package/src/core/schema.ts +74 -0
  250. package/src/core/step.test.ts +362 -0
  251. package/src/core/step.ts +152 -0
  252. package/src/core/workflow.test.ts +184 -0
  253. package/src/core/workflow.ts +127 -0
  254. package/src/database/backend.test.ts +16 -0
  255. package/src/database/backend.testsuite.ts +1376 -0
  256. package/src/database/backend.ts +655 -0
  257. package/src/database/base.ts +23 -0
  258. package/src/database/migrations/20251212000000_0_init.ts +10 -0
  259. package/src/database/migrations/20251212000000_1_tables.ts +54 -0
  260. package/src/database/migrations/20251212000000_2_fk.ts +46 -0
  261. package/src/database/migrations/20251212000000_3_indexes.ts +82 -0
  262. package/src/database/pubsub.test.ts +92 -0
  263. package/src/database/pubsub.ts +92 -0
  264. package/src/execution.test.ts +508 -0
  265. package/src/execution.ts +291 -0
  266. package/src/index.ts +7 -0
  267. package/src/internal.ts +11 -0
  268. package/src/practices/01-remote-workflow.ts +61 -0
  269. package/src/registry.test.ts +122 -0
  270. package/src/registry.ts +65 -0
  271. package/src/testing/connection.ts +44 -0
  272. package/src/worker.test.ts +1138 -0
  273. package/src/worker.ts +281 -0
  274. package/src/workflow.test.ts +68 -0
  275. package/src/workflow.ts +84 -0
  276. package/table_ddl.sql +60 -0
  277. package/templates/openworkflow.config.ts +22 -0
  278. package/tsconfig.json +40 -0
  279. package/tsconfig.test.json +4 -0
  280. package/vite.config.ts +13 -0
package/dist/config.js ADDED
@@ -0,0 +1,23 @@
1
+ import { loadConfig as loadC12Config } from "c12";
2
+ /**
3
+ * Create a typed OpenWorkflow configuration.
4
+ * @param config - the config
5
+ * @returns the config
6
+ */ export function defineConfig(config) {
7
+ return config;
8
+ }
9
+ /**
10
+ * Load the OpenWorkflow config at openworkflow.config.ts (or other extension;
11
+ * see https://github.com/unjs/c12)
12
+ * @param rootDir - Optional root directory to search from (defaults to
13
+ * process.cwd())
14
+ * @returns The loaded configuration and metadata
15
+ */ export async function loadConfig(rootDir) {
16
+ const cwd = rootDir ?? process.cwd();
17
+ return await loadC12Config({
18
+ cwd,
19
+ name: "openworkflow"
20
+ });
21
+ }
22
+
23
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts"],"sourcesContent":["import { loadConfig as loadC12Config } from \"c12\";\nimport type { Backend } from \"./backend\";\nimport type { WorkerOptions } from \"./worker\";\n\nexport interface OpenWorkflowConfig {\n backend: Backend;\n worker?: WorkerConfig;\n}\n\nexport type WorkerConfig = Pick<WorkerOptions, \"concurrency\">;\n\n/**\n * Create a typed OpenWorkflow configuration.\n * @param config - the config\n * @returns the config\n */\nexport function defineConfig(config: OpenWorkflowConfig): OpenWorkflowConfig {\n return config;\n}\n\n/**\n * Load the OpenWorkflow config at openworkflow.config.ts (or other extension;\n * see https://github.com/unjs/c12)\n * @param rootDir - Optional root directory to search from (defaults to\n * process.cwd())\n * @returns The loaded configuration and metadata\n */\nexport async function loadConfig(rootDir?: string) {\n const cwd = rootDir ?? process.cwd();\n\n return await loadC12Config<OpenWorkflowConfig>({\n cwd,\n name: \"openworkflow\",\n });\n}\n"],"names":["loadConfig","loadC12Config","defineConfig","config","rootDir","cwd","process","name"],"mappings":"AAAA,SAASA,cAAcC,aAAa,QAAQ,MAAM;AAWlD;;;;CAIC,GACD,OAAO,SAASC,aAAaC,MAA0B;IACrD,OAAOA;AACT;AAEA;;;;;;CAMC,GACD,OAAO,eAAeH,WAAWI,OAAgB;IAC/C,MAAMC,MAAMD,WAAWE,QAAQD,GAAG;IAElC,OAAO,MAAMJ,cAAkC;QAC7CI;QACAE,MAAM;IACR;AACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=config.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../src/config.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,24 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { defineConfig } from "./config.js";
3
+ import { createBackend } from "./testing/connection.js";
4
+ describe("defineConfig", async ()=>{
5
+ const backend = await createBackend();
6
+ test("returns the same config", ()=>{
7
+ const config = {
8
+ backend
9
+ };
10
+ const result = defineConfig(config);
11
+ expect(result).toBe(config);
12
+ });
13
+ });
14
+ describe("loadConfig", ()=>{
15
+ test("loads config file in the specified directory", async ()=>{
16
+ const { loadConfig } = await import("./config.js");
17
+ const { config, configFile } = await loadConfig("./templates");
18
+ expect(config).toBeDefined();
19
+ expect(config.backend).toBeDefined();
20
+ expect(configFile).toContain("/templates/openworkflow.config.ts");
21
+ });
22
+ });
23
+
24
+ //# sourceMappingURL=config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.test.ts"],"sourcesContent":["import { describe, expect, test } from \"vitest\";\nimport { defineConfig } from \"./config\";\nimport { createBackend } from \"./testing/connection\";\n\ndescribe(\"defineConfig\", async () => {\n const backend = await createBackend();\n\n test(\"returns the same config\", () => {\n const config = { backend };\n const result = defineConfig(config);\n expect(result).toBe(config);\n });\n});\n\ndescribe(\"loadConfig\", () => {\n test(\"loads config file in the specified directory\", async () => {\n const { loadConfig } = await import(\"./config\");\n const { config, configFile } = await loadConfig(\"./templates\");\n expect(config).toBeDefined();\n expect(config.backend).toBeDefined();\n expect(configFile).toContain(\"/templates/openworkflow.config.ts\");\n });\n});\n"],"names":["describe","expect","test","defineConfig","createBackend","backend","config","result","toBe","loadConfig","configFile","toBeDefined","toContain"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,IAAI,QAAQ,SAAS;AAChD,SAASC,YAAY,QAAQ,cAAW;AACxC,SAASC,aAAa,QAAQ,0BAAuB;AAErDJ,SAAS,gBAAgB;IACvB,MAAMK,UAAU,MAAMD;IAEtBF,KAAK,2BAA2B;QAC9B,MAAMI,SAAS;YAAED;QAAQ;QACzB,MAAME,SAASJ,aAAaG;QAC5BL,OAAOM,QAAQC,IAAI,CAACF;IACtB;AACF;AAEAN,SAAS,cAAc;IACrBE,KAAK,gDAAgD;QACnD,MAAM,EAAEO,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC;QACpC,MAAM,EAAEH,MAAM,EAAEI,UAAU,EAAE,GAAG,MAAMD,WAAW;QAChDR,OAAOK,QAAQK,WAAW;QAC1BV,OAAOK,OAAOD,OAAO,EAAEM,WAAW;QAClCV,OAAOS,YAAYE,SAAS,CAAC;IAC/B;AACF"}
@@ -0,0 +1,22 @@
1
+ import type { Result } from "./result";
2
+ type Years = "years" | "year" | "yrs" | "yr" | "y";
3
+ type Months = "months" | "month" | "mo";
4
+ type Weeks = "weeks" | "week" | "w";
5
+ type Days = "days" | "day" | "d";
6
+ type Hours = "hours" | "hour" | "hrs" | "hr" | "h";
7
+ type Minutes = "minutes" | "minute" | "mins" | "min" | "m";
8
+ type Seconds = "seconds" | "second" | "secs" | "sec" | "s";
9
+ type Milliseconds = "milliseconds" | "millisecond" | "msecs" | "msec" | "ms";
10
+ type Unit = Years | Months | Weeks | Days | Hours | Minutes | Seconds | Milliseconds;
11
+ type UnitAnyCase = Capitalize<Unit> | Uppercase<Unit> | Lowercase<Unit>;
12
+ export type DurationString = `${number}` | `${number}${UnitAnyCase}` | `${number} ${UnitAnyCase}`;
13
+ /**
14
+ * Parse a duration string into milliseconds. Exmaples:
15
+ * - short units: "1ms", "5s", "30m", "2h", "7d", "3w", "1y"
16
+ * - long units: "1 millisecond", "5 seconds", "30 minutes", "2 hours", "7 days", "3 weeks", "1 year"
17
+ * @param str - Duration string
18
+ * @returns Milliseconds
19
+ */
20
+ export declare function parseDuration(str: DurationString): Result<number>;
21
+ export {};
22
+ //# sourceMappingURL=duration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duration.d.ts","sourceRoot":"","sources":["../../src/core/duration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGvC,KAAK,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,GAAG,CAAC;AACnD,KAAK,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,IAAI,CAAC;AACxC,KAAK,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,GAAG,CAAC;AACpC,KAAK,IAAI,GAAG,MAAM,GAAG,KAAK,GAAG,GAAG,CAAC;AACjC,KAAK,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,GAAG,CAAC;AACnD,KAAK,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,GAAG,CAAC;AAC3D,KAAK,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,GAAG,CAAC;AAC3D,KAAK,YAAY,GAAG,cAAc,GAAG,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;AAC7E,KAAK,IAAI,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,OAAO,GAAG,OAAO,GAAG,YAAY,CAAC;AACrF,KAAK,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AACxE,MAAM,MAAM,cAAc,GAAG,GAAG,MAAM,EAAE,GAAG,GAAG,MAAM,GAAG,WAAW,EAAE,GAAG,GAAG,MAAM,IAAI,WAAW,EAAE,CAAC;AAElG;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,CA+DjE"}
@@ -0,0 +1,64 @@
1
+ import { err, ok } from "./result.js";
2
+ /**
3
+ * Parse a duration string into milliseconds. Exmaples:
4
+ * - short units: "1ms", "5s", "30m", "2h", "7d", "3w", "1y"
5
+ * - long units: "1 millisecond", "5 seconds", "30 minutes", "2 hours", "7 days", "3 weeks", "1 year"
6
+ * @param str - Duration string
7
+ * @returns Milliseconds
8
+ */ export function parseDuration(str) {
9
+ if (typeof str !== "string") {
10
+ return err(new TypeError(`Invalid duration format: expected a string but received ${typeof str}`));
11
+ }
12
+ if (str.length === 0) {
13
+ return err(new Error('Invalid duration format: ""'));
14
+ }
15
+ const match = /^(-?\.?\d+(?:\.\d+)?)\s*([a-z]+)?$/i.exec(str);
16
+ if (!match?.[1]) {
17
+ return err(new Error(`Invalid duration format: "${str}"`));
18
+ }
19
+ const numValue = Number.parseFloat(match[1]);
20
+ const unit = match[2]?.toLowerCase() ?? "ms"; // default to ms if not provided
21
+ const multipliers = {
22
+ millisecond: 1,
23
+ milliseconds: 1,
24
+ msec: 1,
25
+ msecs: 1,
26
+ ms: 1,
27
+ second: 1000,
28
+ seconds: 1000,
29
+ sec: 1000,
30
+ secs: 1000,
31
+ s: 1000,
32
+ minute: 60 * 1000,
33
+ minutes: 60 * 1000,
34
+ min: 60 * 1000,
35
+ mins: 60 * 1000,
36
+ m: 60 * 1000,
37
+ hour: 60 * 60 * 1000,
38
+ hours: 60 * 60 * 1000,
39
+ hr: 60 * 60 * 1000,
40
+ hrs: 60 * 60 * 1000,
41
+ h: 60 * 60 * 1000,
42
+ day: 24 * 60 * 60 * 1000,
43
+ days: 24 * 60 * 60 * 1000,
44
+ d: 24 * 60 * 60 * 1000,
45
+ week: 7 * 24 * 60 * 60 * 1000,
46
+ weeks: 7 * 24 * 60 * 60 * 1000,
47
+ w: 7 * 24 * 60 * 60 * 1000,
48
+ month: 2_629_800_000,
49
+ months: 2_629_800_000,
50
+ mo: 2_629_800_000,
51
+ year: 31_557_600_000,
52
+ years: 31_557_600_000,
53
+ yr: 31_557_600_000,
54
+ yrs: 31_557_600_000,
55
+ y: 31_557_600_000
56
+ };
57
+ const multiplier = multipliers[unit];
58
+ if (multiplier === undefined) {
59
+ return err(new Error(`Invalid duration format: "${str}"`));
60
+ }
61
+ return ok(numValue * multiplier);
62
+ }
63
+
64
+ //# sourceMappingURL=duration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/duration.ts"],"sourcesContent":["import type { Result } from \"./result\";\nimport { err, ok } from \"./result\";\n\ntype Years = \"years\" | \"year\" | \"yrs\" | \"yr\" | \"y\";\ntype Months = \"months\" | \"month\" | \"mo\";\ntype Weeks = \"weeks\" | \"week\" | \"w\";\ntype Days = \"days\" | \"day\" | \"d\";\ntype Hours = \"hours\" | \"hour\" | \"hrs\" | \"hr\" | \"h\";\ntype Minutes = \"minutes\" | \"minute\" | \"mins\" | \"min\" | \"m\";\ntype Seconds = \"seconds\" | \"second\" | \"secs\" | \"sec\" | \"s\";\ntype Milliseconds = \"milliseconds\" | \"millisecond\" | \"msecs\" | \"msec\" | \"ms\";\ntype Unit = Years | Months | Weeks | Days | Hours | Minutes | Seconds | Milliseconds;\ntype UnitAnyCase = Capitalize<Unit> | Uppercase<Unit> | Lowercase<Unit>;\nexport type DurationString = `${number}` | `${number}${UnitAnyCase}` | `${number} ${UnitAnyCase}`;\n\n/**\n * Parse a duration string into milliseconds. Exmaples:\n * - short units: \"1ms\", \"5s\", \"30m\", \"2h\", \"7d\", \"3w\", \"1y\"\n * - long units: \"1 millisecond\", \"5 seconds\", \"30 minutes\", \"2 hours\", \"7 days\", \"3 weeks\", \"1 year\"\n * @param str - Duration string\n * @returns Milliseconds\n */\nexport function parseDuration(str: DurationString): Result<number> {\n if (typeof str !== \"string\") {\n return err(\n new TypeError(`Invalid duration format: expected a string but received ${typeof str}`),\n );\n }\n\n if (str.length === 0) {\n return err(new Error('Invalid duration format: \"\"'));\n }\n\n const match = /^(-?\\.?\\d+(?:\\.\\d+)?)\\s*([a-z]+)?$/i.exec(str);\n\n if (!match?.[1]) {\n return err(new Error(`Invalid duration format: \"${str}\"`));\n }\n\n const numValue = Number.parseFloat(match[1]);\n const unit = match[2]?.toLowerCase() ?? \"ms\"; // default to ms if not provided\n\n const multipliers: Record<string, number> = {\n millisecond: 1,\n milliseconds: 1,\n msec: 1,\n msecs: 1,\n ms: 1,\n second: 1000,\n seconds: 1000,\n sec: 1000,\n secs: 1000,\n s: 1000,\n minute: 60 * 1000,\n minutes: 60 * 1000,\n min: 60 * 1000,\n mins: 60 * 1000,\n m: 60 * 1000,\n hour: 60 * 60 * 1000,\n hours: 60 * 60 * 1000,\n hr: 60 * 60 * 1000,\n hrs: 60 * 60 * 1000,\n h: 60 * 60 * 1000,\n day: 24 * 60 * 60 * 1000,\n days: 24 * 60 * 60 * 1000,\n d: 24 * 60 * 60 * 1000,\n week: 7 * 24 * 60 * 60 * 1000,\n weeks: 7 * 24 * 60 * 60 * 1000,\n w: 7 * 24 * 60 * 60 * 1000,\n month: 2_629_800_000,\n months: 2_629_800_000,\n mo: 2_629_800_000,\n year: 31_557_600_000,\n years: 31_557_600_000,\n yr: 31_557_600_000,\n yrs: 31_557_600_000,\n y: 31_557_600_000,\n };\n\n const multiplier = multipliers[unit];\n if (multiplier === undefined) {\n return err(new Error(`Invalid duration format: \"${str}\"`));\n }\n\n return ok(numValue * multiplier);\n}\n"],"names":["err","ok","parseDuration","str","TypeError","length","Error","match","exec","numValue","Number","parseFloat","unit","toLowerCase","multipliers","millisecond","milliseconds","msec","msecs","ms","second","seconds","sec","secs","s","minute","minutes","min","mins","m","hour","hours","hr","hrs","h","day","days","d","week","weeks","w","month","months","mo","year","years","yr","yrs","y","multiplier","undefined"],"mappings":"AACA,SAASA,GAAG,EAAEC,EAAE,QAAQ,cAAW;AAcnC;;;;;;CAMC,GACD,OAAO,SAASC,cAAcC,GAAmB;IAC/C,IAAI,OAAOA,QAAQ,UAAU;QAC3B,OAAOH,IACL,IAAII,UAAU,CAAC,wDAAwD,EAAE,OAAOD,KAAK;IAEzF;IAEA,IAAIA,IAAIE,MAAM,KAAK,GAAG;QACpB,OAAOL,IAAI,IAAIM,MAAM;IACvB;IAEA,MAAMC,QAAQ,sCAAsCC,IAAI,CAACL;IAEzD,IAAI,CAACI,OAAO,CAAC,EAAE,EAAE;QACf,OAAOP,IAAI,IAAIM,MAAM,CAAC,0BAA0B,EAAEH,IAAI,CAAC,CAAC;IAC1D;IAEA,MAAMM,WAAWC,OAAOC,UAAU,CAACJ,KAAK,CAAC,EAAE;IAC3C,MAAMK,OAAOL,KAAK,CAAC,EAAE,EAAEM,iBAAiB,MAAM,gCAAgC;IAE9E,MAAMC,cAAsC;QAC1CC,aAAa;QACbC,cAAc;QACdC,MAAM;QACNC,OAAO;QACPC,IAAI;QACJC,QAAQ;QACRC,SAAS;QACTC,KAAK;QACLC,MAAM;QACNC,GAAG;QACHC,QAAQ,KAAK;QACbC,SAAS,KAAK;QACdC,KAAK,KAAK;QACVC,MAAM,KAAK;QACXC,GAAG,KAAK;QACRC,MAAM,KAAK,KAAK;QAChBC,OAAO,KAAK,KAAK;QACjBC,IAAI,KAAK,KAAK;QACdC,KAAK,KAAK,KAAK;QACfC,GAAG,KAAK,KAAK;QACbC,KAAK,KAAK,KAAK,KAAK;QACpBC,MAAM,KAAK,KAAK,KAAK;QACrBC,GAAG,KAAK,KAAK,KAAK;QAClBC,MAAM,IAAI,KAAK,KAAK,KAAK;QACzBC,OAAO,IAAI,KAAK,KAAK,KAAK;QAC1BC,GAAG,IAAI,KAAK,KAAK,KAAK;QACtBC,OAAO;QACPC,QAAQ;QACRC,IAAI;QACJC,MAAM;QACNC,OAAO;QACPC,IAAI;QACJC,KAAK;QACLC,GAAG;IACL;IAEA,MAAMC,aAAanC,WAAW,CAACF,KAAK;IACpC,IAAIqC,eAAeC,WAAW;QAC5B,OAAOlD,IAAI,IAAIM,MAAM,CAAC,0BAA0B,EAAEH,IAAI,CAAC,CAAC;IAC1D;IAEA,OAAOF,GAAGQ,WAAWwC;AACvB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=duration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duration.test.d.ts","sourceRoot":"","sources":["../../src/core/duration.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,265 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { parseDuration } from "./duration.js";
3
+ import { err, ok } from "./result.js";
4
+ describe("parseDuration", ()=>{
5
+ describe("milliseconds", ()=>{
6
+ test("parses integer milliseconds", ()=>{
7
+ expect(parseDuration("100ms")).toEqual(ok(100));
8
+ expect(parseDuration("1ms")).toEqual(ok(1));
9
+ expect(parseDuration("5000ms")).toEqual(ok(5000));
10
+ });
11
+ test("parses decimal milliseconds", ()=>{
12
+ expect(parseDuration("1.5ms")).toEqual(ok(1.5));
13
+ expect(parseDuration("10.25ms")).toEqual(ok(10.25));
14
+ });
15
+ test("parses milliseconds with long format", ()=>{
16
+ expect(parseDuration("53 milliseconds")).toEqual(ok(53));
17
+ expect(parseDuration("17 msecs")).toEqual(ok(17));
18
+ expect(parseDuration("100 millisecond")).toEqual(ok(100));
19
+ });
20
+ test("parses numbers without unit as milliseconds", ()=>{
21
+ expect(parseDuration("100")).toEqual(ok(100));
22
+ expect(parseDuration("1000")).toEqual(ok(1000));
23
+ });
24
+ test("parses negative milliseconds", ()=>{
25
+ expect(parseDuration("-100ms")).toEqual(ok(-100));
26
+ expect(parseDuration("-100 milliseconds")).toEqual(ok(-100));
27
+ });
28
+ });
29
+ describe("seconds", ()=>{
30
+ test("parses integer seconds", ()=>{
31
+ expect(parseDuration("1s")).toEqual(ok(1000));
32
+ expect(parseDuration("5s")).toEqual(ok(5000));
33
+ expect(parseDuration("60s")).toEqual(ok(60_000));
34
+ });
35
+ test("parses decimal seconds", ()=>{
36
+ expect(parseDuration("1.5s")).toEqual(ok(1500));
37
+ expect(parseDuration("0.1s")).toEqual(ok(100));
38
+ expect(parseDuration("2.5s")).toEqual(ok(2500));
39
+ expect(parseDuration("0.001s")).toEqual(ok(1));
40
+ });
41
+ test("parses seconds with long format", ()=>{
42
+ expect(parseDuration("1 sec")).toEqual(ok(1000));
43
+ expect(parseDuration("5 seconds")).toEqual(ok(5000));
44
+ expect(parseDuration("10 secs")).toEqual(ok(10_000));
45
+ });
46
+ test("parses seconds with leading decimal", ()=>{
47
+ expect(parseDuration(".5s")).toEqual(ok(500));
48
+ expect(parseDuration(".5ms")).toEqual(ok(0.5));
49
+ });
50
+ test("parses negative seconds", ()=>{
51
+ expect(parseDuration("-5s")).toEqual(ok(-5000));
52
+ expect(parseDuration("-.5s")).toEqual(ok(-500));
53
+ });
54
+ });
55
+ describe("minutes", ()=>{
56
+ test("parses integer minutes", ()=>{
57
+ expect(parseDuration("1m")).toEqual(ok(60 * 1000));
58
+ expect(parseDuration("5m")).toEqual(ok(5 * 60 * 1000));
59
+ expect(parseDuration("30m")).toEqual(ok(30 * 60 * 1000));
60
+ });
61
+ test("parses decimal minutes", ()=>{
62
+ expect(parseDuration("1.5m")).toEqual(ok(1.5 * 60 * 1000));
63
+ expect(parseDuration("0.5m")).toEqual(ok(30 * 1000));
64
+ });
65
+ test("parses minutes with long format", ()=>{
66
+ expect(parseDuration("1 min")).toEqual(ok(60_000));
67
+ expect(parseDuration("5 minutes")).toEqual(ok(5 * 60 * 1000));
68
+ expect(parseDuration("10 mins")).toEqual(ok(10 * 60 * 1000));
69
+ });
70
+ });
71
+ describe("hours", ()=>{
72
+ test("parses integer hours", ()=>{
73
+ expect(parseDuration("1h")).toEqual(ok(60 * 60 * 1000));
74
+ expect(parseDuration("2h")).toEqual(ok(2 * 60 * 60 * 1000));
75
+ expect(parseDuration("24h")).toEqual(ok(24 * 60 * 60 * 1000));
76
+ });
77
+ test("parses decimal hours", ()=>{
78
+ expect(parseDuration("1.5h")).toEqual(ok(1.5 * 60 * 60 * 1000));
79
+ expect(parseDuration("0.25h")).toEqual(ok(15 * 60 * 1000));
80
+ });
81
+ test("parses hours with long format", ()=>{
82
+ expect(parseDuration("1 hr")).toEqual(ok(3_600_000));
83
+ expect(parseDuration("2 hours")).toEqual(ok(2 * 60 * 60 * 1000));
84
+ expect(parseDuration("3 hrs")).toEqual(ok(3 * 60 * 60 * 1000));
85
+ expect(parseDuration("1.5 hours")).toEqual(ok(5_400_000));
86
+ });
87
+ test("parses negative hours", ()=>{
88
+ expect(parseDuration("-1.5h")).toEqual(ok(-5_400_000));
89
+ expect(parseDuration("-10.5h")).toEqual(ok(-37_800_000));
90
+ expect(parseDuration("-.5h")).toEqual(ok(-1_800_000));
91
+ expect(parseDuration("-1.5 hours")).toEqual(ok(-5_400_000));
92
+ expect(parseDuration("-.5 hr")).toEqual(ok(-1_800_000));
93
+ });
94
+ });
95
+ describe("days", ()=>{
96
+ test("parses integer days", ()=>{
97
+ expect(parseDuration("1d")).toEqual(ok(24 * 60 * 60 * 1000));
98
+ expect(parseDuration("7d")).toEqual(ok(7 * 24 * 60 * 60 * 1000));
99
+ expect(parseDuration("30d")).toEqual(ok(30 * 24 * 60 * 60 * 1000));
100
+ });
101
+ test("parses decimal days", ()=>{
102
+ expect(parseDuration("1.5d")).toEqual(ok(1.5 * 24 * 60 * 60 * 1000));
103
+ expect(parseDuration("0.5d")).toEqual(ok(12 * 60 * 60 * 1000));
104
+ });
105
+ test("parses days with long format", ()=>{
106
+ expect(parseDuration("2 days")).toEqual(ok(172_800_000));
107
+ expect(parseDuration("1 day")).toEqual(ok(24 * 60 * 60 * 1000));
108
+ });
109
+ });
110
+ describe("weeks", ()=>{
111
+ test("parses integer weeks", ()=>{
112
+ expect(parseDuration("1w")).toEqual(ok(7 * 24 * 60 * 60 * 1000));
113
+ expect(parseDuration("2w")).toEqual(ok(2 * 7 * 24 * 60 * 60 * 1000));
114
+ expect(parseDuration("3w")).toEqual(ok(1_814_400_000));
115
+ });
116
+ test("parses decimal weeks", ()=>{
117
+ expect(parseDuration("1.5w")).toEqual(ok(1.5 * 7 * 24 * 60 * 60 * 1000));
118
+ expect(parseDuration("0.5w")).toEqual(ok(3.5 * 24 * 60 * 60 * 1000));
119
+ });
120
+ test("parses weeks with long format", ()=>{
121
+ expect(parseDuration("1 week")).toEqual(ok(604_800_000));
122
+ expect(parseDuration("2 weeks")).toEqual(ok(2 * 7 * 24 * 60 * 60 * 1000));
123
+ });
124
+ });
125
+ describe("months", ()=>{
126
+ test("parses integer months", ()=>{
127
+ expect(parseDuration("1mo")).toEqual(ok(2_629_800_000));
128
+ expect(parseDuration("2mo")).toEqual(ok(2 * 2_629_800_000));
129
+ expect(parseDuration("6mo")).toEqual(ok(6 * 2_629_800_000));
130
+ });
131
+ test("parses decimal months", ()=>{
132
+ expect(parseDuration("1.5mo")).toEqual(ok(1.5 * 2_629_800_000));
133
+ expect(parseDuration("0.5mo")).toEqual(ok(0.5 * 2_629_800_000));
134
+ });
135
+ test("parses months with long format", ()=>{
136
+ expect(parseDuration("1 month")).toEqual(ok(2_629_800_000));
137
+ expect(parseDuration("2 months")).toEqual(ok(2 * 2_629_800_000));
138
+ });
139
+ });
140
+ describe("years", ()=>{
141
+ test("parses integer years", ()=>{
142
+ expect(parseDuration("1y")).toEqual(ok(31_557_600_000));
143
+ expect(parseDuration("2y")).toEqual(ok(2 * 31_557_600_000));
144
+ expect(parseDuration("5y")).toEqual(ok(5 * 31_557_600_000));
145
+ });
146
+ test("parses decimal years", ()=>{
147
+ expect(parseDuration("1.5y")).toEqual(ok(1.5 * 31_557_600_000));
148
+ expect(parseDuration("0.5y")).toEqual(ok(0.5 * 31_557_600_000));
149
+ });
150
+ test("parses years with long format", ()=>{
151
+ expect(parseDuration("1 year")).toEqual(ok(31_557_600_000));
152
+ expect(parseDuration("2 years")).toEqual(ok(2 * 31_557_600_000));
153
+ expect(parseDuration("1 yr")).toEqual(ok(31_557_600_000));
154
+ expect(parseDuration("2 yrs")).toEqual(ok(2 * 31_557_600_000));
155
+ });
156
+ });
157
+ describe("case insensitivity", ()=>{
158
+ test("parses case-insensitive units", ()=>{
159
+ expect(parseDuration("5S")).toEqual(ok(5000));
160
+ expect(parseDuration("5M")).toEqual(ok(5 * 60 * 1000));
161
+ expect(parseDuration("5H")).toEqual(ok(5 * 60 * 60 * 1000));
162
+ expect(parseDuration("5D")).toEqual(ok(5 * 24 * 60 * 60 * 1000));
163
+ expect(parseDuration("5W")).toEqual(ok(5 * 7 * 24 * 60 * 60 * 1000));
164
+ });
165
+ test("parses case-insensitive long format", ()=>{
166
+ // @ts-expect-error - mixed-case (not in type but accepted at runtime)
167
+ expect(parseDuration("53 YeArS")).toEqual(ok(1_672_552_800_000));
168
+ // @ts-expect-error - mixed-case (not in type but accepted at runtime)
169
+ expect(parseDuration("53 WeEkS")).toEqual(ok(32_054_400_000));
170
+ // @ts-expect-error - mixed-case (not in type but accepted at runtime)
171
+ expect(parseDuration("53 DaYS")).toEqual(ok(4_579_200_000));
172
+ // @ts-expect-error - mixed-case (not in type but accepted at runtime)
173
+ expect(parseDuration("53 HoUrs")).toEqual(ok(190_800_000));
174
+ // @ts-expect-error - mixed-case (not in type but accepted at runtime)
175
+ expect(parseDuration("53 MiLliSeCondS")).toEqual(ok(53));
176
+ });
177
+ });
178
+ describe("whitespace handling", ()=>{
179
+ test("parses with single space", ()=>{
180
+ expect(parseDuration("1 s")).toEqual(ok(1000));
181
+ expect(parseDuration("5 m")).toEqual(ok(5 * 60 * 1000));
182
+ expect(parseDuration("2 h")).toEqual(ok(2 * 60 * 60 * 1000));
183
+ });
184
+ test("parses with multiple spaces", ()=>{
185
+ expect(parseDuration("1 s")).toEqual(ok(1000));
186
+ expect(parseDuration("5 m")).toEqual(ok(5 * 60 * 1000));
187
+ });
188
+ });
189
+ describe("edge cases", ()=>{
190
+ test("parses zero values", ()=>{
191
+ expect(parseDuration("0ms")).toEqual(ok(0));
192
+ expect(parseDuration("0s")).toEqual(ok(0));
193
+ expect(parseDuration("0m")).toEqual(ok(0));
194
+ expect(parseDuration("0h")).toEqual(ok(0));
195
+ expect(parseDuration("0d")).toEqual(ok(0));
196
+ expect(parseDuration("0")).toEqual(ok(0));
197
+ });
198
+ test("parses very small decimals", ()=>{
199
+ expect(parseDuration("0.001s")).toEqual(ok(1));
200
+ expect(parseDuration("0.1ms")).toEqual(ok(0.1));
201
+ });
202
+ test("parses large numbers", ()=>{
203
+ expect(parseDuration("999999ms")).toEqual(ok(999_999));
204
+ expect(parseDuration("1000s")).toEqual(ok(1_000_000));
205
+ });
206
+ });
207
+ describe("error cases", ()=>{
208
+ test("returns error on invalid format", ()=>{
209
+ // @ts-expect-error - invalid format
210
+ expect(parseDuration("invalid")).toEqual(err(new Error('Invalid duration format: "invalid"')));
211
+ // @ts-expect-error - invalid format
212
+ expect(parseDuration("10-.5")).toEqual(err(new Error('Invalid duration format: "10-.5"')));
213
+ // @ts-expect-error - invalid format
214
+ expect(parseDuration("foo")).toEqual(err(new Error('Invalid duration format: "foo"')));
215
+ });
216
+ test("returns error on empty string", ()=>{
217
+ // @ts-expect-error - empty string
218
+ expect(parseDuration("")).toEqual(err(new Error('Invalid duration format: ""')));
219
+ });
220
+ test("returns error on missing number", ()=>{
221
+ // @ts-expect-error - unit without number
222
+ expect(parseDuration("ms")).toEqual(err(new Error('Invalid duration format: "ms"')));
223
+ // @ts-expect-error - unit without number
224
+ expect(parseDuration("s")).toEqual(err(new Error('Invalid duration format: "s"')));
225
+ // @ts-expect-error - unit without number
226
+ expect(parseDuration("m")).toEqual(err(new Error('Invalid duration format: "m"')));
227
+ // @ts-expect-error - unit without number
228
+ expect(parseDuration("h")).toEqual(err(new Error('Invalid duration format: "h"')));
229
+ });
230
+ test("returns error on unknown unit", ()=>{
231
+ // @ts-expect-error - unknown unit
232
+ expect(parseDuration("100x")).toEqual(err(new Error('Invalid duration format: "100x"')));
233
+ // @ts-expect-error - unknown unit
234
+ expect(parseDuration("5z")).toEqual(err(new Error('Invalid duration format: "5z"')));
235
+ });
236
+ test("returns error on multiple units", ()=>{
237
+ // @ts-expect-error - multiple units
238
+ expect(parseDuration("1h30m")).toEqual(err(new Error('Invalid duration format: "1h30m"')));
239
+ // @ts-expect-error - multiple units
240
+ expect(parseDuration("5s100ms")).toEqual(err(new Error('Invalid duration format: "5s100ms"')));
241
+ });
242
+ test("returns error on leading/trailing spaces", ()=>{
243
+ expect(parseDuration(" 5s")).toEqual(err(new Error('Invalid duration format: " 5s"')));
244
+ // @ts-expect-error - trailing space
245
+ expect(parseDuration("5s ")).toEqual(err(new Error('Invalid duration format: "5s "')));
246
+ });
247
+ test("returns error on special characters", ()=>{
248
+ // @ts-expect-error - special characters
249
+ expect(parseDuration("5s!")).toEqual(err(new Error('Invalid duration format: "5s!"')));
250
+ // @ts-expect-error - special characters
251
+ expect(parseDuration("@5s")).toEqual(err(new Error('Invalid duration format: "@5s"')));
252
+ });
253
+ test("returns error on non-string types", ()=>{
254
+ expect(parseDuration(undefined)).toEqual(err(new TypeError("Invalid duration format: expected a string but received undefined")));
255
+ expect(parseDuration(null)).toEqual(err(new TypeError("Invalid duration format: expected a string but received object")));
256
+ expect(parseDuration([])).toEqual(err(new TypeError("Invalid duration format: expected a string but received object")));
257
+ expect(parseDuration({})).toEqual(err(new TypeError("Invalid duration format: expected a string but received object")));
258
+ expect(parseDuration(Number.NaN)).toEqual(err(new TypeError("Invalid duration format: expected a string but received number")));
259
+ expect(parseDuration(Number.POSITIVE_INFINITY)).toEqual(err(new TypeError("Invalid duration format: expected a string but received number")));
260
+ expect(parseDuration(Number.NEGATIVE_INFINITY)).toEqual(err(new TypeError("Invalid duration format: expected a string but received number")));
261
+ });
262
+ });
263
+ });
264
+
265
+ //# sourceMappingURL=duration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/duration.test.ts"],"sourcesContent":["import { describe, expect, test } from \"vitest\";\nimport type { DurationString } from \"./duration\";\nimport { parseDuration } from \"./duration\";\nimport { err, ok } from \"./result\";\n\ndescribe(\"parseDuration\", () => {\n describe(\"milliseconds\", () => {\n test(\"parses integer milliseconds\", () => {\n expect(parseDuration(\"100ms\")).toEqual(ok(100));\n expect(parseDuration(\"1ms\")).toEqual(ok(1));\n expect(parseDuration(\"5000ms\")).toEqual(ok(5000));\n });\n\n test(\"parses decimal milliseconds\", () => {\n expect(parseDuration(\"1.5ms\")).toEqual(ok(1.5));\n expect(parseDuration(\"10.25ms\")).toEqual(ok(10.25));\n });\n\n test(\"parses milliseconds with long format\", () => {\n expect(parseDuration(\"53 milliseconds\")).toEqual(ok(53));\n expect(parseDuration(\"17 msecs\")).toEqual(ok(17));\n expect(parseDuration(\"100 millisecond\")).toEqual(ok(100));\n });\n\n test(\"parses numbers without unit as milliseconds\", () => {\n expect(parseDuration(\"100\")).toEqual(ok(100));\n expect(parseDuration(\"1000\")).toEqual(ok(1000));\n });\n\n test(\"parses negative milliseconds\", () => {\n expect(parseDuration(\"-100ms\")).toEqual(ok(-100));\n expect(parseDuration(\"-100 milliseconds\")).toEqual(ok(-100));\n });\n });\n\n describe(\"seconds\", () => {\n test(\"parses integer seconds\", () => {\n expect(parseDuration(\"1s\")).toEqual(ok(1000));\n expect(parseDuration(\"5s\")).toEqual(ok(5000));\n expect(parseDuration(\"60s\")).toEqual(ok(60_000));\n });\n\n test(\"parses decimal seconds\", () => {\n expect(parseDuration(\"1.5s\")).toEqual(ok(1500));\n expect(parseDuration(\"0.1s\")).toEqual(ok(100));\n expect(parseDuration(\"2.5s\")).toEqual(ok(2500));\n expect(parseDuration(\"0.001s\")).toEqual(ok(1));\n });\n\n test(\"parses seconds with long format\", () => {\n expect(parseDuration(\"1 sec\")).toEqual(ok(1000));\n expect(parseDuration(\"5 seconds\")).toEqual(ok(5000));\n expect(parseDuration(\"10 secs\")).toEqual(ok(10_000));\n });\n\n test(\"parses seconds with leading decimal\", () => {\n expect(parseDuration(\".5s\")).toEqual(ok(500));\n expect(parseDuration(\".5ms\")).toEqual(ok(0.5));\n });\n\n test(\"parses negative seconds\", () => {\n expect(parseDuration(\"-5s\")).toEqual(ok(-5000));\n expect(parseDuration(\"-.5s\")).toEqual(ok(-500));\n });\n });\n\n describe(\"minutes\", () => {\n test(\"parses integer minutes\", () => {\n expect(parseDuration(\"1m\")).toEqual(ok(60 * 1000));\n expect(parseDuration(\"5m\")).toEqual(ok(5 * 60 * 1000));\n expect(parseDuration(\"30m\")).toEqual(ok(30 * 60 * 1000));\n });\n\n test(\"parses decimal minutes\", () => {\n expect(parseDuration(\"1.5m\")).toEqual(ok(1.5 * 60 * 1000));\n expect(parseDuration(\"0.5m\")).toEqual(ok(30 * 1000));\n });\n\n test(\"parses minutes with long format\", () => {\n expect(parseDuration(\"1 min\")).toEqual(ok(60_000));\n expect(parseDuration(\"5 minutes\")).toEqual(ok(5 * 60 * 1000));\n expect(parseDuration(\"10 mins\")).toEqual(ok(10 * 60 * 1000));\n });\n });\n\n describe(\"hours\", () => {\n test(\"parses integer hours\", () => {\n expect(parseDuration(\"1h\")).toEqual(ok(60 * 60 * 1000));\n expect(parseDuration(\"2h\")).toEqual(ok(2 * 60 * 60 * 1000));\n expect(parseDuration(\"24h\")).toEqual(ok(24 * 60 * 60 * 1000));\n });\n\n test(\"parses decimal hours\", () => {\n expect(parseDuration(\"1.5h\")).toEqual(ok(1.5 * 60 * 60 * 1000));\n expect(parseDuration(\"0.25h\")).toEqual(ok(15 * 60 * 1000));\n });\n\n test(\"parses hours with long format\", () => {\n expect(parseDuration(\"1 hr\")).toEqual(ok(3_600_000));\n expect(parseDuration(\"2 hours\")).toEqual(ok(2 * 60 * 60 * 1000));\n expect(parseDuration(\"3 hrs\")).toEqual(ok(3 * 60 * 60 * 1000));\n expect(parseDuration(\"1.5 hours\")).toEqual(ok(5_400_000));\n });\n\n test(\"parses negative hours\", () => {\n expect(parseDuration(\"-1.5h\")).toEqual(ok(-5_400_000));\n expect(parseDuration(\"-10.5h\")).toEqual(ok(-37_800_000));\n expect(parseDuration(\"-.5h\")).toEqual(ok(-1_800_000));\n expect(parseDuration(\"-1.5 hours\")).toEqual(ok(-5_400_000));\n expect(parseDuration(\"-.5 hr\")).toEqual(ok(-1_800_000));\n });\n });\n\n describe(\"days\", () => {\n test(\"parses integer days\", () => {\n expect(parseDuration(\"1d\")).toEqual(ok(24 * 60 * 60 * 1000));\n expect(parseDuration(\"7d\")).toEqual(ok(7 * 24 * 60 * 60 * 1000));\n expect(parseDuration(\"30d\")).toEqual(ok(30 * 24 * 60 * 60 * 1000));\n });\n\n test(\"parses decimal days\", () => {\n expect(parseDuration(\"1.5d\")).toEqual(ok(1.5 * 24 * 60 * 60 * 1000));\n expect(parseDuration(\"0.5d\")).toEqual(ok(12 * 60 * 60 * 1000));\n });\n\n test(\"parses days with long format\", () => {\n expect(parseDuration(\"2 days\")).toEqual(ok(172_800_000));\n expect(parseDuration(\"1 day\")).toEqual(ok(24 * 60 * 60 * 1000));\n });\n });\n\n describe(\"weeks\", () => {\n test(\"parses integer weeks\", () => {\n expect(parseDuration(\"1w\")).toEqual(ok(7 * 24 * 60 * 60 * 1000));\n expect(parseDuration(\"2w\")).toEqual(ok(2 * 7 * 24 * 60 * 60 * 1000));\n expect(parseDuration(\"3w\")).toEqual(ok(1_814_400_000));\n });\n\n test(\"parses decimal weeks\", () => {\n expect(parseDuration(\"1.5w\")).toEqual(ok(1.5 * 7 * 24 * 60 * 60 * 1000));\n expect(parseDuration(\"0.5w\")).toEqual(ok(3.5 * 24 * 60 * 60 * 1000));\n });\n\n test(\"parses weeks with long format\", () => {\n expect(parseDuration(\"1 week\")).toEqual(ok(604_800_000));\n expect(parseDuration(\"2 weeks\")).toEqual(ok(2 * 7 * 24 * 60 * 60 * 1000));\n });\n });\n\n describe(\"months\", () => {\n test(\"parses integer months\", () => {\n expect(parseDuration(\"1mo\")).toEqual(ok(2_629_800_000));\n expect(parseDuration(\"2mo\")).toEqual(ok(2 * 2_629_800_000));\n expect(parseDuration(\"6mo\")).toEqual(ok(6 * 2_629_800_000));\n });\n\n test(\"parses decimal months\", () => {\n expect(parseDuration(\"1.5mo\")).toEqual(ok(1.5 * 2_629_800_000));\n expect(parseDuration(\"0.5mo\")).toEqual(ok(0.5 * 2_629_800_000));\n });\n\n test(\"parses months with long format\", () => {\n expect(parseDuration(\"1 month\")).toEqual(ok(2_629_800_000));\n expect(parseDuration(\"2 months\")).toEqual(ok(2 * 2_629_800_000));\n });\n });\n\n describe(\"years\", () => {\n test(\"parses integer years\", () => {\n expect(parseDuration(\"1y\")).toEqual(ok(31_557_600_000));\n expect(parseDuration(\"2y\")).toEqual(ok(2 * 31_557_600_000));\n expect(parseDuration(\"5y\")).toEqual(ok(5 * 31_557_600_000));\n });\n\n test(\"parses decimal years\", () => {\n expect(parseDuration(\"1.5y\")).toEqual(ok(1.5 * 31_557_600_000));\n expect(parseDuration(\"0.5y\")).toEqual(ok(0.5 * 31_557_600_000));\n });\n\n test(\"parses years with long format\", () => {\n expect(parseDuration(\"1 year\")).toEqual(ok(31_557_600_000));\n expect(parseDuration(\"2 years\")).toEqual(ok(2 * 31_557_600_000));\n expect(parseDuration(\"1 yr\")).toEqual(ok(31_557_600_000));\n expect(parseDuration(\"2 yrs\")).toEqual(ok(2 * 31_557_600_000));\n });\n });\n\n describe(\"case insensitivity\", () => {\n test(\"parses case-insensitive units\", () => {\n expect(parseDuration(\"5S\")).toEqual(ok(5000));\n expect(parseDuration(\"5M\")).toEqual(ok(5 * 60 * 1000));\n expect(parseDuration(\"5H\")).toEqual(ok(5 * 60 * 60 * 1000));\n expect(parseDuration(\"5D\")).toEqual(ok(5 * 24 * 60 * 60 * 1000));\n expect(parseDuration(\"5W\")).toEqual(ok(5 * 7 * 24 * 60 * 60 * 1000));\n });\n\n test(\"parses case-insensitive long format\", () => {\n // @ts-expect-error - mixed-case (not in type but accepted at runtime)\n expect(parseDuration(\"53 YeArS\")).toEqual(ok(1_672_552_800_000));\n // @ts-expect-error - mixed-case (not in type but accepted at runtime)\n expect(parseDuration(\"53 WeEkS\")).toEqual(ok(32_054_400_000));\n // @ts-expect-error - mixed-case (not in type but accepted at runtime)\n expect(parseDuration(\"53 DaYS\")).toEqual(ok(4_579_200_000));\n // @ts-expect-error - mixed-case (not in type but accepted at runtime)\n expect(parseDuration(\"53 HoUrs\")).toEqual(ok(190_800_000));\n // @ts-expect-error - mixed-case (not in type but accepted at runtime)\n expect(parseDuration(\"53 MiLliSeCondS\")).toEqual(ok(53));\n });\n });\n\n describe(\"whitespace handling\", () => {\n test(\"parses with single space\", () => {\n expect(parseDuration(\"1 s\")).toEqual(ok(1000));\n expect(parseDuration(\"5 m\")).toEqual(ok(5 * 60 * 1000));\n expect(parseDuration(\"2 h\")).toEqual(ok(2 * 60 * 60 * 1000));\n });\n\n test(\"parses with multiple spaces\", () => {\n expect(parseDuration(\"1 s\")).toEqual(ok(1000));\n expect(parseDuration(\"5 m\")).toEqual(ok(5 * 60 * 1000));\n });\n });\n\n describe(\"edge cases\", () => {\n test(\"parses zero values\", () => {\n expect(parseDuration(\"0ms\")).toEqual(ok(0));\n expect(parseDuration(\"0s\")).toEqual(ok(0));\n expect(parseDuration(\"0m\")).toEqual(ok(0));\n expect(parseDuration(\"0h\")).toEqual(ok(0));\n expect(parseDuration(\"0d\")).toEqual(ok(0));\n expect(parseDuration(\"0\")).toEqual(ok(0));\n });\n\n test(\"parses very small decimals\", () => {\n expect(parseDuration(\"0.001s\")).toEqual(ok(1));\n expect(parseDuration(\"0.1ms\")).toEqual(ok(0.1));\n });\n\n test(\"parses large numbers\", () => {\n expect(parseDuration(\"999999ms\")).toEqual(ok(999_999));\n expect(parseDuration(\"1000s\")).toEqual(ok(1_000_000));\n });\n });\n\n describe(\"error cases\", () => {\n test(\"returns error on invalid format\", () => {\n // @ts-expect-error - invalid format\n expect(parseDuration(\"invalid\")).toEqual(\n err(new Error('Invalid duration format: \"invalid\"')),\n );\n // @ts-expect-error - invalid format\n expect(parseDuration(\"10-.5\")).toEqual(err(new Error('Invalid duration format: \"10-.5\"')));\n // @ts-expect-error - invalid format\n expect(parseDuration(\"foo\")).toEqual(err(new Error('Invalid duration format: \"foo\"')));\n });\n\n test(\"returns error on empty string\", () => {\n // @ts-expect-error - empty string\n expect(parseDuration(\"\")).toEqual(err(new Error('Invalid duration format: \"\"')));\n });\n\n test(\"returns error on missing number\", () => {\n // @ts-expect-error - unit without number\n expect(parseDuration(\"ms\")).toEqual(err(new Error('Invalid duration format: \"ms\"')));\n // @ts-expect-error - unit without number\n expect(parseDuration(\"s\")).toEqual(err(new Error('Invalid duration format: \"s\"')));\n // @ts-expect-error - unit without number\n expect(parseDuration(\"m\")).toEqual(err(new Error('Invalid duration format: \"m\"')));\n // @ts-expect-error - unit without number\n expect(parseDuration(\"h\")).toEqual(err(new Error('Invalid duration format: \"h\"')));\n });\n\n test(\"returns error on unknown unit\", () => {\n // @ts-expect-error - unknown unit\n expect(parseDuration(\"100x\")).toEqual(err(new Error('Invalid duration format: \"100x\"')));\n // @ts-expect-error - unknown unit\n expect(parseDuration(\"5z\")).toEqual(err(new Error('Invalid duration format: \"5z\"')));\n });\n\n test(\"returns error on multiple units\", () => {\n // @ts-expect-error - multiple units\n expect(parseDuration(\"1h30m\")).toEqual(err(new Error('Invalid duration format: \"1h30m\"')));\n // @ts-expect-error - multiple units\n expect(parseDuration(\"5s100ms\")).toEqual(\n err(new Error('Invalid duration format: \"5s100ms\"')),\n );\n });\n\n test(\"returns error on leading/trailing spaces\", () => {\n expect(parseDuration(\" 5s\")).toEqual(err(new Error('Invalid duration format: \" 5s\"')));\n // @ts-expect-error - trailing space\n expect(parseDuration(\"5s \")).toEqual(err(new Error('Invalid duration format: \"5s \"')));\n });\n\n test(\"returns error on special characters\", () => {\n // @ts-expect-error - special characters\n expect(parseDuration(\"5s!\")).toEqual(err(new Error('Invalid duration format: \"5s!\"')));\n // @ts-expect-error - special characters\n expect(parseDuration(\"@5s\")).toEqual(err(new Error('Invalid duration format: \"@5s\"')));\n });\n\n test(\"returns error on non-string types\", () => {\n expect(parseDuration(undefined as unknown as DurationString)).toEqual(\n err(new TypeError(\"Invalid duration format: expected a string but received undefined\")),\n );\n expect(parseDuration(null as unknown as DurationString)).toEqual(\n err(new TypeError(\"Invalid duration format: expected a string but received object\")),\n );\n expect(parseDuration([] as unknown as DurationString)).toEqual(\n err(new TypeError(\"Invalid duration format: expected a string but received object\")),\n );\n expect(parseDuration({} as unknown as DurationString)).toEqual(\n err(new TypeError(\"Invalid duration format: expected a string but received object\")),\n );\n expect(parseDuration(Number.NaN as unknown as DurationString)).toEqual(\n err(new TypeError(\"Invalid duration format: expected a string but received number\")),\n );\n expect(parseDuration(Number.POSITIVE_INFINITY as unknown as DurationString)).toEqual(\n err(new TypeError(\"Invalid duration format: expected a string but received number\")),\n );\n expect(parseDuration(Number.NEGATIVE_INFINITY as unknown as DurationString)).toEqual(\n err(new TypeError(\"Invalid duration format: expected a string but received number\")),\n );\n });\n });\n});\n"],"names":["describe","expect","test","parseDuration","err","ok","toEqual","Error","undefined","TypeError","Number","NaN","POSITIVE_INFINITY","NEGATIVE_INFINITY"],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { JsonValue } from "./json";
2
+ export type SerializedError = {
3
+ name?: string;
4
+ message: string;
5
+ stack?: string;
6
+ } & {
7
+ [key: string]: JsonValue;
8
+ };
9
+ /**
10
+ * Serialize an error to a JSON-compatible format.
11
+ * @param error - The error to serialize (can be Error instance or any value)
12
+ * @returns A JSON-serializable error object
13
+ */
14
+ export declare function serializeError(error: unknown): SerializedError;
15
+ //# sourceMappingURL=error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/core/error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAc9D"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Serialize an error to a JSON-compatible format.
3
+ * @param error - The error to serialize (can be Error instance or any value)
4
+ * @returns A JSON-serializable error object
5
+ */ export function serializeError(error) {
6
+ if (error instanceof Error) {
7
+ const { name, message, stack } = error;
8
+ if (stack) {
9
+ return {
10
+ name,
11
+ message,
12
+ stack
13
+ };
14
+ }
15
+ return {
16
+ name,
17
+ message
18
+ };
19
+ }
20
+ return {
21
+ message: String(error)
22
+ };
23
+ }
24
+
25
+ //# sourceMappingURL=error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/error.ts"],"sourcesContent":["import type { JsonValue } from \"./json\";\n\nexport type SerializedError = {\n name?: string;\n message: string;\n stack?: string;\n} & {\n [key: string]: JsonValue;\n};\n\n/**\n * Serialize an error to a JSON-compatible format.\n * @param error - The error to serialize (can be Error instance or any value)\n * @returns A JSON-serializable error object\n */\nexport function serializeError(error: unknown): SerializedError {\n if (error instanceof Error) {\n const { name, message, stack } = error;\n\n if (stack) {\n return { name, message, stack };\n }\n\n return { name, message };\n }\n\n return {\n message: String(error),\n };\n}\n"],"names":["serializeError","error","Error","name","message","stack","String"],"mappings":"AAUA;;;;CAIC,GACD,OAAO,SAASA,eAAeC,KAAc;IAC3C,IAAIA,iBAAiBC,OAAO;QAC1B,MAAM,EAAEC,IAAI,EAAEC,OAAO,EAAEC,KAAK,EAAE,GAAGJ;QAEjC,IAAII,OAAO;YACT,OAAO;gBAAEF;gBAAMC;gBAASC;YAAM;QAChC;QAEA,OAAO;YAAEF;YAAMC;QAAQ;IACzB;IAEA,OAAO;QACLA,SAASE,OAAOL;IAClB;AACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=error.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.test.d.ts","sourceRoot":"","sources":["../../src/core/error.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,63 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { serializeError } from "./error.js";
3
+ describe("serializeError", ()=>{
4
+ test("serializes Error instance with name, message, and stack", ()=>{
5
+ const error = new Error("Something went wrong");
6
+ const result = serializeError(error);
7
+ expect(result.name).toBe("Error");
8
+ expect(result.message).toBe("Something went wrong");
9
+ expect(result.stack).toBeDefined();
10
+ expect(typeof result.stack).toBe("string");
11
+ });
12
+ test("serializes TypeError with correct name", ()=>{
13
+ const error = new TypeError("Invalid type");
14
+ const result = serializeError(error);
15
+ expect(result.name).toBe("TypeError");
16
+ expect(result.message).toBe("Invalid type");
17
+ });
18
+ test("serializes custom Error subclass", ()=>{
19
+ class CustomError extends Error {
20
+ constructor(message){
21
+ super(message);
22
+ this.name = "CustomError";
23
+ }
24
+ }
25
+ const error = new CustomError("Custom error message");
26
+ const result = serializeError(error);
27
+ expect(result.name).toBe("CustomError");
28
+ expect(result.message).toBe("Custom error message");
29
+ });
30
+ test("serializes Error without stack as undefined", ()=>{
31
+ const error = new Error("No stack");
32
+ error.stack = undefined;
33
+ const result = serializeError(error);
34
+ expect(result.stack).toBeUndefined();
35
+ });
36
+ test("serializes string to message", ()=>{
37
+ const result = serializeError("string error");
38
+ expect(result.message).toBe("string error");
39
+ expect(result.name).toBeUndefined();
40
+ expect(result.stack).toBeUndefined();
41
+ });
42
+ test("serializes number to message", ()=>{
43
+ const result = serializeError(42);
44
+ expect(result.message).toBe("42");
45
+ });
46
+ test("serializes null to message", ()=>{
47
+ const result = serializeError(null);
48
+ expect(result.message).toBe("null");
49
+ });
50
+ test("serializes undefined to message", ()=>{
51
+ // eslint-disable-next-line unicorn/no-useless-undefined
52
+ const result = serializeError(undefined);
53
+ expect(result.message).toBe("undefined");
54
+ });
55
+ test("serializes object to message using String()", ()=>{
56
+ const result = serializeError({
57
+ foo: "bar"
58
+ });
59
+ expect(result.message).toBe("[object Object]");
60
+ });
61
+ });
62
+
63
+ //# sourceMappingURL=error.test.js.map