@package-broker/core 0.17.4 → 0.19.5

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 (334) hide show
  1. package/dist/cache/index.d.ts +0 -1
  2. package/dist/cache/index.d.ts.map +1 -1
  3. package/dist/cache/index.js +0 -1
  4. package/dist/cache/index.js.map +1 -1
  5. package/dist/cache/memory-driver.d.ts +1 -1
  6. package/dist/cache/memory-driver.d.ts.map +1 -1
  7. package/dist/cache/memory-driver.js +4 -2
  8. package/dist/cache/memory-driver.js.map +1 -1
  9. package/dist/db/create-database.d.ts +8 -0
  10. package/dist/db/create-database.d.ts.map +1 -0
  11. package/dist/db/create-database.js +13 -0
  12. package/dist/db/create-database.js.map +1 -0
  13. package/dist/db/index.d.ts +0 -1
  14. package/dist/db/index.d.ts.map +1 -1
  15. package/dist/db/index.js +0 -1
  16. package/dist/db/index.js.map +1 -1
  17. package/dist/db/schema.d.ts +557 -0
  18. package/dist/db/schema.d.ts.map +1 -1
  19. package/dist/db/schema.js +72 -2
  20. package/dist/db/schema.js.map +1 -1
  21. package/dist/factory.d.ts.map +1 -1
  22. package/dist/factory.js +22 -2
  23. package/dist/factory.js.map +1 -1
  24. package/dist/index.d.ts +2 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +2 -2
  27. package/dist/index.js.map +1 -1
  28. package/dist/jobs/processor.js +1 -1
  29. package/dist/jobs/processor.js.map +1 -1
  30. package/dist/kernel/container.d.ts +12 -0
  31. package/dist/kernel/container.d.ts.map +1 -0
  32. package/dist/kernel/container.js +43 -0
  33. package/dist/kernel/container.js.map +1 -0
  34. package/dist/kernel/events.d.ts +17 -0
  35. package/dist/kernel/events.d.ts.map +1 -0
  36. package/dist/kernel/events.js +54 -0
  37. package/dist/kernel/events.js.map +1 -0
  38. package/dist/kernel/hooks.d.ts +14 -0
  39. package/dist/kernel/hooks.d.ts.map +1 -0
  40. package/dist/kernel/hooks.js +31 -0
  41. package/dist/kernel/hooks.js.map +1 -0
  42. package/dist/kernel/index.d.ts +5 -0
  43. package/dist/kernel/index.d.ts.map +1 -0
  44. package/dist/kernel/index.js +5 -0
  45. package/dist/kernel/index.js.map +1 -0
  46. package/dist/kernel/plugin.d.ts +21 -0
  47. package/dist/kernel/plugin.d.ts.map +1 -0
  48. package/dist/kernel/plugin.js +30 -0
  49. package/dist/kernel/plugin.js.map +1 -0
  50. package/dist/middleware/auth.d.ts +2 -0
  51. package/dist/middleware/auth.d.ts.map +1 -1
  52. package/dist/middleware/auth.js +20 -5
  53. package/dist/middleware/auth.js.map +1 -1
  54. package/dist/modules/admin/admin.handlers.d.ts +1 -1
  55. package/dist/modules/admin/admin.handlers.d.ts.map +1 -1
  56. package/dist/modules/artifacts/artifacts.handlers.d.ts +1 -1
  57. package/dist/modules/artifacts/artifacts.handlers.d.ts.map +1 -1
  58. package/dist/modules/auth/auth.handlers.js +1 -1
  59. package/dist/modules/auth/auth.handlers.js.map +1 -1
  60. package/dist/modules/composer/index.d.ts.map +1 -1
  61. package/dist/modules/composer/index.js +5 -0
  62. package/dist/modules/composer/index.js.map +1 -1
  63. package/dist/modules/composer/tenant-composer.d.ts +32 -0
  64. package/dist/modules/composer/tenant-composer.d.ts.map +1 -0
  65. package/dist/modules/composer/tenant-composer.js +198 -0
  66. package/dist/modules/composer/tenant-composer.js.map +1 -0
  67. package/dist/modules/import/import.handlers.d.ts +4 -0
  68. package/dist/modules/import/import.handlers.d.ts.map +1 -0
  69. package/dist/modules/import/import.handlers.js +16 -0
  70. package/dist/modules/import/import.handlers.js.map +1 -0
  71. package/dist/{routes/api/openapi/settings.d.ts → modules/import/import.routes.d.ts} +20 -35
  72. package/dist/modules/import/import.routes.d.ts.map +1 -0
  73. package/dist/modules/import/import.routes.js +63 -0
  74. package/dist/modules/import/import.routes.js.map +1 -0
  75. package/dist/modules/import/index.d.ts +8 -0
  76. package/dist/modules/import/index.d.ts.map +1 -0
  77. package/dist/modules/import/index.js +8 -0
  78. package/dist/modules/import/index.js.map +1 -0
  79. package/dist/modules/organizations/index.d.ts +8 -0
  80. package/dist/modules/organizations/index.d.ts.map +1 -0
  81. package/dist/modules/organizations/index.js +22 -0
  82. package/dist/modules/organizations/index.js.map +1 -0
  83. package/dist/modules/organizations/organizations.handlers.d.ts +24 -0
  84. package/dist/modules/organizations/organizations.handlers.d.ts.map +1 -0
  85. package/dist/modules/organizations/organizations.handlers.js +278 -0
  86. package/dist/modules/organizations/organizations.handlers.js.map +1 -0
  87. package/dist/modules/organizations/organizations.routes.d.ts +596 -0
  88. package/dist/modules/organizations/organizations.routes.d.ts.map +1 -0
  89. package/dist/modules/organizations/organizations.routes.js +263 -0
  90. package/dist/modules/organizations/organizations.routes.js.map +1 -0
  91. package/dist/modules/packages/packages.handlers.d.ts +1 -1
  92. package/dist/modules/packages/packages.handlers.d.ts.map +1 -1
  93. package/dist/modules/packages/packages.handlers.js +3 -69
  94. package/dist/modules/packages/packages.handlers.js.map +1 -1
  95. package/dist/modules/repositories/repositories.handlers.d.ts +1 -1
  96. package/dist/modules/repositories/repositories.handlers.d.ts.map +1 -1
  97. package/dist/modules/repositories/repositories.handlers.js +74 -3
  98. package/dist/modules/repositories/repositories.handlers.js.map +1 -1
  99. package/dist/modules/repositories/repositories.routes.d.ts +12 -0
  100. package/dist/modules/repositories/repositories.routes.d.ts.map +1 -1
  101. package/dist/modules/system/index.d.ts.map +1 -1
  102. package/dist/modules/system/index.js +2 -1
  103. package/dist/modules/system/index.js.map +1 -1
  104. package/dist/modules/system/system.handlers.d.ts +11 -1
  105. package/dist/modules/system/system.handlers.d.ts.map +1 -1
  106. package/dist/modules/system/system.handlers.js +31 -1
  107. package/dist/modules/system/system.handlers.js.map +1 -1
  108. package/dist/modules/system/system.routes.d.ts +34 -4
  109. package/dist/modules/system/system.routes.d.ts.map +1 -1
  110. package/dist/modules/system/system.routes.js +21 -1
  111. package/dist/modules/system/system.routes.js.map +1 -1
  112. package/dist/modules/tenants/index.d.ts +8 -0
  113. package/dist/modules/tenants/index.d.ts.map +1 -0
  114. package/dist/modules/tenants/index.js +21 -0
  115. package/dist/modules/tenants/index.js.map +1 -0
  116. package/dist/modules/tenants/tenants.handlers.d.ts +24 -0
  117. package/dist/modules/tenants/tenants.handlers.d.ts.map +1 -0
  118. package/dist/modules/tenants/tenants.handlers.js +268 -0
  119. package/dist/modules/tenants/tenants.handlers.js.map +1 -0
  120. package/dist/modules/tenants/tenants.routes.d.ts +486 -0
  121. package/dist/modules/tenants/tenants.routes.d.ts.map +1 -0
  122. package/dist/modules/tenants/tenants.routes.js +227 -0
  123. package/dist/modules/tenants/tenants.routes.js.map +1 -0
  124. package/dist/modules/tokens/tokens.handlers.d.ts +1 -1
  125. package/dist/modules/tokens/tokens.handlers.d.ts.map +1 -1
  126. package/dist/modules/users/users.handlers.d.ts +1 -1
  127. package/dist/modules/users/users.handlers.d.ts.map +1 -1
  128. package/dist/modules/users/users.handlers.js +1 -1
  129. package/dist/modules/users/users.handlers.js.map +1 -1
  130. package/dist/plugins/security-advisories/advisory-db.d.ts +85 -0
  131. package/dist/plugins/security-advisories/advisory-db.d.ts.map +1 -0
  132. package/dist/plugins/security-advisories/advisory-db.js +161 -0
  133. package/dist/plugins/security-advisories/advisory-db.js.map +1 -0
  134. package/dist/plugins/security-advisories/advisory-service.d.ts +44 -0
  135. package/dist/plugins/security-advisories/advisory-service.d.ts.map +1 -0
  136. package/dist/plugins/security-advisories/advisory-service.js +122 -0
  137. package/dist/plugins/security-advisories/advisory-service.js.map +1 -0
  138. package/dist/plugins/security-advisories/advisory.handlers.d.ts +13 -0
  139. package/dist/plugins/security-advisories/advisory.handlers.d.ts.map +1 -0
  140. package/dist/plugins/security-advisories/advisory.handlers.js +87 -0
  141. package/dist/plugins/security-advisories/advisory.handlers.js.map +1 -0
  142. package/dist/plugins/security-advisories/advisory.module.d.ts +4 -0
  143. package/dist/plugins/security-advisories/advisory.module.d.ts.map +1 -0
  144. package/dist/plugins/security-advisories/advisory.module.js +13 -0
  145. package/dist/plugins/security-advisories/advisory.module.js.map +1 -0
  146. package/dist/plugins/security-advisories/advisory.routes.d.ts +73 -0
  147. package/dist/plugins/security-advisories/advisory.routes.d.ts.map +1 -0
  148. package/dist/plugins/security-advisories/advisory.routes.js +76 -0
  149. package/dist/plugins/security-advisories/advisory.routes.js.map +1 -0
  150. package/dist/plugins/security-advisories/index.d.ts +31 -0
  151. package/dist/plugins/security-advisories/index.d.ts.map +1 -0
  152. package/dist/plugins/security-advisories/index.js +100 -0
  153. package/dist/plugins/security-advisories/index.js.map +1 -0
  154. package/dist/ports.d.ts +39 -21
  155. package/dist/ports.d.ts.map +1 -1
  156. package/dist/queue/consumer.js +2 -2
  157. package/dist/queue/consumer.js.map +1 -1
  158. package/dist/queue/memory-driver.d.ts +3 -2
  159. package/dist/queue/memory-driver.d.ts.map +1 -1
  160. package/dist/queue/memory-driver.js.map +1 -1
  161. package/dist/routes/composer.d.ts.map +1 -1
  162. package/dist/routes/composer.js +71 -19
  163. package/dist/routes/composer.js.map +1 -1
  164. package/dist/routes/dist.d.ts.map +1 -1
  165. package/dist/routes/dist.js +26 -80
  166. package/dist/routes/dist.js.map +1 -1
  167. package/dist/routes/index.d.ts +0 -1
  168. package/dist/routes/index.d.ts.map +1 -1
  169. package/dist/routes/index.js +0 -1
  170. package/dist/routes/index.js.map +1 -1
  171. package/dist/services/GitHubOrgImporter.d.ts +21 -0
  172. package/dist/services/GitHubOrgImporter.d.ts.map +1 -0
  173. package/dist/services/GitHubOrgImporter.js +51 -0
  174. package/dist/services/GitHubOrgImporter.js.map +1 -0
  175. package/dist/services/TokenScopeService.d.ts +15 -0
  176. package/dist/services/TokenScopeService.d.ts.map +1 -0
  177. package/dist/services/TokenScopeService.js +42 -0
  178. package/dist/services/TokenScopeService.js.map +1 -0
  179. package/dist/storage/index.d.ts +0 -1
  180. package/dist/storage/index.d.ts.map +1 -1
  181. package/dist/storage/index.js +0 -1
  182. package/dist/storage/index.js.map +1 -1
  183. package/dist/sync/repository-sync.d.ts.map +1 -1
  184. package/dist/sync/repository-sync.js +35 -23
  185. package/dist/sync/repository-sync.js.map +1 -1
  186. package/dist/sync/strategies/git-ssh.d.ts +17 -0
  187. package/dist/sync/strategies/git-ssh.d.ts.map +1 -0
  188. package/dist/sync/strategies/git-ssh.js +325 -0
  189. package/dist/sync/strategies/git-ssh.js.map +1 -0
  190. package/dist/{routes/api/types.d.ts → types/openapi.d.ts} +3 -4
  191. package/dist/types/openapi.d.ts.map +1 -0
  192. package/dist/{routes/api/types.js → types/openapi.js} +1 -1
  193. package/dist/types/openapi.js.map +1 -0
  194. package/dist/utils/background.d.ts +7 -0
  195. package/dist/utils/background.d.ts.map +1 -0
  196. package/dist/utils/background.js +11 -0
  197. package/dist/utils/background.js.map +1 -0
  198. package/dist/utils/environment.d.ts +15 -0
  199. package/dist/utils/environment.d.ts.map +1 -0
  200. package/dist/utils/environment.js +38 -0
  201. package/dist/utils/environment.js.map +1 -0
  202. package/dist/utils/index.d.ts +1 -0
  203. package/dist/utils/index.d.ts.map +1 -1
  204. package/dist/utils/index.js +1 -0
  205. package/dist/utils/index.js.map +1 -1
  206. package/dist/utils/package-filter.d.ts +7 -0
  207. package/dist/utils/package-filter.d.ts.map +1 -0
  208. package/dist/utils/package-filter.js +23 -0
  209. package/dist/utils/package-filter.js.map +1 -0
  210. package/dist/utils/package-validator.d.ts +3 -3
  211. package/dist/utils/package-validator.d.ts.map +1 -1
  212. package/dist/utils/package-validator.js +4 -37
  213. package/dist/utils/package-validator.js.map +1 -1
  214. package/dist/utils/upstream-fetch.d.ts +8 -0
  215. package/dist/utils/upstream-fetch.d.ts.map +1 -1
  216. package/dist/utils/upstream-fetch.js +42 -0
  217. package/dist/utils/upstream-fetch.js.map +1 -1
  218. package/dist/utils/zip-utils.d.ts +13 -0
  219. package/dist/utils/zip-utils.d.ts.map +1 -0
  220. package/dist/utils/zip-utils.js +66 -0
  221. package/dist/utils/zip-utils.js.map +1 -0
  222. package/dist/vcs/bitbucket-provider.d.ts +19 -0
  223. package/dist/vcs/bitbucket-provider.d.ts.map +1 -0
  224. package/dist/vcs/bitbucket-provider.js +249 -0
  225. package/dist/vcs/bitbucket-provider.js.map +1 -0
  226. package/dist/vcs/github-provider.d.ts +16 -0
  227. package/dist/vcs/github-provider.d.ts.map +1 -0
  228. package/dist/vcs/github-provider.js +117 -0
  229. package/dist/vcs/github-provider.js.map +1 -0
  230. package/dist/vcs/gitlab-provider.d.ts +17 -0
  231. package/dist/vcs/gitlab-provider.d.ts.map +1 -0
  232. package/dist/vcs/gitlab-provider.js +216 -0
  233. package/dist/vcs/gitlab-provider.js.map +1 -0
  234. package/dist/vcs/index.d.ts +10 -0
  235. package/dist/vcs/index.d.ts.map +1 -0
  236. package/dist/vcs/index.js +24 -0
  237. package/dist/vcs/index.js.map +1 -0
  238. package/dist/vcs/registry.d.ts +32 -0
  239. package/dist/vcs/registry.d.ts.map +1 -0
  240. package/dist/vcs/registry.js +47 -0
  241. package/dist/vcs/registry.js.map +1 -0
  242. package/dist/workflows/package-storage.d.ts.map +1 -1
  243. package/dist/workflows/package-storage.js +3 -3
  244. package/dist/workflows/package-storage.js.map +1 -1
  245. package/package.json +11 -8
  246. package/dist/cache/kv-driver.d.ts +0 -16
  247. package/dist/cache/kv-driver.d.ts.map +0 -1
  248. package/dist/cache/kv-driver.js +0 -23
  249. package/dist/cache/kv-driver.js.map +0 -1
  250. package/dist/db/d1-driver.d.ts +0 -3
  251. package/dist/db/d1-driver.d.ts.map +0 -1
  252. package/dist/db/d1-driver.js +0 -7
  253. package/dist/db/d1-driver.js.map +0 -1
  254. package/dist/routes/api/artifacts.d.ts +0 -27
  255. package/dist/routes/api/artifacts.d.ts.map +0 -1
  256. package/dist/routes/api/artifacts.js +0 -57
  257. package/dist/routes/api/artifacts.js.map +0 -1
  258. package/dist/routes/api/auth.d.ts +0 -52
  259. package/dist/routes/api/auth.d.ts.map +0 -1
  260. package/dist/routes/api/auth.js +0 -277
  261. package/dist/routes/api/auth.js.map +0 -1
  262. package/dist/routes/api/index.d.ts +0 -10
  263. package/dist/routes/api/index.d.ts.map +0 -1
  264. package/dist/routes/api/index.js +0 -11
  265. package/dist/routes/api/index.js.map +0 -1
  266. package/dist/routes/api/openapi/artifacts.d.ts +0 -80
  267. package/dist/routes/api/openapi/artifacts.d.ts.map +0 -1
  268. package/dist/routes/api/openapi/artifacts.js +0 -73
  269. package/dist/routes/api/openapi/artifacts.js.map +0 -1
  270. package/dist/routes/api/openapi/auth.d.ts +0 -187
  271. package/dist/routes/api/openapi/auth.d.ts.map +0 -1
  272. package/dist/routes/api/openapi/auth.js +0 -135
  273. package/dist/routes/api/openapi/auth.js.map +0 -1
  274. package/dist/routes/api/openapi/health.d.ts +0 -23
  275. package/dist/routes/api/openapi/health.d.ts.map +0 -1
  276. package/dist/routes/api/openapi/health.js +0 -25
  277. package/dist/routes/api/openapi/health.js.map +0 -1
  278. package/dist/routes/api/openapi/index.d.ts +0 -10
  279. package/dist/routes/api/openapi/index.d.ts.map +0 -1
  280. package/dist/routes/api/openapi/index.js +0 -16
  281. package/dist/routes/api/openapi/index.js.map +0 -1
  282. package/dist/routes/api/openapi/packages.d.ts +0 -172
  283. package/dist/routes/api/openapi/packages.d.ts.map +0 -1
  284. package/dist/routes/api/openapi/packages.js +0 -126
  285. package/dist/routes/api/openapi/packages.js.map +0 -1
  286. package/dist/routes/api/openapi/repositories.d.ts +0 -451
  287. package/dist/routes/api/openapi/repositories.d.ts.map +0 -1
  288. package/dist/routes/api/openapi/repositories.js +0 -238
  289. package/dist/routes/api/openapi/repositories.js.map +0 -1
  290. package/dist/routes/api/openapi/settings.d.ts.map +0 -1
  291. package/dist/routes/api/openapi/settings.js +0 -72
  292. package/dist/routes/api/openapi/settings.js.map +0 -1
  293. package/dist/routes/api/openapi/stats.d.ts +0 -59
  294. package/dist/routes/api/openapi/stats.d.ts.map +0 -1
  295. package/dist/routes/api/openapi/stats.js +0 -53
  296. package/dist/routes/api/openapi/stats.js.map +0 -1
  297. package/dist/routes/api/openapi/tokens.d.ts +0 -202
  298. package/dist/routes/api/openapi/tokens.d.ts.map +0 -1
  299. package/dist/routes/api/openapi/tokens.js +0 -132
  300. package/dist/routes/api/openapi/tokens.js.map +0 -1
  301. package/dist/routes/api/openapi/users.d.ts +0 -190
  302. package/dist/routes/api/openapi/users.d.ts.map +0 -1
  303. package/dist/routes/api/openapi/users.js +0 -126
  304. package/dist/routes/api/openapi/users.js.map +0 -1
  305. package/dist/routes/api/packages.d.ts +0 -50
  306. package/dist/routes/api/packages.d.ts.map +0 -1
  307. package/dist/routes/api/packages.js +0 -708
  308. package/dist/routes/api/packages.js.map +0 -1
  309. package/dist/routes/api/repositories.d.ts +0 -58
  310. package/dist/routes/api/repositories.d.ts.map +0 -1
  311. package/dist/routes/api/repositories.js +0 -321
  312. package/dist/routes/api/repositories.js.map +0 -1
  313. package/dist/routes/api/settings.d.ts +0 -29
  314. package/dist/routes/api/settings.d.ts.map +0 -1
  315. package/dist/routes/api/settings.js +0 -81
  316. package/dist/routes/api/settings.js.map +0 -1
  317. package/dist/routes/api/stats.d.ts +0 -21
  318. package/dist/routes/api/stats.d.ts.map +0 -1
  319. package/dist/routes/api/stats.js +0 -51
  320. package/dist/routes/api/stats.js.map +0 -1
  321. package/dist/routes/api/tokens.d.ts +0 -40
  322. package/dist/routes/api/tokens.d.ts.map +0 -1
  323. package/dist/routes/api/tokens.js +0 -187
  324. package/dist/routes/api/tokens.js.map +0 -1
  325. package/dist/routes/api/types.d.ts.map +0 -1
  326. package/dist/routes/api/types.js.map +0 -1
  327. package/dist/routes/api/users.d.ts +0 -6
  328. package/dist/routes/api/users.d.ts.map +0 -1
  329. package/dist/routes/api/users.js +0 -115
  330. package/dist/routes/api/users.js.map +0 -1
  331. package/dist/storage/r2-driver.d.ts +0 -16
  332. package/dist/storage/r2-driver.d.ts.map +0 -1
  333. package/dist/storage/r2-driver.js +0 -28
  334. package/dist/storage/r2-driver.js.map +0 -1
@@ -0,0 +1,249 @@
1
+ /*
2
+ * PACKAGE.broker
3
+ * Copyright (C) 2025 Łukasz Bajsarowicz
4
+ * Licensed under AGPL-3.0
5
+ */
6
+ import { COMPOSER_USER_AGENT } from '@package-broker/shared';
7
+ import pRetry from 'p-retry';
8
+ import { getLogger } from '../utils/logger';
9
+ import semver from 'semver';
10
+ const BITBUCKET_CLOUD_PATTERN = /bitbucket\.org\/([^/]+)\/([^/.]+)/;
11
+ export class BitbucketProvider {
12
+ name = 'bitbucket';
13
+ async discoverPackages(org, token, filter) {
14
+ const logger = getLogger();
15
+ const packages = [];
16
+ try {
17
+ // List repositories in the workspace
18
+ const repos = await this.listWorkspaceRepos(org, token);
19
+ for (const repo of repos) {
20
+ // Check if repo has a composer.json
21
+ const composerJson = await this.fetchComposerJson(org, repo.slug, token);
22
+ if (!composerJson?.name)
23
+ continue;
24
+ if (filter && !composerJson.name.toLowerCase().includes(filter.toLowerCase())) {
25
+ continue;
26
+ }
27
+ // Get tags as versions
28
+ const tags = await this.fetchTags(org, repo.slug, { token });
29
+ const versions = tags
30
+ .map((tag) => semver.clean(tag.name) || tag.name)
31
+ .filter((v) => semver.valid(v));
32
+ packages.push({
33
+ name: composerJson.name,
34
+ versions,
35
+ source: 'bitbucket_api',
36
+ });
37
+ }
38
+ }
39
+ catch (err) {
40
+ logger.error('Bitbucket package discovery error', { org }, err instanceof Error ? err : new Error(String(err)));
41
+ }
42
+ return packages;
43
+ }
44
+ async fetchPackageMetadata(repoUrl, token) {
45
+ const match = repoUrl.match(BITBUCKET_CLOUD_PATTERN);
46
+ if (!match)
47
+ return null;
48
+ const [, workspace, repoSlug] = match;
49
+ const composerJson = await this.fetchComposerJson(workspace, repoSlug, token);
50
+ if (!composerJson?.name)
51
+ return null;
52
+ return {
53
+ name: composerJson.name,
54
+ description: composerJson.description,
55
+ versions: {},
56
+ };
57
+ }
58
+ async verifyCredentials(url, credentialType, credentials) {
59
+ const validTypes = [
60
+ 'bitbucket_app_password',
61
+ 'bitbucket_api_token',
62
+ 'bitbucket_api_key',
63
+ 'bitbucket_server_pat',
64
+ 'none',
65
+ ];
66
+ if (!validTypes.includes(credentialType)) {
67
+ return false;
68
+ }
69
+ const parsed = this.parseCredentials(credentials);
70
+ const headers = this.buildHeaders(credentialType, parsed);
71
+ try {
72
+ const response = await fetch('https://api.bitbucket.org/2.0/user', { headers });
73
+ return response.ok;
74
+ }
75
+ catch {
76
+ return false;
77
+ }
78
+ }
79
+ /**
80
+ * Sync a Bitbucket repository by fetching composer.json and discovering versions via tags.
81
+ */
82
+ async syncRepository(url, credentials, credentialType, composerJsonPath) {
83
+ const logger = getLogger();
84
+ const match = url.match(BITBUCKET_CLOUD_PATTERN);
85
+ if (!match) {
86
+ return { success: false, packages: [], error: 'invalid_bitbucket_url' };
87
+ }
88
+ const [, workspace, repoSlug] = match;
89
+ const headers = this.buildHeaders(credentialType, credentials);
90
+ try {
91
+ // Get repo info for default branch
92
+ const repoResponse = await pRetry(() => fetch(`https://api.bitbucket.org/2.0/repositories/${encodeURIComponent(workspace)}/${encodeURIComponent(repoSlug)}`, {
93
+ headers,
94
+ }), { retries: 2 });
95
+ if (!repoResponse.ok) {
96
+ if (repoResponse.status === 401 || repoResponse.status === 403) {
97
+ return { success: false, packages: [], error: 'auth_failed' };
98
+ }
99
+ if (repoResponse.status === 404) {
100
+ return { success: false, packages: [], error: 'repo_not_found' };
101
+ }
102
+ return { success: false, packages: [], error: `bitbucket_api_${repoResponse.status}` };
103
+ }
104
+ const repoInfo = (await repoResponse.json());
105
+ const defaultBranch = repoInfo.mainbranch?.name || 'main';
106
+ // Fetch composer.json
107
+ const composerPath = composerJsonPath || 'composer.json';
108
+ const composerResponse = await pRetry(() => fetch(`https://api.bitbucket.org/2.0/repositories/${encodeURIComponent(workspace)}/${encodeURIComponent(repoSlug)}/src/${encodeURIComponent(defaultBranch)}/${encodeURIComponent(composerPath)}`, { headers }), { retries: 2 });
109
+ if (!composerResponse.ok) {
110
+ return { success: false, packages: [], error: 'no_composer_json_found' };
111
+ }
112
+ const composerJson = (await composerResponse.json());
113
+ if (!composerJson.name) {
114
+ return { success: false, packages: [], error: 'no_valid_composer_json' };
115
+ }
116
+ // Fetch tags for version discovery
117
+ const tags = await this.fetchTags(workspace, repoSlug, credentials, credentialType);
118
+ const packages = [];
119
+ // Dev branch package
120
+ packages.push({
121
+ name: composerJson.name,
122
+ version: `dev-${defaultBranch}`,
123
+ description: composerJson.description,
124
+ license: composerJson.license,
125
+ type: composerJson.type,
126
+ homepage: composerJson.homepage || repoInfo.links.html.href,
127
+ require: composerJson.require,
128
+ 'require-dev': composerJson['require-dev'],
129
+ dist: {
130
+ type: 'zip',
131
+ url: `https://bitbucket.org/${encodeURIComponent(workspace)}/${encodeURIComponent(repoSlug)}/get/${encodeURIComponent(defaultBranch)}.zip`,
132
+ reference: defaultBranch,
133
+ },
134
+ });
135
+ // Tagged version packages
136
+ for (const tag of tags) {
137
+ const version = semver.clean(tag.name) || tag.name;
138
+ if (!semver.valid(version))
139
+ continue;
140
+ packages.push({
141
+ name: composerJson.name,
142
+ version,
143
+ description: composerJson.description,
144
+ license: composerJson.license,
145
+ type: composerJson.type,
146
+ homepage: composerJson.homepage || repoInfo.links.html.href,
147
+ require: composerJson.require,
148
+ 'require-dev': composerJson['require-dev'],
149
+ dist: {
150
+ type: 'zip',
151
+ url: `https://bitbucket.org/${encodeURIComponent(workspace)}/${encodeURIComponent(repoSlug)}/get/${encodeURIComponent(tag.name)}.zip`,
152
+ reference: tag.target.hash,
153
+ },
154
+ time: tag.target.date,
155
+ });
156
+ }
157
+ logger.info('Bitbucket sync completed', {
158
+ workspace,
159
+ repo: repoSlug,
160
+ packageCount: packages.length,
161
+ tagCount: tags.length,
162
+ });
163
+ return { success: true, packages, strategy: 'bitbucket_api' };
164
+ }
165
+ catch (err) {
166
+ logger.error('Bitbucket sync error', { workspace, repo: repoSlug }, err instanceof Error ? err : new Error(String(err)));
167
+ return { success: false, packages: [], error: 'network_error' };
168
+ }
169
+ }
170
+ matchesUrl(url) {
171
+ return BITBUCKET_CLOUD_PATTERN.test(url);
172
+ }
173
+ async listWorkspaceRepos(workspace, token) {
174
+ const headers = this.buildHeaders('bitbucket_app_password', { token });
175
+ const response = await pRetry(() => fetch(`https://api.bitbucket.org/2.0/repositories/${encodeURIComponent(workspace)}?pagelen=100`, { headers }), { retries: 2 });
176
+ if (!response.ok)
177
+ return [];
178
+ const data = (await response.json());
179
+ return data.values;
180
+ }
181
+ async fetchComposerJson(workspace, repoSlug, token, credentialType = 'bitbucket_app_password') {
182
+ const headers = this.buildHeaders(credentialType, { token });
183
+ try {
184
+ const response = await pRetry(() => fetch(`https://api.bitbucket.org/2.0/repositories/${encodeURIComponent(workspace)}/${encodeURIComponent(repoSlug)}/src/HEAD/composer.json`, { headers }), { retries: 2 });
185
+ if (!response.ok)
186
+ return null;
187
+ return (await response.json());
188
+ }
189
+ catch {
190
+ return null;
191
+ }
192
+ }
193
+ async fetchTags(workspace, repoSlug, credentials, credentialType = 'bitbucket_app_password') {
194
+ const headers = this.buildHeaders(credentialType, credentials);
195
+ try {
196
+ const response = await pRetry(() => fetch(`https://api.bitbucket.org/2.0/repositories/${encodeURIComponent(workspace)}/${encodeURIComponent(repoSlug)}/refs/tags?pagelen=100`, { headers }), { retries: 2 });
197
+ if (!response.ok)
198
+ return [];
199
+ const data = (await response.json());
200
+ return data.values;
201
+ }
202
+ catch {
203
+ return [];
204
+ }
205
+ }
206
+ buildHeaders(credentialType, credentials) {
207
+ const headers = {
208
+ Accept: 'application/json',
209
+ 'User-Agent': COMPOSER_USER_AGENT,
210
+ };
211
+ switch (credentialType) {
212
+ case 'bitbucket_app_password': {
213
+ const username = credentials.username || '';
214
+ const password = credentials.password || credentials.token || '';
215
+ if (username && password) {
216
+ headers['Authorization'] = `Basic ${btoa(`${username}:${password}`)}`;
217
+ }
218
+ break;
219
+ }
220
+ case 'bitbucket_api_token':
221
+ case 'bitbucket_server_pat': {
222
+ const token = credentials.token || '';
223
+ if (token) {
224
+ headers['Authorization'] = `Bearer ${token}`;
225
+ }
226
+ break;
227
+ }
228
+ case 'bitbucket_api_key': {
229
+ const key = credentials.key || '';
230
+ if (key) {
231
+ headers['Authorization'] = `Basic ${btoa(`${key}:`)}`;
232
+ }
233
+ break;
234
+ }
235
+ case 'none':
236
+ break;
237
+ }
238
+ return headers;
239
+ }
240
+ parseCredentials(credentials) {
241
+ try {
242
+ return JSON.parse(credentials);
243
+ }
244
+ catch {
245
+ return { token: credentials };
246
+ }
247
+ }
248
+ }
249
+ //# sourceMappingURL=bitbucket-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bitbucket-provider.js","sourceRoot":"","sources":["../../src/vcs/bitbucket-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { VcsProviderPort, DiscoveredPackage, PackageMetadata } from '../ports';
2
+ import type { SyncResult } from '../sync/types';
3
+ export declare class GitHubProvider implements VcsProviderPort {
4
+ readonly name = "github";
5
+ discoverPackages(org: string, token: string, filter?: string): Promise<DiscoveredPackage[]>;
6
+ fetchPackageMetadata(repoUrl: string, token: string): Promise<PackageMetadata | null>;
7
+ verifyCredentials(url: string, credentialType: string, credentials: string): Promise<boolean>;
8
+ /**
9
+ * Sync a GitHub repository using the existing strategy-based sync.
10
+ * This bridges the VcsProviderPort interface with the current sync implementation.
11
+ */
12
+ syncRepository(url: string, credentials: Record<string, string>, credentialType: string, composerJsonPath?: string): Promise<SyncResult>;
13
+ matchesUrl(url: string): boolean;
14
+ private parseCredentials;
15
+ }
16
+ //# sourceMappingURL=github-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-provider.d.ts","sourceRoot":"","sources":["../../src/vcs/github-provider.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AACpF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAOhD,qBAAa,cAAe,YAAW,eAAe;IACpD,QAAQ,CAAC,IAAI,YAAY;IAEnB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAkC3F,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAuCrF,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA+BnG;;;OAGG;IACG,cAAc,CAClB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,cAAc,EAAE,MAAM,EACtB,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC,UAAU,CAAC;IAkBtB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIhC,OAAO,CAAC,gBAAgB;CAOzB"}
@@ -0,0 +1,117 @@
1
+ /*
2
+ * PACKAGE.broker
3
+ * Copyright (C) 2025 Łukasz Bajsarowicz
4
+ * Licensed under AGPL-3.0
5
+ */
6
+ import { syncGitHubRepository } from '../sync/github-sync';
7
+ import { COMPOSER_USER_AGENT } from '@package-broker/shared';
8
+ import pRetry from 'p-retry';
9
+ const GITHUB_URL_PATTERN = /github\.com[:/]([^/]+)\/([^/.]+)/;
10
+ export class GitHubProvider {
11
+ name = 'github';
12
+ async discoverPackages(org, token, filter) {
13
+ const url = `https://composer.pkg.github.com/${encodeURIComponent(org)}/packages.json`;
14
+ const response = await pRetry(() => fetch(url, {
15
+ headers: {
16
+ Authorization: `Bearer ${token}`,
17
+ Accept: 'application/json',
18
+ 'User-Agent': COMPOSER_USER_AGENT,
19
+ },
20
+ }), { retries: 3 });
21
+ if (!response.ok) {
22
+ return [];
23
+ }
24
+ const data = (await response.json());
25
+ const packages = [];
26
+ for (const [name, versions] of Object.entries(data.packages || {})) {
27
+ if (filter && !name.toLowerCase().includes(filter.toLowerCase())) {
28
+ continue;
29
+ }
30
+ packages.push({ name, versions: Object.keys(versions), source: 'github_packages' });
31
+ }
32
+ return packages;
33
+ }
34
+ async fetchPackageMetadata(repoUrl, token) {
35
+ const match = repoUrl.match(GITHUB_URL_PATTERN);
36
+ if (!match)
37
+ return null;
38
+ const [, owner, repo] = match;
39
+ const headers = {
40
+ Accept: 'application/vnd.github.raw+json',
41
+ 'User-Agent': 'PackageBroker/1.0',
42
+ 'X-GitHub-Api-Version': '2022-11-28',
43
+ };
44
+ if (token) {
45
+ headers['Authorization'] = `Bearer ${token}`;
46
+ }
47
+ const response = await pRetry(() => fetch(`https://api.github.com/repos/${owner}/${repo}/contents/composer.json`, {
48
+ headers,
49
+ }), { retries: 2 });
50
+ if (!response.ok)
51
+ return null;
52
+ const composerJson = (await response.json());
53
+ if (!composerJson.name)
54
+ return null;
55
+ return {
56
+ name: composerJson.name,
57
+ description: composerJson.description,
58
+ versions: {},
59
+ };
60
+ }
61
+ async verifyCredentials(url, credentialType, credentials) {
62
+ if (credentialType !== 'github_token' && credentialType !== 'none') {
63
+ return false;
64
+ }
65
+ const parsed = this.parseCredentials(credentials);
66
+ const token = parsed.token || '';
67
+ const headers = {
68
+ Accept: 'application/vnd.github+json',
69
+ 'User-Agent': 'PackageBroker/1.0',
70
+ 'X-GitHub-Api-Version': '2022-11-28',
71
+ };
72
+ if (token) {
73
+ headers['Authorization'] = `Bearer ${token}`;
74
+ }
75
+ try {
76
+ const match = url.match(GITHUB_URL_PATTERN);
77
+ const apiUrl = match
78
+ ? `https://api.github.com/repos/${match[1]}/${match[2]}`
79
+ : 'https://api.github.com/user';
80
+ const response = await fetch(apiUrl, { headers });
81
+ return response.ok;
82
+ }
83
+ catch {
84
+ return false;
85
+ }
86
+ }
87
+ /**
88
+ * Sync a GitHub repository using the existing strategy-based sync.
89
+ * This bridges the VcsProviderPort interface with the current sync implementation.
90
+ */
91
+ async syncRepository(url, credentials, credentialType, composerJsonPath) {
92
+ const match = url.match(GITHUB_URL_PATTERN);
93
+ if (!match) {
94
+ return { success: false, packages: [], error: 'invalid_github_url' };
95
+ }
96
+ const [, owner, repo] = match;
97
+ const token = credentialType === 'none' ? null : credentials.token || credentials.password || '';
98
+ return syncGitHubRepository({
99
+ owner,
100
+ repo: repo.replace('.git', ''),
101
+ token,
102
+ composerJsonPath,
103
+ });
104
+ }
105
+ matchesUrl(url) {
106
+ return GITHUB_URL_PATTERN.test(url);
107
+ }
108
+ parseCredentials(credentials) {
109
+ try {
110
+ return JSON.parse(credentials);
111
+ }
112
+ catch {
113
+ return { token: credentials };
114
+ }
115
+ }
116
+ }
117
+ //# sourceMappingURL=github-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-provider.js","sourceRoot":"","sources":["../../src/vcs/github-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { VcsProviderPort, DiscoveredPackage, PackageMetadata } from '../ports';
2
+ import type { SyncResult } from '../sync/types';
3
+ export declare class GitLabProvider implements VcsProviderPort {
4
+ readonly name = "gitlab";
5
+ discoverPackages(org: string, token: string, filter?: string): Promise<DiscoveredPackage[]>;
6
+ fetchPackageMetadata(repoUrl: string, token: string): Promise<PackageMetadata | null>;
7
+ verifyCredentials(url: string, credentialType: string, credentials: string): Promise<boolean>;
8
+ /**
9
+ * Sync a GitLab repository by fetching composer.json from the repo and tags for versions.
10
+ */
11
+ syncRepository(url: string, credentials: Record<string, string>, credentialType: string, composerJsonPath?: string): Promise<SyncResult>;
12
+ matchesUrl(url: string): boolean;
13
+ private parseUrl;
14
+ private buildHeaders;
15
+ private parseCredentials;
16
+ }
17
+ //# sourceMappingURL=gitlab-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitlab-provider.d.ts","sourceRoot":"","sources":["../../src/vcs/gitlab-provider.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AACpF,OAAO,KAAK,EAAE,UAAU,EAAmB,MAAM,eAAe,CAAC;AAuBjE,qBAAa,cAAe,YAAW,eAAe;IACpD,QAAQ,CAAC,IAAI,YAAY;IAEnB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAmD3F,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IA8CrF,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAmBnG;;OAEG;IACG,cAAc,CAClB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,cAAc,EAAE,MAAM,EACtB,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC,UAAU,CAAC;IAmItB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIhC,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,gBAAgB;CAOzB"}
@@ -0,0 +1,216 @@
1
+ /*
2
+ * PACKAGE.broker
3
+ * Copyright (C) 2025 Łukasz Bajsarowicz
4
+ * Licensed under AGPL-3.0
5
+ */
6
+ import { COMPOSER_USER_AGENT } from '@package-broker/shared';
7
+ import pRetry from 'p-retry';
8
+ import { getLogger } from '../utils/logger';
9
+ import semver from 'semver';
10
+ // Only match gitlab.com — self-hosted instances are not supported to prevent SSRF.
11
+ // Self-hosted GitLab support would require an explicit allowlist.
12
+ const GITLAB_URL_PATTERN = /gitlab\.com[:/]([^/]+(?:\/[^/]+)*)\/([^/.]+)/;
13
+ export class GitLabProvider {
14
+ name = 'gitlab';
15
+ async discoverPackages(org, token, filter) {
16
+ const logger = getLogger();
17
+ const packages = [];
18
+ // GitLab Groups have a Composer package registry
19
+ const url = `https://gitlab.com/api/v4/groups/${encodeURIComponent(org)}/packages?package_type=composer&per_page=100`;
20
+ try {
21
+ const response = await pRetry(() => fetch(url, {
22
+ headers: this.buildHeaders(token),
23
+ }), { retries: 3 });
24
+ if (!response.ok) {
25
+ logger.warn('GitLab package discovery failed', { org, status: response.status });
26
+ return [];
27
+ }
28
+ const data = (await response.json());
29
+ // Group versions by package name
30
+ const packageMap = new Map();
31
+ for (const pkg of data) {
32
+ if (filter && !pkg.name.toLowerCase().includes(filter.toLowerCase())) {
33
+ continue;
34
+ }
35
+ const versions = packageMap.get(pkg.name) || [];
36
+ versions.push(pkg.version);
37
+ packageMap.set(pkg.name, versions);
38
+ }
39
+ for (const [name, versions] of packageMap) {
40
+ packages.push({ name, versions, source: 'gitlab_packages' });
41
+ }
42
+ }
43
+ catch (err) {
44
+ logger.error('GitLab package discovery error', { org }, err instanceof Error ? err : new Error(String(err)));
45
+ }
46
+ return packages;
47
+ }
48
+ async fetchPackageMetadata(repoUrl, token) {
49
+ const { host, projectPath } = this.parseUrl(repoUrl);
50
+ if (!projectPath)
51
+ return null;
52
+ const apiBase = `https://${host}/api/v4`;
53
+ const encodedPath = encodeURIComponent(projectPath);
54
+ const headers = this.buildHeaders(token);
55
+ try {
56
+ // Fetch project to get default branch (don't assume 'main')
57
+ const projectResponse = await pRetry(() => fetch(`${apiBase}/projects/${encodedPath}`, { headers }), { retries: 2 });
58
+ const defaultBranch = projectResponse.ok
59
+ ? (await projectResponse.json()).default_branch || 'main'
60
+ : 'main';
61
+ const response = await pRetry(() => fetch(`${apiBase}/projects/${encodedPath}/repository/files/composer.json/raw?ref=${encodeURIComponent(defaultBranch)}`, {
62
+ headers,
63
+ }), { retries: 2 });
64
+ if (!response.ok)
65
+ return null;
66
+ const composerJson = (await response.json());
67
+ if (!composerJson.name)
68
+ return null;
69
+ return {
70
+ name: composerJson.name,
71
+ description: composerJson.description,
72
+ versions: {},
73
+ };
74
+ }
75
+ catch {
76
+ return null;
77
+ }
78
+ }
79
+ async verifyCredentials(url, credentialType, credentials) {
80
+ if (credentialType !== 'gitlab_token' && credentialType !== 'none') {
81
+ return false;
82
+ }
83
+ const parsed = this.parseCredentials(credentials);
84
+ const token = parsed.token || '';
85
+ const { host } = this.parseUrl(url);
86
+ try {
87
+ const response = await fetch(`https://${host}/api/v4/user`, {
88
+ headers: this.buildHeaders(token),
89
+ });
90
+ return response.ok;
91
+ }
92
+ catch {
93
+ return false;
94
+ }
95
+ }
96
+ /**
97
+ * Sync a GitLab repository by fetching composer.json from the repo and tags for versions.
98
+ */
99
+ async syncRepository(url, credentials, credentialType, composerJsonPath) {
100
+ const logger = getLogger();
101
+ const { host, projectPath } = this.parseUrl(url);
102
+ if (!projectPath) {
103
+ return { success: false, packages: [], error: 'invalid_gitlab_url' };
104
+ }
105
+ const token = credentialType === 'none' ? '' : credentials.token || '';
106
+ const apiBase = `https://${host}/api/v4`;
107
+ const encodedPath = encodeURIComponent(projectPath);
108
+ const headers = this.buildHeaders(token);
109
+ try {
110
+ // Get project info for default branch
111
+ const projectResponse = await pRetry(() => fetch(`${apiBase}/projects/${encodedPath}`, { headers }), { retries: 2 });
112
+ if (!projectResponse.ok) {
113
+ if (projectResponse.status === 401 || projectResponse.status === 403) {
114
+ return { success: false, packages: [], error: 'auth_failed' };
115
+ }
116
+ if (projectResponse.status === 404) {
117
+ return { success: false, packages: [], error: 'repo_not_found' };
118
+ }
119
+ return { success: false, packages: [], error: `gitlab_api_${projectResponse.status}` };
120
+ }
121
+ const project = (await projectResponse.json());
122
+ const defaultBranch = project.default_branch || 'main';
123
+ // Fetch composer.json from default branch
124
+ const composerPath = composerJsonPath || 'composer.json';
125
+ const composerResponse = await pRetry(() => fetch(`${apiBase}/projects/${encodedPath}/repository/files/${encodeURIComponent(composerPath)}/raw?ref=${encodeURIComponent(defaultBranch)}`, { headers }), { retries: 2 });
126
+ if (!composerResponse.ok) {
127
+ return { success: false, packages: [], error: 'no_composer_json_found' };
128
+ }
129
+ const composerJson = (await composerResponse.json());
130
+ if (!composerJson.name) {
131
+ return { success: false, packages: [], error: 'no_valid_composer_json' };
132
+ }
133
+ // Fetch tags for version discovery
134
+ const tagsResponse = await pRetry(() => fetch(`${apiBase}/projects/${encodedPath}/repository/tags?per_page=100`, { headers }), { retries: 2 });
135
+ const tags = tagsResponse.ok ? (await tagsResponse.json()) : [];
136
+ // Build packages from tags
137
+ const packages = [];
138
+ // Dev branch package
139
+ packages.push({
140
+ name: composerJson.name,
141
+ version: `dev-${defaultBranch}`,
142
+ description: composerJson.description,
143
+ license: composerJson.license,
144
+ type: composerJson.type,
145
+ homepage: composerJson.homepage || project.web_url,
146
+ require: composerJson.require,
147
+ 'require-dev': composerJson['require-dev'],
148
+ dist: {
149
+ type: 'zip',
150
+ url: `${apiBase}/projects/${encodedPath}/repository/archive.zip?sha=${encodeURIComponent(defaultBranch)}`,
151
+ reference: defaultBranch,
152
+ },
153
+ });
154
+ // Tagged version packages
155
+ for (const tag of tags) {
156
+ const version = semver.clean(tag.name) || tag.name;
157
+ if (!semver.valid(version))
158
+ continue;
159
+ packages.push({
160
+ name: composerJson.name,
161
+ version,
162
+ description: composerJson.description,
163
+ license: composerJson.license,
164
+ type: composerJson.type,
165
+ homepage: composerJson.homepage || project.web_url,
166
+ require: composerJson.require,
167
+ 'require-dev': composerJson['require-dev'],
168
+ dist: {
169
+ type: 'zip',
170
+ url: `${apiBase}/projects/${encodedPath}/repository/archive.zip?sha=${encodeURIComponent(tag.name)}`,
171
+ reference: tag.commit.id,
172
+ },
173
+ });
174
+ }
175
+ logger.info('GitLab sync completed', {
176
+ project: projectPath,
177
+ packageCount: packages.length,
178
+ tagCount: tags.length,
179
+ });
180
+ return { success: true, packages, strategy: 'gitlab_api' };
181
+ }
182
+ catch (err) {
183
+ logger.error('GitLab sync error', { project: projectPath }, err instanceof Error ? err : new Error(String(err)));
184
+ return { success: false, packages: [], error: 'network_error' };
185
+ }
186
+ }
187
+ matchesUrl(url) {
188
+ return GITLAB_URL_PATTERN.test(url);
189
+ }
190
+ parseUrl(url) {
191
+ const gitlabMatch = url.match(GITLAB_URL_PATTERN);
192
+ if (gitlabMatch) {
193
+ return { host: 'gitlab.com', projectPath: `${gitlabMatch[1]}/${gitlabMatch[2]}` };
194
+ }
195
+ return { host: 'gitlab.com', projectPath: null };
196
+ }
197
+ buildHeaders(token) {
198
+ const headers = {
199
+ Accept: 'application/json',
200
+ 'User-Agent': COMPOSER_USER_AGENT,
201
+ };
202
+ if (token) {
203
+ headers['PRIVATE-TOKEN'] = token;
204
+ }
205
+ return headers;
206
+ }
207
+ parseCredentials(credentials) {
208
+ try {
209
+ return JSON.parse(credentials);
210
+ }
211
+ catch {
212
+ return { token: credentials };
213
+ }
214
+ }
215
+ }
216
+ //# sourceMappingURL=gitlab-provider.js.map