@schafevormfenster/rest-commons 0.1.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 (264) hide show
  1. package/CONTRIBUTING.md +1190 -0
  2. package/README.md +275 -0
  3. package/bin/setup.js +10 -0
  4. package/dist/api-schemas/error.schema.d.ts +20 -0
  5. package/dist/api-schemas/error.schema.d.ts.map +1 -0
  6. package/dist/api-schemas/error.schema.js +17 -0
  7. package/dist/api-schemas/health.schema.d.ts +497 -0
  8. package/dist/api-schemas/health.schema.d.ts.map +1 -0
  9. package/dist/api-schemas/health.schema.js +33 -0
  10. package/dist/api-schemas/okay.schema.d.ts +13 -0
  11. package/dist/api-schemas/okay.schema.d.ts.map +1 -0
  12. package/dist/api-schemas/okay.schema.js +5 -0
  13. package/dist/api-schemas/paginated-results.schema.d.ts +59 -0
  14. package/dist/api-schemas/paginated-results.schema.d.ts.map +1 -0
  15. package/dist/api-schemas/paginated-results.schema.js +10 -0
  16. package/dist/api-schemas/partial-results.schema.d.ts +30 -0
  17. package/dist/api-schemas/partial-results.schema.d.ts.map +1 -0
  18. package/dist/api-schemas/partial-results.schema.js +10 -0
  19. package/dist/api-schemas/result.schema.d.ts +17 -0
  20. package/dist/api-schemas/result.schema.d.ts.map +1 -0
  21. package/dist/api-schemas/result.schema.js +5 -0
  22. package/dist/api-schemas/results.schema.d.ts +21 -0
  23. package/dist/api-schemas/results.schema.d.ts.map +1 -0
  24. package/dist/api-schemas/results.schema.js +5 -0
  25. package/dist/helpers/correlation/get-correlation-id.d.ts +7 -0
  26. package/dist/helpers/correlation/get-correlation-id.d.ts.map +1 -0
  27. package/dist/helpers/correlation/get-correlation-id.js +16 -0
  28. package/dist/helpers/correlation/get-header.d.ts +7 -0
  29. package/dist/helpers/correlation/get-header.d.ts.map +1 -0
  30. package/dist/helpers/correlation/get-header.js +11 -0
  31. package/dist/helpers/detect-mime-type.d.ts +11 -0
  32. package/dist/helpers/detect-mime-type.d.ts.map +1 -0
  33. package/dist/helpers/detect-mime-type.js +40 -0
  34. package/dist/helpers/detect-suspicious-patterns.d.ts +8 -0
  35. package/dist/helpers/detect-suspicious-patterns.d.ts.map +1 -0
  36. package/dist/helpers/detect-suspicious-patterns.js +55 -0
  37. package/dist/helpers/eventify-constants.types.d.ts +32 -0
  38. package/dist/helpers/eventify-constants.types.d.ts.map +1 -0
  39. package/dist/helpers/eventify-constants.types.js +40 -0
  40. package/dist/helpers/hash-binary.d.ts +21 -0
  41. package/dist/helpers/hash-binary.d.ts.map +1 -0
  42. package/dist/helpers/hash-binary.js +28 -0
  43. package/dist/helpers/mime-types/detect-image-mime-type.d.ts +5 -0
  44. package/dist/helpers/mime-types/detect-image-mime-type.d.ts.map +1 -0
  45. package/dist/helpers/mime-types/detect-image-mime-type.js +41 -0
  46. package/dist/helpers/mime-types/detect-ole-mime-type.d.ts +6 -0
  47. package/dist/helpers/mime-types/detect-ole-mime-type.d.ts.map +1 -0
  48. package/dist/helpers/mime-types/detect-ole-mime-type.js +34 -0
  49. package/dist/helpers/mime-types/detect-pdf-mime-type.d.ts +5 -0
  50. package/dist/helpers/mime-types/detect-pdf-mime-type.d.ts.map +1 -0
  51. package/dist/helpers/mime-types/detect-pdf-mime-type.js +13 -0
  52. package/dist/helpers/mime-types/detect-zip-mime-type.d.ts +6 -0
  53. package/dist/helpers/mime-types/detect-zip-mime-type.d.ts.map +1 -0
  54. package/dist/helpers/mime-types/detect-zip-mime-type.js +23 -0
  55. package/dist/helpers/parameter-validation.d.ts +6 -0
  56. package/dist/helpers/parameter-validation.d.ts.map +1 -0
  57. package/dist/helpers/parameter-validation.js +19 -0
  58. package/dist/helpers/parameter-validation.types.d.ts +16 -0
  59. package/dist/helpers/parameter-validation.types.d.ts.map +1 -0
  60. package/dist/helpers/parameter-validation.types.js +38 -0
  61. package/dist/helpers/response-headers/build-api-unauthorized-headers.d.ts +6 -0
  62. package/dist/helpers/response-headers/build-api-unauthorized-headers.d.ts.map +1 -0
  63. package/dist/helpers/response-headers/build-api-unauthorized-headers.js +23 -0
  64. package/dist/helpers/response-headers/environment.types.d.ts +2 -0
  65. package/dist/helpers/response-headers/environment.types.d.ts.map +1 -0
  66. package/dist/helpers/response-headers/environment.types.js +1 -0
  67. package/dist/helpers/response-headers/resolve-environment.d.ts +8 -0
  68. package/dist/helpers/response-headers/resolve-environment.d.ts.map +1 -0
  69. package/dist/helpers/response-headers/resolve-environment.js +18 -0
  70. package/dist/helpers/slugify.d.ts +15 -0
  71. package/dist/helpers/slugify.d.ts.map +1 -0
  72. package/dist/helpers/slugify.js +32 -0
  73. package/dist/index.d.ts +36 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +41 -0
  76. package/dist/normalization/normalize-list.d.ts +11 -0
  77. package/dist/normalization/normalize-list.d.ts.map +1 -0
  78. package/dist/normalization/normalize-list.js +19 -0
  79. package/dist/normalization/normalize-location.d.ts +16 -0
  80. package/dist/normalization/normalize-location.d.ts.map +1 -0
  81. package/dist/normalization/normalize-location.js +26 -0
  82. package/dist/primitives/coordinate-precision.d.ts +10 -0
  83. package/dist/primitives/coordinate-precision.d.ts.map +1 -0
  84. package/dist/primitives/coordinate-precision.js +27 -0
  85. package/dist/primitives/geo-point.schema.d.ts +8 -0
  86. package/dist/primitives/geo-point.schema.d.ts.map +1 -0
  87. package/dist/primitives/geo-point.schema.js +10 -0
  88. package/dist/primitives/geoname-id.schema.d.ts +8 -0
  89. package/dist/primitives/geoname-id.schema.d.ts.map +1 -0
  90. package/dist/primitives/geoname-id.schema.js +9 -0
  91. package/dist/primitives/international-zip.schema.d.ts +76 -0
  92. package/dist/primitives/international-zip.schema.d.ts.map +1 -0
  93. package/dist/primitives/international-zip.schema.js +81 -0
  94. package/dist/primitives/latitude.schema.d.ts +9 -0
  95. package/dist/primitives/latitude.schema.d.ts.map +1 -0
  96. package/dist/primitives/latitude.schema.js +13 -0
  97. package/dist/primitives/location.schema.d.ts +8 -0
  98. package/dist/primitives/location.schema.d.ts.map +1 -0
  99. package/dist/primitives/location.schema.js +15 -0
  100. package/dist/primitives/longitude.schema.d.ts +9 -0
  101. package/dist/primitives/longitude.schema.d.ts.map +1 -0
  102. package/dist/primitives/longitude.schema.js +13 -0
  103. package/dist/primitives/numeric-id.schema.d.ts +8 -0
  104. package/dist/primitives/numeric-id.schema.d.ts.map +1 -0
  105. package/dist/primitives/numeric-id.schema.js +10 -0
  106. package/dist/primitives/slug.schema.d.ts +17 -0
  107. package/dist/primitives/slug.schema.d.ts.map +1 -0
  108. package/dist/primitives/slug.schema.js +30 -0
  109. package/dist/primitives/uuid.schema.d.ts +8 -0
  110. package/dist/primitives/uuid.schema.d.ts.map +1 -0
  111. package/dist/primitives/uuid.schema.js +9 -0
  112. package/dist/primitives/wikidata-id.schema.d.ts +9 -0
  113. package/dist/primitives/wikidata-id.schema.d.ts.map +1 -0
  114. package/dist/primitives/wikidata-id.schema.js +10 -0
  115. package/dist/time/boundary-enforcement.d.ts +11 -0
  116. package/dist/time/boundary-enforcement.d.ts.map +1 -0
  117. package/dist/time/boundary-enforcement.js +43 -0
  118. package/dist/time/bounded-time.schema.d.ts +31 -0
  119. package/dist/time/bounded-time.schema.d.ts.map +1 -0
  120. package/dist/time/bounded-time.schema.js +77 -0
  121. package/dist/time/flexible-time-parser.d.ts +12 -0
  122. package/dist/time/flexible-time-parser.d.ts.map +1 -0
  123. package/dist/time/flexible-time-parser.js +94 -0
  124. package/dist/time/flexible-time.schema.d.ts +31 -0
  125. package/dist/time/flexible-time.schema.d.ts.map +1 -0
  126. package/dist/time/flexible-time.schema.js +31 -0
  127. package/dist/time/get-week-end.d.ts +10 -0
  128. package/dist/time/get-week-end.d.ts.map +1 -0
  129. package/dist/time/get-week-end.js +25 -0
  130. package/dist/time/get-week-start.d.ts +10 -0
  131. package/dist/time/get-week-start.d.ts.map +1 -0
  132. package/dist/time/get-week-start.js +25 -0
  133. package/dist/time/is-relative-time.d.ts +8 -0
  134. package/dist/time/is-relative-time.d.ts.map +1 -0
  135. package/dist/time/is-relative-time.js +9 -0
  136. package/dist/time/iso8601.schema.d.ts +14 -0
  137. package/dist/time/iso8601.schema.d.ts.map +1 -0
  138. package/dist/time/iso8601.schema.js +17 -0
  139. package/dist/time/iso8601.types.d.ts +6 -0
  140. package/dist/time/iso8601.types.d.ts.map +1 -0
  141. package/dist/time/iso8601.types.js +11 -0
  142. package/dist/time/parse-relative-time.d.ts +9 -0
  143. package/dist/time/parse-relative-time.d.ts.map +1 -0
  144. package/dist/time/parse-relative-time.js +36 -0
  145. package/dist/time/relative-time.schema.d.ts +23 -0
  146. package/dist/time/relative-time.schema.d.ts.map +1 -0
  147. package/dist/time/relative-time.schema.js +25 -0
  148. package/dist/time/since-parameter.schema.d.ts +8 -0
  149. package/dist/time/since-parameter.schema.d.ts.map +1 -0
  150. package/dist/time/since-parameter.schema.js +56 -0
  151. package/dist/time/time-helpers.d.ts +19 -0
  152. package/dist/time/time-helpers.d.ts.map +1 -0
  153. package/dist/time/time-helpers.js +56 -0
  154. package/dist/time/time-schemas.d.ts +20 -0
  155. package/dist/time/time-schemas.d.ts.map +1 -0
  156. package/dist/time/time-schemas.js +25 -0
  157. package/dist/time/timezone.types.d.ts +17 -0
  158. package/dist/time/timezone.types.d.ts.map +1 -0
  159. package/dist/time/timezone.types.js +15 -0
  160. package/dist/validation/zod-error-handler.d.ts +3 -0
  161. package/dist/validation/zod-error-handler.d.ts.map +1 -0
  162. package/dist/validation/zod-error-handler.js +189 -0
  163. package/dist/validation/zod-utils.d.ts +9 -0
  164. package/dist/validation/zod-utils.d.ts.map +1 -0
  165. package/dist/validation/zod-utils.js +23 -0
  166. package/eslint.config.mjs +16 -0
  167. package/package.json +44 -0
  168. package/src/api-schemas/error.schema.test.ts +27 -0
  169. package/src/api-schemas/error.schema.ts +23 -0
  170. package/src/api-schemas/health.schema.test.ts +104 -0
  171. package/src/api-schemas/health.schema.ts +63 -0
  172. package/src/api-schemas/okay.schema.test.ts +15 -0
  173. package/src/api-schemas/okay.schema.ts +8 -0
  174. package/src/api-schemas/paginated-results.schema.ts +17 -0
  175. package/src/api-schemas/partial-results.schema.ts +13 -0
  176. package/src/api-schemas/result.schema.test.ts +19 -0
  177. package/src/api-schemas/result.schema.ts +9 -0
  178. package/src/api-schemas/results.schema.test.ts +15 -0
  179. package/src/api-schemas/results.schema.ts +9 -0
  180. package/src/helpers/correlation/get-correlation-id.test.ts +126 -0
  181. package/src/helpers/correlation/get-correlation-id.ts +22 -0
  182. package/src/helpers/correlation/get-header.test.ts +179 -0
  183. package/src/helpers/correlation/get-header.ts +21 -0
  184. package/src/helpers/detect-mime-type.test.ts +100 -0
  185. package/src/helpers/detect-mime-type.ts +46 -0
  186. package/src/helpers/detect-suspicious-patterns.test.ts +45 -0
  187. package/src/helpers/detect-suspicious-patterns.ts +57 -0
  188. package/src/helpers/eventify-constants.test.ts +52 -0
  189. package/src/helpers/eventify-constants.types.test.ts +52 -0
  190. package/src/helpers/eventify-constants.types.ts +51 -0
  191. package/src/helpers/hash-binary.test.ts +60 -0
  192. package/src/helpers/hash-binary.ts +30 -0
  193. package/src/helpers/mime-types/detect-image-mime-type.test.ts +73 -0
  194. package/src/helpers/mime-types/detect-image-mime-type.ts +50 -0
  195. package/src/helpers/mime-types/detect-ole-mime-type.test.ts +86 -0
  196. package/src/helpers/mime-types/detect-ole-mime-type.ts +44 -0
  197. package/src/helpers/mime-types/detect-pdf-mime-type.test.ts +39 -0
  198. package/src/helpers/mime-types/detect-pdf-mime-type.ts +15 -0
  199. package/src/helpers/mime-types/detect-zip-mime-type.test.ts +88 -0
  200. package/src/helpers/mime-types/detect-zip-mime-type.ts +28 -0
  201. package/src/helpers/parameter-validation.test.ts +35 -0
  202. package/src/helpers/parameter-validation.ts +32 -0
  203. package/src/helpers/process-eventify-request.ts +146 -0
  204. package/src/helpers/response-headers/build-api-unauthorized-headers.ts +30 -0
  205. package/src/helpers/response-headers/environment.types.ts +1 -0
  206. package/src/helpers/response-headers/resolve-environment.ts +17 -0
  207. package/src/helpers/slugify.test.ts +77 -0
  208. package/src/helpers/slugify.ts +34 -0
  209. package/src/index.ts +46 -0
  210. package/src/normalization/normalize-list.test.ts +43 -0
  211. package/src/normalization/normalize-list.ts +21 -0
  212. package/src/normalization/normalize-location.test.ts +91 -0
  213. package/src/normalization/normalize-location.ts +29 -0
  214. package/src/primitives/coordinate-precision.test.ts +46 -0
  215. package/src/primitives/coordinate-precision.ts +30 -0
  216. package/src/primitives/geo-point.schema.test.ts +70 -0
  217. package/src/primitives/geo-point.schema.ts +14 -0
  218. package/src/primitives/geoname-id.schema.test.ts +60 -0
  219. package/src/primitives/geoname-id.schema.ts +12 -0
  220. package/src/primitives/international-zip.schema.test.ts +212 -0
  221. package/src/primitives/international-zip.schema.ts +103 -0
  222. package/src/primitives/latitude.schema.test.ts +77 -0
  223. package/src/primitives/latitude.schema.ts +20 -0
  224. package/src/primitives/location.schema.test.ts +21 -0
  225. package/src/primitives/location.schema.ts +22 -0
  226. package/src/primitives/longitude.schema.test.ts +77 -0
  227. package/src/primitives/longitude.schema.ts +20 -0
  228. package/src/primitives/numeric-id.schema.test.ts +32 -0
  229. package/src/primitives/numeric-id.schema.ts +13 -0
  230. package/src/primitives/slug.schema.test.ts +101 -0
  231. package/src/primitives/slug.schema.ts +41 -0
  232. package/src/primitives/uuid.schema.test.ts +45 -0
  233. package/src/primitives/uuid.schema.ts +12 -0
  234. package/src/primitives/wikidata-id.schema.test.ts +51 -0
  235. package/src/primitives/wikidata-id.schema.ts +16 -0
  236. package/src/time/README.md +220 -0
  237. package/src/time/boundary-enforcement.test.ts +130 -0
  238. package/src/time/boundary-enforcement.ts +59 -0
  239. package/src/time/bounded-time.schema.test.ts +294 -0
  240. package/src/time/bounded-time.schema.ts +111 -0
  241. package/src/time/flexible-time-parser.test.ts +586 -0
  242. package/src/time/flexible-time-parser.ts +122 -0
  243. package/src/time/flexible-time.schema.test.ts +243 -0
  244. package/src/time/flexible-time.schema.ts +43 -0
  245. package/src/time/is-relative-time.test.ts +23 -0
  246. package/src/time/is-relative-time.ts +9 -0
  247. package/src/time/iso8601.schema.ts +29 -0
  248. package/src/time/iso8601.types.test.ts +112 -0
  249. package/src/time/iso8601.types.ts +21 -0
  250. package/src/time/parse-relative-time.test.ts +49 -0
  251. package/src/time/parse-relative-time.ts +50 -0
  252. package/src/time/relative-time.schema.test.ts +23 -0
  253. package/src/time/relative-time.schema.ts +38 -0
  254. package/src/time/since-parameter.schema.test.ts +59 -0
  255. package/src/time/since-parameter.schema.ts +69 -0
  256. package/src/time/time-helpers.test.ts +263 -0
  257. package/src/time/time-helpers.ts +78 -0
  258. package/src/time/time-schemas.test.ts +181 -0
  259. package/src/time/time-schemas.ts +42 -0
  260. package/src/time/time.schema.test.ts +237 -0
  261. package/src/time/timezone-independence.test.ts +188 -0
  262. package/src/time/timezone.types.test.ts +55 -0
  263. package/src/time/timezone.types.ts +22 -0
  264. package/tsconfig.json +26 -0
@@ -0,0 +1,17 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Zod schema for validating slug parameter in community slug endpoint.
4
+ * Checks for length between 2-150 characters and suspicious patterns.
5
+ * Enforces lowercase, no spaces, no special characters (only alphanumeric and hyphens).
6
+ */
7
+ export declare const SlugSchema: z.ZodEffects<z.ZodString, string, string>;
8
+ /**
9
+ * Zod schema that validates and transforms strings into slugs.
10
+ * Automatically converts input to URL-safe format.
11
+ *
12
+ * @example
13
+ * SlugSchemaWithTransform.parse("Hello World!") // "hello-world"
14
+ */
15
+ export declare const SlugSchemaWithTransform: z.ZodPipeline<z.ZodEffects<z.ZodString, string, string>, z.ZodEffects<z.ZodString, string, string>>;
16
+ export type Slug = z.infer<typeof SlugSchema>;
17
+ //# sourceMappingURL=slug.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slug.schema.d.ts","sourceRoot":"","sources":["../../src/primitives/slug.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;GAIG;AACH,eAAO,MAAM,UAAU,2CAgBpB,CAAC;AAEJ;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,qGAGjB,CAAC;AAEpB,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { z } from "zod";
2
+ import { validateNoSuspiciousPatterns } from "../helpers/parameter-validation";
3
+ import { slugify } from "../helpers/slugify";
4
+ /**
5
+ * Zod schema for validating slug parameter in community slug endpoint.
6
+ * Checks for length between 2-150 characters and suspicious patterns.
7
+ * Enforces lowercase, no spaces, no special characters (only alphanumeric and hyphens).
8
+ */
9
+ export const SlugSchema = z
10
+ .string()
11
+ .min(2, "Slug must be at least 2 characters long")
12
+ .max(150, "Slug must not exceed 150 characters")
13
+ .regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "Slug must be lowercase, contain only alphanumeric characters and hyphens, and not start or end with a hyphen")
14
+ .refine((value) => {
15
+ validateNoSuspiciousPatterns(value, "slug");
16
+ return true;
17
+ }, {
18
+ message: "Slug parameter contains suspicious patterns that are not allowed",
19
+ });
20
+ /**
21
+ * Zod schema that validates and transforms strings into slugs.
22
+ * Automatically converts input to URL-safe format.
23
+ *
24
+ * @example
25
+ * SlugSchemaWithTransform.parse("Hello World!") // "hello-world"
26
+ */
27
+ export const SlugSchemaWithTransform = z
28
+ .string()
29
+ .transform(slugify)
30
+ .pipe(SlugSchema);
@@ -0,0 +1,8 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Zod schema for validating UUID v4 format.
4
+ * Follows RFC 4122 specification.
5
+ */
6
+ export declare const UuidSchema: z.ZodString;
7
+ export type Uuid = z.infer<typeof UuidSchema>;
8
+ //# sourceMappingURL=uuid.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uuid.schema.d.ts","sourceRoot":"","sources":["../../src/primitives/uuid.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,eAAO,MAAM,UAAU,aAGqD,CAAC;AAE7E,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Zod schema for validating UUID v4 format.
4
+ * Follows RFC 4122 specification.
5
+ */
6
+ export const UuidSchema = z
7
+ .string()
8
+ .uuid("Must be a valid UUID v4")
9
+ .describe("UUID v4 format (e.g., '550e8400-e29b-41d4-a716-446655440000')");
@@ -0,0 +1,9 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Zod schema for validating Wikidata QID format.
4
+ * QIDs are unique identifiers for entities in Wikidata.
5
+ * Format: Q followed by one or more digits (e.g., "Q64" for Berlin)
6
+ */
7
+ export declare const WikidataIdSchema: z.ZodString;
8
+ export type WikidataId = z.infer<typeof WikidataIdSchema>;
9
+ //# sourceMappingURL=wikidata-id.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wikidata-id.schema.d.ts","sourceRoot":"","sources":["../../src/primitives/wikidata-id.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,aAMkB,CAAC;AAEhD,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Zod schema for validating Wikidata QID format.
4
+ * QIDs are unique identifiers for entities in Wikidata.
5
+ * Format: Q followed by one or more digits (e.g., "Q64" for Berlin)
6
+ */
7
+ export const WikidataIdSchema = z
8
+ .string()
9
+ .regex(/^Q[1-9]\d*$/, "Must be a valid Wikidata QID (e.g., 'Q64')")
10
+ .describe("Wikidata entity identifier (QID)");
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Helper function to clamp a timestamp to the allowed boundaries (-1w to +12m from now)
3
+ * Returns the clamped ISO8601 timestamp and a boolean indicating if clamping occurred
4
+ * All calculations are performed in UTC timezone
5
+ */
6
+ export declare function clampToBoundaries(timestamp: string, fieldName: string, now?: Date): {
7
+ clamped: string;
8
+ wasClamped: boolean;
9
+ originalValue: string;
10
+ };
11
+ //# sourceMappingURL=boundary-enforcement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundary-enforcement.d.ts","sourceRoot":"","sources":["../../src/time/boundary-enforcement.ts"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,GAAG,GAAE,IAAiB,GACrB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAyCjE"}
@@ -0,0 +1,43 @@
1
+ import { getLogger } from "@schafevormfenster/logging";
2
+ import dayjs from "dayjs";
3
+ import utc from "dayjs/plugin/utc.js";
4
+ dayjs.extend(utc);
5
+ const log = getLogger("helpers.time.boundary-enforcement");
6
+ /**
7
+ * Helper function to clamp a timestamp to the allowed boundaries (-1w to +12m from now)
8
+ * Returns the clamped ISO8601 timestamp and a boolean indicating if clamping occurred
9
+ * All calculations are performed in UTC timezone
10
+ */
11
+ export function clampToBoundaries(timestamp, fieldName, now = new Date()) {
12
+ const timestampMs = new Date(timestamp).getTime();
13
+ // Calculate boundaries using Day.js in UTC
14
+ const minBoundaryMs = dayjs.utc(now).subtract(1, "week").valueOf();
15
+ const maxBoundaryMs = dayjs.utc(now).add(12, "month").valueOf();
16
+ let clampedMs = timestampMs;
17
+ let wasClamped = false;
18
+ if (timestampMs < minBoundaryMs) {
19
+ clampedMs = minBoundaryMs;
20
+ wasClamped = true;
21
+ log.warn({
22
+ field: fieldName,
23
+ originalValue: timestamp,
24
+ clampedValue: new Date(clampedMs).toISOString(),
25
+ boundary: "minimum (-1w)",
26
+ }, `Calendar update query ${fieldName} clamped to minimum boundary`);
27
+ }
28
+ else if (timestampMs > maxBoundaryMs) {
29
+ clampedMs = maxBoundaryMs;
30
+ wasClamped = true;
31
+ log.warn({
32
+ field: fieldName,
33
+ originalValue: timestamp,
34
+ clampedValue: new Date(clampedMs).toISOString(),
35
+ boundary: "maximum (+12m)",
36
+ }, `Calendar update query ${fieldName} clamped to maximum boundary`);
37
+ }
38
+ return {
39
+ clamped: new Date(clampedMs).toISOString(),
40
+ wasClamped,
41
+ originalValue: timestamp,
42
+ };
43
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Options for creating bounded schemas
3
+ */
4
+ export interface BoundaryOptions {
5
+ /** Minimum allowed time (ISO8601 or relative from now) */
6
+ min?: string;
7
+ /** Maximum allowed time (ISO8601 or relative from now) */
8
+ max?: string;
9
+ }
10
+ /**
11
+ * Creates a flexible time schema with min/max boundaries
12
+ * @param options - Boundary configuration
13
+ * @returns Zod schema with boundary validation
14
+ * @example
15
+ * const schema = createBoundedFlexibleTimeSchema({ min: "1w", max: "1M" });
16
+ * schema.parse("3d"); // valid (between 1 week ago and 1 month in future)
17
+ * schema.parse("2M"); // throws error (exceeds max)
18
+ */
19
+ export declare function createBoundedFlexibleTimeSchema(options?: BoundaryOptions): any;
20
+ /**
21
+ * Creates a relative time schema with min/max boundaries
22
+ * @param options - Boundary configuration (relative times going backwards from now)
23
+ * @returns Zod schema with boundary validation
24
+ * @example
25
+ * const schema = createBoundedRelativeTimeSchema({ min: "1h", max: "30d" });
26
+ * schema.parse("3d"); // valid (3 days ago, between 1h and 30d ago)
27
+ * schema.parse("30m"); // throws error (too recent, less than 1h ago)
28
+ * schema.parse("60d"); // throws error (too old, more than 30d ago)
29
+ */
30
+ export declare function createBoundedRelativeTimeSchema(options?: BoundaryOptions): any;
31
+ //# sourceMappingURL=bounded-time.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounded-time.schema.d.ts","sourceRoot":"","sources":["../../src/time/bounded-time.schema.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,CAAC,OAAO,GAAE,eAAoB,OAsC5E;AAED;;;;;;;;;GASG;AACH,wBAAgB,+BAA+B,CAAC,OAAO,GAAE,eAAoB,OAqC5E"}
@@ -0,0 +1,77 @@
1
+ import { FlexibleTimePastSchema } from "./flexible-time.schema";
2
+ import { RelativeTimePastSchema } from "./relative-time.schema";
3
+ import { parseRelativeTime } from "./time-helpers";
4
+ /**
5
+ * Creates a flexible time schema with min/max boundaries
6
+ * @param options - Boundary configuration
7
+ * @returns Zod schema with boundary validation
8
+ * @example
9
+ * const schema = createBoundedFlexibleTimeSchema({ min: "1w", max: "1M" });
10
+ * schema.parse("3d"); // valid (between 1 week ago and 1 month in future)
11
+ * schema.parse("2M"); // throws error (exceeds max)
12
+ */
13
+ export function createBoundedFlexibleTimeSchema(options = {}) {
14
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
+ let schema = FlexibleTimePastSchema;
16
+ if (options.min) {
17
+ // Min is the oldest allowed time (furthest in the past)
18
+ // For relative times going backwards, larger values are older
19
+ const minTime = parseRelativeTime(options.min, new Date(), "past");
20
+ const minMs = new Date(minTime).getTime();
21
+ schema = schema.refine((value) => {
22
+ const valueMs = new Date(value).getTime();
23
+ return valueMs >= minMs;
24
+ }, {
25
+ message: `Time must be more recent than ${options.min} ago (minimum: ${minTime})`,
26
+ });
27
+ }
28
+ if (options.max) {
29
+ // Max is the newest allowed time (can be in future for flexible time)
30
+ const maxTime = parseRelativeTime(options.max, new Date(), "future");
31
+ const maxMs = new Date(maxTime).getTime();
32
+ schema = schema.refine((value) => {
33
+ const valueMs = new Date(value).getTime();
34
+ return valueMs <= maxMs;
35
+ }, {
36
+ message: `Time must be before ${options.max} in the future (maximum: ${maxTime})`,
37
+ });
38
+ }
39
+ return schema;
40
+ }
41
+ /**
42
+ * Creates a relative time schema with min/max boundaries
43
+ * @param options - Boundary configuration (relative times going backwards from now)
44
+ * @returns Zod schema with boundary validation
45
+ * @example
46
+ * const schema = createBoundedRelativeTimeSchema({ min: "1h", max: "30d" });
47
+ * schema.parse("3d"); // valid (3 days ago, between 1h and 30d ago)
48
+ * schema.parse("30m"); // throws error (too recent, less than 1h ago)
49
+ * schema.parse("60d"); // throws error (too old, more than 30d ago)
50
+ */
51
+ export function createBoundedRelativeTimeSchema(options = {}) {
52
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
53
+ let schema = RelativeTimePastSchema;
54
+ if (options.min) {
55
+ // Min is the most recent allowed (closest to now)
56
+ const minTime = parseRelativeTime(options.min, new Date(), "past");
57
+ const minMs = new Date(minTime).getTime();
58
+ schema = schema.refine((value) => {
59
+ const valueMs = new Date(value).getTime();
60
+ return valueMs <= minMs; // Value must be older (earlier) than min
61
+ }, {
62
+ message: `Time must be at least ${options.min} ago (more recent than ${minTime})`,
63
+ });
64
+ }
65
+ if (options.max) {
66
+ // Max is the oldest allowed (furthest from now)
67
+ const maxTime = parseRelativeTime(options.max, new Date(), "past");
68
+ const maxMs = new Date(maxTime).getTime();
69
+ schema = schema.refine((value) => {
70
+ const valueMs = new Date(value).getTime();
71
+ return valueMs >= maxMs; // Value must be newer (later) than max
72
+ }, {
73
+ message: `Time cannot be more than ${options.max} ago (older than ${maxTime})`,
74
+ });
75
+ }
76
+ return schema;
77
+ }
@@ -0,0 +1,12 @@
1
+ import { FlexibleTime } from "./time-schemas";
2
+ /**
3
+ * Parse a flexible time input (ISO 8601 or relative format) to ISO 8601 string
4
+ * Uses Zod schemas for validation instead of manual parsing
5
+ * All calculations are performed in UTC timezone
6
+ */
7
+ export declare function parseFlexibleTime(input: FlexibleTime, baseTime?: Date): string;
8
+ /**
9
+ * Create a flexible time parser with a specific base time (useful for testing)
10
+ */
11
+ export declare function createFlexibleTimeParser(baseTime: Date): (input: FlexibleTime) => string;
12
+ //# sourceMappingURL=flexible-time-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flexible-time-parser.d.ts","sourceRoot":"","sources":["../../src/time/flexible-time-parser.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,YAAY,EACb,MAAM,gBAAgB,CAAC;AAKxB;;;;GAIG;AAEH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,YAAY,EACnB,QAAQ,GAAE,IAAiB,GAC1B,MAAM,CA2FR;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,IAAI,IAC7C,OAAO,YAAY,YAC5B"}
@@ -0,0 +1,94 @@
1
+ import dayjs from "dayjs";
2
+ import isoWeek from "dayjs/plugin/isoWeek.js";
3
+ import utc from "dayjs/plugin/utc.js";
4
+ import { ISO8601Schema } from "./iso8601.types";
5
+ import { RelativeTimeSchema, FlexibleTimeSchema, } from "./time-schemas";
6
+ dayjs.extend(isoWeek);
7
+ dayjs.extend(utc);
8
+ /**
9
+ * Parse a flexible time input (ISO 8601 or relative format) to ISO 8601 string
10
+ * Uses Zod schemas for validation instead of manual parsing
11
+ * All calculations are performed in UTC timezone
12
+ */
13
+ // eslint-disable-next-line sonarjs/cognitive-complexity -- Complex time parsing logic requires multiple conditional branches
14
+ export function parseFlexibleTime(input, baseTime = new Date()) {
15
+ // First, validate that input is a valid flexible time format
16
+ const flexibleResult = FlexibleTimeSchema.safeParse(input);
17
+ if (!flexibleResult.success) {
18
+ throw new Error(`Invalid time format: ${input}. Expected ISO 8601 date, 'now', 'today', 'tomorrow', 'yesterday', relative format (1s, 2m, 3h, 4d, 5w, -1d, -2w), or week notation (week-start, week-end, week-start+1w, week-end-2w)`);
19
+ }
20
+ // Try to parse as ISO 8601 first using Zod validation
21
+ const isoResult = ISO8601Schema.safeParse(input);
22
+ if (isoResult.success) {
23
+ return isoResult.data;
24
+ }
25
+ // Try to parse as relative time using Zod validation
26
+ const relativeResult = RelativeTimeSchema.safeParse(input);
27
+ if (relativeResult.success) {
28
+ // Check if it's week notation format
29
+ const weekMatch = input.match(/^week-(start|end)(([+-])\d+w)?$/);
30
+ if (weekMatch) {
31
+ const [, boundary, offsetPart] = weekMatch;
32
+ let weekOffset = 0;
33
+ // Parse offset if present (e.g., "+1w", "-2w")
34
+ if (offsetPart) {
35
+ const offsetMatch = offsetPart.match(/^([+-])(\d+)w$/);
36
+ if (offsetMatch) {
37
+ const [, sign, amount] = offsetMatch;
38
+ weekOffset = Number.parseInt(amount, 10);
39
+ if (sign === "-") {
40
+ weekOffset = -weekOffset;
41
+ }
42
+ // Zero offset is not allowed
43
+ if (weekOffset === 0) {
44
+ throw new Error(`Week offset cannot be zero: ${offsetPart}`);
45
+ }
46
+ }
47
+ }
48
+ // Calculate week boundary based on type (in UTC)
49
+ return boundary === "start" ? dayjs.utc(baseTime).add(weekOffset, "week").startOf("isoWeek").toISOString() : dayjs.utc(baseTime).add(weekOffset, "week").endOf("isoWeek").endOf("day").toISOString();
50
+ }
51
+ // Handle literal values
52
+ if (input === "now") {
53
+ return baseTime.toISOString();
54
+ }
55
+ if (input === "today") {
56
+ return dayjs.utc(baseTime).startOf("day").toISOString();
57
+ }
58
+ // Map shortcuts to relative time format
59
+ let normalizedInput = input;
60
+ if (input === "tomorrow") {
61
+ normalizedInput = "1d";
62
+ }
63
+ else if (input === "yesterday") {
64
+ normalizedInput = "-1d";
65
+ }
66
+ // Extract the validated parts using regex (since Zod already validated the format)
67
+ const match = normalizedInput.match(/^(-?\d+)([smhdw])$/);
68
+ if (!match) {
69
+ throw new Error(`Invalid time format: ${input}`);
70
+ }
71
+ const [, amountString, unit] = match;
72
+ const amount = Number.parseInt(amountString, 10);
73
+ if (amount === 0) {
74
+ throw new Error(`Time amount cannot be zero: ${amount}`);
75
+ }
76
+ // Map unit to Day.js unit names
77
+ const unitMap = {
78
+ s: "second",
79
+ m: "minute",
80
+ h: "hour",
81
+ d: "day",
82
+ w: "week",
83
+ };
84
+ const dayjsUnit = unitMap[unit];
85
+ return dayjs.utc(baseTime).add(amount, dayjsUnit).toISOString();
86
+ }
87
+ throw new Error(`Invalid time format: ${input}. Expected ISO 8601 date, 'now', 'today', 'tomorrow', 'yesterday', relative format (1s, 2m, 3h, 4d, 5w, -1d, -2w), or week notation (week-start, week-end, week-start+1w, week-end-2w)`);
88
+ }
89
+ /**
90
+ * Create a flexible time parser with a specific base time (useful for testing)
91
+ */
92
+ export function createFlexibleTimeParser(baseTime) {
93
+ return (input) => parseFlexibleTime(input, baseTime);
94
+ }
@@ -0,0 +1,31 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Core validation schema for flexible time input
4
+ * Accepts either ISO8601 datetime or relative time expression
5
+ * Validates format but does not transform
6
+ */
7
+ export declare const FlexibleTimeSchema: z.ZodUnion<[z.ZodString, z.ZodString]>;
8
+ export type FlexibleTime = z.infer<typeof FlexibleTimeSchema>;
9
+ /**
10
+ * Transformation schema that converts flexible time to ISO8601
11
+ * Direction: past (relative times subtract from current time)
12
+ * @example
13
+ * FlexibleTimePastSchema.parse("1d") // "2024-01-14T12:00:00.000Z"
14
+ * FlexibleTimePastSchema.parse("2024-01-15T12:00:00Z") // "2024-01-15T12:00:00.000Z"
15
+ */
16
+ export declare const FlexibleTimePastSchema: z.ZodEffects<z.ZodUnion<[z.ZodString, z.ZodString]>, string, string>;
17
+ /**
18
+ * Transformation schema that converts flexible time to ISO8601
19
+ * Direction: future (relative times add to current time)
20
+ * @example
21
+ * FlexibleTimeFutureSchema.parse("1d") // "2024-01-16T12:00:00.000Z"
22
+ * FlexibleTimeFutureSchema.parse("2024-01-15T12:00:00Z") // "2024-01-15T12:00:00.000Z"
23
+ */
24
+ export declare const FlexibleTimeFutureSchema: z.ZodEffects<z.ZodUnion<[z.ZodString, z.ZodString]>, string, string>;
25
+ /**
26
+ * Deprecated: Use FlexibleTimePastSchema instead
27
+ * @deprecated
28
+ */
29
+ export declare const SinceParameterSchema: z.ZodEffects<z.ZodUnion<[z.ZodString, z.ZodString]>, string, string>;
30
+ export type SinceParameter = z.infer<typeof SinceParameterSchema>;
31
+ //# sourceMappingURL=flexible-time.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flexible-time.schema.d.ts","sourceRoot":"","sources":["../../src/time/flexible-time.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,wCAA+C,CAAC;AAE/E,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,sEAElC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,sEAEpC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,sEAAyB,CAAC;AAC3D,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { z } from "zod";
2
+ import { ISO8601Schema } from "./iso8601.schema";
3
+ import { RelativeTimeSchema } from "./relative-time.schema";
4
+ import { parseFlexibleTime } from "./time-helpers";
5
+ /**
6
+ * Core validation schema for flexible time input
7
+ * Accepts either ISO8601 datetime or relative time expression
8
+ * Validates format but does not transform
9
+ */
10
+ export const FlexibleTimeSchema = z.union([ISO8601Schema, RelativeTimeSchema]);
11
+ /**
12
+ * Transformation schema that converts flexible time to ISO8601
13
+ * Direction: past (relative times subtract from current time)
14
+ * @example
15
+ * FlexibleTimePastSchema.parse("1d") // "2024-01-14T12:00:00.000Z"
16
+ * FlexibleTimePastSchema.parse("2024-01-15T12:00:00Z") // "2024-01-15T12:00:00.000Z"
17
+ */
18
+ export const FlexibleTimePastSchema = FlexibleTimeSchema.transform((value) => parseFlexibleTime(value, new Date(), "past"));
19
+ /**
20
+ * Transformation schema that converts flexible time to ISO8601
21
+ * Direction: future (relative times add to current time)
22
+ * @example
23
+ * FlexibleTimeFutureSchema.parse("1d") // "2024-01-16T12:00:00.000Z"
24
+ * FlexibleTimeFutureSchema.parse("2024-01-15T12:00:00Z") // "2024-01-15T12:00:00.000Z"
25
+ */
26
+ export const FlexibleTimeFutureSchema = FlexibleTimeSchema.transform((value) => parseFlexibleTime(value, new Date(), "future"));
27
+ /**
28
+ * Deprecated: Use FlexibleTimePastSchema instead
29
+ * @deprecated
30
+ */
31
+ export const SinceParameterSchema = FlexibleTimePastSchema;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Get the end of the week (Sunday at 23:59:59.999 UTC) for a given date
3
+ * Follows ISO 8601 standard where Sunday is the last day of the week
4
+ *
5
+ * @param date - The reference date
6
+ * @param weekOffset - Number of weeks to offset (positive = future, negative = past)
7
+ * @returns ISO 8601 string for Sunday 23:59:59.999 UTC
8
+ */
9
+ export declare function getWeekEnd(date: Date, weekOffset?: number): string;
10
+ //# sourceMappingURL=get-week-end.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-week-end.d.ts","sourceRoot":"","sources":["../../src/time/get-week-end.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,SAAI,GAAG,MAAM,CAsB7D"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Get the end of the week (Sunday at 23:59:59.999 UTC) for a given date
3
+ * Follows ISO 8601 standard where Sunday is the last day of the week
4
+ *
5
+ * @param date - The reference date
6
+ * @param weekOffset - Number of weeks to offset (positive = future, negative = past)
7
+ * @returns ISO 8601 string for Sunday 23:59:59.999 UTC
8
+ */
9
+ export function getWeekEnd(date, weekOffset = 0) {
10
+ const result = new Date(date);
11
+ // Get current day of week (0 = Sunday, 1 = Monday, ..., 6 = Saturday)
12
+ const dayOfWeek = result.getUTCDay();
13
+ // Calculate days to add to get to Sunday
14
+ // If Sunday (0), stay on same day; otherwise add (7 - dayOfWeek) days
15
+ const daysToSunday = dayOfWeek === 0 ? 0 : 7 - dayOfWeek;
16
+ // Set to Sunday of the current week
17
+ result.setUTCDate(result.getUTCDate() + daysToSunday);
18
+ // Apply week offset
19
+ if (weekOffset !== 0) {
20
+ result.setUTCDate(result.getUTCDate() + weekOffset * 7);
21
+ }
22
+ // Set to end of day (23:59:59.999)
23
+ result.setUTCHours(23, 59, 59, 999);
24
+ return result.toISOString();
25
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Get the start of the week (Monday at 00:00:00 UTC) for a given date
3
+ * Follows ISO 8601 standard where Monday is the first day of the week
4
+ *
5
+ * @param date - The reference date
6
+ * @param weekOffset - Number of weeks to offset (positive = future, negative = past)
7
+ * @returns ISO 8601 string for Monday 00:00:00 UTC
8
+ */
9
+ export declare function getWeekStart(date: Date, weekOffset?: number): string;
10
+ //# sourceMappingURL=get-week-start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-week-start.d.ts","sourceRoot":"","sources":["../../src/time/get-week-start.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,SAAI,GAAG,MAAM,CAsB/D"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Get the start of the week (Monday at 00:00:00 UTC) for a given date
3
+ * Follows ISO 8601 standard where Monday is the first day of the week
4
+ *
5
+ * @param date - The reference date
6
+ * @param weekOffset - Number of weeks to offset (positive = future, negative = past)
7
+ * @returns ISO 8601 string for Monday 00:00:00 UTC
8
+ */
9
+ export function getWeekStart(date, weekOffset = 0) {
10
+ const result = new Date(date);
11
+ // Get current day of week (0 = Sunday, 1 = Monday, ..., 6 = Saturday)
12
+ const dayOfWeek = result.getUTCDay();
13
+ // Calculate days to subtract to get to Monday
14
+ // If Sunday (0), go back 6 days; otherwise go back (dayOfWeek - 1) days
15
+ const daysToMonday = dayOfWeek === 0 ? 6 : dayOfWeek - 1;
16
+ // Set to Monday of the current week
17
+ result.setUTCDate(result.getUTCDate() - daysToMonday);
18
+ // Apply week offset
19
+ if (weekOffset !== 0) {
20
+ result.setUTCDate(result.getUTCDate() + weekOffset * 7);
21
+ }
22
+ // Set to start of day (00:00:00.000)
23
+ result.setUTCHours(0, 0, 0, 0);
24
+ return result.toISOString();
25
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Check if a string is a relative time expression
3
+ *
4
+ * @param value - String to check
5
+ * @returns true if it's a relative time expression
6
+ */
7
+ export declare const isRelativeTime: (value: string) => boolean;
8
+ //# sourceMappingURL=is-relative-time.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-relative-time.d.ts","sourceRoot":"","sources":["../../src/time/is-relative-time.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,OAE9C,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Check if a string is a relative time expression
3
+ *
4
+ * @param value - String to check
5
+ * @returns true if it's a relative time expression
6
+ */
7
+ export const isRelativeTime = (value) => {
8
+ return /^(\d+)[mhdwM]$/.test(value);
9
+ };
@@ -0,0 +1,14 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Core validation schema for ISO8601 datetime strings
4
+ * Validates format but does not transform
5
+ */
6
+ export declare const ISO8601Schema: z.ZodString;
7
+ export type ISO8601 = z.infer<typeof ISO8601Schema>;
8
+ /**
9
+ * Core validation schema for ISO8601 date strings (YYYY-MM-DD)
10
+ * Validates format but does not transform
11
+ */
12
+ export declare const ISO8601DateSchema: z.ZodString;
13
+ export type ISO8601Date = z.infer<typeof ISO8601DateSchema>;
14
+ //# sourceMappingURL=iso8601.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iso8601.schema.d.ts","sourceRoot":"","sources":["../../src/time/iso8601.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,eAAO,MAAM,aAAa,aAMvB,CAAC;AAEJ,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,aAM3B,CAAC;AAEJ,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Core validation schema for ISO8601 datetime strings
4
+ * Validates format but does not transform
5
+ */
6
+ export const ISO8601Schema = z
7
+ .string()
8
+ .describe("Datetime in ISO8601 format")
9
+ .regex(/^((?:(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2}(?:\.\d+)?))(Z|[\+-]\d{2}:\d{2})?)$/, "Must be a valid ISO8601 datetime (e.g., '2024-01-01T12:00:00Z')");
10
+ /**
11
+ * Core validation schema for ISO8601 date strings (YYYY-MM-DD)
12
+ * Validates format but does not transform
13
+ */
14
+ export const ISO8601DateSchema = z
15
+ .string()
16
+ .describe("Date in ISO8601 format")
17
+ .regex(/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/, "Date must be in YYYY-MM-DD format with valid month (01-12) and day (01-31)");
@@ -0,0 +1,6 @@
1
+ import { z } from "zod";
2
+ export declare const ISO8601Schema: z.ZodEffects<z.ZodString, string, string>;
3
+ export type ISO8601 = z.infer<typeof ISO8601Schema>;
4
+ export declare const ISO8601DateSchema: z.ZodString;
5
+ export type ISO8601Date = z.infer<typeof ISO8601DateSchema>;
6
+ //# sourceMappingURL=iso8601.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iso8601.types.d.ts","sourceRoot":"","sources":["../../src/time/iso8601.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,aAAa,2CAMoB,CAAC;AAE/C,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAGpD,eAAO,MAAM,iBAAiB,aAM3B,CAAC;AACJ,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { z } from "zod";
2
+ export const ISO8601Schema = z
3
+ .string()
4
+ .describe("Datetime in ISO8601 format")
5
+ .regex(/^((?:(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2}(?:\.\d+)?))(Z|[\+-]\d{2}:\d{2})?)$/)
6
+ .transform((v) => new Date(v).toISOString());
7
+ // ensure valid month and valid day
8
+ export const ISO8601DateSchema = z
9
+ .string()
10
+ .describe("Date in ISO8601 format")
11
+ .regex(/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/, "Date must be in YYYY-MM-DD format with valid month (01-12) and day (01-31)");
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Helper function to convert relative time expressions to ISO8601 timestamps
3
+ * All calculations are performed in UTC timezone
4
+ *
5
+ * @param relativeTime - Relative time expression like "1d", "3h", "30m"
6
+ * @returns ISO8601 timestamp string
7
+ */
8
+ export declare const parseRelativeTime: (relativeTime: string) => string;
9
+ //# sourceMappingURL=parse-relative-time.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-relative-time.d.ts","sourceRoot":"","sources":["../../src/time/parse-relative-time.ts"],"names":[],"mappings":"AAQA;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,cAAc,MAAM,KAAG,MAkCxD,CAAC"}