@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,755 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Creates a git commit model.
5
+ *
6
+ * @param options - Commit creation options
7
+ * @returns A new GitCommit object
8
+ *
9
+ * @example
10
+ * const commit = createGitCommit({
11
+ * hash: 'abc123...',
12
+ * authorName: 'John Doe',
13
+ * authorEmail: 'john@example.com',
14
+ * authorDate: '2026-03-12T10:00:00Z',
15
+ * subject: 'feat: add new feature',
16
+ * })
17
+ */
18
+ function createGitCommit(options) {
19
+ const body = options.body ?? '';
20
+ const subject = options.subject;
21
+ return {
22
+ hash: options.hash,
23
+ shortHash: getShortHash(options.hash),
24
+ authorName: options.authorName,
25
+ authorEmail: options.authorEmail,
26
+ authorDate: options.authorDate,
27
+ committerName: options.committerName ?? options.authorName,
28
+ committerEmail: options.committerEmail ?? options.authorEmail,
29
+ commitDate: options.commitDate ?? options.authorDate,
30
+ subject,
31
+ body,
32
+ message: body ? `${subject}\n\n${body}` : subject,
33
+ parents: options.parents ?? [],
34
+ refs: options.refs ?? [],
35
+ };
36
+ }
37
+ /**
38
+ * Gets a short hash (7 characters) from a full commit hash.
39
+ *
40
+ * @param hash - Full commit hash
41
+ * @returns Short hash (7 characters)
42
+ */
43
+ function getShortHash(hash) {
44
+ return hash.slice(0, 7);
45
+ }
46
+ /**
47
+ * Checks if two commits are the same based on their hash.
48
+ *
49
+ * @param a - First commit
50
+ * @param b - Second commit
51
+ * @returns True if commits have the same hash
52
+ */
53
+ function isSameCommit(a, b) {
54
+ return a.hash === b.hash;
55
+ }
56
+ /**
57
+ * Checks if a commit is a merge commit (has multiple parents).
58
+ *
59
+ * @param commit - Commit to check
60
+ * @returns True if commit has more than one parent
61
+ */
62
+ function isMergeCommit(commit) {
63
+ return commit.parents.length > 1;
64
+ }
65
+ /**
66
+ * Checks if a commit is a root commit (has no parents).
67
+ *
68
+ * @param commit - Commit to check
69
+ * @returns True if commit has no parents
70
+ */
71
+ function isRootCommit(commit) {
72
+ return commit.parents.length === 0;
73
+ }
74
+ /**
75
+ * Extracts the scope from a commit subject if it follows conventional commit format.
76
+ * Uses character-by-character parsing (no regex).
77
+ *
78
+ * @param subject - Commit subject line
79
+ * @returns Scope string or undefined if no scope found
80
+ *
81
+ * @example
82
+ * extractScope('feat(lib-versioning): add git support') // 'lib-versioning'
83
+ * extractScope('fix: resolve issue') // undefined
84
+ */
85
+ function extractScope(subject) {
86
+ // Look for pattern: type(scope): or type(scope)!:
87
+ let i = 0;
88
+ // Skip type characters (a-z)
89
+ while (i < subject.length) {
90
+ const code = subject.charCodeAt(i);
91
+ if (code >= 97 && code <= 122) {
92
+ // a-z
93
+ i++;
94
+ }
95
+ else {
96
+ break;
97
+ }
98
+ }
99
+ // Must find opening parenthesis
100
+ if (i >= subject.length || subject[i] !== '(') {
101
+ return undefined;
102
+ }
103
+ // Skip '('
104
+ i++;
105
+ const scopeStart = i;
106
+ // Find closing parenthesis
107
+ while (i < subject.length && subject[i] !== ')') {
108
+ i++;
109
+ }
110
+ if (i >= subject.length) {
111
+ return undefined;
112
+ }
113
+ const scope = subject.slice(scopeStart, i);
114
+ return scope || undefined;
115
+ }
116
+ /**
117
+ * Extracts the type from a commit subject if it follows conventional commit format.
118
+ * Uses character-by-character parsing (no regex).
119
+ *
120
+ * @param subject - Commit subject line
121
+ * @returns Type string or undefined if no valid type found
122
+ *
123
+ * @example
124
+ * extractType('feat(lib-versioning): add git support') // 'feat'
125
+ * extractType('fix: resolve issue') // 'fix'
126
+ * extractType('random message') // undefined
127
+ */
128
+ function extractType(subject) {
129
+ let i = 0;
130
+ // Collect type characters (a-z)
131
+ while (i < subject.length) {
132
+ const code = subject.charCodeAt(i);
133
+ if (code >= 97 && code <= 122) {
134
+ // a-z
135
+ i++;
136
+ }
137
+ else {
138
+ break;
139
+ }
140
+ }
141
+ if (i === 0) {
142
+ return undefined;
143
+ }
144
+ const type = subject.slice(0, i);
145
+ // Next character must be '(' , '!' or ':'
146
+ if (i >= subject.length) {
147
+ return undefined;
148
+ }
149
+ const next = subject[i];
150
+ if (next === '(' || next === ':' || next === '!') {
151
+ return type;
152
+ }
153
+ return undefined;
154
+ }
155
+
156
+ /**
157
+ * Safe copies of Math built-in methods.
158
+ *
159
+ * These references are captured at module initialization time to protect against
160
+ * prototype pollution attacks. Import only what you need for tree-shaking.
161
+ *
162
+ * @module @hyperfrontend/immutable-api-utils/built-in-copy/math
163
+ */
164
+ // Capture references at module initialization time
165
+ const _Math = globalThis.Math;
166
+ // ============================================================================
167
+ // Min/Max
168
+ // ============================================================================
169
+ /**
170
+ * (Safe copy) Returns the larger of zero or more numbers.
171
+ */
172
+ const max = _Math.max;
173
+
174
+ /**
175
+ * Creates a lightweight git tag.
176
+ *
177
+ * @param options - Tag creation options
178
+ * @returns A new GitTag object
179
+ *
180
+ * @example
181
+ * const tag = createLightweightTag({
182
+ * name: 'v1.0.0',
183
+ * commitHash: 'abc123...',
184
+ * })
185
+ */
186
+ function createLightweightTag(options) {
187
+ return {
188
+ name: options.name,
189
+ commitHash: options.commitHash,
190
+ type: 'lightweight',
191
+ };
192
+ }
193
+ /**
194
+ * Creates an annotated git tag.
195
+ *
196
+ * @param options - Tag creation options
197
+ * @returns A new GitTag object
198
+ *
199
+ * @example
200
+ * const tag = createAnnotatedTag({
201
+ * name: 'v1.0.0',
202
+ * commitHash: 'abc123...',
203
+ * message: 'Release v1.0.0',
204
+ * taggerName: 'John Doe',
205
+ * taggerEmail: 'john@example.com',
206
+ * tagDate: '2026-03-12T10:00:00Z',
207
+ * })
208
+ */
209
+ function createAnnotatedTag(options) {
210
+ return {
211
+ name: options.name,
212
+ commitHash: options.commitHash,
213
+ type: 'annotated',
214
+ message: options.message,
215
+ taggerName: options.taggerName,
216
+ taggerEmail: options.taggerEmail,
217
+ tagDate: options.tagDate,
218
+ };
219
+ }
220
+ /**
221
+ * Checks if a tag is annotated.
222
+ *
223
+ * @param tag - Tag to check
224
+ * @returns True if tag is annotated
225
+ */
226
+ function isAnnotatedTag(tag) {
227
+ return tag.type === 'annotated';
228
+ }
229
+ /**
230
+ * Checks if a tag is lightweight.
231
+ *
232
+ * @param tag - Tag to check
233
+ * @returns True if tag is lightweight
234
+ */
235
+ function isLightweightTag(tag) {
236
+ return tag.type === 'lightweight';
237
+ }
238
+ /**
239
+ * Extracts version from tag name.
240
+ * Handles common formats: v1.2.3, `@scope/package@1.2.3`, package@1.2.3
241
+ * Uses character-by-character parsing (no regex).
242
+ *
243
+ * @param tagName - Tag name to parse
244
+ * @returns The extracted version string or undefined if no version found
245
+ *
246
+ * @example
247
+ * extractVersionFromTag('v1.2.3') // '1.2.3'
248
+ * extractVersionFromTag('@scope/pkg@1.2.3') // '1.2.3'
249
+ * extractVersionFromTag('release-1.2.3') // '1.2.3'
250
+ */
251
+ function extractVersionFromTag(tagName) {
252
+ // Strategy: Find last occurrence of '@' followed by version, or 'v' followed by version
253
+ // Version starts with digit and contains digits, dots, and possibly prerelease identifiers
254
+ // First, try to find @version pattern (for scoped packages)
255
+ let i = tagName.length - 1;
256
+ // Find last '@'
257
+ while (i >= 0 && tagName[i] !== '@') {
258
+ i--;
259
+ }
260
+ if (i >= 0) {
261
+ // Found '@', check if followed by version
262
+ const afterAt = tagName.slice(i + 1);
263
+ const version = parseVersionPart(afterAt);
264
+ if (version) {
265
+ return version;
266
+ }
267
+ }
268
+ // Try to find 'v' followed by version
269
+ i = 0;
270
+ while (i < tagName.length) {
271
+ if ((tagName[i] === 'v' || tagName[i] === 'V') && i + 1 < tagName.length) {
272
+ const nextCode = tagName.charCodeAt(i + 1);
273
+ if (nextCode >= 48 && nextCode <= 57) {
274
+ // 0-9
275
+ const version = parseVersionPart(tagName.slice(i + 1));
276
+ if (version) {
277
+ return version;
278
+ }
279
+ }
280
+ }
281
+ i++;
282
+ }
283
+ // Try to find digit sequence after common separators (-, _)
284
+ i = 0;
285
+ while (i < tagName.length) {
286
+ const char = tagName[i];
287
+ if (char === '-' || char === '_') {
288
+ const afterSep = tagName.slice(i + 1);
289
+ const code = afterSep.charCodeAt(0);
290
+ if (code >= 48 && code <= 57) {
291
+ // 0-9
292
+ const version = parseVersionPart(afterSep);
293
+ if (version) {
294
+ return version;
295
+ }
296
+ }
297
+ }
298
+ i++;
299
+ }
300
+ // Last resort: if entire string is a version
301
+ return parseVersionPart(tagName);
302
+ }
303
+ /**
304
+ * Parses a version-like string from the start of input.
305
+ * Uses character-by-character parsing (no regex).
306
+ *
307
+ * @param input - String to parse
308
+ * @returns Version string or undefined
309
+ */
310
+ function parseVersionPart(input) {
311
+ if (!input)
312
+ return undefined;
313
+ // Must start with digit
314
+ const firstCode = input.charCodeAt(0);
315
+ if (firstCode < 48 || firstCode > 57) {
316
+ return undefined;
317
+ }
318
+ // Collect version characters: digits, dots, hyphens, plus, letters (for prerelease)
319
+ let i = 0;
320
+ let dotCount = 0;
321
+ while (i < input.length) {
322
+ const code = input.charCodeAt(i);
323
+ if (code >= 48 && code <= 57) {
324
+ // 0-9
325
+ i++;
326
+ }
327
+ else if (code === 46) {
328
+ // .
329
+ dotCount++;
330
+ i++;
331
+ }
332
+ else if (code === 45) {
333
+ // -
334
+ i++;
335
+ }
336
+ else if (code === 43) {
337
+ // +
338
+ i++;
339
+ }
340
+ else if ((code >= 97 && code <= 122) || (code >= 65 && code <= 90)) {
341
+ // a-z, A-Z
342
+ i++;
343
+ }
344
+ else {
345
+ break;
346
+ }
347
+ }
348
+ // Must have at least one dot (e.g., 1.0)
349
+ if (dotCount === 0) {
350
+ return undefined;
351
+ }
352
+ const version = input.slice(0, i);
353
+ // Basic validation: must contain at least two parts separated by dots
354
+ if (!version.includes('.')) {
355
+ return undefined;
356
+ }
357
+ return version;
358
+ }
359
+ /**
360
+ * Extracts package name from tag name.
361
+ * Handles formats like: `@scope/package@1.2.3`, package@1.2.3, package-v1.2.3
362
+ * Uses character-by-character parsing (no regex).
363
+ *
364
+ * @param tagName - Tag name to parse
365
+ * @returns The extracted package name or undefined if not found
366
+ *
367
+ * @example
368
+ * extractPackageFromTag('@scope/pkg@1.2.3') // '@scope/pkg'
369
+ * extractPackageFromTag('lib-utils@1.2.3') // 'lib-utils'
370
+ * extractPackageFromTag('v1.2.3') // undefined
371
+ */
372
+ function extractPackageFromTag(tagName) {
373
+ // Find the last '@' that's followed by a version number
374
+ let lastVersionAt = -1;
375
+ let i = tagName.length - 1;
376
+ while (i >= 0) {
377
+ if (tagName[i] === '@') {
378
+ // Check if followed by a digit
379
+ if (i + 1 < tagName.length) {
380
+ const nextCode = tagName.charCodeAt(i + 1);
381
+ if (nextCode >= 48 && nextCode <= 57) {
382
+ // 0-9
383
+ lastVersionAt = i;
384
+ break;
385
+ }
386
+ }
387
+ }
388
+ i--;
389
+ }
390
+ if (lastVersionAt > 0) {
391
+ return tagName.slice(0, lastVersionAt);
392
+ }
393
+ // Check for -v or _v pattern
394
+ i = tagName.length - 1;
395
+ while (i > 0) {
396
+ if (tagName[i] === 'v' || tagName[i] === 'V') {
397
+ const prev = tagName[i - 1];
398
+ if (prev === '-' || prev === '_') {
399
+ // Check if followed by digit
400
+ if (i + 1 < tagName.length) {
401
+ const nextCode = tagName.charCodeAt(i + 1);
402
+ if (nextCode >= 48 && nextCode <= 57) {
403
+ return tagName.slice(0, i - 1);
404
+ }
405
+ }
406
+ }
407
+ }
408
+ i--;
409
+ }
410
+ return undefined;
411
+ }
412
+ /**
413
+ * Builds a tag name from package name and version.
414
+ *
415
+ * @param packageName - Package name (e.g., '@scope/package' or 'package')
416
+ * @param version - Version string (e.g., '1.2.3')
417
+ * @param format - Tag format template, uses ${package} and ${version} placeholders
418
+ * @returns Formatted tag name
419
+ *
420
+ * @example
421
+ * buildTagName('@scope/pkg', '1.2.3') // '@scope/pkg@1.2.3'
422
+ * buildTagName('utils', '1.0.0', 'v${version}') // 'v1.0.0'
423
+ * buildTagName('pkg', '2.0.0', '${package}-v${version}') // 'pkg-v2.0.0'
424
+ */
425
+ function buildTagName(packageName, version, format = '${package}@${version}') {
426
+ // Simple character-by-character replacement (no regex)
427
+ let result = '';
428
+ let i = 0;
429
+ while (i < format.length) {
430
+ if (i + 9 < format.length && format.slice(i, i + 10) === '${package}') {
431
+ result += packageName;
432
+ i += 10;
433
+ }
434
+ else if (i + 9 < format.length && format.slice(i, i + 10) === '${version}') {
435
+ result += version;
436
+ i += 10;
437
+ }
438
+ else {
439
+ result += format[i];
440
+ i++;
441
+ }
442
+ }
443
+ return result;
444
+ }
445
+ /**
446
+ * Compares two tags by version (newest first).
447
+ * Useful for sorting tags.
448
+ *
449
+ * @param a - First tag
450
+ * @param b - Second tag
451
+ * @returns Comparison result (-1, 0, or 1)
452
+ */
453
+ function compareTagsByVersion(a, b) {
454
+ const versionA = extractVersionFromTag(a.name);
455
+ const versionB = extractVersionFromTag(b.name);
456
+ if (!versionA && !versionB)
457
+ return 0;
458
+ if (!versionA)
459
+ return 1;
460
+ if (!versionB)
461
+ return -1;
462
+ return compareVersionStrings(versionB, versionA); // Descending order
463
+ }
464
+ /**
465
+ * Simple version string comparison.
466
+ * Compares major.minor.patch numerically.
467
+ *
468
+ * @param a - First version
469
+ * @param b - Second version
470
+ * @returns Comparison result (-1, 0, or 1)
471
+ */
472
+ function compareVersionStrings(a, b) {
473
+ const partsA = a.split('.');
474
+ const partsB = b.split('.');
475
+ const maxLen = max(partsA.length, partsB.length);
476
+ for (let i = 0; i < maxLen; i++) {
477
+ const numA = parseNumericPart(partsA[i]);
478
+ const numB = parseNumericPart(partsB[i]);
479
+ if (numA < numB)
480
+ return -1;
481
+ if (numA > numB)
482
+ return 1;
483
+ }
484
+ return 0;
485
+ }
486
+ /**
487
+ * Parses numeric part of version segment.
488
+ *
489
+ * @param part - Version part to parse
490
+ * @returns Numeric value
491
+ */
492
+ function parseNumericPart(part) {
493
+ if (!part)
494
+ return 0;
495
+ // Extract leading digits only
496
+ let num = 0;
497
+ for (let i = 0; i < part.length; i++) {
498
+ const code = part.charCodeAt(i);
499
+ if (code >= 48 && code <= 57) {
500
+ num = num * 10 + (code - 48);
501
+ }
502
+ else {
503
+ break;
504
+ }
505
+ }
506
+ return num;
507
+ }
508
+
509
+ /**
510
+ * Creates a git reference from full name.
511
+ * Parses the reference type from the full name.
512
+ *
513
+ * @param options - Reference creation options
514
+ * @returns A new GitRef object
515
+ *
516
+ * @example
517
+ * const ref = createGitRef({
518
+ * fullName: 'refs/heads/main',
519
+ * commitHash: 'abc123...',
520
+ * })
521
+ */
522
+ function createGitRef(options) {
523
+ const { type, name, remote } = parseRefName(options.fullName);
524
+ return {
525
+ fullName: options.fullName,
526
+ name,
527
+ type,
528
+ commitHash: options.commitHash,
529
+ remote,
530
+ isHead: options.isHead,
531
+ };
532
+ }
533
+ /**
534
+ * Parses a full reference name into its components.
535
+ * Uses character-by-character parsing (no regex).
536
+ *
537
+ * @param fullName - Full reference name
538
+ * @returns Parsed components
539
+ *
540
+ * @example
541
+ * parseRefName('refs/heads/main') // { type: 'branch', name: 'main' }
542
+ * parseRefName('refs/remotes/origin/main') // { type: 'remote', name: 'main', remote: 'origin' }
543
+ */
544
+ function parseRefName(fullName) {
545
+ // Handle HEAD specially
546
+ if (fullName === 'HEAD') {
547
+ return { type: 'head', name: 'HEAD' };
548
+ }
549
+ // Split by '/' character
550
+ const parts = splitByChar(fullName, '/');
551
+ // refs/heads/... -> branch
552
+ if (parts.length >= 3 && parts[0] === 'refs' && parts[1] === 'heads') {
553
+ return {
554
+ type: 'branch',
555
+ name: parts.slice(2).join('/'),
556
+ };
557
+ }
558
+ // refs/tags/... -> tag
559
+ if (parts.length >= 3 && parts[0] === 'refs' && parts[1] === 'tags') {
560
+ return {
561
+ type: 'tag',
562
+ name: parts.slice(2).join('/'),
563
+ };
564
+ }
565
+ // refs/remotes/origin/... -> remote
566
+ if (parts.length >= 4 && parts[0] === 'refs' && parts[1] === 'remotes') {
567
+ return {
568
+ type: 'remote',
569
+ name: parts.slice(3).join('/'),
570
+ remote: parts[2],
571
+ };
572
+ }
573
+ // refs/stash -> stash
574
+ if (parts.length >= 2 && parts[0] === 'refs' && parts[1] === 'stash') {
575
+ return {
576
+ type: 'stash',
577
+ name: parts.slice(1).join('/'),
578
+ };
579
+ }
580
+ // Default to branch for unknown patterns
581
+ return {
582
+ type: 'branch',
583
+ name: fullName,
584
+ };
585
+ }
586
+ /**
587
+ * Splits a string by a character.
588
+ * Character-by-character implementation (no regex).
589
+ *
590
+ * @param str - String to split
591
+ * @param char - Character to split by
592
+ * @returns Array of parts
593
+ */
594
+ function splitByChar(str, char) {
595
+ const parts = [];
596
+ let current = '';
597
+ for (let i = 0; i < str.length; i++) {
598
+ if (str[i] === char) {
599
+ parts.push(current);
600
+ current = '';
601
+ }
602
+ else {
603
+ current += str[i];
604
+ }
605
+ }
606
+ parts.push(current);
607
+ return parts;
608
+ }
609
+ /**
610
+ * Checks if a reference is a branch.
611
+ *
612
+ * @param ref - Reference to check
613
+ * @returns True if reference is a branch
614
+ */
615
+ function isBranchRef(ref) {
616
+ return ref.type === 'branch';
617
+ }
618
+ /**
619
+ * Checks if a reference is a tag.
620
+ *
621
+ * @param ref - Reference to check
622
+ * @returns True if reference is a tag
623
+ */
624
+ function isTagRef(ref) {
625
+ return ref.type === 'tag';
626
+ }
627
+ /**
628
+ * Checks if a reference is a remote tracking branch.
629
+ *
630
+ * @param ref - Reference to check
631
+ * @returns True if reference is a remote
632
+ */
633
+ function isRemoteRef(ref) {
634
+ return ref.type === 'remote';
635
+ }
636
+ /**
637
+ * Checks if a reference points to the current HEAD.
638
+ *
639
+ * @param ref - Reference to check
640
+ * @returns True if reference is HEAD
641
+ */
642
+ function isHeadRef(ref) {
643
+ return ref.type === 'head' || ref.isHead === true;
644
+ }
645
+ /**
646
+ * Gets the tracking remote for a reference.
647
+ *
648
+ * @param ref - Reference to check
649
+ * @returns Remote name or undefined
650
+ */
651
+ function getRemote(ref) {
652
+ return ref.remote;
653
+ }
654
+ /**
655
+ * Builds a full reference name from type and name.
656
+ *
657
+ * @param type - Reference type
658
+ * @param name - Reference name
659
+ * @param remote - Remote name (for remote type)
660
+ * @returns Full reference name
661
+ *
662
+ * @example
663
+ * buildRefName('branch', 'main') // 'refs/heads/main'
664
+ * buildRefName('tag', 'v1.0.0') // 'refs/tags/v1.0.0'
665
+ * buildRefName('remote', 'main', 'origin') // 'refs/remotes/origin/main'
666
+ */
667
+ function buildRefName(type, name, remote) {
668
+ switch (type) {
669
+ case 'branch':
670
+ return `refs/heads/${name}`;
671
+ case 'tag':
672
+ return `refs/tags/${name}`;
673
+ case 'remote':
674
+ return remote ? `refs/remotes/${remote}/${name}` : `refs/remotes/${name}`;
675
+ case 'head':
676
+ return 'HEAD';
677
+ case 'stash':
678
+ return `refs/stash`;
679
+ default:
680
+ return name;
681
+ }
682
+ }
683
+ /**
684
+ * Compares two references by name (alphabetically).
685
+ *
686
+ * @param a - First reference
687
+ * @param b - Second reference
688
+ * @returns Comparison result (-1, 0, or 1)
689
+ */
690
+ function compareRefsByName(a, b) {
691
+ if (a.name < b.name)
692
+ return -1;
693
+ if (a.name > b.name)
694
+ return 1;
695
+ return 0;
696
+ }
697
+ /**
698
+ * Filters references by type.
699
+ *
700
+ * @param refs - References to filter
701
+ * @param type - Type to filter by
702
+ * @returns Filtered references
703
+ */
704
+ function filterRefsByType(refs, type) {
705
+ const result = [];
706
+ for (const ref of refs) {
707
+ if (ref.type === type) {
708
+ result.push(ref);
709
+ }
710
+ }
711
+ return result;
712
+ }
713
+ /**
714
+ * Filters references by remote.
715
+ *
716
+ * @param refs - References to filter
717
+ * @param remote - Remote name to filter by
718
+ * @returns Filtered references
719
+ */
720
+ function filterRefsByRemote(refs, remote) {
721
+ const result = [];
722
+ for (const ref of refs) {
723
+ if (ref.remote === remote) {
724
+ result.push(ref);
725
+ }
726
+ }
727
+ return result;
728
+ }
729
+
730
+ exports.buildRefName = buildRefName;
731
+ exports.buildTagName = buildTagName;
732
+ exports.compareRefsByName = compareRefsByName;
733
+ exports.compareTagsByVersion = compareTagsByVersion;
734
+ exports.createAnnotatedTag = createAnnotatedTag;
735
+ exports.createGitCommit = createGitCommit;
736
+ exports.createGitRef = createGitRef;
737
+ exports.createLightweightTag = createLightweightTag;
738
+ exports.extractPackageFromTag = extractPackageFromTag;
739
+ exports.extractScope = extractScope;
740
+ exports.extractType = extractType;
741
+ exports.extractVersionFromTag = extractVersionFromTag;
742
+ exports.filterRefsByRemote = filterRefsByRemote;
743
+ exports.filterRefsByType = filterRefsByType;
744
+ exports.getRemote = getRemote;
745
+ exports.getShortHash = getShortHash;
746
+ exports.isAnnotatedTag = isAnnotatedTag;
747
+ exports.isBranchRef = isBranchRef;
748
+ exports.isHeadRef = isHeadRef;
749
+ exports.isLightweightTag = isLightweightTag;
750
+ exports.isMergeCommit = isMergeCommit;
751
+ exports.isRemoteRef = isRemoteRef;
752
+ exports.isRootCommit = isRootCommit;
753
+ exports.isSameCommit = isSameCommit;
754
+ exports.isTagRef = isTagRef;
755
+ //# sourceMappingURL=index.cjs.js.map