polen 0.10.0-next.3 → 0.10.0-next.4

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 (268) hide show
  1. package/README.md +49 -376
  2. package/build/api/api.d.ts +1 -0
  3. package/build/api/api.d.ts.map +1 -1
  4. package/build/api/api.js +1 -0
  5. package/build/api/api.js.map +1 -1
  6. package/build/api/static/index.d.ts +2 -0
  7. package/build/api/static/index.d.ts.map +1 -0
  8. package/build/api/static/index.js +2 -0
  9. package/build/api/static/index.js.map +1 -0
  10. package/build/api/static/manifest.d.ts +18 -0
  11. package/build/api/static/manifest.d.ts.map +1 -0
  12. package/build/api/static/manifest.js +13 -0
  13. package/build/api/static/manifest.js.map +1 -0
  14. package/build/api/static/rebase.d.ts +14 -0
  15. package/build/api/static/rebase.d.ts.map +1 -0
  16. package/build/api/static/rebase.js +110 -0
  17. package/build/api/static/rebase.js.map +1 -0
  18. package/build/api/static/static.d.ts +3 -0
  19. package/build/api/static/static.d.ts.map +1 -0
  20. package/build/api/static/static.js +3 -0
  21. package/build/api/static/static.js.map +1 -0
  22. package/build/api/vite/plugins/build.d.ts.map +1 -1
  23. package/build/api/vite/plugins/build.js +22 -1
  24. package/build/api/vite/plugins/build.js.map +1 -1
  25. package/build/cli/commands/static/$default.d.ts +3 -0
  26. package/build/cli/commands/static/$default.d.ts.map +1 -0
  27. package/build/cli/commands/static/$default.js +38 -0
  28. package/build/cli/commands/static/$default.js.map +1 -0
  29. package/build/cli/commands/static/rebase.d.ts +2 -0
  30. package/build/cli/commands/static/rebase.d.ts.map +1 -0
  31. package/build/cli/commands/static/rebase.js +26 -0
  32. package/build/cli/commands/static/rebase.js.map +1 -0
  33. package/build/cli/commands/static.d.ts +3 -0
  34. package/build/cli/commands/static.d.ts.map +1 -0
  35. package/build/cli/commands/static.js +5 -0
  36. package/build/cli/commands/static.js.map +1 -0
  37. package/build/lib/demos/builder.d.ts +83 -0
  38. package/build/lib/demos/builder.d.ts.map +1 -0
  39. package/build/lib/demos/builder.js +237 -0
  40. package/build/lib/demos/builder.js.map +1 -0
  41. package/build/lib/demos/config-schema.d.ts +243 -0
  42. package/build/lib/demos/config-schema.d.ts.map +1 -0
  43. package/build/lib/demos/config-schema.js +52 -0
  44. package/build/lib/demos/config-schema.js.map +1 -0
  45. package/build/lib/demos/config.d.ts +40 -0
  46. package/build/lib/demos/config.d.ts.map +1 -0
  47. package/build/lib/demos/config.js +180 -0
  48. package/build/lib/demos/config.js.map +1 -0
  49. package/build/lib/demos/index.d.ts +9 -0
  50. package/build/lib/demos/index.d.ts.map +1 -0
  51. package/build/lib/demos/index.js +8 -0
  52. package/build/lib/demos/index.js.map +1 -0
  53. package/build/lib/demos/ui/components.d.ts +33 -0
  54. package/build/lib/demos/ui/components.d.ts.map +1 -0
  55. package/build/lib/demos/ui/components.js +699 -0
  56. package/build/lib/demos/ui/components.js.map +1 -0
  57. package/build/lib/demos/ui/data-collector.d.ts +88 -0
  58. package/build/lib/demos/ui/data-collector.d.ts.map +1 -0
  59. package/build/lib/demos/ui/data-collector.js +174 -0
  60. package/build/lib/demos/ui/data-collector.js.map +1 -0
  61. package/build/lib/demos/ui/landing-page-cli.d.ts +3 -0
  62. package/build/lib/demos/ui/landing-page-cli.d.ts.map +1 -0
  63. package/build/lib/demos/ui/landing-page-cli.js +21 -0
  64. package/build/lib/demos/ui/landing-page-cli.js.map +1 -0
  65. package/build/lib/demos/ui/landing-page.d.ts +32 -0
  66. package/build/lib/demos/ui/landing-page.d.ts.map +1 -0
  67. package/build/lib/demos/ui/landing-page.js +83 -0
  68. package/build/lib/demos/ui/landing-page.js.map +1 -0
  69. package/build/lib/demos/ui/page-renderer.d.ts +26 -0
  70. package/build/lib/demos/ui/page-renderer.d.ts.map +1 -0
  71. package/build/lib/demos/ui/page-renderer.js +104 -0
  72. package/build/lib/demos/ui/page-renderer.js.map +1 -0
  73. package/build/lib/demos/utils.d.ts +14 -0
  74. package/build/lib/demos/utils.d.ts.map +1 -0
  75. package/build/lib/demos/utils.js +37 -0
  76. package/build/lib/demos/utils.js.map +1 -0
  77. package/build/lib/deployment/$$.d.ts +3 -0
  78. package/build/lib/deployment/$$.d.ts.map +1 -0
  79. package/build/lib/deployment/$$.js +3 -0
  80. package/build/lib/deployment/$$.js.map +1 -0
  81. package/build/lib/deployment/$.d.ts +2 -0
  82. package/build/lib/deployment/$.d.ts.map +1 -0
  83. package/build/lib/deployment/$.js +2 -0
  84. package/build/lib/deployment/$.js.map +1 -0
  85. package/build/lib/deployment/metadata.d.ts +32 -0
  86. package/build/lib/deployment/metadata.d.ts.map +1 -0
  87. package/build/lib/deployment/metadata.js +37 -0
  88. package/build/lib/deployment/metadata.js.map +1 -0
  89. package/build/lib/deployment/path-manager.d.ts +41 -0
  90. package/build/lib/deployment/path-manager.d.ts.map +1 -0
  91. package/build/lib/deployment/path-manager.js +157 -0
  92. package/build/lib/deployment/path-manager.js.map +1 -0
  93. package/build/lib/github-actions/git-controller.d.ts +50 -0
  94. package/build/lib/github-actions/git-controller.d.ts.map +1 -0
  95. package/build/lib/github-actions/git-controller.js +90 -0
  96. package/build/lib/github-actions/git-controller.js.map +1 -0
  97. package/build/lib/github-actions/github-actions.d.ts +7 -0
  98. package/build/lib/github-actions/github-actions.d.ts.map +1 -0
  99. package/build/lib/github-actions/github-actions.js +7 -0
  100. package/build/lib/github-actions/github-actions.js.map +1 -0
  101. package/build/lib/github-actions/index.d.ts +2 -0
  102. package/build/lib/github-actions/index.d.ts.map +1 -0
  103. package/build/lib/github-actions/index.js +2 -0
  104. package/build/lib/github-actions/index.js.map +1 -0
  105. package/build/lib/github-actions/lib/get-pr-deployments.d.ts +12 -0
  106. package/build/lib/github-actions/lib/get-pr-deployments.d.ts.map +1 -0
  107. package/build/lib/github-actions/lib/get-pr-deployments.js +51 -0
  108. package/build/lib/github-actions/lib/get-pr-deployments.js.map +1 -0
  109. package/build/lib/github-actions/pr-controller.d.ts +39 -0
  110. package/build/lib/github-actions/pr-controller.d.ts.map +1 -0
  111. package/build/lib/github-actions/pr-controller.js +122 -0
  112. package/build/lib/github-actions/pr-controller.js.map +1 -0
  113. package/build/lib/github-actions/run-step-cli.d.ts +9 -0
  114. package/build/lib/github-actions/run-step-cli.d.ts.map +1 -0
  115. package/build/lib/github-actions/run-step-cli.js +71 -0
  116. package/build/lib/github-actions/run-step-cli.js.map +1 -0
  117. package/build/lib/github-actions/runner.d.ts +17 -0
  118. package/build/lib/github-actions/runner.d.ts.map +1 -0
  119. package/build/lib/github-actions/runner.js +195 -0
  120. package/build/lib/github-actions/runner.js.map +1 -0
  121. package/build/lib/github-actions/schemas/context.d.ts +933 -0
  122. package/build/lib/github-actions/schemas/context.d.ts.map +1 -0
  123. package/build/lib/github-actions/schemas/context.js +407 -0
  124. package/build/lib/github-actions/schemas/context.js.map +1 -0
  125. package/build/lib/github-actions/schemas/index.d.ts +5 -0
  126. package/build/lib/github-actions/schemas/index.d.ts.map +1 -0
  127. package/build/lib/github-actions/schemas/index.js +5 -0
  128. package/build/lib/github-actions/schemas/index.js.map +1 -0
  129. package/build/lib/github-actions/search-module.d.ts +38 -0
  130. package/build/lib/github-actions/search-module.d.ts.map +1 -0
  131. package/build/lib/github-actions/search-module.js +40 -0
  132. package/build/lib/github-actions/search-module.js.map +1 -0
  133. package/build/lib/github-actions/step.d.ts +163 -0
  134. package/build/lib/github-actions/step.d.ts.map +1 -0
  135. package/build/lib/github-actions/step.js +121 -0
  136. package/build/lib/github-actions/step.js.map +1 -0
  137. package/build/lib/helpers.d.ts.map +1 -1
  138. package/build/lib/helpers.js +5 -3
  139. package/build/lib/helpers.js.map +1 -1
  140. package/build/lib/kit-temp.d.ts +54 -0
  141. package/build/lib/kit-temp.d.ts.map +1 -1
  142. package/build/lib/kit-temp.js +80 -14
  143. package/build/lib/kit-temp.js.map +1 -1
  144. package/build/lib/kit-temp.test-d.d.ts +2 -0
  145. package/build/lib/kit-temp.test-d.d.ts.map +1 -0
  146. package/build/lib/kit-temp.test-d.js +75 -0
  147. package/build/lib/kit-temp.test-d.js.map +1 -0
  148. package/build/lib/mask/$$.d.ts +3 -0
  149. package/build/lib/mask/$$.d.ts.map +1 -0
  150. package/build/lib/mask/$$.js +3 -0
  151. package/build/lib/mask/$$.js.map +1 -0
  152. package/build/lib/mask/$.d.ts +2 -0
  153. package/build/lib/mask/$.d.ts.map +1 -0
  154. package/build/lib/mask/$.js +2 -0
  155. package/build/lib/mask/$.js.map +1 -0
  156. package/build/lib/mask/apply.d.ts +86 -0
  157. package/build/lib/mask/apply.d.ts.map +1 -0
  158. package/build/lib/mask/apply.js +86 -0
  159. package/build/lib/mask/apply.js.map +1 -0
  160. package/build/lib/mask/mask.d.ts +124 -0
  161. package/build/lib/mask/mask.d.ts.map +1 -0
  162. package/build/lib/mask/mask.js +137 -0
  163. package/build/lib/mask/mask.js.map +1 -0
  164. package/build/lib/mask/mask.test-d.d.ts +2 -0
  165. package/build/lib/mask/mask.test-d.d.ts.map +1 -0
  166. package/build/lib/mask/mask.test-d.js +102 -0
  167. package/build/lib/mask/mask.test-d.js.map +1 -0
  168. package/build/lib/task/$$.d.ts +3 -0
  169. package/build/lib/task/$$.d.ts.map +1 -0
  170. package/build/lib/task/$$.js +3 -0
  171. package/build/lib/task/$$.js.map +1 -0
  172. package/build/lib/task/$.d.ts +2 -0
  173. package/build/lib/task/$.d.ts.map +1 -0
  174. package/build/lib/task/$.js +2 -0
  175. package/build/lib/task/$.js.map +1 -0
  176. package/build/lib/task/report.d.ts +28 -0
  177. package/build/lib/task/report.d.ts.map +1 -0
  178. package/build/lib/task/report.js +33 -0
  179. package/build/lib/task/report.js.map +1 -0
  180. package/build/lib/task/task.d.ts +44 -0
  181. package/build/lib/task/task.d.ts.map +1 -0
  182. package/build/lib/task/task.js +63 -0
  183. package/build/lib/task/task.js.map +1 -0
  184. package/build/lib/version-history/index.d.ts +3 -0
  185. package/build/lib/version-history/index.d.ts.map +1 -0
  186. package/build/lib/version-history/index.js +2 -0
  187. package/build/lib/version-history/index.js.map +1 -0
  188. package/build/lib/version-history/types.d.ts +64 -0
  189. package/build/lib/version-history/types.d.ts.map +1 -0
  190. package/build/lib/version-history/types.js +5 -0
  191. package/build/lib/version-history/types.js.map +1 -0
  192. package/build/lib/version-history/version-history.d.ts +85 -0
  193. package/build/lib/version-history/version-history.d.ts.map +1 -0
  194. package/build/lib/version-history/version-history.js +248 -0
  195. package/build/lib/version-history/version-history.js.map +1 -0
  196. package/build/sandbox.d.ts +2 -0
  197. package/build/sandbox.d.ts.map +1 -0
  198. package/build/sandbox.js +3 -0
  199. package/build/sandbox.js.map +1 -0
  200. package/build/template/components/Link.jsx +1 -1
  201. package/package.json +16 -9
  202. package/src/api/api.ts +1 -0
  203. package/src/api/singletons/markdown/markdown.test.ts +1 -1
  204. package/src/api/static/index.ts +1 -0
  205. package/src/api/static/manifest.test.ts +106 -0
  206. package/src/api/static/manifest.ts +16 -0
  207. package/src/api/static/rebase.test.ts +229 -0
  208. package/src/api/static/rebase.ts +140 -0
  209. package/src/api/static/static.ts +2 -0
  210. package/src/api/utils/asset-url/asset-url.test.ts +4 -4
  211. package/src/api/vite/plugins/build.ts +25 -1
  212. package/src/api/vite/plugins/core.ts +1 -1
  213. package/src/cli/commands/static/$default.ts +43 -0
  214. package/src/cli/commands/static/rebase.ts +37 -0
  215. package/src/cli/commands/static.ts +6 -0
  216. package/src/lib/demos/builder.ts +298 -0
  217. package/src/lib/demos/config-schema.ts +56 -0
  218. package/src/lib/demos/config.test.ts +193 -0
  219. package/src/lib/demos/config.ts +205 -0
  220. package/src/lib/demos/index.ts +9 -0
  221. package/src/lib/demos/ui/components.ts +739 -0
  222. package/src/lib/demos/ui/data-collector.ts +246 -0
  223. package/src/lib/demos/ui/landing-page-cli.ts +23 -0
  224. package/src/lib/demos/ui/landing-page.ts +126 -0
  225. package/src/lib/demos/ui/page-renderer.ts +124 -0
  226. package/src/lib/demos/utils.ts +43 -0
  227. package/src/lib/deployment/$$.ts +2 -0
  228. package/src/lib/deployment/$.test.ts +53 -0
  229. package/src/lib/deployment/$.ts +1 -0
  230. package/src/lib/deployment/metadata.ts +40 -0
  231. package/src/lib/deployment/path-manager.ts +186 -0
  232. package/src/lib/github-actions/git-controller.ts +151 -0
  233. package/src/lib/github-actions/github-actions.ts +6 -0
  234. package/src/lib/github-actions/index.ts +1 -0
  235. package/src/lib/github-actions/lib/get-pr-deployments.ts +76 -0
  236. package/src/lib/github-actions/pr-controller.test.ts +172 -0
  237. package/src/lib/github-actions/pr-controller.ts +183 -0
  238. package/src/lib/github-actions/run-step-cli.ts +84 -0
  239. package/src/lib/github-actions/runner.test.ts +192 -0
  240. package/src/lib/github-actions/runner.ts +226 -0
  241. package/src/lib/github-actions/schemas/context.ts +424 -0
  242. package/src/lib/github-actions/schemas/index.ts +5 -0
  243. package/src/lib/github-actions/search-module.test.ts +110 -0
  244. package/src/lib/github-actions/search-module.ts +76 -0
  245. package/src/lib/github-actions/step.test.ts +149 -0
  246. package/src/lib/github-actions/step.ts +232 -0
  247. package/src/lib/helpers.ts +4 -3
  248. package/src/lib/kit-temp.test-d.ts +115 -0
  249. package/src/lib/kit-temp.test.ts +127 -0
  250. package/src/lib/kit-temp.ts +126 -14
  251. package/src/lib/mask/$$.ts +2 -0
  252. package/src/lib/mask/$.test.ts +248 -0
  253. package/src/lib/mask/$.ts +1 -0
  254. package/src/lib/mask/apply.ts +134 -0
  255. package/src/lib/mask/mask.test-d.ts +144 -0
  256. package/src/lib/mask/mask.ts +244 -0
  257. package/src/lib/shiki/shiki.test.ts +1 -1
  258. package/src/lib/task/$$.ts +2 -0
  259. package/src/lib/task/$.test.ts +209 -0
  260. package/src/lib/task/$.ts +1 -0
  261. package/src/lib/task/report.ts +72 -0
  262. package/src/lib/task/task.ts +112 -0
  263. package/src/lib/version-history/index.test.ts +188 -0
  264. package/src/lib/version-history/index.ts +4 -0
  265. package/src/lib/version-history/types.ts +68 -0
  266. package/src/lib/version-history/version-history.ts +293 -0
  267. package/src/sandbox.ts +1 -0
  268. package/src/template/components/Link.tsx +1 -1
@@ -0,0 +1,188 @@
1
+ import { parse as semverParse } from '@vltpkg/semver'
2
+ import type { SimpleGit } from 'simple-git'
3
+ import { beforeEach, describe, expect, it, type Mock, vi } from 'vitest'
4
+ import { VersionHistory } from './index.ts'
5
+
6
+ describe('VersionHistory', () => {
7
+ describe('parseSemver', () => {
8
+ it('parses standard semver tags', () => {
9
+ const version = VersionHistory.parseSemver('1.2.3')
10
+ expect(version).not.toBeNull()
11
+ expect(version?.major).toBe(1)
12
+ expect(version?.minor).toBe(2)
13
+ expect(version?.patch).toBe(3)
14
+ expect(version?.prerelease).toBeUndefined()
15
+ })
16
+
17
+ it('parses semver tags with v prefix', () => {
18
+ const version = VersionHistory.parseSemver('v1.2.3')
19
+ expect(version).not.toBeNull()
20
+ expect(version?.major).toBe(1)
21
+ expect(version?.minor).toBe(2)
22
+ expect(version?.patch).toBe(3)
23
+ })
24
+
25
+ it('parses prerelease versions', () => {
26
+ const version = VersionHistory.parseSemver('1.2.3-beta.1')
27
+ expect(version).not.toBeNull()
28
+ expect(version?.major).toBe(1)
29
+ expect(version?.minor).toBe(2)
30
+ expect(version?.patch).toBe(3)
31
+ expect(version?.prerelease).toEqual(['beta', 1])
32
+ })
33
+
34
+ it('returns null for invalid semver', () => {
35
+ expect(VersionHistory.parseSemver('not-a-version')).toBeNull()
36
+ expect(VersionHistory.parseSemver('1.2')).toBeNull()
37
+ expect(VersionHistory.parseSemver('latest')).toBeNull()
38
+ })
39
+ })
40
+
41
+ describe('isSemverTag', () => {
42
+ it('identifies valid semver tags', () => {
43
+ expect(VersionHistory.isSemverTag('1.2.3')).toBe(true)
44
+ expect(VersionHistory.isSemverTag('v1.2.3')).toBe(true)
45
+ expect(VersionHistory.isSemverTag('1.0.0-beta.1')).toBe(true)
46
+ expect(VersionHistory.isSemverTag('0.0.1')).toBe(true)
47
+ })
48
+
49
+ it('rejects invalid semver tags', () => {
50
+ expect(VersionHistory.isSemverTag('latest')).toBe(false)
51
+ expect(VersionHistory.isSemverTag('next')).toBe(false)
52
+ expect(VersionHistory.isSemverTag('1.2')).toBe(false)
53
+ expect(VersionHistory.isSemverTag('v1.2')).toBe(false)
54
+ expect(VersionHistory.isSemverTag('not-a-version')).toBe(false)
55
+ })
56
+ })
57
+
58
+ describe('isPrerelease', () => {
59
+ it('identifies prerelease versions', () => {
60
+ expect(VersionHistory.isPrerelease('1.0.0-beta.1')).toBe(true)
61
+ expect(VersionHistory.isPrerelease('2.0.0-next.5')).toBe(true)
62
+ expect(VersionHistory.isPrerelease('3.0.0-alpha')).toBe(true)
63
+ })
64
+
65
+ it('identifies stable versions', () => {
66
+ expect(VersionHistory.isPrerelease('1.0.0')).toBe(false)
67
+ expect(VersionHistory.isPrerelease('v2.3.4')).toBe(false)
68
+ })
69
+ })
70
+
71
+ describe('version sorting', () => {
72
+ it('sorts versions correctly', () => {
73
+ const versions = [
74
+ { semver: semverParse('1.0.0')!, isPrerelease: false },
75
+ { semver: semverParse('2.0.0')!, isPrerelease: false },
76
+ { semver: semverParse('1.1.0')!, isPrerelease: false },
77
+ { semver: semverParse('1.0.1')!, isPrerelease: false },
78
+ { semver: semverParse('2.0.0-beta.1')!, isPrerelease: true },
79
+ ]
80
+
81
+ const sorted = [...versions].sort((a, b) => {
82
+ // Reverse comparison for descending order
83
+ return b.semver.compare(a.semver)
84
+ })
85
+
86
+ expect(sorted[0]!.semver.toString()).toBe('2.0.0')
87
+ expect(sorted[1]!.semver.toString()).toBe('2.0.0-beta.1')
88
+ expect(sorted[2]!.semver.toString()).toBe('1.1.0')
89
+ expect(sorted[3]!.semver.toString()).toBe('1.0.1')
90
+ expect(sorted[4]!.semver.toString()).toBe('1.0.0')
91
+ })
92
+ })
93
+
94
+ describe('getCurrentDevelopmentCycle', () => {
95
+ let mockGit: {
96
+ tags: Mock
97
+ show: Mock
98
+ revparse: Mock
99
+ tag: Mock
100
+ }
101
+
102
+ beforeEach(() => {
103
+ mockGit = {
104
+ tags: vi.fn(),
105
+ show: vi.fn(),
106
+ revparse: vi.fn(),
107
+ tag: vi.fn(),
108
+ }
109
+ // versionHistory = new VersionHistory()
110
+ // @ts-expect-error - mocking private property
111
+ VersionHistory.git = mockGit as unknown as SimpleGit
112
+ })
113
+
114
+ it('returns latest stable and newer prereleases', async () => {
115
+ // Mock git tags
116
+ mockGit.tags.mockResolvedValue({
117
+ all: ['1.0.0', '1.1.0', '1.2.0', '2.0.0-beta.1', '2.0.0-beta.2', '2.0.0'],
118
+ })
119
+
120
+ // Mock git show for each tag
121
+ const mockDates = {
122
+ '1.0.0': '1234567890',
123
+ '1.1.0': '1234567900',
124
+ '1.2.0': '1234567910',
125
+ '2.0.0-beta.1': '1234567920',
126
+ '2.0.0-beta.2': '1234567930',
127
+ '2.0.0': '1234567940',
128
+ }
129
+
130
+ mockGit.show.mockImplementation((args: string[]) => {
131
+ const tag = args[0]?.replace('^{commit}', '') || ''
132
+ const timestamp = mockDates[tag as keyof typeof mockDates]
133
+ return Promise.resolve(`abc123 ${timestamp}`)
134
+ })
135
+
136
+ const cycle = await VersionHistory.getCurrentDevelopmentCycle()
137
+
138
+ expect(cycle.stable?.git.tag).toBe('2.0.0')
139
+ expect(cycle.prereleases).toHaveLength(0) // No prereleases after stable version 2.0.0
140
+ expect(cycle.all).toHaveLength(1) // Just the stable version
141
+ })
142
+
143
+ it('includes prereleases newer than latest stable', async () => {
144
+ // Mock git tags
145
+ mockGit.tags.mockResolvedValue({
146
+ all: ['1.0.0', '1.1.0', '2.0.0-beta.1', '2.0.0-beta.2'],
147
+ })
148
+
149
+ // Mock git show for each tag
150
+ const mockDates = {
151
+ '1.0.0': '1234567890',
152
+ '1.1.0': '1234567900',
153
+ '2.0.0-beta.1': '1234567910',
154
+ '2.0.0-beta.2': '1234567920',
155
+ }
156
+
157
+ mockGit.show.mockImplementation((args: string[]) => {
158
+ const tag = args[0]?.replace('^{commit}', '') || ''
159
+ const timestamp = mockDates[tag as keyof typeof mockDates]
160
+ return Promise.resolve(`abc123 ${timestamp}`)
161
+ })
162
+
163
+ const cycle = await VersionHistory.getCurrentDevelopmentCycle()
164
+
165
+ expect(cycle.stable?.git.tag).toBe('1.1.0') // Latest stable version
166
+ expect(cycle.prereleases).toHaveLength(2) // Prereleases newer than stable
167
+ expect(cycle.prereleases[0]?.git.tag).toBe('2.0.0-beta.2')
168
+ expect(cycle.prereleases[1]?.git.tag).toBe('2.0.0-beta.1')
169
+ expect(cycle.all).toHaveLength(3) // Stable + 2 prereleases
170
+ })
171
+
172
+ it('returns all versions as prereleases when no stable version exists', async () => {
173
+ // Mock git tags with only prereleases
174
+ mockGit.tags.mockResolvedValue({
175
+ all: ['0.1.0-alpha.1', '0.1.0-alpha.2', '0.1.0-beta.1'],
176
+ })
177
+
178
+ // Mock git show for each tag
179
+ mockGit.show.mockImplementation(() => Promise.resolve('abc123 1234567890'))
180
+
181
+ const cycle = await VersionHistory.getCurrentDevelopmentCycle()
182
+
183
+ expect(cycle.stable).toBeNull()
184
+ expect(cycle.prereleases).toHaveLength(3)
185
+ expect(cycle.all).toHaveLength(3)
186
+ })
187
+ })
188
+ })
@@ -0,0 +1,4 @@
1
+ export * as VersionHistory from './version-history.ts'
2
+
3
+ // Re-export types at the top level for convenience
4
+ export type { DevelopmentCycle, DistTagInfo, Version, VersionCatalog } from './types.ts'
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Version history types
3
+ */
4
+
5
+ import type { Version as Semver } from '@vltpkg/semver'
6
+
7
+ export interface Version {
8
+ /**
9
+ * Git-related information for this version
10
+ */
11
+ git: {
12
+ /**
13
+ * The git tag name for this version (e.g., "1.2.3" or "2.0.0-beta.1")
14
+ */
15
+ tag: string
16
+ /**
17
+ * The full git commit SHA associated with this version tag
18
+ */
19
+ sha: string
20
+ }
21
+ /**
22
+ * The date when this version tag was created
23
+ */
24
+ date: Date
25
+ /**
26
+ * Whether this version is a prerelease (contains -alpha, -beta, -rc, etc.)
27
+ */
28
+ isPrerelease: boolean
29
+ /**
30
+ * Parsed semver object containing major, minor, patch, and prerelease info
31
+ */
32
+ semver: Semver
33
+ }
34
+
35
+ export interface DistTagInfo {
36
+ name: string
37
+ commit: string
38
+ semverTag?: string
39
+ }
40
+
41
+ export interface DevelopmentCycle {
42
+ stable: Version | null
43
+ prereleases: Version[]
44
+ all: Version[]
45
+ }
46
+
47
+ /**
48
+ * Complete registry of all versions and dist-tags in the repository
49
+ */
50
+ export interface VersionCatalog {
51
+ /**
52
+ * All dist-tags mapped to their corresponding versions
53
+ */
54
+ distTags: {
55
+ latest?: Version
56
+ next?: Version
57
+ [tagName: string]: Version | undefined
58
+ }
59
+ /**
60
+ * All versions sorted by semver (newest first)
61
+ */
62
+ versions: Version[]
63
+ /**
64
+ * Quick access to commonly needed subsets
65
+ */
66
+ stable: Version[]
67
+ prerelease: Version[]
68
+ }
@@ -0,0 +1,293 @@
1
+ import {
2
+ compare as semverCompare,
3
+ parse as semverParse,
4
+ prerelease as semverPrerelease,
5
+ type Version as SemverVersion,
6
+ } from '@vltpkg/semver'
7
+ import { type SimpleGit, simpleGit } from 'simple-git'
8
+ import type { DevelopmentCycle, DistTagInfo, Version, VersionCatalog } from './types.ts'
9
+
10
+ export type { DevelopmentCycle, DistTagInfo, Version, VersionCatalog } from './types.ts'
11
+
12
+ // Helper to get git instance
13
+ function getGit(repoPath: string = process.cwd()): SimpleGit {
14
+ return simpleGit(repoPath)
15
+ }
16
+
17
+ /**
18
+ * Parse a semver string into a Version object
19
+ */
20
+ export function parseSemver(tag: string): SemverVersion | null {
21
+ return semverParse(tag) || null
22
+ }
23
+
24
+ /**
25
+ * Check if a tag is a semver tag
26
+ */
27
+ export function isSemverTag(tag: string): boolean {
28
+ return semverParse(tag) !== undefined
29
+ }
30
+
31
+ /**
32
+ * Check if a version is a prerelease
33
+ */
34
+ export function isPrerelease(tag: string): boolean {
35
+ const prereleaseArray = semverPrerelease(tag)
36
+ return prereleaseArray !== undefined && prereleaseArray.length > 0
37
+ }
38
+
39
+ /**
40
+ * Check if a version is stable (not a prerelease)
41
+ */
42
+ export function isStableVersion(tag: string): boolean {
43
+ return !isPrerelease(tag)
44
+ }
45
+
46
+ /**
47
+ * Get the deployment path for a version
48
+ * Stable versions go to /latest/, prereleases go to /[version]/
49
+ */
50
+ export function getDeploymentPath(version: string, prefix: string = '/polen'): string {
51
+ const isStable = isStableVersion(version)
52
+ return isStable ? `${prefix}/latest/` : `${prefix}/${version}/`
53
+ }
54
+
55
+ /**
56
+ * Get all versions from the repository
57
+ */
58
+ export async function getVersions(repoPath?: string): Promise<Version[]> {
59
+ const git = getGit(repoPath)
60
+ const tags = await git.tags()
61
+ const versions: Version[] = []
62
+
63
+ for (const tag of tags.all) {
64
+ if (!isSemverTag(tag)) continue
65
+
66
+ const semver = parseSemver(tag)
67
+ if (!semver) continue
68
+
69
+ try {
70
+ const tagInfo = await git.show([`${tag}^{commit}`, `--format=%H %at`])
71
+ const [commit, timestamp] = tagInfo.trim().split(' ')
72
+
73
+ if (!commit) continue
74
+
75
+ versions.push({
76
+ git: {
77
+ tag,
78
+ sha: commit,
79
+ },
80
+ date: new Date(parseInt(timestamp || '0', 10) * 1000),
81
+ isPrerelease: isPrerelease(tag),
82
+ semver,
83
+ })
84
+ } catch (e) {
85
+ // Skip tags that can't be resolved
86
+ console.warn(`Failed to get info for tag ${tag}:`, e)
87
+ }
88
+ }
89
+
90
+ // Sort by semver (newest first) - reverse of semverCompare
91
+ return versions.sort((a, b) => semverCompare(b.semver, a.semver))
92
+ }
93
+
94
+ /**
95
+ * Get dist-tag information (latest, next, etc.)
96
+ */
97
+ export async function getDistTag(tagName: string, repoPath?: string): Promise<DistTagInfo | null> {
98
+ const git = getGit(repoPath)
99
+ try {
100
+ const commit = await git.revparse([tagName])
101
+
102
+ // Find semver tag at this commit
103
+ const tags = await git.tag([`--points-at`, commit])
104
+ const semverTags = tags.split('\n').filter(isSemverTag)
105
+
106
+ return {
107
+ name: tagName,
108
+ commit: commit.trim(),
109
+ semverTag: semverTags[0],
110
+ }
111
+ } catch (e) {
112
+ return null
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Get the 'latest' dist-tag
118
+ */
119
+ export async function getDistTagLatest(repoPath?: string): Promise<DistTagInfo | null> {
120
+ return getDistTag('latest', repoPath)
121
+ }
122
+
123
+ /**
124
+ * Get all dist-tags
125
+ */
126
+ export async function getDistTags(repoPath?: string): Promise<DistTagInfo[]> {
127
+ const commonDistTags = ['latest', 'next', 'beta', 'alpha', 'canary']
128
+ const distTags: DistTagInfo[] = []
129
+
130
+ for (const tag of commonDistTags) {
131
+ const info = await getDistTag(tag, repoPath)
132
+ if (info) {
133
+ distTags.push(info)
134
+ }
135
+ }
136
+
137
+ return distTags
138
+ }
139
+
140
+ /**
141
+ * Get the latest stable version
142
+ */
143
+ export async function getLatestStableVersion(repoPath?: string): Promise<Version | null> {
144
+ const versions = await getVersions(repoPath)
145
+ return versions.find(v => !v.isPrerelease) || null
146
+ }
147
+
148
+ /**
149
+ * Get the latest prerelease version
150
+ */
151
+ export async function getLatestPrereleaseVersion(repoPath?: string): Promise<Version | null> {
152
+ const versions = await getVersions(repoPath)
153
+ return versions.find(v => v.isPrerelease) || null
154
+ }
155
+
156
+ /**
157
+ * Get version at a specific commit
158
+ */
159
+ export async function getVersionAtCommit(commit: string, repoPath?: string): Promise<Version | null> {
160
+ const git = getGit(repoPath)
161
+ const tags = await git.tag([`--points-at`, commit])
162
+ const semverTags = tags.split('\n').filter(isSemverTag)
163
+
164
+ if (semverTags.length === 0) return null
165
+
166
+ // Get full info for the first semver tag
167
+ const versions = await getVersions(repoPath)
168
+ return versions.find(v => v.git.tag === semverTags[0]) || null
169
+ }
170
+
171
+ /**
172
+ * Get deployment history for demos (versions that should have demos)
173
+ */
174
+ export async function getDeploymentHistory(minimumVersion?: string, repoPath?: string): Promise<Version[]> {
175
+ const versions = await getVersions(repoPath)
176
+
177
+ if (!minimumVersion) return versions
178
+
179
+ const minSemver = parseSemver(minimumVersion)
180
+ if (!minSemver) return versions
181
+
182
+ return versions.filter(v => semverCompare(v.semver, minSemver) >= 0)
183
+ }
184
+
185
+ /**
186
+ * Get the current development cycle: latest stable + all newer prereleases
187
+ */
188
+ export async function getCurrentDevelopmentCycle(repoPath?: string): Promise<DevelopmentCycle> {
189
+ const latestStable = await getLatestStableVersion(repoPath)
190
+ if (!latestStable) {
191
+ // No stable version yet, return all versions as prereleases
192
+ const allVersions = await getVersions(repoPath)
193
+ return {
194
+ stable: null,
195
+ prereleases: allVersions,
196
+ all: allVersions,
197
+ }
198
+ }
199
+
200
+ const allVersions = await getVersions(repoPath)
201
+ const prereleases = allVersions.filter(
202
+ v => v.isPrerelease && semverCompare(v.semver, latestStable.semver) > 0,
203
+ )
204
+
205
+ return {
206
+ stable: latestStable,
207
+ prereleases,
208
+ all: [latestStable, ...prereleases],
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Get versions since a specific version (inclusive)
214
+ */
215
+ export async function getVersionsSince(
216
+ sinceVersion: string,
217
+ skipVersions: string[] = [],
218
+ repoPath?: string,
219
+ ): Promise<Version[]> {
220
+ const sinceSemver = parseSemver(sinceVersion)
221
+ if (!sinceSemver) {
222
+ throw new Error(`Invalid version: ${sinceVersion}`)
223
+ }
224
+
225
+ const allVersions = await getVersions(repoPath)
226
+ return allVersions.filter(v => {
227
+ // Skip if in skip list
228
+ if (skipVersions.includes(v.git.tag)) return false
229
+ // Include if >= sinceVersion
230
+ return semverCompare(v.semver, sinceSemver) >= 0
231
+ })
232
+ }
233
+
234
+ /**
235
+ * Get all prereleases from past development cycles
236
+ *
237
+ * A development cycle is the set of prereleases between stable versions.
238
+ * This returns all prereleases that are not part of the current development cycle.
239
+ *
240
+ * Note: This only returns prereleases. Stable versions are not part of development cycles.
241
+ */
242
+ export async function getPastDevelopmentCycles(repoPath?: string): Promise<Version[]> {
243
+ const allVersions = await getVersions(repoPath)
244
+ const currentCycle = await getCurrentDevelopmentCycle(repoPath)
245
+ const currentCycleTags = new Set(currentCycle.all.map(v => v.git.tag))
246
+
247
+ // Return prereleases not in the current cycle
248
+ return allVersions.filter(v => {
249
+ return v.isPrerelease && !currentCycleTags.has(v.git.tag)
250
+ })
251
+ }
252
+
253
+ /**
254
+ * Get a complete registry of all versions and dist-tags
255
+ */
256
+ export async function getVersionCatalog(repoPath?: string): Promise<VersionCatalog> {
257
+ const [allVersions, distTagInfos] = await Promise.all([
258
+ getVersions(repoPath),
259
+ getDistTags(repoPath),
260
+ ])
261
+
262
+ // Map dist-tags to versions
263
+ const distTags: VersionCatalog['distTags'] = {}
264
+ for (const tagInfo of distTagInfos) {
265
+ if (tagInfo.semverTag) {
266
+ const version = allVersions.find(v => v.git.tag === tagInfo.semverTag)
267
+ if (version) {
268
+ distTags[tagInfo.name] = version
269
+ }
270
+ }
271
+ }
272
+
273
+ // Separate stable and prerelease versions
274
+ const stable = allVersions.filter(v => !v.isPrerelease)
275
+ const prerelease = allVersions.filter(v => v.isPrerelease)
276
+
277
+ return {
278
+ distTags,
279
+ versions: allVersions,
280
+ stable,
281
+ prerelease,
282
+ }
283
+ }
284
+
285
+ // Legacy class export for backward compatibility
286
+ // TODO: Remove this once all usages are migrated
287
+ export class VersionHistory {
288
+ static parseSemver = parseSemver
289
+ static isSemverTag = isSemverTag
290
+ static isPrerelease = isPrerelease
291
+ static isStableVersion = isStableVersion
292
+ static getDeploymentPath = getDeploymentPath
293
+ }
package/src/sandbox.ts ADDED
@@ -0,0 +1 @@
1
+ // Sandbox file for temporary testing
@@ -2,7 +2,7 @@ import type { FC } from 'react'
2
2
  import type { LinkProps as LinkPropsReactRouter } from 'react-router'
3
3
  import { Link as LinkReactRouter, useLocation } from 'react-router'
4
4
  // todo: #lib/kit-temp does not work as import
5
- import { ObjPartition } from '../../lib/kit-temp.js'
5
+ import { ObjPartition } from '../../lib/kit-temp.ts'
6
6
  import type { LinkPropsRadix } from './RadixLink.jsx'
7
7
  import { LinkRadix } from './RadixLink.jsx'
8
8