@hyperfrontend/versioning 0.1.0

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 (353) hide show
  1. package/ARCHITECTURE.md +593 -0
  2. package/CHANGELOG.md +35 -0
  3. package/FUNDING.md +141 -0
  4. package/LICENSE.md +21 -0
  5. package/README.md +195 -0
  6. package/SECURITY.md +82 -0
  7. package/changelog/compare/diff.d.ts +128 -0
  8. package/changelog/compare/diff.d.ts.map +1 -0
  9. package/changelog/compare/index.cjs.js +628 -0
  10. package/changelog/compare/index.cjs.js.map +1 -0
  11. package/changelog/compare/index.d.ts +4 -0
  12. package/changelog/compare/index.d.ts.map +1 -0
  13. package/changelog/compare/index.esm.js +612 -0
  14. package/changelog/compare/index.esm.js.map +1 -0
  15. package/changelog/compare/is-equal.d.ts +114 -0
  16. package/changelog/compare/is-equal.d.ts.map +1 -0
  17. package/changelog/index.cjs.js +6448 -0
  18. package/changelog/index.cjs.js.map +1 -0
  19. package/changelog/index.d.ts +6 -0
  20. package/changelog/index.d.ts.map +1 -0
  21. package/changelog/index.esm.js +6358 -0
  22. package/changelog/index.esm.js.map +1 -0
  23. package/changelog/models/changelog.d.ts +86 -0
  24. package/changelog/models/changelog.d.ts.map +1 -0
  25. package/changelog/models/commit-ref.d.ts +51 -0
  26. package/changelog/models/commit-ref.d.ts.map +1 -0
  27. package/changelog/models/entry.d.ts +84 -0
  28. package/changelog/models/entry.d.ts.map +1 -0
  29. package/changelog/models/index.cjs.js +2043 -0
  30. package/changelog/models/index.cjs.js.map +1 -0
  31. package/changelog/models/index.d.ts +11 -0
  32. package/changelog/models/index.d.ts.map +1 -0
  33. package/changelog/models/index.esm.js +2026 -0
  34. package/changelog/models/index.esm.js.map +1 -0
  35. package/changelog/models/schema.d.ts +68 -0
  36. package/changelog/models/schema.d.ts.map +1 -0
  37. package/changelog/models/section.d.ts +25 -0
  38. package/changelog/models/section.d.ts.map +1 -0
  39. package/changelog/operations/add-entry.d.ts +56 -0
  40. package/changelog/operations/add-entry.d.ts.map +1 -0
  41. package/changelog/operations/add-item.d.ts +18 -0
  42. package/changelog/operations/add-item.d.ts.map +1 -0
  43. package/changelog/operations/filter-by-predicate.d.ts +81 -0
  44. package/changelog/operations/filter-by-predicate.d.ts.map +1 -0
  45. package/changelog/operations/filter-by-range.d.ts +63 -0
  46. package/changelog/operations/filter-by-range.d.ts.map +1 -0
  47. package/changelog/operations/filter-entries.d.ts +9 -0
  48. package/changelog/operations/filter-entries.d.ts.map +1 -0
  49. package/changelog/operations/index.cjs.js +2455 -0
  50. package/changelog/operations/index.cjs.js.map +1 -0
  51. package/changelog/operations/index.d.ts +15 -0
  52. package/changelog/operations/index.d.ts.map +1 -0
  53. package/changelog/operations/index.esm.js +2411 -0
  54. package/changelog/operations/index.esm.js.map +1 -0
  55. package/changelog/operations/merge.d.ts +88 -0
  56. package/changelog/operations/merge.d.ts.map +1 -0
  57. package/changelog/operations/remove-entry.d.ts +45 -0
  58. package/changelog/operations/remove-entry.d.ts.map +1 -0
  59. package/changelog/operations/remove-section.d.ts +50 -0
  60. package/changelog/operations/remove-section.d.ts.map +1 -0
  61. package/changelog/operations/transform.d.ts +143 -0
  62. package/changelog/operations/transform.d.ts.map +1 -0
  63. package/changelog/parse/index.cjs.js +1282 -0
  64. package/changelog/parse/index.cjs.js.map +1 -0
  65. package/changelog/parse/index.d.ts +5 -0
  66. package/changelog/parse/index.d.ts.map +1 -0
  67. package/changelog/parse/index.esm.js +1275 -0
  68. package/changelog/parse/index.esm.js.map +1 -0
  69. package/changelog/parse/line.d.ts +48 -0
  70. package/changelog/parse/line.d.ts.map +1 -0
  71. package/changelog/parse/parser.d.ts +16 -0
  72. package/changelog/parse/parser.d.ts.map +1 -0
  73. package/changelog/parse/tokenizer.d.ts +49 -0
  74. package/changelog/parse/tokenizer.d.ts.map +1 -0
  75. package/changelog/serialize/index.cjs.js +574 -0
  76. package/changelog/serialize/index.cjs.js.map +1 -0
  77. package/changelog/serialize/index.d.ts +6 -0
  78. package/changelog/serialize/index.d.ts.map +1 -0
  79. package/changelog/serialize/index.esm.js +564 -0
  80. package/changelog/serialize/index.esm.js.map +1 -0
  81. package/changelog/serialize/templates.d.ts +81 -0
  82. package/changelog/serialize/templates.d.ts.map +1 -0
  83. package/changelog/serialize/to-json.d.ts +57 -0
  84. package/changelog/serialize/to-json.d.ts.map +1 -0
  85. package/changelog/serialize/to-string.d.ts +30 -0
  86. package/changelog/serialize/to-string.d.ts.map +1 -0
  87. package/commits/index.cjs.js +648 -0
  88. package/commits/index.cjs.js.map +1 -0
  89. package/commits/index.d.ts +3 -0
  90. package/commits/index.d.ts.map +1 -0
  91. package/commits/index.esm.js +629 -0
  92. package/commits/index.esm.js.map +1 -0
  93. package/commits/models/breaking.d.ts +39 -0
  94. package/commits/models/breaking.d.ts.map +1 -0
  95. package/commits/models/commit-type.d.ts +32 -0
  96. package/commits/models/commit-type.d.ts.map +1 -0
  97. package/commits/models/conventional.d.ts +49 -0
  98. package/commits/models/conventional.d.ts.map +1 -0
  99. package/commits/models/index.cjs.js +207 -0
  100. package/commits/models/index.cjs.js.map +1 -0
  101. package/commits/models/index.d.ts +7 -0
  102. package/commits/models/index.d.ts.map +1 -0
  103. package/commits/models/index.esm.js +193 -0
  104. package/commits/models/index.esm.js.map +1 -0
  105. package/commits/parse/body.d.ts +18 -0
  106. package/commits/parse/body.d.ts.map +1 -0
  107. package/commits/parse/footer.d.ts +16 -0
  108. package/commits/parse/footer.d.ts.map +1 -0
  109. package/commits/parse/header.d.ts +15 -0
  110. package/commits/parse/header.d.ts.map +1 -0
  111. package/commits/parse/index.cjs.js +505 -0
  112. package/commits/parse/index.cjs.js.map +1 -0
  113. package/commits/parse/index.d.ts +5 -0
  114. package/commits/parse/index.d.ts.map +1 -0
  115. package/commits/parse/index.esm.js +499 -0
  116. package/commits/parse/index.esm.js.map +1 -0
  117. package/commits/parse/message.d.ts +17 -0
  118. package/commits/parse/message.d.ts.map +1 -0
  119. package/commits/utils/replace-char.d.ts +19 -0
  120. package/commits/utils/replace-char.d.ts.map +1 -0
  121. package/flow/executor/execute.d.ts +72 -0
  122. package/flow/executor/execute.d.ts.map +1 -0
  123. package/flow/executor/index.cjs.js +4402 -0
  124. package/flow/executor/index.cjs.js.map +1 -0
  125. package/flow/executor/index.d.ts +3 -0
  126. package/flow/executor/index.d.ts.map +1 -0
  127. package/flow/executor/index.esm.js +4398 -0
  128. package/flow/executor/index.esm.js.map +1 -0
  129. package/flow/factory.d.ts +58 -0
  130. package/flow/factory.d.ts.map +1 -0
  131. package/flow/index.cjs.js +8506 -0
  132. package/flow/index.cjs.js.map +1 -0
  133. package/flow/index.d.ts +7 -0
  134. package/flow/index.d.ts.map +1 -0
  135. package/flow/index.esm.js +8451 -0
  136. package/flow/index.esm.js.map +1 -0
  137. package/flow/models/flow.d.ts +130 -0
  138. package/flow/models/flow.d.ts.map +1 -0
  139. package/flow/models/index.cjs.js +285 -0
  140. package/flow/models/index.cjs.js.map +1 -0
  141. package/flow/models/index.d.ts +7 -0
  142. package/flow/models/index.d.ts.map +1 -0
  143. package/flow/models/index.esm.js +268 -0
  144. package/flow/models/index.esm.js.map +1 -0
  145. package/flow/models/step.d.ts +108 -0
  146. package/flow/models/step.d.ts.map +1 -0
  147. package/flow/models/types.d.ts +150 -0
  148. package/flow/models/types.d.ts.map +1 -0
  149. package/flow/presets/conventional.d.ts +59 -0
  150. package/flow/presets/conventional.d.ts.map +1 -0
  151. package/flow/presets/independent.d.ts +61 -0
  152. package/flow/presets/independent.d.ts.map +1 -0
  153. package/flow/presets/index.cjs.js +3903 -0
  154. package/flow/presets/index.cjs.js.map +1 -0
  155. package/flow/presets/index.d.ts +4 -0
  156. package/flow/presets/index.d.ts.map +1 -0
  157. package/flow/presets/index.esm.js +3889 -0
  158. package/flow/presets/index.esm.js.map +1 -0
  159. package/flow/presets/synced.d.ts +65 -0
  160. package/flow/presets/synced.d.ts.map +1 -0
  161. package/flow/steps/analyze-commits.d.ts +19 -0
  162. package/flow/steps/analyze-commits.d.ts.map +1 -0
  163. package/flow/steps/calculate-bump.d.ts +27 -0
  164. package/flow/steps/calculate-bump.d.ts.map +1 -0
  165. package/flow/steps/create-commit.d.ts +16 -0
  166. package/flow/steps/create-commit.d.ts.map +1 -0
  167. package/flow/steps/create-tag.d.ts +22 -0
  168. package/flow/steps/create-tag.d.ts.map +1 -0
  169. package/flow/steps/fetch-registry.d.ts +19 -0
  170. package/flow/steps/fetch-registry.d.ts.map +1 -0
  171. package/flow/steps/generate-changelog.d.ts +25 -0
  172. package/flow/steps/generate-changelog.d.ts.map +1 -0
  173. package/flow/steps/index.cjs.js +3523 -0
  174. package/flow/steps/index.cjs.js.map +1 -0
  175. package/flow/steps/index.d.ts +8 -0
  176. package/flow/steps/index.d.ts.map +1 -0
  177. package/flow/steps/index.esm.js +3504 -0
  178. package/flow/steps/index.esm.js.map +1 -0
  179. package/flow/steps/update-packages.d.ts +25 -0
  180. package/flow/steps/update-packages.d.ts.map +1 -0
  181. package/flow/utils/interpolate.d.ts +11 -0
  182. package/flow/utils/interpolate.d.ts.map +1 -0
  183. package/git/factory.d.ts +233 -0
  184. package/git/factory.d.ts.map +1 -0
  185. package/git/index.cjs.js +2863 -0
  186. package/git/index.cjs.js.map +1 -0
  187. package/git/index.d.ts +5 -0
  188. package/git/index.d.ts.map +1 -0
  189. package/git/index.esm.js +2785 -0
  190. package/git/index.esm.js.map +1 -0
  191. package/git/models/commit.d.ts +129 -0
  192. package/git/models/commit.d.ts.map +1 -0
  193. package/git/models/index.cjs.js +755 -0
  194. package/git/models/index.cjs.js.map +1 -0
  195. package/git/models/index.d.ts +7 -0
  196. package/git/models/index.d.ts.map +1 -0
  197. package/git/models/index.esm.js +729 -0
  198. package/git/models/index.esm.js.map +1 -0
  199. package/git/models/ref.d.ts +120 -0
  200. package/git/models/ref.d.ts.map +1 -0
  201. package/git/models/tag.d.ts +141 -0
  202. package/git/models/tag.d.ts.map +1 -0
  203. package/git/operations/commit.d.ts +97 -0
  204. package/git/operations/commit.d.ts.map +1 -0
  205. package/git/operations/head-info.d.ts +29 -0
  206. package/git/operations/head-info.d.ts.map +1 -0
  207. package/git/operations/index.cjs.js +1954 -0
  208. package/git/operations/index.cjs.js.map +1 -0
  209. package/git/operations/index.d.ts +14 -0
  210. package/git/operations/index.d.ts.map +1 -0
  211. package/git/operations/index.esm.js +1903 -0
  212. package/git/operations/index.esm.js.map +1 -0
  213. package/git/operations/log.d.ts +104 -0
  214. package/git/operations/log.d.ts.map +1 -0
  215. package/git/operations/manage-tags.d.ts +60 -0
  216. package/git/operations/manage-tags.d.ts.map +1 -0
  217. package/git/operations/query-tags.d.ts +88 -0
  218. package/git/operations/query-tags.d.ts.map +1 -0
  219. package/git/operations/stage.d.ts +66 -0
  220. package/git/operations/stage.d.ts.map +1 -0
  221. package/git/operations/status.d.ts +173 -0
  222. package/git/operations/status.d.ts.map +1 -0
  223. package/index.cjs.js +16761 -0
  224. package/index.cjs.js.map +1 -0
  225. package/index.d.ts +102 -0
  226. package/index.d.ts.map +1 -0
  227. package/index.esm.js +16427 -0
  228. package/index.esm.js.map +1 -0
  229. package/package.json +200 -0
  230. package/registry/factory.d.ts +18 -0
  231. package/registry/factory.d.ts.map +1 -0
  232. package/registry/index.cjs.js +543 -0
  233. package/registry/index.cjs.js.map +1 -0
  234. package/registry/index.d.ts +5 -0
  235. package/registry/index.d.ts.map +1 -0
  236. package/registry/index.esm.js +535 -0
  237. package/registry/index.esm.js.map +1 -0
  238. package/registry/models/index.cjs.js +69 -0
  239. package/registry/models/index.cjs.js.map +1 -0
  240. package/registry/models/index.d.ts +6 -0
  241. package/registry/models/index.d.ts.map +1 -0
  242. package/registry/models/index.esm.js +66 -0
  243. package/registry/models/index.esm.js.map +1 -0
  244. package/registry/models/package-info.d.ts +55 -0
  245. package/registry/models/package-info.d.ts.map +1 -0
  246. package/registry/models/registry.d.ts +62 -0
  247. package/registry/models/registry.d.ts.map +1 -0
  248. package/registry/models/version-info.d.ts +67 -0
  249. package/registry/models/version-info.d.ts.map +1 -0
  250. package/registry/npm/cache.d.ts +50 -0
  251. package/registry/npm/cache.d.ts.map +1 -0
  252. package/registry/npm/client.d.ts +30 -0
  253. package/registry/npm/client.d.ts.map +1 -0
  254. package/registry/npm/index.cjs.js +456 -0
  255. package/registry/npm/index.cjs.js.map +1 -0
  256. package/registry/npm/index.d.ts +4 -0
  257. package/registry/npm/index.d.ts.map +1 -0
  258. package/registry/npm/index.esm.js +451 -0
  259. package/registry/npm/index.esm.js.map +1 -0
  260. package/semver/compare/compare.d.ts +100 -0
  261. package/semver/compare/compare.d.ts.map +1 -0
  262. package/semver/compare/index.cjs.js +386 -0
  263. package/semver/compare/index.cjs.js.map +1 -0
  264. package/semver/compare/index.d.ts +3 -0
  265. package/semver/compare/index.d.ts.map +1 -0
  266. package/semver/compare/index.esm.js +370 -0
  267. package/semver/compare/index.esm.js.map +1 -0
  268. package/semver/compare/sort.d.ts +36 -0
  269. package/semver/compare/sort.d.ts.map +1 -0
  270. package/semver/format/index.cjs.js +58 -0
  271. package/semver/format/index.cjs.js.map +1 -0
  272. package/semver/format/index.d.ts +2 -0
  273. package/semver/format/index.d.ts.map +1 -0
  274. package/semver/format/index.esm.js +53 -0
  275. package/semver/format/index.esm.js.map +1 -0
  276. package/semver/format/to-string.d.ts +31 -0
  277. package/semver/format/to-string.d.ts.map +1 -0
  278. package/semver/increment/bump.d.ts +37 -0
  279. package/semver/increment/bump.d.ts.map +1 -0
  280. package/semver/increment/index.cjs.js +223 -0
  281. package/semver/increment/index.cjs.js.map +1 -0
  282. package/semver/increment/index.d.ts +2 -0
  283. package/semver/increment/index.d.ts.map +1 -0
  284. package/semver/increment/index.esm.js +219 -0
  285. package/semver/increment/index.esm.js.map +1 -0
  286. package/semver/index.cjs.js +1499 -0
  287. package/semver/index.cjs.js.map +1 -0
  288. package/semver/index.d.ts +6 -0
  289. package/semver/index.d.ts.map +1 -0
  290. package/semver/index.esm.js +1458 -0
  291. package/semver/index.esm.js.map +1 -0
  292. package/semver/models/index.cjs.js +153 -0
  293. package/semver/models/index.cjs.js.map +1 -0
  294. package/semver/models/index.d.ts +5 -0
  295. package/semver/models/index.d.ts.map +1 -0
  296. package/semver/models/index.esm.js +139 -0
  297. package/semver/models/index.esm.js.map +1 -0
  298. package/semver/models/range.d.ts +83 -0
  299. package/semver/models/range.d.ts.map +1 -0
  300. package/semver/models/version.d.ts +78 -0
  301. package/semver/models/version.d.ts.map +1 -0
  302. package/semver/parse/index.cjs.js +799 -0
  303. package/semver/parse/index.cjs.js.map +1 -0
  304. package/semver/parse/index.d.ts +5 -0
  305. package/semver/parse/index.d.ts.map +1 -0
  306. package/semver/parse/index.esm.js +793 -0
  307. package/semver/parse/index.esm.js.map +1 -0
  308. package/semver/parse/range.d.ts +38 -0
  309. package/semver/parse/range.d.ts.map +1 -0
  310. package/semver/parse/version.d.ts +49 -0
  311. package/semver/parse/version.d.ts.map +1 -0
  312. package/workspace/discovery/changelog-path.d.ts +21 -0
  313. package/workspace/discovery/changelog-path.d.ts.map +1 -0
  314. package/workspace/discovery/dependencies.d.ts +145 -0
  315. package/workspace/discovery/dependencies.d.ts.map +1 -0
  316. package/workspace/discovery/discover-changelogs.d.ts +76 -0
  317. package/workspace/discovery/discover-changelogs.d.ts.map +1 -0
  318. package/workspace/discovery/index.cjs.js +2300 -0
  319. package/workspace/discovery/index.cjs.js.map +1 -0
  320. package/workspace/discovery/index.d.ts +13 -0
  321. package/workspace/discovery/index.d.ts.map +1 -0
  322. package/workspace/discovery/index.esm.js +2283 -0
  323. package/workspace/discovery/index.esm.js.map +1 -0
  324. package/workspace/discovery/packages.d.ts +83 -0
  325. package/workspace/discovery/packages.d.ts.map +1 -0
  326. package/workspace/index.cjs.js +4445 -0
  327. package/workspace/index.cjs.js.map +1 -0
  328. package/workspace/index.d.ts +52 -0
  329. package/workspace/index.d.ts.map +1 -0
  330. package/workspace/index.esm.js +4394 -0
  331. package/workspace/index.esm.js.map +1 -0
  332. package/workspace/models/index.cjs.js +284 -0
  333. package/workspace/models/index.cjs.js.map +1 -0
  334. package/workspace/models/index.d.ts +10 -0
  335. package/workspace/models/index.d.ts.map +1 -0
  336. package/workspace/models/index.esm.js +261 -0
  337. package/workspace/models/index.esm.js.map +1 -0
  338. package/workspace/models/project.d.ts +118 -0
  339. package/workspace/models/project.d.ts.map +1 -0
  340. package/workspace/models/workspace.d.ts +139 -0
  341. package/workspace/models/workspace.d.ts.map +1 -0
  342. package/workspace/operations/batch-update.d.ts +99 -0
  343. package/workspace/operations/batch-update.d.ts.map +1 -0
  344. package/workspace/operations/cascade-bump.d.ts +125 -0
  345. package/workspace/operations/cascade-bump.d.ts.map +1 -0
  346. package/workspace/operations/index.cjs.js +2675 -0
  347. package/workspace/operations/index.cjs.js.map +1 -0
  348. package/workspace/operations/index.d.ts +12 -0
  349. package/workspace/operations/index.d.ts.map +1 -0
  350. package/workspace/operations/index.esm.js +2663 -0
  351. package/workspace/operations/index.esm.js.map +1 -0
  352. package/workspace/operations/validate.d.ts +85 -0
  353. package/workspace/operations/validate.d.ts.map +1 -0
@@ -0,0 +1,2026 @@
1
+ /**
2
+ * Creates a new changelog with default values.
3
+ *
4
+ * @param options - Optional configuration to customize the changelog
5
+ * @returns A new Changelog object with the specified options or defaults
6
+ */
7
+ function createChangelog(options) {
8
+ return {
9
+ source: options?.source,
10
+ header: options?.header ?? {
11
+ title: '# Changelog',
12
+ description: [],
13
+ links: [],
14
+ },
15
+ entries: options?.entries ?? [],
16
+ metadata: options?.metadata ?? {
17
+ format: 'unknown',
18
+ isConventional: false,
19
+ warnings: [],
20
+ },
21
+ };
22
+ }
23
+ /**
24
+ * Creates a new empty changelog with standard header.
25
+ *
26
+ * @returns A new empty Changelog with Keep a Changelog format
27
+ */
28
+ function createEmptyChangelog() {
29
+ return {
30
+ header: {
31
+ title: '# Changelog',
32
+ description: [
33
+ 'All notable changes to this project will be documented in this file.',
34
+ '',
35
+ 'The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),',
36
+ 'and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).',
37
+ ],
38
+ links: [],
39
+ },
40
+ entries: [],
41
+ metadata: {
42
+ format: 'keep-a-changelog',
43
+ isConventional: false,
44
+ warnings: [],
45
+ },
46
+ };
47
+ }
48
+ /**
49
+ * Creates a changelog link.
50
+ *
51
+ * @param label - The display text for the link
52
+ * @param url - The URL the link points to
53
+ * @returns A new ChangelogLink object
54
+ */
55
+ function createChangelogLink(label, url) {
56
+ return { label, url };
57
+ }
58
+
59
+ /**
60
+ * Creates a new changelog item.
61
+ *
62
+ * @param description - The description text of the change
63
+ * @param options - Optional configuration for scope, commits, references, and breaking flag
64
+ * @returns A new ChangelogItem object
65
+ */
66
+ function createChangelogItem(description, options) {
67
+ return {
68
+ description,
69
+ scope: options?.scope,
70
+ commits: options?.commits ?? [],
71
+ references: options?.references ?? [],
72
+ breaking: options?.breaking ?? false,
73
+ };
74
+ }
75
+ /**
76
+ * Creates a new changelog section.
77
+ *
78
+ * @param type - The type of section (features, fixes, breaking, etc.)
79
+ * @param heading - The display heading for the section
80
+ * @param items - Optional array of changelog items in this section
81
+ * @returns A new ChangelogSection object
82
+ */
83
+ function createChangelogSection(type, heading, items = []) {
84
+ return {
85
+ type,
86
+ heading,
87
+ items,
88
+ };
89
+ }
90
+ /**
91
+ * Creates a new changelog entry.
92
+ *
93
+ * @param version - The version string (e.g., '1.0.0')
94
+ * @param options - Optional configuration for date, sections, and other properties
95
+ * @returns A new ChangelogEntry object
96
+ */
97
+ function createChangelogEntry(version, options) {
98
+ return {
99
+ version,
100
+ date: options?.date ?? null,
101
+ unreleased: options?.unreleased ?? false,
102
+ compareUrl: options?.compareUrl,
103
+ sections: options?.sections ?? [],
104
+ rawContent: options?.rawContent,
105
+ };
106
+ }
107
+ /**
108
+ * Creates an unreleased changelog entry.
109
+ *
110
+ * @param sections - Optional array of changelog sections
111
+ * @returns A new ChangelogEntry object marked as unreleased
112
+ */
113
+ function createUnreleasedEntry(sections = []) {
114
+ return {
115
+ version: 'Unreleased',
116
+ date: null,
117
+ unreleased: true,
118
+ sections,
119
+ };
120
+ }
121
+
122
+ /**
123
+ * Maps section headings to their canonical types.
124
+ * Used during parsing to normalize different heading styles.
125
+ */
126
+ const SECTION_TYPE_MAP = {
127
+ // Breaking changes
128
+ 'breaking changes': 'breaking',
129
+ breaking: 'breaking',
130
+ 'breaking change': 'breaking',
131
+ // Features
132
+ features: 'features',
133
+ feature: 'features',
134
+ added: 'features',
135
+ new: 'features',
136
+ // Fixes
137
+ fixes: 'fixes',
138
+ fix: 'fixes',
139
+ 'bug fixes': 'fixes',
140
+ bugfixes: 'fixes',
141
+ fixed: 'fixes',
142
+ // Performance
143
+ performance: 'performance',
144
+ 'performance improvements': 'performance',
145
+ perf: 'performance',
146
+ // Documentation
147
+ documentation: 'documentation',
148
+ docs: 'documentation',
149
+ // Deprecations
150
+ deprecations: 'deprecations',
151
+ deprecated: 'deprecations',
152
+ // Refactoring
153
+ refactoring: 'refactoring',
154
+ refactor: 'refactoring',
155
+ 'code refactoring': 'refactoring',
156
+ // Tests
157
+ tests: 'tests',
158
+ test: 'tests',
159
+ testing: 'tests',
160
+ // Build
161
+ build: 'build',
162
+ 'build system': 'build',
163
+ dependencies: 'build',
164
+ // CI
165
+ ci: 'ci',
166
+ 'continuous integration': 'ci',
167
+ // Chores
168
+ chores: 'chores',
169
+ chore: 'chores',
170
+ maintenance: 'chores',
171
+ // Other
172
+ other: 'other',
173
+ miscellaneous: 'other',
174
+ misc: 'other',
175
+ changed: 'other',
176
+ changes: 'other',
177
+ removed: 'other',
178
+ security: 'other',
179
+ };
180
+ /**
181
+ * Standard section headings for serialization.
182
+ * Maps section types to their preferred heading text.
183
+ */
184
+ const SECTION_HEADINGS = {
185
+ breaking: 'Breaking Changes',
186
+ features: 'Features',
187
+ fixes: 'Bug Fixes',
188
+ performance: 'Performance',
189
+ documentation: 'Documentation',
190
+ deprecations: 'Deprecations',
191
+ refactoring: 'Refactoring',
192
+ tests: 'Tests',
193
+ build: 'Build',
194
+ ci: 'CI',
195
+ chores: 'Chores',
196
+ other: 'Other',
197
+ };
198
+ /**
199
+ * Determines the section type from a heading string.
200
+ * Returns 'other' if the heading is not recognized.
201
+ *
202
+ * @param heading - The heading string to parse
203
+ * @returns The corresponding ChangelogSectionType
204
+ */
205
+ function getSectionType(heading) {
206
+ const normalized = heading.toLowerCase().trim();
207
+ return SECTION_TYPE_MAP[normalized] ?? 'other';
208
+ }
209
+
210
+ /**
211
+ * Creates a commit reference from a full hash.
212
+ *
213
+ * @param hash - The full commit hash
214
+ * @param url - Optional URL to the commit
215
+ * @returns A new CommitRef object with both full and short hash
216
+ */
217
+ function createCommitRef(hash, url) {
218
+ return {
219
+ hash,
220
+ shortHash: hash.slice(0, 7),
221
+ url,
222
+ };
223
+ }
224
+ /**
225
+ * Creates an issue reference.
226
+ *
227
+ * @param number - The issue or PR number
228
+ * @param type - The type of reference ('issue' or 'pull-request')
229
+ * @param url - Optional URL to the issue or PR
230
+ * @returns A new IssueRef object
231
+ */
232
+ function createIssueRef(number, type = 'issue', url) {
233
+ return {
234
+ number,
235
+ type,
236
+ url,
237
+ };
238
+ }
239
+ /**
240
+ * Extracts the short hash from a full commit hash.
241
+ *
242
+ * @param hash - The full commit hash
243
+ * @returns The first 7 characters of the hash
244
+ */
245
+ function getShortHash(hash) {
246
+ return hash.slice(0, 7);
247
+ }
248
+
249
+ /**
250
+ * Safe copies of Set built-in via factory function.
251
+ *
252
+ * Since constructors cannot be safely captured via Object.assign, this module
253
+ * provides a factory function that uses Reflect.construct internally.
254
+ *
255
+ * These references are captured at module initialization time to protect against
256
+ * prototype pollution attacks. Import only what you need for tree-shaking.
257
+ *
258
+ * @module @hyperfrontend/immutable-api-utils/built-in-copy/set
259
+ */
260
+ // Capture references at module initialization time
261
+ const _Set = globalThis.Set;
262
+ const _Reflect$5 = globalThis.Reflect;
263
+ /**
264
+ * (Safe copy) Creates a new Set using the captured Set constructor.
265
+ * Use this instead of `new Set()`.
266
+ *
267
+ * @param iterable - Optional iterable of values.
268
+ * @returns A new Set instance.
269
+ */
270
+ const createSet = (iterable) => _Reflect$5.construct(_Set, iterable ? [iterable] : []);
271
+
272
+ /**
273
+ * Safe copies of Array built-in static methods.
274
+ *
275
+ * These references are captured at module initialization time to protect against
276
+ * prototype pollution attacks. Import only what you need for tree-shaking.
277
+ *
278
+ * @module @hyperfrontend/immutable-api-utils/built-in-copy/array
279
+ */
280
+ // Capture references at module initialization time
281
+ const _Array = globalThis.Array;
282
+ /**
283
+ * (Safe copy) Determines whether the passed value is an Array.
284
+ */
285
+ const isArray = _Array.isArray;
286
+
287
+ /**
288
+ * Safe copies of Map built-in via factory function.
289
+ *
290
+ * Since constructors cannot be safely captured via Object.assign, this module
291
+ * provides a factory function that uses Reflect.construct internally.
292
+ *
293
+ * These references are captured at module initialization time to protect against
294
+ * prototype pollution attacks. Import only what you need for tree-shaking.
295
+ *
296
+ * @module @hyperfrontend/immutable-api-utils/built-in-copy/map
297
+ */
298
+ // Capture references at module initialization time
299
+ const _Map = globalThis.Map;
300
+ const _Reflect$4 = globalThis.Reflect;
301
+ /**
302
+ * (Safe copy) Creates a new Map using the captured Map constructor.
303
+ * Use this instead of `new Map()`.
304
+ *
305
+ * @param iterable - Optional iterable of key-value pairs.
306
+ * @returns A new Map instance.
307
+ */
308
+ const createMap = (iterable) => _Reflect$4.construct(_Map, iterable ? [iterable] : []);
309
+
310
+ /**
311
+ * Safe copies of Object built-in methods.
312
+ *
313
+ * These references are captured at module initialization time to protect against
314
+ * prototype pollution attacks. Import only what you need for tree-shaking.
315
+ *
316
+ * @module @hyperfrontend/immutable-api-utils/built-in-copy/object
317
+ */
318
+ // Capture references at module initialization time
319
+ const _Object = globalThis.Object;
320
+ const _Reflect$3 = globalThis.Reflect;
321
+ const _ObjectPrototype = _Object.prototype;
322
+ const _hasOwnProperty = _ObjectPrototype.hasOwnProperty;
323
+ /**
324
+ * (Safe copy) Returns the names of the enumerable string properties and methods of an object.
325
+ */
326
+ const keys = _Object.keys;
327
+ /**
328
+ * (Safe copy) Returns an array of key/values of the enumerable own properties of an object.
329
+ */
330
+ const entries = _Object.entries;
331
+ /**
332
+ * (Safe copy) Adds a property to an object, or modifies attributes of an existing property.
333
+ */
334
+ const defineProperty = _Object.defineProperty;
335
+ /**
336
+ * (Safe copy) Safe wrapper for Object.prototype.hasOwnProperty.call().
337
+ * Checks if an object has a property as its own (not inherited) property.
338
+ *
339
+ * @param obj - The object to check.
340
+ * @param key - The property key to check.
341
+ * @returns True if the object has the property as its own property.
342
+ */
343
+ const hasOwn = (obj, key) => _Reflect$3.apply(_hasOwnProperty, obj, [key]);
344
+
345
+ /**
346
+ * Creates a new validation context.
347
+ *
348
+ * @param rootSchema - The root schema being validated against
349
+ * @param validator - The schema validator function
350
+ * @param collectAllErrors - Whether to collect all errors (default: true)
351
+ * @param strictPatterns - Whether to report errors for invalid regex patterns (default: false)
352
+ * @param patternSafetyChecker - Optional pattern safety checker for ReDoS detection
353
+ * @returns A new validation context
354
+ */
355
+ function createValidationContext(rootSchema, validator, collectAllErrors = true, strictPatterns = false, patternSafetyChecker) {
356
+ const definitions = createMap();
357
+ // Pre-populate definitions from root schema
358
+ if (rootSchema.definitions) {
359
+ for (const [name, schema] of entries(rootSchema.definitions)) {
360
+ definitions.set(`#/definitions/${name}`, schema);
361
+ }
362
+ }
363
+ return {
364
+ path: '',
365
+ errors: [],
366
+ rootSchema,
367
+ definitions,
368
+ collectAllErrors,
369
+ strictPatterns,
370
+ patternSafetyChecker,
371
+ validate: validator,
372
+ };
373
+ }
374
+ /**
375
+ * Creates a child context with updated path.
376
+ *
377
+ * @param ctx - Parent context
378
+ * @param segment - Path segment to append
379
+ * @returns New context with updated path
380
+ */
381
+ function pushPath(ctx, segment) {
382
+ const escapedSegment = String(segment).replace(/~/g, '~0').replace(/\//g, '~1');
383
+ return {
384
+ ...ctx,
385
+ path: `${ctx.path}/${escapedSegment}`,
386
+ };
387
+ }
388
+ /**
389
+ * Adds a validation error to the context.
390
+ *
391
+ * @param ctx - Validation context
392
+ * @param message - Human-readable error message
393
+ * @param instance - The failing value
394
+ * @param code - Optional error code for programmatic handling
395
+ * @param params - Optional additional parameters
396
+ */
397
+ function addError(ctx, message, instance, code, params) {
398
+ ctx.errors.push({
399
+ message,
400
+ path: ctx.path || '/',
401
+ instance,
402
+ code,
403
+ params,
404
+ });
405
+ }
406
+ /**
407
+ * Checks if we should continue validation after an error.
408
+ *
409
+ * @param ctx - Validation context
410
+ * @returns true if we should continue, false if we should stop
411
+ */
412
+ function shouldContinue(ctx) {
413
+ return ctx.collectAllErrors || ctx.errors.length === 0;
414
+ }
415
+
416
+ /**
417
+ * Performs deep equality check for JSON values.
418
+ *
419
+ * Used for enum validation and uniqueItems validation.
420
+ *
421
+ * @param a - First value to compare
422
+ * @param b - Second value to compare
423
+ * @returns true if values are deeply equal, false otherwise
424
+ */
425
+ function isEqual(a, b) {
426
+ if (a === b)
427
+ return true;
428
+ if (a === null || b === null)
429
+ return false;
430
+ if (typeof a !== typeof b)
431
+ return false;
432
+ if (typeof a === 'object') {
433
+ if (isArray(a) && isArray(b)) {
434
+ if (a.length !== b.length)
435
+ return false;
436
+ for (let i = 0; i < a.length; i++) {
437
+ if (!isEqual(a[i], b[i]))
438
+ return false;
439
+ }
440
+ return true;
441
+ }
442
+ if (isArray(a) || isArray(b))
443
+ return false;
444
+ const keysA = keys(a);
445
+ const keysB = keys(b);
446
+ if (keysA.length !== keysB.length)
447
+ return false;
448
+ for (const key of keysA) {
449
+ if (!hasOwn(b, key))
450
+ return false;
451
+ if (!isEqual(a[key], b[key]))
452
+ return false;
453
+ }
454
+ return true;
455
+ }
456
+ return false;
457
+ }
458
+
459
+ /**
460
+ * Validates array length and uniqueItems constraints.
461
+ *
462
+ * @param instance - Array being validated
463
+ * @param schema - Schema containing array bounds
464
+ * @param ctx - Validation context
465
+ * @returns true if validation passes, false otherwise
466
+ */
467
+ function validateArrayBounds(instance, schema, ctx) {
468
+ let valid = true;
469
+ if (schema.minItems !== undefined && instance.length < schema.minItems) {
470
+ addError(ctx, `Array must have at least ${schema.minItems} items, got ${instance.length}`, instance, 'minItems', {
471
+ limit: schema.minItems,
472
+ actual: instance.length,
473
+ });
474
+ valid = false;
475
+ if (!shouldContinue(ctx))
476
+ return false;
477
+ }
478
+ if (schema.maxItems !== undefined && instance.length > schema.maxItems) {
479
+ addError(ctx, `Array must have at most ${schema.maxItems} items, got ${instance.length}`, instance, 'maxItems', {
480
+ limit: schema.maxItems,
481
+ actual: instance.length,
482
+ });
483
+ valid = false;
484
+ if (!shouldContinue(ctx))
485
+ return false;
486
+ }
487
+ if (schema.uniqueItems === true) {
488
+ // Check for duplicates
489
+ for (let i = 0; i < instance.length; i++) {
490
+ for (let j = i + 1; j < instance.length; j++) {
491
+ if (isEqual(instance[i], instance[j])) {
492
+ addError(ctx, `Array items must be unique. Duplicate found at indices ${i} and ${j}`, instance, 'uniqueItems');
493
+ valid = false;
494
+ if (!shouldContinue(ctx))
495
+ return false;
496
+ }
497
+ }
498
+ }
499
+ }
500
+ return valid;
501
+ }
502
+
503
+ /**
504
+ * Validates 'allOf' keyword - all schemas must match.
505
+ *
506
+ * @param instance - Value being validated
507
+ * @param schema - Schema containing the allOf constraint
508
+ * @param ctx - Validation context
509
+ * @returns true if validation passes, false otherwise
510
+ */
511
+ function validateAllOf(instance, schema, ctx) {
512
+ const allOf = schema.allOf;
513
+ if (!allOf || allOf.length === 0) {
514
+ return true;
515
+ }
516
+ let valid = true;
517
+ for (let i = 0; i < allOf.length; i++) {
518
+ const subSchema = allOf[i];
519
+ /* istanbul ignore if -- defensive null check for sparse arrays */
520
+ if (!subSchema)
521
+ continue;
522
+ if (!ctx.validate(instance, subSchema, ctx)) {
523
+ valid = false;
524
+ if (!shouldContinue(ctx))
525
+ return false;
526
+ }
527
+ }
528
+ return valid;
529
+ }
530
+ /**
531
+ * Validates 'anyOf' keyword - at least one schema must match.
532
+ *
533
+ * @param instance - Value being validated
534
+ * @param schema - Schema containing the anyOf constraint
535
+ * @param ctx - Validation context
536
+ * @returns true if validation passes, false otherwise
537
+ */
538
+ function validateAnyOf(instance, schema, ctx) {
539
+ const anyOf = schema.anyOf;
540
+ if (!anyOf || anyOf.length === 0) {
541
+ return true;
542
+ }
543
+ // Try each schema - if any matches, we pass
544
+ for (const subSchema of anyOf) {
545
+ const subCtx = createValidationContext(ctx.rootSchema, ctx.validate, false);
546
+ // Copy path from parent context
547
+ defineProperty(subCtx, 'path', { value: ctx.path, writable: false });
548
+ if (ctx.validate(instance, subSchema, subCtx)) {
549
+ return true;
550
+ }
551
+ }
552
+ addError(ctx, 'Value does not match any of the allowed schemas (anyOf)', instance, 'anyOf');
553
+ return false;
554
+ }
555
+ /**
556
+ * Validates 'oneOf' keyword - exactly one schema must match.
557
+ *
558
+ * @param instance - Value being validated
559
+ * @param schema - Schema containing the oneOf constraint
560
+ * @param ctx - Validation context
561
+ * @returns true if validation passes, false otherwise
562
+ */
563
+ function validateOneOf(instance, schema, ctx) {
564
+ const oneOf = schema.oneOf;
565
+ if (!oneOf || oneOf.length === 0) {
566
+ return true;
567
+ }
568
+ let matchCount = 0;
569
+ for (const subSchema of oneOf) {
570
+ const subCtx = createValidationContext(ctx.rootSchema, ctx.validate, false);
571
+ defineProperty(subCtx, 'path', { value: ctx.path, writable: false });
572
+ if (ctx.validate(instance, subSchema, subCtx)) {
573
+ matchCount++;
574
+ if (matchCount > 1)
575
+ break; // Early exit if more than one match
576
+ }
577
+ }
578
+ if (matchCount === 1) {
579
+ return true;
580
+ }
581
+ if (matchCount === 0) {
582
+ addError(ctx, 'Value does not match any of the schemas (oneOf)', instance, 'oneOf');
583
+ }
584
+ else {
585
+ addError(ctx, `Value matches ${matchCount} schemas but must match exactly one (oneOf)`, instance, 'oneOf', {
586
+ matches: matchCount,
587
+ });
588
+ }
589
+ return false;
590
+ }
591
+ /**
592
+ * Validates 'not' keyword - schema must NOT match.
593
+ *
594
+ * @param instance - Value being validated
595
+ * @param schema - Schema containing the not constraint
596
+ * @param ctx - Validation context
597
+ * @returns true if validation passes, false otherwise
598
+ */
599
+ function validateNot(instance, schema, ctx) {
600
+ const not = schema.not;
601
+ if (!not) {
602
+ return true;
603
+ }
604
+ const subCtx = createValidationContext(ctx.rootSchema, ctx.validate, false);
605
+ defineProperty(subCtx, 'path', { value: ctx.path, writable: false });
606
+ if (ctx.validate(instance, not, subCtx)) {
607
+ // Schema matched when it shouldn't have
608
+ addError(ctx, 'Value should NOT match the schema', instance, 'not');
609
+ return false;
610
+ }
611
+ return true;
612
+ }
613
+
614
+ /**
615
+ * Validates object 'dependencies' keyword.
616
+ *
617
+ * @param instance - Object being validated
618
+ * @param schema - Schema containing the dependencies constraint
619
+ * @param ctx - Validation context
620
+ * @returns true if validation passes, false otherwise
621
+ */
622
+ function validateDependencies(instance, schema, ctx) {
623
+ if (!schema.dependencies) {
624
+ return true;
625
+ }
626
+ let valid = true;
627
+ for (const [key, dependency] of entries(schema.dependencies)) {
628
+ // Only check dependency if the key is present
629
+ /* istanbul ignore next -- key presence check */
630
+ if (!hasOwn(instance, key)) {
631
+ continue;
632
+ }
633
+ /* istanbul ignore next -- dependency type check */
634
+ if (isArray(dependency)) {
635
+ // Property dependency: if key is present, these properties must also be present
636
+ for (const requiredKey of dependency) {
637
+ /* istanbul ignore next -- required key check */
638
+ if (!hasOwn(instance, requiredKey)) {
639
+ addError(ctx, `Property '${key}' requires property '${requiredKey}' to also be present`, instance, 'dependencies', {
640
+ property: key,
641
+ /* istanbul ignore next -- required key assignment */
642
+ required: requiredKey,
643
+ });
644
+ valid = false;
645
+ /* istanbul ignore if -- early exit tested in validate.spec.ts */
646
+ if (!shouldContinue(ctx))
647
+ return false;
648
+ }
649
+ }
650
+ }
651
+ else {
652
+ // Schema dependency: if key is present, the object must also validate against this schema
653
+ /* istanbul ignore next -- schema dependency validation */
654
+ if (!ctx.validate(instance, dependency, ctx)) {
655
+ /* istanbul ignore next -- failure path */
656
+ valid = false;
657
+ /* istanbul ignore if -- early exit tested in validate.spec.ts */
658
+ if (!shouldContinue(ctx))
659
+ return false;
660
+ }
661
+ }
662
+ }
663
+ return valid;
664
+ }
665
+
666
+ /**
667
+ * Safe copies of JSON built-in methods.
668
+ *
669
+ * These references are captured at module initialization time to protect against
670
+ * prototype pollution attacks. Import only what you need for tree-shaking.
671
+ *
672
+ * @module @hyperfrontend/immutable-api-utils/built-in-copy/json
673
+ */
674
+ // Capture references at module initialization time
675
+ const _JSON = globalThis.JSON;
676
+ /**
677
+ * (Safe copy) Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
678
+ */
679
+ const stringify = _JSON.stringify;
680
+
681
+ /**
682
+ * Validates enum constraint.
683
+ *
684
+ * @param instance - Value being validated
685
+ * @param schema - Schema containing the enum constraint
686
+ * @param ctx - Validation context
687
+ * @returns true if validation passes, false otherwise
688
+ */
689
+ function validateEnum(instance, schema, ctx) {
690
+ if (!schema.enum) {
691
+ return true;
692
+ }
693
+ for (const enumValue of schema.enum) {
694
+ if (isEqual(instance, enumValue)) {
695
+ return true;
696
+ }
697
+ }
698
+ const allowedValues = schema.enum.map((v) => stringify(v)).join(', ');
699
+ addError(ctx, `Value must be one of: ${allowedValues}`, instance, 'enum', {
700
+ allowedValues: schema.enum,
701
+ });
702
+ return false;
703
+ }
704
+
705
+ /**
706
+ * Safe copies of Date built-in via factory function and static methods.
707
+ *
708
+ * Since constructors cannot be safely captured via Object.assign, this module
709
+ * provides a factory function that uses Reflect.construct internally.
710
+ *
711
+ * These references are captured at module initialization time to protect against
712
+ * prototype pollution attacks. Import only what you need for tree-shaking.
713
+ *
714
+ * @module @hyperfrontend/immutable-api-utils/built-in-copy/date
715
+ */
716
+ // Capture references at module initialization time
717
+ const _Date = globalThis.Date;
718
+ const _Reflect$2 = globalThis.Reflect;
719
+ function createDate(...args) {
720
+ return _Reflect$2.construct(_Date, args);
721
+ }
722
+ /**
723
+ * (Safe copy) Parses a string representation of a date.
724
+ */
725
+ const dateParse = _Date.parse;
726
+ /**
727
+ * (Safe copy) Returns the number of milliseconds in a Date object since January 1, 1970 UTC.
728
+ */
729
+ const dateUTC = _Date.UTC;
730
+
731
+ /**
732
+ * Safe copies of Number built-in methods and constants.
733
+ *
734
+ * These references are captured at module initialization time to protect against
735
+ * prototype pollution attacks. Import only what you need for tree-shaking.
736
+ *
737
+ * @module @hyperfrontend/immutable-api-utils/built-in-copy/number
738
+ */
739
+ // Capture references at module initialization time
740
+ const _Number = globalThis.Number;
741
+ const _parseInt = globalThis.parseInt;
742
+ const _isNaN = globalThis.isNaN;
743
+ const _isFinite = globalThis.isFinite;
744
+ /**
745
+ * (Safe copy) Determines whether the passed value is an integer.
746
+ */
747
+ const isInteger = _Number.isInteger;
748
+ // ============================================================================
749
+ // Parsing
750
+ // ============================================================================
751
+ /**
752
+ * (Safe copy) Parses a string and returns an integer.
753
+ */
754
+ const parseInt = _parseInt;
755
+ // ============================================================================
756
+ // Global Type Checking (legacy, less strict)
757
+ // ============================================================================
758
+ /**
759
+ * (Safe copy) Global isNaN function (coerces to number first, less strict than Number.isNaN).
760
+ */
761
+ const globalIsNaN = _isNaN;
762
+ /**
763
+ * (Safe copy) Global isFinite function (coerces to number first, less strict than Number.isFinite).
764
+ */
765
+ const globalIsFinite = _isFinite;
766
+
767
+ /**
768
+ * Safe copies of RegExp built-in via factory function.
769
+ *
770
+ * Since constructors cannot be safely captured via Object.assign, this module
771
+ * provides a factory function that uses Reflect.construct internally.
772
+ *
773
+ * These references are captured at module initialization time to protect against
774
+ * prototype pollution attacks. Import only what you need for tree-shaking.
775
+ *
776
+ * @module @hyperfrontend/immutable-api-utils/built-in-copy/regexp
777
+ */
778
+ // Capture references at module initialization time
779
+ const _RegExp = globalThis.RegExp;
780
+ const _Reflect$1 = globalThis.Reflect;
781
+ /**
782
+ * (Safe copy) Creates a new RegExp using the captured RegExp constructor.
783
+ * Use this instead of `new RegExp()`.
784
+ *
785
+ * @param pattern - The pattern string or RegExp to copy.
786
+ * @param flags - Optional flags string.
787
+ * @returns A new RegExp instance.
788
+ */
789
+ const createRegExp = (pattern, flags) => _Reflect$1.construct(_RegExp, [pattern, flags]);
790
+
791
+ /**
792
+ * Safe copies of URL built-ins via factory functions.
793
+ *
794
+ * Provides safe references to URL and URLSearchParams.
795
+ * These references are captured at module initialization time to protect against
796
+ * prototype pollution attacks. Import only what you need for tree-shaking.
797
+ *
798
+ * @module @hyperfrontend/immutable-api-utils/built-in-copy/url
799
+ */
800
+ // Capture references at module initialization time
801
+ const _URL = globalThis.URL;
802
+ const _Reflect = globalThis.Reflect;
803
+ // ============================================================================
804
+ // URL
805
+ // ============================================================================
806
+ /**
807
+ * (Safe copy) Creates a new URL using the captured URL constructor.
808
+ * Use this instead of `new URL()`.
809
+ *
810
+ * @param url - The URL string to parse.
811
+ * @param base - Optional base URL for relative URLs.
812
+ * @returns A new URL instance.
813
+ */
814
+ const createURL = (url, base) => _Reflect.construct(_URL, [url, base]);
815
+ /**
816
+ * (Safe copy) Creates an object URL for the given object.
817
+ * Use this instead of `URL.createObjectURL()`.
818
+ *
819
+ * Note: This is a browser-only API. In Node.js environments, this will throw.
820
+ */
821
+ typeof _URL.createObjectURL === 'function'
822
+ ? _URL.createObjectURL.bind(_URL)
823
+ : () => {
824
+ throw new Error('URL.createObjectURL is not available in this environment');
825
+ };
826
+ /**
827
+ * (Safe copy) Revokes an object URL previously created with createObjectURL.
828
+ * Use this instead of `URL.revokeObjectURL()`.
829
+ *
830
+ * Note: This is a browser-only API. In Node.js environments, this will throw.
831
+ */
832
+ typeof _URL.revokeObjectURL === 'function'
833
+ ? _URL.revokeObjectURL.bind(_URL)
834
+ : () => {
835
+ throw new Error('URL.revokeObjectURL is not available in this environment');
836
+ };
837
+
838
+ /**
839
+ * Format validators for common string formats.
840
+ */
841
+ const formatValidators = {
842
+ 'date-time': (v) => {
843
+ // ISO 8601 date-time format - anchored to prevent matching at unexpected locations
844
+ if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/.test(v))
845
+ return false;
846
+ const date = dateParse(v);
847
+ return !globalIsNaN(date);
848
+ },
849
+ date: (v) => {
850
+ // ISO 8601 date format (YYYY-MM-DD)
851
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(v))
852
+ return false;
853
+ const [year, month, day] = v.split('-').map(Number);
854
+ const date = createDate(dateUTC(year, month - 1, day));
855
+ // Check that the date components match exactly
856
+ return date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day;
857
+ },
858
+ time: (v) => {
859
+ // ISO 8601 time format (HH:MM:SS or HH:MM:SS.sss with optional timezone)
860
+ // Parse segments to avoid nested quantifiers
861
+ const mainMatch = v.match(/^(\d{2}):(\d{2}):(\d{2})/);
862
+ if (!mainMatch)
863
+ return false;
864
+ const hour = Number(mainMatch[1]);
865
+ const minute = Number(mainMatch[2]);
866
+ const second = Number(mainMatch[3]);
867
+ if (hour > 23 || minute > 59 || second > 59)
868
+ return false;
869
+ // Validate remaining part (fractional seconds and/or timezone)
870
+ const rest = v.slice(8);
871
+ if (rest === '')
872
+ return true;
873
+ // Fractional seconds: .ddd where d is digits (1-6 typically)
874
+ if (rest.match(/^\.\d{1,9}$/))
875
+ return true;
876
+ // Timezone only: Z or +HH:MM or -HH:MM
877
+ if (rest.match(/^(Z|[+-]\d{2}:\d{2})$/))
878
+ return true;
879
+ // Fractional + timezone
880
+ if (rest.match(/^\.\d{1,9}(Z|[+-]\d{2}:\d{2})$/))
881
+ return true;
882
+ return false;
883
+ },
884
+ email: (v) => {
885
+ // Basic email validation - fixed to prevent ReDoS by excluding dots from domain part
886
+ return /^[^\s@]+@[^\s@.]+\.[^\s@.]+$/.test(v);
887
+ },
888
+ hostname: (v) => {
889
+ // RFC 1123 hostname - validated per label to prevent ReDoS
890
+ if (v.length > 253 || v.length === 0)
891
+ return false; // Max hostname length per RFC
892
+ const labels = v.split('.');
893
+ for (const label of labels) {
894
+ if (label.length === 0 || label.length > 63)
895
+ return false;
896
+ // Start and end with alphanumeric
897
+ if (!/^[a-zA-Z0-9]$/.test(label[0]))
898
+ return false;
899
+ if (label.length > 1 && !/^[a-zA-Z0-9]$/.test(label[label.length - 1]))
900
+ return false;
901
+ // Middle can include hyphens
902
+ for (let i = 1; i < label.length - 1; i++) {
903
+ if (!/^[a-zA-Z0-9-]$/.test(label[i]))
904
+ return false;
905
+ }
906
+ }
907
+ return true;
908
+ },
909
+ ipv4: (v) => {
910
+ // IPv4 address
911
+ const parts = v.split('.');
912
+ if (parts.length !== 4)
913
+ return false;
914
+ return parts.every((part) => {
915
+ const num = parseInt(part, 10);
916
+ return !globalIsNaN(num) && num >= 0 && num <= 255 && part === String(num);
917
+ });
918
+ },
919
+ ipv6: (v) => {
920
+ // Simplified IPv6 validation - procedural approach to avoid ReDoS
921
+ if (v === '::')
922
+ return true;
923
+ // Check for double colon (compressed form)
924
+ const hasDoubleColon = v.includes('::');
925
+ if (!hasDoubleColon) {
926
+ // Full form: exactly 8 groups separated by single colons
927
+ const groups = v.split(':');
928
+ if (groups.length !== 8)
929
+ return false;
930
+ const hexGroup = /^[0-9a-fA-F]{1,4}$/;
931
+ return groups.every((g) => hexGroup.test(g));
932
+ }
933
+ // Compressed form: validate :: appears exactly once and total groups <= 8
934
+ const parts = v.split('::');
935
+ if (parts.length !== 2)
936
+ return false;
937
+ const left = parts[0] ? parts[0].split(':').filter(Boolean) : [];
938
+ const right = parts[1] ? parts[1].split(':').filter(Boolean) : [];
939
+ if (left.length + right.length > 7)
940
+ return false;
941
+ const hexGroup = /^[0-9a-fA-F]{1,4}$/;
942
+ return left.every((g) => hexGroup.test(g)) && right.every((g) => hexGroup.test(g));
943
+ },
944
+ uri: (v) => {
945
+ // Basic URI validation
946
+ try {
947
+ createURL(v);
948
+ return true;
949
+ /* istanbul ignore next -- URL constructor always throws for invalid URI */
950
+ }
951
+ catch {
952
+ return false;
953
+ }
954
+ },
955
+ 'uri-reference': (v) => {
956
+ // URI or relative reference
957
+ try {
958
+ createURL(v, 'http://example.com');
959
+ /* istanbul ignore next -- success path just returns true */
960
+ return true;
961
+ }
962
+ catch {
963
+ /* istanbul ignore next -- URL constructor is very permissive with base URL */
964
+ return false;
965
+ }
966
+ },
967
+ uuid: (v) => {
968
+ // UUID format
969
+ return /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(v);
970
+ },
971
+ regex: (v) => {
972
+ // Valid regex pattern
973
+ try {
974
+ // eslint-disable-next-line workspace/no-unsafe-regex -- intentionally validating user-provided regex patterns
975
+ createRegExp(v);
976
+ return true;
977
+ }
978
+ catch {
979
+ return false;
980
+ }
981
+ },
982
+ 'json-pointer': (v) => {
983
+ // JSON Pointer format - validate segment by segment to avoid nested quantifiers
984
+ if (v === '')
985
+ return true;
986
+ if (!v.startsWith('/'))
987
+ return false;
988
+ const segments = v.slice(1).split('/');
989
+ const validSegment = /^([^/~]|~[01])*$/;
990
+ return segments.every((seg) => validSegment.test(seg));
991
+ },
992
+ };
993
+ /**
994
+ * Validates string format constraint.
995
+ *
996
+ * @param instance - String being validated
997
+ * @param schema - Schema containing the format constraint
998
+ * @param ctx - Validation context
999
+ * @returns true if validation passes, false otherwise
1000
+ */
1001
+ function validateFormat(instance, schema, ctx) {
1002
+ if (!schema.format) {
1003
+ return true;
1004
+ }
1005
+ const validator = formatValidators[schema.format];
1006
+ if (!validator) {
1007
+ // Unknown format - allow by default (as per JSON Schema spec)
1008
+ return true;
1009
+ }
1010
+ if (!validator(instance)) {
1011
+ addError(ctx, `String does not match format '${schema.format}'`, instance, 'format', {
1012
+ format: schema.format,
1013
+ });
1014
+ return false;
1015
+ }
1016
+ return true;
1017
+ }
1018
+
1019
+ /**
1020
+ * Validates array 'items' keyword.
1021
+ *
1022
+ * @param instance - Array being validated
1023
+ * @param schema - Schema containing the items constraint
1024
+ * @param ctx - Validation context
1025
+ * @returns true if validation passes, false otherwise
1026
+ */
1027
+ function validateItems(instance, schema, ctx) {
1028
+ const items = schema.items;
1029
+ if (items === undefined) {
1030
+ return true;
1031
+ }
1032
+ let valid = true;
1033
+ if (isArray(items)) {
1034
+ // Tuple validation
1035
+ for (let i = 0; i < items.length && i < instance.length; i++) {
1036
+ const itemSchema = items[i];
1037
+ /* istanbul ignore if -- defensive null check for sparse arrays */
1038
+ if (!itemSchema)
1039
+ continue;
1040
+ const itemCtx = pushPath(ctx, i);
1041
+ if (!ctx.validate(instance[i], itemSchema, itemCtx)) {
1042
+ valid = false;
1043
+ /* istanbul ignore if -- early exit already tested in validate.spec.ts */
1044
+ if (!shouldContinue(ctx))
1045
+ return false;
1046
+ }
1047
+ }
1048
+ // Handle additional items beyond the tuple
1049
+ if (instance.length > items.length) {
1050
+ if (!validateAdditionalItems(instance, schema, ctx, items.length)) {
1051
+ valid = false;
1052
+ }
1053
+ }
1054
+ }
1055
+ else {
1056
+ // All items must match the single schema
1057
+ for (let i = 0; i < instance.length; i++) {
1058
+ const itemCtx = pushPath(ctx, i);
1059
+ if (!ctx.validate(instance[i], items, itemCtx)) {
1060
+ valid = false;
1061
+ if (!shouldContinue(ctx))
1062
+ return false;
1063
+ }
1064
+ }
1065
+ }
1066
+ return valid;
1067
+ }
1068
+ /**
1069
+ * Validates 'additionalItems' keyword for tuple arrays.
1070
+ *
1071
+ * @param instance - Array being validated
1072
+ * @param schema - Schema containing the additionalItems constraint
1073
+ * @param ctx - Validation context
1074
+ * @param startIndex - Index from which to start checking additional items
1075
+ * @returns true if validation passes, false otherwise
1076
+ */
1077
+ function validateAdditionalItems(instance, schema, ctx, startIndex) {
1078
+ const additionalItems = schema.additionalItems;
1079
+ // If not specified, additional items are allowed
1080
+ /* istanbul ignore if -- default case handled in items.spec.ts */
1081
+ if (additionalItems === undefined) {
1082
+ return true;
1083
+ }
1084
+ /* istanbul ignore next -- additionalItems initialization and branching */
1085
+ let valid = true;
1086
+ /* istanbul ignore next -- additionalItems branching */
1087
+ if (additionalItems === false) {
1088
+ // No additional items allowed
1089
+ if (instance.length > startIndex) {
1090
+ addError(ctx, `Array has too many items. Expected at most ${startIndex}, got ${instance.length}`, instance, 'additionalItems', {
1091
+ limit: startIndex,
1092
+ actual: instance.length,
1093
+ });
1094
+ valid = false;
1095
+ }
1096
+ }
1097
+ else if (typeof additionalItems === 'object') {
1098
+ // Additional items must match the schema
1099
+ for (let i = startIndex; i < instance.length; i++) {
1100
+ const itemCtx = pushPath(ctx, i);
1101
+ /* istanbul ignore else -- validation failure tested in items.spec.ts */
1102
+ if (!ctx.validate(instance[i], additionalItems, itemCtx)) {
1103
+ valid = false;
1104
+ /* istanbul ignore if -- early exit tested in validate.spec.ts */
1105
+ if (!shouldContinue(ctx))
1106
+ return false;
1107
+ }
1108
+ }
1109
+ }
1110
+ // If additionalItems === true, any additional items are allowed
1111
+ return valid;
1112
+ }
1113
+
1114
+ /**
1115
+ * Safe copies of Math built-in methods.
1116
+ *
1117
+ * These references are captured at module initialization time to protect against
1118
+ * prototype pollution attacks. Import only what you need for tree-shaking.
1119
+ *
1120
+ * @module @hyperfrontend/immutable-api-utils/built-in-copy/math
1121
+ */
1122
+ // Capture references at module initialization time
1123
+ const _Math = globalThis.Math;
1124
+ // ============================================================================
1125
+ // Basic Operations
1126
+ // ============================================================================
1127
+ /**
1128
+ * (Safe copy) Returns the absolute value of a number.
1129
+ */
1130
+ const abs = _Math.abs;
1131
+
1132
+ /**
1133
+ * Validates number range and multipleOf constraints.
1134
+ *
1135
+ * @param instance - Number being validated
1136
+ * @param schema - Schema containing number constraints
1137
+ * @param ctx - Validation context
1138
+ * @returns true if validation passes, false otherwise
1139
+ */
1140
+ function validateNumberBounds(instance, schema, ctx) {
1141
+ let valid = true;
1142
+ if (schema.minimum !== undefined) {
1143
+ const isExclusive = schema.exclusiveMinimum === true;
1144
+ if (isExclusive ? instance <= schema.minimum : instance < schema.minimum) {
1145
+ const comparison = isExclusive ? 'greater than' : 'at least';
1146
+ addError(ctx, `Number must be ${comparison} ${schema.minimum}, got ${instance}`, instance, 'minimum', {
1147
+ limit: schema.minimum,
1148
+ exclusive: isExclusive,
1149
+ actual: instance,
1150
+ });
1151
+ valid = false;
1152
+ if (!shouldContinue(ctx))
1153
+ return false;
1154
+ }
1155
+ }
1156
+ if (schema.maximum !== undefined) {
1157
+ const isExclusive = schema.exclusiveMaximum === true;
1158
+ if (isExclusive ? instance >= schema.maximum : instance > schema.maximum) {
1159
+ const comparison = isExclusive ? 'less than' : 'at most';
1160
+ addError(ctx, `Number must be ${comparison} ${schema.maximum}, got ${instance}`, instance, 'maximum', {
1161
+ limit: schema.maximum,
1162
+ exclusive: isExclusive,
1163
+ actual: instance,
1164
+ });
1165
+ valid = false;
1166
+ if (!shouldContinue(ctx))
1167
+ return false;
1168
+ }
1169
+ }
1170
+ if (schema.multipleOf !== undefined && schema.multipleOf > 0) {
1171
+ // Use epsilon comparison for floating point precision
1172
+ const remainder = abs(instance % schema.multipleOf);
1173
+ const epsilon = 1e-10;
1174
+ if (remainder > epsilon && schema.multipleOf - remainder > epsilon) {
1175
+ addError(ctx, `Number must be a multiple of ${schema.multipleOf}, got ${instance}`, instance, 'multipleOf', {
1176
+ multipleOf: schema.multipleOf,
1177
+ actual: instance,
1178
+ });
1179
+ valid = false;
1180
+ if (!shouldContinue(ctx))
1181
+ return false;
1182
+ }
1183
+ }
1184
+ return valid;
1185
+ }
1186
+
1187
+ /**
1188
+ * Validates object bounds constraints (minProperties, maxProperties).
1189
+ *
1190
+ * @param instance - Object being validated
1191
+ * @param schema - Schema containing object bounds
1192
+ * @param ctx - Validation context
1193
+ * @returns true if validation passes, false otherwise
1194
+ */
1195
+ function validateObjectBounds(instance, schema, ctx) {
1196
+ let valid = true;
1197
+ const propertyCount = keys(instance).length;
1198
+ if (schema.minProperties !== undefined && propertyCount < schema.minProperties) {
1199
+ addError(ctx, `Object must have at least ${schema.minProperties} properties, got ${propertyCount}`, instance, 'minProperties', {
1200
+ limit: schema.minProperties,
1201
+ actual: propertyCount,
1202
+ });
1203
+ valid = false;
1204
+ if (!shouldContinue(ctx))
1205
+ return false;
1206
+ }
1207
+ if (schema.maxProperties !== undefined && propertyCount > schema.maxProperties) {
1208
+ addError(ctx, `Object must have at most ${schema.maxProperties} properties, got ${propertyCount}`, instance, 'maxProperties', {
1209
+ limit: schema.maxProperties,
1210
+ actual: propertyCount,
1211
+ });
1212
+ valid = false;
1213
+ if (!shouldContinue(ctx))
1214
+ return false;
1215
+ }
1216
+ return valid;
1217
+ }
1218
+
1219
+ /**
1220
+ * Validates object 'patternProperties' keyword.
1221
+ *
1222
+ * @param instance - Object being validated
1223
+ * @param schema - Schema containing the patternProperties constraint
1224
+ * @param ctx - Validation context
1225
+ * @returns true if validation passes, false otherwise
1226
+ */
1227
+ function validatePatternProperties(instance, schema, ctx) {
1228
+ if (!schema.patternProperties) {
1229
+ return true;
1230
+ }
1231
+ let valid = true;
1232
+ const patterns = [];
1233
+ // Pre-compile all patterns
1234
+ for (const [pattern, patternSchema] of entries(schema.patternProperties)) {
1235
+ // Check pattern safety if a checker is configured
1236
+ /* istanbul ignore if -- patternSafetyChecker branch tested in validate.spec.ts */
1237
+ if (ctx.patternSafetyChecker) {
1238
+ const safetyResult = ctx.patternSafetyChecker(pattern);
1239
+ if (!safetyResult.safe) {
1240
+ addError(ctx, `Unsafe regex pattern in patternProperties: ${safetyResult.reason ?? 'Pattern may cause ReDoS'}`, instance, 'patternProperties', {
1241
+ pattern,
1242
+ reason: safetyResult.reason,
1243
+ });
1244
+ valid = false;
1245
+ if (!shouldContinue(ctx))
1246
+ return false;
1247
+ continue; // Skip this unsafe pattern
1248
+ }
1249
+ }
1250
+ try {
1251
+ // eslint-disable-next-line workspace/no-unsafe-regex -- Pattern safety validated above when safePatterns enabled
1252
+ patterns.push({ regex: createRegExp(pattern), schema: patternSchema });
1253
+ }
1254
+ catch (e) {
1255
+ // Invalid regex
1256
+ /* istanbul ignore next -- strictPatterns mode verified in validate.spec.ts */
1257
+ if (ctx.strictPatterns) {
1258
+ /* istanbul ignore next -- error reporting for invalid regex */
1259
+ addError(ctx, `Invalid regex pattern in patternProperties: ${pattern}`, instance, 'patternProperties', {
1260
+ /* istanbul ignore next -- error message extraction */
1261
+ pattern,
1262
+ /* istanbul ignore next -- ternary expression */
1263
+ error: e instanceof Error ? e.message : 'Invalid regex',
1264
+ });
1265
+ valid = false;
1266
+ /* istanbul ignore if -- early exit tested in validate.spec.ts */
1267
+ if (!shouldContinue(ctx))
1268
+ return false;
1269
+ }
1270
+ // Otherwise skip silently
1271
+ }
1272
+ }
1273
+ // Check each property against matching patterns
1274
+ for (const key of keys(instance)) {
1275
+ for (const { regex, schema: patternSchema } of patterns) {
1276
+ if (regex.test(key)) {
1277
+ const propCtx = pushPath(ctx, key);
1278
+ if (!ctx.validate(instance[key], patternSchema, propCtx)) {
1279
+ valid = false;
1280
+ if (!shouldContinue(ctx))
1281
+ return false;
1282
+ }
1283
+ }
1284
+ }
1285
+ }
1286
+ return valid;
1287
+ }
1288
+
1289
+ /**
1290
+ * Validates object 'properties' keyword.
1291
+ *
1292
+ * @param instance - Object being validated
1293
+ * @param schema - Schema containing the properties constraint
1294
+ * @param ctx - Validation context
1295
+ * @returns true if validation passes, false otherwise
1296
+ */
1297
+ function validateProperties(instance, schema, ctx) {
1298
+ if (!schema.properties) {
1299
+ return true;
1300
+ }
1301
+ let valid = true;
1302
+ for (const [key, propSchema] of entries(schema.properties)) {
1303
+ if (hasOwn(instance, key)) {
1304
+ const propCtx = pushPath(ctx, key);
1305
+ if (!ctx.validate(instance[key], propSchema, propCtx)) {
1306
+ valid = false;
1307
+ if (!shouldContinue(ctx))
1308
+ return false;
1309
+ }
1310
+ }
1311
+ }
1312
+ return valid;
1313
+ }
1314
+ /**
1315
+ * Validates object 'required' keyword.
1316
+ *
1317
+ * @param instance - Object being validated
1318
+ * @param schema - Schema containing the required constraint
1319
+ * @param ctx - Validation context
1320
+ * @returns true if validation passes, false otherwise
1321
+ */
1322
+ function validateRequired(instance, schema, ctx) {
1323
+ if (!schema.required) {
1324
+ return true;
1325
+ }
1326
+ let valid = true;
1327
+ for (const key of schema.required) {
1328
+ if (!hasOwn(instance, key)) {
1329
+ addError(ctx, `Missing required property: ${key}`, undefined, 'required', { missing: key });
1330
+ valid = false;
1331
+ if (!shouldContinue(ctx))
1332
+ return false;
1333
+ }
1334
+ }
1335
+ return valid;
1336
+ }
1337
+ /**
1338
+ * Validates object 'additionalProperties' keyword.
1339
+ *
1340
+ * @param instance - Object being validated
1341
+ * @param schema - Schema containing the additionalProperties constraint
1342
+ * @param ctx - Validation context
1343
+ * @returns true if validation passes, false otherwise
1344
+ */
1345
+ function validateAdditionalProperties(instance, schema, ctx) {
1346
+ const additionalProperties = schema.additionalProperties;
1347
+ if (additionalProperties === undefined) {
1348
+ return true;
1349
+ }
1350
+ /* istanbul ignore next -- definedKeys initialization */
1351
+ // Collect defined property names
1352
+ const definedKeys = createSet();
1353
+ /* istanbul ignore next -- schema.properties may not exist */
1354
+ if (schema.properties) {
1355
+ for (const key of keys(schema.properties)) {
1356
+ definedKeys.add(key);
1357
+ }
1358
+ }
1359
+ // Collect pattern property regexes
1360
+ const patterns = [];
1361
+ /* istanbul ignore next -- patternProperties may not always be present */
1362
+ if (schema.patternProperties) {
1363
+ for (const pattern of keys(schema.patternProperties)) {
1364
+ // Skip unsafe patterns if a checker is configured (already reported in patternProperties validator)
1365
+ if (ctx.patternSafetyChecker) {
1366
+ const safetyResult = ctx.patternSafetyChecker(pattern);
1367
+ if (!safetyResult.safe) {
1368
+ continue; // Skip this unsafe pattern
1369
+ }
1370
+ }
1371
+ try {
1372
+ // eslint-disable-next-line workspace/no-unsafe-regex -- Pattern safety validated above when safePatterns enabled
1373
+ patterns.push(createRegExp(pattern));
1374
+ /* istanbul ignore next -- invalid regex patterns handled in patternProperties validator */
1375
+ }
1376
+ catch {
1377
+ // Invalid regex, skip
1378
+ }
1379
+ }
1380
+ }
1381
+ let valid = true;
1382
+ for (const key of keys(instance)) {
1383
+ // Skip if property is defined in 'properties'
1384
+ if (definedKeys.has(key)) {
1385
+ continue;
1386
+ }
1387
+ // Skip if property matches any pattern in 'patternProperties'
1388
+ if (patterns.some((p) => p.test(key))) {
1389
+ continue;
1390
+ }
1391
+ // This is an additional property
1392
+ if (additionalProperties === false) {
1393
+ addError(ctx, `Additional property not allowed: ${key}`, instance[key], 'additionalProperties', {
1394
+ property: key,
1395
+ });
1396
+ valid = false;
1397
+ /* istanbul ignore if -- early exit tested in validate.spec.ts */
1398
+ if (!shouldContinue(ctx))
1399
+ return false;
1400
+ }
1401
+ else if (typeof additionalProperties === 'object') {
1402
+ const propCtx = pushPath(ctx, key);
1403
+ if (!ctx.validate(instance[key], additionalProperties, propCtx)) {
1404
+ valid = false;
1405
+ /* istanbul ignore if -- early exit tested in validate.spec.ts */
1406
+ if (!shouldContinue(ctx))
1407
+ return false;
1408
+ }
1409
+ }
1410
+ // If additionalProperties === true, any additional property is allowed
1411
+ }
1412
+ return valid;
1413
+ }
1414
+
1415
+ /**
1416
+ * Validates string length and pattern constraints.
1417
+ *
1418
+ * @param instance - String being validated
1419
+ * @param schema - Schema containing string constraints
1420
+ * @param ctx - Validation context
1421
+ * @returns true if validation passes, false otherwise
1422
+ */
1423
+ function validateStringBounds(instance, schema, ctx) {
1424
+ let valid = true;
1425
+ if (schema.minLength !== undefined && instance.length < schema.minLength) {
1426
+ addError(ctx, `String must be at least ${schema.minLength} characters, got ${instance.length}`, instance, 'minLength', {
1427
+ limit: schema.minLength,
1428
+ actual: instance.length,
1429
+ });
1430
+ valid = false;
1431
+ if (!shouldContinue(ctx))
1432
+ return false;
1433
+ }
1434
+ if (schema.maxLength !== undefined && instance.length > schema.maxLength) {
1435
+ addError(ctx, `String must be at most ${schema.maxLength} characters, got ${instance.length}`, instance, 'maxLength', {
1436
+ limit: schema.maxLength,
1437
+ actual: instance.length,
1438
+ });
1439
+ valid = false;
1440
+ if (!shouldContinue(ctx))
1441
+ return false;
1442
+ }
1443
+ if (schema.pattern !== undefined) {
1444
+ // Check pattern safety if a checker is configured
1445
+ if (ctx.patternSafetyChecker) {
1446
+ const safetyResult = ctx.patternSafetyChecker(schema.pattern);
1447
+ if (!safetyResult.safe) {
1448
+ addError(ctx, `Unsafe regex pattern: ${safetyResult.reason ?? 'Pattern may cause ReDoS'}`, instance, 'pattern', {
1449
+ pattern: schema.pattern,
1450
+ reason: safetyResult.reason,
1451
+ });
1452
+ valid = false;
1453
+ if (!shouldContinue(ctx))
1454
+ return false;
1455
+ // Skip executing the unsafe pattern
1456
+ return valid;
1457
+ }
1458
+ }
1459
+ try {
1460
+ // eslint-disable-next-line workspace/no-unsafe-regex -- Pattern safety validated above when safePatterns enabled
1461
+ const regex = createRegExp(schema.pattern);
1462
+ if (!regex.test(instance)) {
1463
+ addError(ctx, `String does not match pattern: ${schema.pattern}`, instance, 'pattern', {
1464
+ pattern: schema.pattern,
1465
+ });
1466
+ valid = false;
1467
+ if (!shouldContinue(ctx))
1468
+ return false;
1469
+ }
1470
+ }
1471
+ catch (e) {
1472
+ // Invalid regex pattern
1473
+ /* istanbul ignore next -- strictPatterns mode verified in validate.spec.ts */
1474
+ if (ctx.strictPatterns) {
1475
+ /* istanbul ignore next -- error reporting for invalid regex */
1476
+ addError(ctx, `Invalid regex pattern: ${schema.pattern}`, instance, 'pattern', {
1477
+ pattern: schema.pattern,
1478
+ /* istanbul ignore next -- error message extraction ternary */
1479
+ error: e instanceof Error ? e.message : 'Invalid regex',
1480
+ });
1481
+ valid = false;
1482
+ /* istanbul ignore if -- early exit tested in validate.spec.ts */
1483
+ if (!shouldContinue(ctx))
1484
+ return false;
1485
+ }
1486
+ // Otherwise skip validation silently
1487
+ }
1488
+ }
1489
+ return valid;
1490
+ }
1491
+
1492
+ /**
1493
+ * Type checking functions for JSON Schema types.
1494
+ */
1495
+ const typeCheckers = {
1496
+ string: (v) => typeof v === 'string',
1497
+ number: (v) => typeof v === 'number' && globalIsFinite(v),
1498
+ integer: (v) => typeof v === 'number' && globalIsFinite(v) && isInteger(v),
1499
+ boolean: (v) => typeof v === 'boolean',
1500
+ array: (v) => isArray(v),
1501
+ object: (v) => v !== null && typeof v === 'object' && !isArray(v),
1502
+ null: (v) => v === null,
1503
+ };
1504
+ /**
1505
+ * Gets the actual JSON type of a value for error messages.
1506
+ *
1507
+ * @param value - The value to get the type of
1508
+ * @returns The JSON type as a string
1509
+ */
1510
+ function getActualType(value) {
1511
+ if (value === null)
1512
+ return 'null';
1513
+ if (isArray(value))
1514
+ return 'array';
1515
+ const t = typeof value;
1516
+ if (t === 'number') {
1517
+ const num = value;
1518
+ /* istanbul ignore next -- NaN/Infinity edge case */
1519
+ if (!globalIsFinite(num))
1520
+ return 'number'; // NaN/Infinity
1521
+ return isInteger(num) ? 'integer' : 'number';
1522
+ }
1523
+ return t;
1524
+ }
1525
+ /**
1526
+ * Validates the 'type' keyword.
1527
+ *
1528
+ * @param instance - Value being validated
1529
+ * @param schema - Schema containing the type constraint
1530
+ * @param ctx - Validation context
1531
+ * @returns true if validation passes, false otherwise
1532
+ */
1533
+ function validateType(instance, schema, ctx) {
1534
+ const schemaType = schema.type;
1535
+ if (schemaType === undefined) {
1536
+ return true;
1537
+ }
1538
+ const types = isArray(schemaType) ? schemaType : [schemaType];
1539
+ for (const type of types) {
1540
+ const checker = typeCheckers[type];
1541
+ /* istanbul ignore if -- defensive check for unknown type */
1542
+ if (checker && checker(instance)) {
1543
+ // Special case: 'integer' should also pass 'number' check
1544
+ return true;
1545
+ }
1546
+ // If type is 'number' and value is an integer, it's still valid
1547
+ /* istanbul ignore if -- defensive fallback for integer/number coercion */
1548
+ if (type === 'number' && typeCheckers['integer']?.(instance)) {
1549
+ return true;
1550
+ }
1551
+ }
1552
+ const actualType = getActualType(instance);
1553
+ const expectedTypes = types.join(' or ');
1554
+ addError(ctx, `Expected type ${expectedTypes} but got ${actualType}`, instance, 'type', {
1555
+ expected: types,
1556
+ actual: actualType,
1557
+ });
1558
+ return false;
1559
+ }
1560
+
1561
+ /**
1562
+ * Resolves a $ref JSON Pointer to its target schema.
1563
+ *
1564
+ * @param ref - The $ref string (e.g., '#/definitions/Address')
1565
+ * @param ctx - Validation context containing root schema and definitions
1566
+ * @returns The resolved schema, or undefined if not found
1567
+ */
1568
+ function resolveRef(ref, ctx) {
1569
+ // Check pre-populated definitions first
1570
+ const cached = ctx.definitions.get(ref);
1571
+ if (cached) {
1572
+ return cached;
1573
+ }
1574
+ // Only support internal references (starting with #)
1575
+ if (!ref.startsWith('#')) {
1576
+ return undefined;
1577
+ }
1578
+ // Handle root reference
1579
+ if (ref === '#') {
1580
+ return ctx.rootSchema;
1581
+ }
1582
+ // Parse JSON Pointer path
1583
+ const path = ref.slice(1); // Remove leading #
1584
+ if (!path.startsWith('/')) {
1585
+ return undefined;
1586
+ }
1587
+ const segments = path
1588
+ .split('/')
1589
+ .slice(1) // Remove empty first segment
1590
+ .map((segment) => segment.replace(/~1/g, '/').replace(/~0/g, '~'));
1591
+ // Navigate to the referenced schema
1592
+ let current = ctx.rootSchema;
1593
+ for (const segment of segments) {
1594
+ if (current === null || typeof current !== 'object') {
1595
+ return undefined;
1596
+ }
1597
+ current = current[segment];
1598
+ }
1599
+ // Cache the resolved schema
1600
+ if (current && typeof current === 'object') {
1601
+ const resolved = current;
1602
+ ctx.definitions.set(ref, resolved);
1603
+ return resolved;
1604
+ }
1605
+ return undefined;
1606
+ }
1607
+
1608
+ /**
1609
+ * Validates a value against a JSON Schema.
1610
+ *
1611
+ * @param instance - The value to validate
1612
+ * @param schema - The JSON Schema to validate against
1613
+ * @param options - Validation options
1614
+ * @returns Validation result with valid flag and any errors
1615
+ *
1616
+ * @example
1617
+ * ```typescript
1618
+ * const schema = { type: 'string', minLength: 1 }
1619
+ * const result = validate('hello', schema)
1620
+ * console.log(result.valid) // true
1621
+ * ```
1622
+ */
1623
+ function validate(instance, schema, options) {
1624
+ // Resolve safePatterns option to a checker function
1625
+ let patternSafetyChecker;
1626
+ const ctx = createValidationContext(schema, validateSchema, true, false, patternSafetyChecker);
1627
+ const valid = validateSchema(instance, schema, ctx);
1628
+ return {
1629
+ valid,
1630
+ errors: ctx.errors,
1631
+ };
1632
+ }
1633
+ /**
1634
+ * Internal recursive validation function.
1635
+ *
1636
+ * @param instance - Value being validated
1637
+ * @param schema - Schema to validate against
1638
+ * @param ctx - Validation context
1639
+ * @returns true if validation passes, false otherwise
1640
+ */
1641
+ function validateSchema(instance, schema, ctx) {
1642
+ // Handle $ref
1643
+ if (schema.$ref) {
1644
+ const resolved = resolveRef(schema.$ref, ctx);
1645
+ /* istanbul ignore if -- $ref resolution failures are tested in resolve-ref.spec.ts */
1646
+ if (!resolved) {
1647
+ // Could not resolve reference - treat as valid
1648
+ return true;
1649
+ }
1650
+ return validateSchema(instance, resolved, ctx);
1651
+ }
1652
+ let valid = true;
1653
+ // Type validation
1654
+ if (!validateType(instance, schema, ctx)) {
1655
+ valid = false;
1656
+ if (!shouldContinue(ctx))
1657
+ return false;
1658
+ }
1659
+ // Enum validation
1660
+ if (!validateEnum(instance, schema, ctx)) {
1661
+ valid = false;
1662
+ if (!shouldContinue(ctx))
1663
+ return false;
1664
+ }
1665
+ // String-specific validations
1666
+ if (typeof instance === 'string') {
1667
+ if (!validateStringBounds(instance, schema, ctx)) {
1668
+ valid = false;
1669
+ if (!shouldContinue(ctx))
1670
+ return false;
1671
+ }
1672
+ if (!validateFormat(instance, schema, ctx)) {
1673
+ valid = false;
1674
+ if (!shouldContinue(ctx))
1675
+ return false;
1676
+ }
1677
+ }
1678
+ // Number-specific validations
1679
+ if (typeof instance === 'number') {
1680
+ if (!validateNumberBounds(instance, schema, ctx)) {
1681
+ valid = false;
1682
+ if (!shouldContinue(ctx))
1683
+ return false;
1684
+ }
1685
+ }
1686
+ // Array-specific validations
1687
+ if (isArray(instance)) {
1688
+ if (!validateItems(instance, schema, ctx)) {
1689
+ valid = false;
1690
+ if (!shouldContinue(ctx))
1691
+ return false;
1692
+ }
1693
+ if (!validateArrayBounds(instance, schema, ctx)) {
1694
+ valid = false;
1695
+ if (!shouldContinue(ctx))
1696
+ return false;
1697
+ }
1698
+ }
1699
+ // Object-specific validations
1700
+ if (instance !== null && typeof instance === 'object' && !isArray(instance)) {
1701
+ const obj = instance;
1702
+ if (!validateProperties(obj, schema, ctx)) {
1703
+ valid = false;
1704
+ if (!shouldContinue(ctx))
1705
+ return false;
1706
+ }
1707
+ if (!validateRequired(obj, schema, ctx)) {
1708
+ valid = false;
1709
+ /* istanbul ignore if -- early exit tested elsewhere */
1710
+ if (!shouldContinue(ctx))
1711
+ return false;
1712
+ }
1713
+ /* istanbul ignore next -- patternProperties validation */
1714
+ if (!validatePatternProperties(obj, schema, ctx)) {
1715
+ valid = false;
1716
+ /* istanbul ignore next -- early exit tested elsewhere */
1717
+ if (!shouldContinue(ctx))
1718
+ return false;
1719
+ }
1720
+ /* istanbul ignore next -- additionalProperties validation */
1721
+ if (!validateAdditionalProperties(obj, schema, ctx)) {
1722
+ valid = false;
1723
+ /* istanbul ignore next -- early exit tested elsewhere */
1724
+ if (!shouldContinue(ctx))
1725
+ return false;
1726
+ }
1727
+ /* istanbul ignore next -- objectBounds validation */
1728
+ if (!validateObjectBounds(obj, schema, ctx)) {
1729
+ valid = false;
1730
+ /* istanbul ignore next -- early exit tested elsewhere */
1731
+ if (!shouldContinue(ctx))
1732
+ return false;
1733
+ }
1734
+ /* istanbul ignore next -- dependencies validation */
1735
+ if (!validateDependencies(obj, schema, ctx)) {
1736
+ valid = false;
1737
+ /* istanbul ignore next -- early exit tested elsewhere */
1738
+ if (!shouldContinue(ctx))
1739
+ return false;
1740
+ }
1741
+ }
1742
+ // Composition keywords
1743
+ if (!validateAllOf(instance, schema, ctx)) {
1744
+ valid = false;
1745
+ if (!shouldContinue(ctx))
1746
+ return false;
1747
+ }
1748
+ if (!validateAnyOf(instance, schema, ctx)) {
1749
+ valid = false;
1750
+ if (!shouldContinue(ctx))
1751
+ return false;
1752
+ }
1753
+ if (!validateOneOf(instance, schema, ctx)) {
1754
+ valid = false;
1755
+ if (!shouldContinue(ctx))
1756
+ return false;
1757
+ }
1758
+ if (!validateNot(instance, schema, ctx)) {
1759
+ valid = false;
1760
+ if (!shouldContinue(ctx))
1761
+ return false;
1762
+ }
1763
+ return valid;
1764
+ }
1765
+
1766
+ /**
1767
+ * Changelog JSON Schema
1768
+ *
1769
+ * JSON Schema definitions for changelog validation and schema compatibility checking.
1770
+ * Uses `@hyperfrontend/json-utils` for validation.
1771
+ */
1772
+ /**
1773
+ * JSON Schema for a ChangelogLink.
1774
+ */
1775
+ const changelogLinkSchema = {
1776
+ type: 'object',
1777
+ required: ['label', 'url'],
1778
+ properties: {
1779
+ label: { type: 'string' },
1780
+ url: { type: 'string' },
1781
+ },
1782
+ additionalProperties: false,
1783
+ };
1784
+ /**
1785
+ * JSON Schema for a CommitRef.
1786
+ */
1787
+ const commitRefSchema = {
1788
+ type: 'object',
1789
+ required: ['hash', 'shortHash'],
1790
+ properties: {
1791
+ hash: { type: 'string', minLength: 7, maxLength: 40 },
1792
+ shortHash: { type: 'string', minLength: 7, maxLength: 7 },
1793
+ url: { type: 'string' },
1794
+ },
1795
+ additionalProperties: false,
1796
+ };
1797
+ /**
1798
+ * JSON Schema for an IssueRef.
1799
+ */
1800
+ const issueRefSchema = {
1801
+ type: 'object',
1802
+ required: ['number', 'type'],
1803
+ properties: {
1804
+ number: { type: 'integer', minimum: 1 },
1805
+ type: { type: 'string', enum: ['issue', 'pull-request'] },
1806
+ url: { type: 'string' },
1807
+ },
1808
+ additionalProperties: false,
1809
+ };
1810
+ /**
1811
+ * JSON Schema for a ChangelogItem.
1812
+ */
1813
+ const changelogItemSchema = {
1814
+ type: 'object',
1815
+ required: ['description', 'commits', 'references', 'breaking'],
1816
+ properties: {
1817
+ scope: { type: 'string' },
1818
+ description: { type: 'string' },
1819
+ breaking: { type: 'boolean' },
1820
+ commits: {
1821
+ type: 'array',
1822
+ items: commitRefSchema,
1823
+ },
1824
+ references: {
1825
+ type: 'array',
1826
+ items: issueRefSchema,
1827
+ },
1828
+ },
1829
+ additionalProperties: false,
1830
+ };
1831
+ /**
1832
+ * JSON Schema for a ChangelogSection.
1833
+ */
1834
+ const changelogSectionSchema = {
1835
+ type: 'object',
1836
+ required: ['type', 'heading', 'items'],
1837
+ properties: {
1838
+ type: {
1839
+ type: 'string',
1840
+ enum: [
1841
+ 'breaking',
1842
+ 'features',
1843
+ 'fixes',
1844
+ 'performance',
1845
+ 'documentation',
1846
+ 'deprecations',
1847
+ 'refactoring',
1848
+ 'tests',
1849
+ 'build',
1850
+ 'ci',
1851
+ 'chores',
1852
+ 'other',
1853
+ ],
1854
+ },
1855
+ heading: { type: 'string' },
1856
+ items: {
1857
+ type: 'array',
1858
+ items: changelogItemSchema,
1859
+ },
1860
+ },
1861
+ additionalProperties: false,
1862
+ };
1863
+ /**
1864
+ * JSON Schema for a ChangelogEntry.
1865
+ */
1866
+ const changelogEntrySchema = {
1867
+ type: 'object',
1868
+ required: ['version', 'date', 'unreleased', 'sections'],
1869
+ properties: {
1870
+ version: { type: 'string' },
1871
+ date: { type: ['string', 'null'] },
1872
+ unreleased: { type: 'boolean' },
1873
+ compareUrl: { type: 'string' },
1874
+ sections: {
1875
+ type: 'array',
1876
+ items: changelogSectionSchema,
1877
+ },
1878
+ rawContent: { type: 'string' },
1879
+ },
1880
+ additionalProperties: false,
1881
+ };
1882
+ /**
1883
+ * JSON Schema for ChangelogHeader.
1884
+ */
1885
+ const changelogHeaderSchema = {
1886
+ type: 'object',
1887
+ required: ['title', 'description', 'links'],
1888
+ properties: {
1889
+ title: { type: 'string' },
1890
+ description: {
1891
+ type: 'array',
1892
+ items: { type: 'string' },
1893
+ },
1894
+ links: {
1895
+ type: 'array',
1896
+ items: changelogLinkSchema,
1897
+ },
1898
+ },
1899
+ additionalProperties: false,
1900
+ };
1901
+ /**
1902
+ * JSON Schema for ChangelogMetadata.
1903
+ */
1904
+ const changelogMetadataSchema = {
1905
+ type: 'object',
1906
+ required: ['format', 'isConventional', 'warnings'],
1907
+ properties: {
1908
+ format: {
1909
+ type: 'string',
1910
+ enum: ['keep-a-changelog', 'conventional', 'custom', 'unknown'],
1911
+ },
1912
+ isConventional: { type: 'boolean' },
1913
+ repositoryUrl: { type: 'string' },
1914
+ packageName: { type: 'string' },
1915
+ warnings: {
1916
+ type: 'array',
1917
+ items: { type: 'string' },
1918
+ },
1919
+ },
1920
+ additionalProperties: false,
1921
+ };
1922
+ /**
1923
+ * JSON Schema for a complete Changelog document.
1924
+ * Used for validation and format compatibility checking.
1925
+ */
1926
+ const changelogSchema = {
1927
+ type: 'object',
1928
+ required: ['header', 'entries', 'metadata'],
1929
+ properties: {
1930
+ source: { type: 'string' },
1931
+ header: changelogHeaderSchema,
1932
+ entries: {
1933
+ type: 'array',
1934
+ items: changelogEntrySchema,
1935
+ },
1936
+ metadata: changelogMetadataSchema,
1937
+ },
1938
+ additionalProperties: false,
1939
+ };
1940
+ /**
1941
+ * Validates a changelog object against the schema.
1942
+ *
1943
+ * @param changelog - The changelog object to validate
1944
+ * @returns Validation result with any errors
1945
+ *
1946
+ * @example
1947
+ * ```ts
1948
+ * const result = validateChangelog(myChangelog)
1949
+ * if (!result.valid) {
1950
+ * console.log('Validation errors:', result.errors)
1951
+ * }
1952
+ * ```
1953
+ */
1954
+ function validateChangelog(changelog) {
1955
+ return validate(changelog, changelogSchema);
1956
+ }
1957
+ /**
1958
+ * Checks if two changelogs have compatible schemas.
1959
+ * Used to detect format incompatibilities before merge/compare.
1960
+ *
1961
+ * @param source - The source changelog
1962
+ * @param target - The target changelog
1963
+ * @returns Compatibility result with any differences found
1964
+ *
1965
+ * @example
1966
+ * ```ts
1967
+ * const result = checkSchemaCompatibility(mainChangelog, branchChangelog)
1968
+ * if (!result.compatible) {
1969
+ * console.log('Schema differences:', result.differences)
1970
+ * }
1971
+ * ```
1972
+ */
1973
+ function checkSchemaCompatibility(source, target) {
1974
+ const differences = [];
1975
+ // Check format compatibility
1976
+ if (source.metadata.format !== target.metadata.format) {
1977
+ differences.push({
1978
+ path: 'metadata.format',
1979
+ type: 'type-mismatch',
1980
+ sourceType: source.metadata.format,
1981
+ targetType: target.metadata.format,
1982
+ });
1983
+ }
1984
+ // Check header structure
1985
+ if (source.header.title !== target.header.title) ;
1986
+ // Check section types used
1987
+ const sourceSectionTypes = createSet();
1988
+ const targetSectionTypes = createSet();
1989
+ for (const entry of source.entries) {
1990
+ for (const section of entry.sections) {
1991
+ sourceSectionTypes.add(section.type);
1992
+ }
1993
+ }
1994
+ for (const entry of target.entries) {
1995
+ for (const section of entry.sections) {
1996
+ targetSectionTypes.add(section.type);
1997
+ }
1998
+ }
1999
+ // Find section types in source but not in target
2000
+ for (const type of sourceSectionTypes) {
2001
+ if (!targetSectionTypes.has(type)) {
2002
+ differences.push({
2003
+ path: `sections[type=${type}]`,
2004
+ type: 'missing-property',
2005
+ sourceType: type,
2006
+ });
2007
+ }
2008
+ }
2009
+ // Find section types in target but not in source
2010
+ for (const type of targetSectionTypes) {
2011
+ if (!sourceSectionTypes.has(type)) {
2012
+ differences.push({
2013
+ path: `sections[type=${type}]`,
2014
+ type: 'extra-property',
2015
+ targetType: type,
2016
+ });
2017
+ }
2018
+ }
2019
+ return {
2020
+ compatible: differences.length === 0,
2021
+ differences,
2022
+ };
2023
+ }
2024
+
2025
+ export { SECTION_HEADINGS, SECTION_TYPE_MAP, changelogSchema, checkSchemaCompatibility, createChangelog, createChangelogEntry, createChangelogItem, createChangelogLink, createChangelogSection, createCommitRef, createEmptyChangelog, createIssueRef, createUnreleasedEntry, getSectionType, getShortHash, validateChangelog };
2026
+ //# sourceMappingURL=index.esm.js.map