@burdenoff/website-sdk 2026.1031.3 → 2026.1101.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (274) hide show
  1. package/README.md +42 -8
  2. package/dist/analytics/index.js +19 -69
  3. package/dist/analytics/index.js.map +1 -1
  4. package/dist/analytics/index.mjs +3 -69
  5. package/dist/analytics/index.mjs.map +1 -1
  6. package/dist/avatar-live/index.js +1 -0
  7. package/dist/avatar-live/index.js.map +1 -1
  8. package/dist/avatar-live/index.mjs +1 -0
  9. package/dist/avatar-live/index.mjs.map +1 -1
  10. package/dist/avatar-live-view/index.js +10 -30
  11. package/dist/avatar-live-view/index.js.map +1 -1
  12. package/dist/avatar-live-view/index.mjs +4 -24
  13. package/dist/avatar-live-view/index.mjs.map +1 -1
  14. package/dist/chunk-23H4JUL4.js +41 -0
  15. package/dist/chunk-23H4JUL4.js.map +1 -0
  16. package/dist/chunk-34RX5P75.mjs +25 -0
  17. package/dist/chunk-34RX5P75.mjs.map +1 -0
  18. package/dist/chunk-3LFFY7AZ.js +184 -0
  19. package/dist/chunk-3LFFY7AZ.js.map +1 -0
  20. package/dist/chunk-3X26GE4S.js +2794 -0
  21. package/dist/chunk-3X26GE4S.js.map +1 -0
  22. package/dist/chunk-45GCA4GG.js +85 -0
  23. package/dist/chunk-45GCA4GG.js.map +1 -0
  24. package/dist/chunk-4SAGVLHN.js +876 -0
  25. package/dist/chunk-4SAGVLHN.js.map +1 -0
  26. package/dist/chunk-4U6YAII5.js +218 -0
  27. package/dist/chunk-4U6YAII5.js.map +1 -0
  28. package/dist/chunk-5GMTBOO6.js +21 -0
  29. package/dist/chunk-5GMTBOO6.js.map +1 -0
  30. package/dist/chunk-5JRJ57CL.mjs +329 -0
  31. package/dist/chunk-5JRJ57CL.mjs.map +1 -0
  32. package/dist/chunk-6C2DKIC7.js +4 -0
  33. package/dist/chunk-6C2DKIC7.js.map +1 -0
  34. package/dist/chunk-6IBFBWC5.mjs +17 -0
  35. package/dist/chunk-6IBFBWC5.mjs.map +1 -0
  36. package/dist/chunk-6KY2ZRVI.js +116 -0
  37. package/dist/chunk-6KY2ZRVI.js.map +1 -0
  38. package/dist/chunk-6VJT3SM4.mjs +182 -0
  39. package/dist/chunk-6VJT3SM4.mjs.map +1 -0
  40. package/dist/chunk-6YZUFMK2.mjs +40 -0
  41. package/dist/chunk-6YZUFMK2.mjs.map +1 -0
  42. package/dist/chunk-7A6R7CGG.js +47 -0
  43. package/dist/chunk-7A6R7CGG.js.map +1 -0
  44. package/dist/chunk-7PWL4V2R.js +4 -0
  45. package/dist/chunk-7PWL4V2R.js.map +1 -0
  46. package/dist/chunk-AA33WDYS.js +161 -0
  47. package/dist/chunk-AA33WDYS.js.map +1 -0
  48. package/dist/chunk-AHRGFXV2.js +525 -0
  49. package/dist/chunk-AHRGFXV2.js.map +1 -0
  50. package/dist/chunk-B63XLDZH.mjs +109 -0
  51. package/dist/chunk-B63XLDZH.mjs.map +1 -0
  52. package/dist/chunk-BX2USEWF.mjs +35 -0
  53. package/dist/chunk-BX2USEWF.mjs.map +1 -0
  54. package/dist/chunk-BYSZT35R.js +150 -0
  55. package/dist/chunk-BYSZT35R.js.map +1 -0
  56. package/dist/chunk-C6OJIHNO.js +12 -0
  57. package/dist/chunk-C6OJIHNO.js.map +1 -0
  58. package/dist/chunk-COOELBX7.mjs +63 -0
  59. package/dist/chunk-COOELBX7.mjs.map +1 -0
  60. package/dist/chunk-D2TW7MNC.mjs +2771 -0
  61. package/dist/chunk-D2TW7MNC.mjs.map +1 -0
  62. package/dist/chunk-D5KEZ6V6.mjs +3 -0
  63. package/dist/chunk-D5KEZ6V6.mjs.map +1 -0
  64. package/dist/chunk-E3GUGJMY.js +46 -0
  65. package/dist/chunk-E3GUGJMY.js.map +1 -0
  66. package/dist/chunk-EBZ2HGJ2.mjs +52 -0
  67. package/dist/chunk-EBZ2HGJ2.mjs.map +1 -0
  68. package/dist/chunk-EDLTUOIA.mjs +210 -0
  69. package/dist/chunk-EDLTUOIA.mjs.map +1 -0
  70. package/dist/chunk-EJQSOT4X.js +4 -0
  71. package/dist/chunk-EJQSOT4X.js.map +1 -0
  72. package/dist/chunk-EUPFS6MZ.mjs +2019 -0
  73. package/dist/chunk-EUPFS6MZ.mjs.map +1 -0
  74. package/dist/chunk-F3XWDC3B.js +77 -0
  75. package/dist/chunk-F3XWDC3B.js.map +1 -0
  76. package/dist/chunk-FFADMVIK.mjs +5127 -0
  77. package/dist/chunk-FFADMVIK.mjs.map +1 -0
  78. package/dist/chunk-FJWS7BKT.mjs +3 -0
  79. package/dist/chunk-FJWS7BKT.mjs.map +1 -0
  80. package/dist/chunk-FJZJDUOR.mjs +3 -0
  81. package/dist/chunk-FJZJDUOR.mjs.map +1 -0
  82. package/dist/chunk-GCFLCO2Z.mjs +145 -0
  83. package/dist/chunk-GCFLCO2Z.mjs.map +1 -0
  84. package/dist/chunk-GEXC4LRP.js +61 -0
  85. package/dist/chunk-GEXC4LRP.js.map +1 -0
  86. package/dist/chunk-GTRAXQGC.mjs +3 -0
  87. package/dist/chunk-GTRAXQGC.mjs.map +1 -0
  88. package/dist/chunk-IKOIRUKW.js +270 -0
  89. package/dist/chunk-IKOIRUKW.js.map +1 -0
  90. package/dist/chunk-IXTWOPRN.js +45 -0
  91. package/dist/chunk-IXTWOPRN.js.map +1 -0
  92. package/dist/chunk-JDXOXGOK.js +547 -0
  93. package/dist/chunk-JDXOXGOK.js.map +1 -0
  94. package/dist/chunk-JSLDWYV7.mjs +558 -0
  95. package/dist/chunk-JSLDWYV7.mjs.map +1 -0
  96. package/dist/chunk-JXLSTVBK.js +336 -0
  97. package/dist/chunk-JXLSTVBK.js.map +1 -0
  98. package/dist/chunk-KHYXK7FG.mjs +49 -0
  99. package/dist/chunk-KHYXK7FG.mjs.map +1 -0
  100. package/dist/chunk-KSMBOWQQ.js +2034 -0
  101. package/dist/chunk-KSMBOWQQ.js.map +1 -0
  102. package/dist/chunk-KU2PXHGB.mjs +83 -0
  103. package/dist/chunk-KU2PXHGB.mjs.map +1 -0
  104. package/dist/chunk-KZANIV3S.mjs +37 -0
  105. package/dist/chunk-KZANIV3S.mjs.map +1 -0
  106. package/dist/chunk-L4BP6YOB.js +20 -0
  107. package/dist/chunk-L4BP6YOB.js.map +1 -0
  108. package/dist/chunk-MRKA2OAF.mjs +75 -0
  109. package/dist/chunk-MRKA2OAF.mjs.map +1 -0
  110. package/dist/chunk-N5EC53MH.mjs +80 -0
  111. package/dist/chunk-N5EC53MH.mjs.map +1 -0
  112. package/dist/chunk-NZANQGDM.mjs +34 -0
  113. package/dist/chunk-NZANQGDM.mjs.map +1 -0
  114. package/dist/chunk-O4GS3XPZ.js +10 -0
  115. package/dist/chunk-O4GS3XPZ.js.map +1 -0
  116. package/dist/chunk-O76QDGRM.js +5154 -0
  117. package/dist/chunk-O76QDGRM.js.map +1 -0
  118. package/dist/chunk-OYEUNZJY.js +114 -0
  119. package/dist/chunk-OYEUNZJY.js.map +1 -0
  120. package/dist/chunk-PHXAGQNB.js +74 -0
  121. package/dist/chunk-PHXAGQNB.js.map +1 -0
  122. package/dist/chunk-PIHHPP7J.mjs +16 -0
  123. package/dist/chunk-PIHHPP7J.mjs.map +1 -0
  124. package/dist/chunk-PXRHVVOU.mjs +499 -0
  125. package/dist/chunk-PXRHVVOU.mjs.map +1 -0
  126. package/dist/chunk-QMA6U6AU.js +36 -0
  127. package/dist/chunk-QMA6U6AU.js.map +1 -0
  128. package/dist/chunk-R6J7IULF.js +44 -0
  129. package/dist/chunk-R6J7IULF.js.map +1 -0
  130. package/dist/chunk-R7G6TWIS.mjs +10 -0
  131. package/dist/chunk-R7G6TWIS.mjs.map +1 -0
  132. package/dist/chunk-RUMGFI6L.mjs +544 -0
  133. package/dist/chunk-RUMGFI6L.mjs.map +1 -0
  134. package/dist/chunk-S54JWSJF.js +565 -0
  135. package/dist/chunk-S54JWSJF.js.map +1 -0
  136. package/dist/chunk-SK5UGG6A.js +2041 -0
  137. package/dist/chunk-SK5UGG6A.js.map +1 -0
  138. package/dist/chunk-SKIYDKIS.mjs +70 -0
  139. package/dist/chunk-SKIYDKIS.mjs.map +1 -0
  140. package/dist/chunk-SZNS5IK6.mjs +322 -0
  141. package/dist/chunk-SZNS5IK6.mjs.map +1 -0
  142. package/dist/chunk-T7JIPZAC.js +66 -0
  143. package/dist/chunk-T7JIPZAC.js.map +1 -0
  144. package/dist/chunk-TGYQHO2E.mjs +864 -0
  145. package/dist/chunk-TGYQHO2E.mjs.map +1 -0
  146. package/dist/chunk-TT3MHN42.mjs +8 -0
  147. package/dist/chunk-TT3MHN42.mjs.map +1 -0
  148. package/dist/chunk-UM55U65W.mjs +268 -0
  149. package/dist/chunk-UM55U65W.mjs.map +1 -0
  150. package/dist/chunk-UQ2HALUD.js +72 -0
  151. package/dist/chunk-UQ2HALUD.js.map +1 -0
  152. package/dist/chunk-UXWT7G77.js +82 -0
  153. package/dist/chunk-UXWT7G77.js.map +1 -0
  154. package/dist/chunk-VNS5WDWO.mjs +7 -0
  155. package/dist/chunk-VNS5WDWO.mjs.map +1 -0
  156. package/dist/chunk-VRWZLGR7.js +4 -0
  157. package/dist/chunk-VRWZLGR7.js.map +1 -0
  158. package/dist/chunk-VZLDSNH4.mjs +22 -0
  159. package/dist/chunk-VZLDSNH4.mjs.map +1 -0
  160. package/dist/chunk-W6P3YETJ.js +92 -0
  161. package/dist/chunk-W6P3YETJ.js.map +1 -0
  162. package/dist/chunk-WPKFFQCR.mjs +90 -0
  163. package/dist/chunk-WPKFFQCR.mjs.map +1 -0
  164. package/dist/chunk-WTVTI5TO.mjs +22 -0
  165. package/dist/chunk-WTVTI5TO.mjs.map +1 -0
  166. package/dist/chunk-XJOBZ4RJ.js +44 -0
  167. package/dist/chunk-XJOBZ4RJ.js.map +1 -0
  168. package/dist/chunk-XP2JDNDU.js +325 -0
  169. package/dist/chunk-XP2JDNDU.js.map +1 -0
  170. package/dist/chunk-Y4V5CEWD.mjs +112 -0
  171. package/dist/chunk-Y4V5CEWD.mjs.map +1 -0
  172. package/dist/chunk-YERN2UWM.js +116 -0
  173. package/dist/chunk-YERN2UWM.js.map +1 -0
  174. package/dist/chunk-ZKJQWFAA.mjs +114 -0
  175. package/dist/chunk-ZKJQWFAA.mjs.map +1 -0
  176. package/dist/chunk-ZOON3S3Y.mjs +138 -0
  177. package/dist/chunk-ZOON3S3Y.mjs.map +1 -0
  178. package/dist/chunk-ZP6QRAYC.mjs +2024 -0
  179. package/dist/chunk-ZP6QRAYC.mjs.map +1 -0
  180. package/dist/chunk-ZSTFX7FV.js +9 -0
  181. package/dist/chunk-ZSTFX7FV.js.map +1 -0
  182. package/dist/client/index.js +23 -331
  183. package/dist/client/index.js.map +1 -1
  184. package/dist/client/index.mjs +3 -330
  185. package/dist/client/index.mjs.map +1 -1
  186. package/dist/comparison/index.js +28 -111
  187. package/dist/comparison/index.js.map +1 -1
  188. package/dist/comparison/index.mjs +2 -107
  189. package/dist/comparison/index.mjs.map +1 -1
  190. package/dist/components/contact.js +21 -931
  191. package/dist/components/contact.js.map +1 -1
  192. package/dist/components/contact.mjs +12 -909
  193. package/dist/components/contact.mjs.map +1 -1
  194. package/dist/components/electron-download.js +12 -124
  195. package/dist/components/electron-download.js.map +1 -1
  196. package/dist/components/electron-download.mjs +4 -106
  197. package/dist/components/electron-download.mjs.map +1 -1
  198. package/dist/components/explore-cta.js +8 -112
  199. package/dist/components/explore-cta.js.map +1 -1
  200. package/dist/components/explore-cta.mjs +3 -114
  201. package/dist/components/explore-cta.mjs.map +1 -1
  202. package/dist/components/explore.js +62 -7833
  203. package/dist/components/explore.js.map +1 -1
  204. package/dist/components/explore.mjs +13 -7800
  205. package/dist/components/explore.mjs.map +1 -1
  206. package/dist/components/launch-countdown.js +8 -83
  207. package/dist/components/launch-countdown.js.map +1 -1
  208. package/dist/components/launch-countdown.mjs +3 -85
  209. package/dist/components/launch-countdown.mjs.map +1 -1
  210. package/dist/components/newsletter.js +20 -993
  211. package/dist/components/newsletter.js.map +1 -1
  212. package/dist/components/newsletter.mjs +11 -971
  213. package/dist/components/newsletter.mjs.map +1 -1
  214. package/dist/components/partners.js +24 -1302
  215. package/dist/components/partners.js.map +1 -1
  216. package/dist/components/partners.mjs +15 -1276
  217. package/dist/components/partners.mjs.map +1 -1
  218. package/dist/components/pricing.js +49 -1249
  219. package/dist/components/pricing.js.map +1 -1
  220. package/dist/components/pricing.mjs +8 -1226
  221. package/dist/components/pricing.mjs.map +1 -1
  222. package/dist/components/problems-solved.js +8 -150
  223. package/dist/components/problems-solved.js.map +1 -1
  224. package/dist/components/problems-solved.mjs +4 -133
  225. package/dist/components/problems-solved.mjs.map +1 -1
  226. package/dist/components/resource-links.js +8 -304
  227. package/dist/components/resource-links.js.map +1 -1
  228. package/dist/components/resource-links.mjs +5 -308
  229. package/dist/components/resource-links.mjs.map +1 -1
  230. package/dist/components/social-links.js +8 -343
  231. package/dist/components/social-links.js.map +1 -1
  232. package/dist/components/social-links.mjs +5 -347
  233. package/dist/components/social-links.mjs.map +1 -1
  234. package/dist/components/unsubscribe.js +10 -627
  235. package/dist/components/unsubscribe.js.map +1 -1
  236. package/dist/components/unsubscribe.mjs +6 -611
  237. package/dist/components/unsubscribe.mjs.map +1 -1
  238. package/dist/components/waitlist.js +21 -1001
  239. package/dist/components/waitlist.js.map +1 -1
  240. package/dist/components/waitlist.mjs +12 -982
  241. package/dist/components/waitlist.mjs.map +1 -1
  242. package/dist/components/website-switcher.js +12 -175
  243. package/dist/components/website-switcher.js.map +1 -1
  244. package/dist/components/website-switcher.mjs +4 -157
  245. package/dist/components/website-switcher.mjs.map +1 -1
  246. package/dist/content/index.js +118 -3616
  247. package/dist/content/index.js.map +1 -1
  248. package/dist/content/index.mjs +12 -3567
  249. package/dist/content/index.mjs.map +1 -1
  250. package/dist/hooks/index.js +37 -2321
  251. package/dist/hooks/index.js.map +1 -1
  252. package/dist/hooks/index.mjs +6 -2318
  253. package/dist/hooks/index.mjs.map +1 -1
  254. package/dist/index.js +4145 -20599
  255. package/dist/index.js.map +1 -1
  256. package/dist/index.mjs +3766 -20567
  257. package/dist/index.mjs.map +1 -1
  258. package/dist/product/index.js +20 -393
  259. package/dist/product/index.js.map +1 -1
  260. package/dist/product/index.mjs +5 -394
  261. package/dist/product/index.mjs.map +1 -1
  262. package/dist/seo/index.js +8 -76
  263. package/dist/seo/index.js.map +1 -1
  264. package/dist/seo/index.mjs +3 -78
  265. package/dist/seo/index.mjs.map +1 -1
  266. package/dist/store/index.js +51 -2650
  267. package/dist/store/index.js.map +1 -1
  268. package/dist/store/index.mjs +13 -2619
  269. package/dist/store/index.mjs.map +1 -1
  270. package/dist/utils/index.js +69 -134
  271. package/dist/utils/index.js.map +1 -1
  272. package/dist/utils/index.mjs +5 -122
  273. package/dist/utils/index.mjs.map +1 -1
  274. package/package.json +2 -1
@@ -1,109 +1,4 @@
1
- // src/comparison/index.ts
2
- var DEFAULT_COMPARISON_MAX_AGE_DAYS = 180;
3
- var DAY_MS = 24 * 60 * 60 * 1e3;
4
- var ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
5
- function parseVerifiedAt(value) {
6
- if (typeof value !== "string" || !ISO_DATE.test(value)) return null;
7
- const date = /* @__PURE__ */ new Date(`${value}T00:00:00.000Z`);
8
- if (Number.isNaN(date.getTime())) return null;
9
- return date.toISOString().slice(0, 10) === value ? date : null;
10
- }
11
- function isHttpUrl(value) {
12
- try {
13
- const url = new URL(value);
14
- return url.protocol === "https:" || url.protocol === "http:";
15
- } catch {
16
- return false;
17
- }
18
- }
19
- function checkComparisonFreshness(claims, options = {}) {
20
- const maxAgeDays = options.maxAgeDays ?? DEFAULT_COMPARISON_MAX_AGE_DAYS;
21
- const now = options.now ?? /* @__PURE__ */ new Date();
22
- const issues = [];
23
- for (const claim of claims) {
24
- const sources = claim.sources ?? [];
25
- if (sources.length === 0) {
26
- issues.push({
27
- path: claim.path,
28
- problem: "missing-source",
29
- detail: "no source: add { url, verifiedAt } for the vendor page this claim was checked against"
30
- });
31
- continue;
32
- }
33
- let newest = null;
34
- for (const source of sources) {
35
- if (!isHttpUrl(source.url)) {
36
- issues.push({
37
- path: claim.path,
38
- problem: "invalid-url",
39
- detail: `source URL is not an http(s) URL: ${JSON.stringify(source.url)}`
40
- });
41
- }
42
- const verified = parseVerifiedAt(source.verifiedAt);
43
- if (!verified) {
44
- issues.push({
45
- path: claim.path,
46
- problem: "invalid-date",
47
- detail: `verifiedAt must be YYYY-MM-DD, got ${JSON.stringify(source.verifiedAt)}`
48
- });
49
- continue;
50
- }
51
- if (verified.getTime() > now.getTime() + DAY_MS) {
52
- issues.push({
53
- path: claim.path,
54
- problem: "future-date",
55
- detail: `verifiedAt ${source.verifiedAt} is in the future`
56
- });
57
- continue;
58
- }
59
- if (!newest || verified.getTime() > newest.getTime()) newest = verified;
60
- }
61
- if (newest) {
62
- const ageDays = Math.floor((now.getTime() - newest.getTime()) / DAY_MS);
63
- if (ageDays > maxAgeDays) {
64
- issues.push({
65
- path: claim.path,
66
- problem: "stale",
67
- detail: `last verified ${newest.toISOString().slice(0, 10)} (${ageDays} days ago, limit ${maxAgeDays}): re-read the vendor page and update verifiedAt or the claim`
68
- });
69
- }
70
- }
71
- }
72
- return issues;
73
- }
74
- function latestVerification(claims) {
75
- let latest = null;
76
- for (const claim of claims) {
77
- for (const source of claim.sources ?? []) {
78
- if (parseVerifiedAt(source.verifiedAt) && (!latest || source.verifiedAt > latest)) {
79
- latest = source.verifiedAt;
80
- }
81
- }
82
- }
83
- return latest;
84
- }
85
- function oldestVerification(claims) {
86
- let oldest = null;
87
- for (const claim of claims) {
88
- for (const source of claim.sources ?? []) {
89
- if (parseVerifiedAt(source.verifiedAt) && (!oldest || source.verifiedAt < oldest)) {
90
- oldest = source.verifiedAt;
91
- }
92
- }
93
- }
94
- return oldest;
95
- }
96
- function formatFreshnessReport(issues) {
97
- if (issues.length === 0)
98
- return "Comparison sources: all claims sourced and fresh.";
99
- const lines = issues.map((i) => ` - [${i.problem}] ${i.path}: ${i.detail}`);
100
- return [
101
- `Comparison sources: ${issues.length} problem(s) found.`,
102
- ...lines,
103
- "Re-check each claim against the vendor's current page, then update the claim and its verifiedAt."
104
- ].join("\n");
105
- }
106
-
107
- export { DEFAULT_COMPARISON_MAX_AGE_DAYS, checkComparisonFreshness, formatFreshnessReport, latestVerification, oldestVerification, parseVerifiedAt };
1
+ export { DEFAULT_COMPARISON_MAX_AGE_DAYS, checkComparisonFreshness, formatFreshnessReport, latestVerification, oldestVerification, parseVerifiedAt } from '../chunk-B63XLDZH.mjs';
2
+ import '../chunk-VNS5WDWO.mjs';
108
3
  //# sourceMappingURL=index.mjs.map
109
4
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/comparison/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * @burdenoff/website-sdk - Comparison page sources and freshness (BOFF-9971)\n *\n * Every product website with a /vs (competitor comparison) page makes claims\n * about other vendors. Those claims age fast: a vendor ships the feature we\n * said it lacked, or changes its prices. This module gives every site the same\n * contract and the same check:\n *\n * - each claim carries at least one source `{ url, verifiedAt }` (enforced by\n * the `Sourced` type at compile time), and\n * - `checkComparisonFreshness` fails when a claim has no source, a source is\n * not an http(s) URL, a date is malformed or in the future, or the newest\n * verification is older than `maxAgeDays` (180 by default).\n *\n * Sites run the check in their PR Check workflow, so a stale or unsourced\n * comparison blocks the next change until someone re-reads the vendor's page.\n *\n * @example\n * ```ts\n * import { checkComparisonFreshness, formatFreshnessReport } from '@burdenoff/website-sdk/comparison'\n *\n * const issues = checkComparisonFreshness(collectClaims(COMPETITORS))\n * if (issues.length) {\n * console.error(formatFreshnessReport(issues))\n * process.exit(1)\n * }\n * ```\n */\n\n/** Where a comparison claim was checked, and when (ISO date, YYYY-MM-DD). */\nexport interface ComparisonSource {\n /** The vendor page (or docs page) the claim was checked against. */\n url: string;\n /** The day a person last read that page and confirmed the claim. */\n verifiedAt: string;\n /** Optional short label shown with the link, e.g. \"Pricing\". */\n label?: string;\n}\n\n/** A non-empty list: a sourced claim always has at least one source. */\nexport type NonEmptySources = readonly [\n ComparisonSource,\n ...ComparisonSource[],\n];\n\n/** Mix-in for any comparison claim (table row, profile, pricing row). */\nexport interface Sourced {\n sources: NonEmptySources;\n}\n\n/** One claim to check, located by a human-readable path for the report. */\nexport interface ComparisonClaim {\n /** Where the claim lives, e.g. \"zapier.featureRows[Workflow versioning]\". */\n path: string;\n /** Its sources; missing or empty fails the check. */\n sources?: readonly ComparisonSource[] | null;\n}\n\nexport type FreshnessProblem =\n \"missing-source\" | \"invalid-url\" | \"invalid-date\" | \"future-date\" | \"stale\";\n\nexport interface FreshnessIssue {\n path: string;\n problem: FreshnessProblem;\n detail: string;\n}\n\nexport interface FreshnessOptions {\n /** Oldest acceptable verification, in days. Default 180. */\n maxAgeDays?: number;\n /** The clock to check against. Default: now. */\n now?: Date;\n}\n\n/** Default staleness threshold for comparison claims. */\nexport const DEFAULT_COMPARISON_MAX_AGE_DAYS = 180;\n\nconst DAY_MS = 24 * 60 * 60 * 1000;\nconst ISO_DATE = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/** Parse a strict YYYY-MM-DD date as UTC midnight, or null when invalid. */\nexport function parseVerifiedAt(value: string): Date | null {\n if (typeof value !== \"string\" || !ISO_DATE.test(value)) return null;\n const date = new Date(`${value}T00:00:00.000Z`);\n if (Number.isNaN(date.getTime())) return null;\n // Reject rollovers such as 2026-02-31 → 2026-03-03.\n return date.toISOString().slice(0, 10) === value ? date : null;\n}\n\nfunction isHttpUrl(value: string): boolean {\n try {\n const url = new URL(value);\n return url.protocol === \"https:\" || url.protocol === \"http:\";\n } catch {\n return false;\n }\n}\n\n/**\n * Check every claim and return the problems found (empty when all is well).\n * A claim passes on its newest valid source, so adding a fresh source to an\n * old claim is enough to clear a \"stale\" issue.\n */\nexport function checkComparisonFreshness(\n claims: readonly ComparisonClaim[],\n options: FreshnessOptions = {},\n): FreshnessIssue[] {\n const maxAgeDays = options.maxAgeDays ?? DEFAULT_COMPARISON_MAX_AGE_DAYS;\n const now = options.now ?? new Date();\n const issues: FreshnessIssue[] = [];\n\n for (const claim of claims) {\n const sources = claim.sources ?? [];\n if (sources.length === 0) {\n issues.push({\n path: claim.path,\n problem: \"missing-source\",\n detail:\n \"no source: add { url, verifiedAt } for the vendor page this claim was checked against\",\n });\n continue;\n }\n\n let newest: Date | null = null;\n for (const source of sources) {\n if (!isHttpUrl(source.url)) {\n issues.push({\n path: claim.path,\n problem: \"invalid-url\",\n detail: `source URL is not an http(s) URL: ${JSON.stringify(source.url)}`,\n });\n }\n const verified = parseVerifiedAt(source.verifiedAt);\n if (!verified) {\n issues.push({\n path: claim.path,\n problem: \"invalid-date\",\n detail: `verifiedAt must be YYYY-MM-DD, got ${JSON.stringify(source.verifiedAt)}`,\n });\n continue;\n }\n if (verified.getTime() > now.getTime() + DAY_MS) {\n issues.push({\n path: claim.path,\n problem: \"future-date\",\n detail: `verifiedAt ${source.verifiedAt} is in the future`,\n });\n continue;\n }\n if (!newest || verified.getTime() > newest.getTime()) newest = verified;\n }\n\n if (newest) {\n const ageDays = Math.floor((now.getTime() - newest.getTime()) / DAY_MS);\n if (ageDays > maxAgeDays) {\n issues.push({\n path: claim.path,\n problem: \"stale\",\n detail: `last verified ${newest.toISOString().slice(0, 10)} (${ageDays} days ago, limit ${maxAgeDays}): re-read the vendor page and update verifiedAt or the claim`,\n });\n }\n }\n }\n\n return issues;\n}\n\n/** Newest valid verification date across all claims, or null. */\nexport function latestVerification(\n claims: readonly ComparisonClaim[],\n): string | null {\n let latest: string | null = null;\n for (const claim of claims) {\n for (const source of claim.sources ?? []) {\n if (\n parseVerifiedAt(source.verifiedAt) &&\n (!latest || source.verifiedAt > latest)\n ) {\n latest = source.verifiedAt;\n }\n }\n }\n return latest;\n}\n\n/** Oldest valid verification date across all claims, or null. */\nexport function oldestVerification(\n claims: readonly ComparisonClaim[],\n): string | null {\n let oldest: string | null = null;\n for (const claim of claims) {\n for (const source of claim.sources ?? []) {\n if (\n parseVerifiedAt(source.verifiedAt) &&\n (!oldest || source.verifiedAt < oldest)\n ) {\n oldest = source.verifiedAt;\n }\n }\n }\n return oldest;\n}\n\n/** A plain-text report for CI logs, one line per issue. */\nexport function formatFreshnessReport(\n issues: readonly FreshnessIssue[],\n): string {\n if (issues.length === 0)\n return \"Comparison sources: all claims sourced and fresh.\";\n const lines = issues.map((i) => ` - [${i.problem}] ${i.path}: ${i.detail}`);\n return [\n `Comparison sources: ${issues.length} problem(s) found.`,\n ...lines,\n \"Re-check each claim against the vendor's current page, then update the claim and its verifiedAt.\",\n ].join(\"\\n\");\n}\n"]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.mjs"}