@rynt/sdk 0.9.53

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 (332) hide show
  1. package/README.md +122 -0
  2. package/REGISTRIES.md +189 -0
  3. package/env.d.ts +11 -0
  4. package/host-shims.d.ts +30 -0
  5. package/package.json +88 -0
  6. package/src/extension-marketplace/api-types.ts +141 -0
  7. package/src/extension-marketplace/client.ts +296 -0
  8. package/src/extension-marketplace/index.ts +22 -0
  9. package/src/extension-marketplace/schemas.ts +178 -0
  10. package/src/extensions/ExtensionRoutePage.vue +17 -0
  11. package/src/extensions/context.ts +37 -0
  12. package/src/extensions/disabled-folder.ts +21 -0
  13. package/src/extensions/extension-expose-map.ts +5 -0
  14. package/src/extensions/extension-expose.ts +48 -0
  15. package/src/extensions/graph.ts +67 -0
  16. package/src/extensions/index.ts +251 -0
  17. package/src/extensions/invite-handler/types.ts +20 -0
  18. package/src/extensions/launcher-entities/create-launcher-entity.ts +25 -0
  19. package/src/extensions/launcher-entities/keys.ts +46 -0
  20. package/src/extensions/launcher-entities/launcher-entity-components.ts +177 -0
  21. package/src/extensions/launcher-entities/props-map.ts +69 -0
  22. package/src/extensions/launcher-entities/registry.ts +32 -0
  23. package/src/extensions/launcher-models/apis/accounts-contracts.ts +102 -0
  24. package/src/extensions/launcher-models/apis/launcher-model-apis.ts +553 -0
  25. package/src/extensions/launcher-models/keys.ts +23 -0
  26. package/src/extensions/launcher-models/public.ts +9 -0
  27. package/src/extensions/launcher-models/registry-core.ts +34 -0
  28. package/src/extensions/manifest-types.ts +22 -0
  29. package/src/extensions/manifest.ts +46 -0
  30. package/src/extensions/marketplace-open-key.ts +26 -0
  31. package/src/extensions/plugin-types.ts +44 -0
  32. package/src/extensions/plugin.ts +62 -0
  33. package/src/extensions/registries/bootstrap.ts +11 -0
  34. package/src/extensions/registries/builtins/account-provider.ts +6 -0
  35. package/src/extensions/registries/builtins/app-topbar-left-widgets.ts +6 -0
  36. package/src/extensions/registries/builtins/app-topbar-right-widgets.ts +6 -0
  37. package/src/extensions/registries/builtins/app-topbar-status-widgets.ts +6 -0
  38. package/src/extensions/registries/builtins/build-card-actions.ts +6 -0
  39. package/src/extensions/registries/builtins/build-card-after-meta.ts +6 -0
  40. package/src/extensions/registries/builtins/build-card-before-media.ts +6 -0
  41. package/src/extensions/registries/builtins/build-card-before-meta.ts +6 -0
  42. package/src/extensions/registries/builtins/build-card-footer-actions.ts +6 -0
  43. package/src/extensions/registries/builtins/build-detail-after-content.ts +6 -0
  44. package/src/extensions/registries/builtins/build-detail-before-content.ts +6 -0
  45. package/src/extensions/registries/builtins/build-detail-before-hero.ts +6 -0
  46. package/src/extensions/registries/builtins/build-detail-header-actions.ts +6 -0
  47. package/src/extensions/registries/builtins/build-detail-mod-row-actions.ts +6 -0
  48. package/src/extensions/registries/builtins/build-detail-resourcepack-row-actions.ts +6 -0
  49. package/src/extensions/registries/builtins/build-detail-right-column-bottom.ts +6 -0
  50. package/src/extensions/registries/builtins/build-detail-right-column-top.ts +6 -0
  51. package/src/extensions/registries/builtins/dialog-footer-actions.ts +6 -0
  52. package/src/extensions/registries/builtins/feed-after-content.ts +6 -0
  53. package/src/extensions/registries/builtins/feed-before-content.ts +6 -0
  54. package/src/extensions/registries/builtins/file-editor.ts +19 -0
  55. package/src/extensions/registries/builtins/friends-after-list.ts +6 -0
  56. package/src/extensions/registries/builtins/friends-before-list.ts +6 -0
  57. package/src/extensions/registries/builtins/index.ts +141 -0
  58. package/src/extensions/registries/builtins/invite-handler.ts +7 -0
  59. package/src/extensions/registries/builtins/library-after-content.ts +6 -0
  60. package/src/extensions/registries/builtins/library-before-content.ts +6 -0
  61. package/src/extensions/registries/builtins/loader.ts +8 -0
  62. package/src/extensions/registries/builtins/map-card-actions.ts +6 -0
  63. package/src/extensions/registries/builtins/map-card-after-meta.ts +6 -0
  64. package/src/extensions/registries/builtins/map-card-before-meta.ts +6 -0
  65. package/src/extensions/registries/builtins/map-card-footer-actions.ts +6 -0
  66. package/src/extensions/registries/builtins/map-detail-after-content.ts +6 -0
  67. package/src/extensions/registries/builtins/map-detail-before-content.ts +6 -0
  68. package/src/extensions/registries/builtins/map-detail-header-actions.ts +6 -0
  69. package/src/extensions/registries/builtins/markdown-editor-tiptap-extensions.ts +7 -0
  70. package/src/extensions/registries/builtins/markdown-editor-toolbar-actions.ts +6 -0
  71. package/src/extensions/registries/builtins/markdown-renderer-after-content.ts +6 -0
  72. package/src/extensions/registries/builtins/markdown-renderer-before-content.ts +6 -0
  73. package/src/extensions/registries/builtins/mod-details-footer-actions.ts +6 -0
  74. package/src/extensions/registries/builtins/mod-manage-actions.ts +6 -0
  75. package/src/extensions/registries/builtins/mod-provider.ts +5 -0
  76. package/src/extensions/registries/builtins/nav.ts +7 -0
  77. package/src/extensions/registries/builtins/page.ts +13 -0
  78. package/src/extensions/registries/builtins/projects-after-content.ts +6 -0
  79. package/src/extensions/registries/builtins/projects-before-content.ts +6 -0
  80. package/src/extensions/registries/builtins/resourcepack-manage-actions.ts +7 -0
  81. package/src/extensions/registries/builtins/server-card-actions.ts +6 -0
  82. package/src/extensions/registries/builtins/server-card-after-meta.ts +6 -0
  83. package/src/extensions/registries/builtins/server-card-before-meta.ts +6 -0
  84. package/src/extensions/registries/builtins/server-card-footer-actions.ts +6 -0
  85. package/src/extensions/registries/builtins/server-detail-after-content.ts +6 -0
  86. package/src/extensions/registries/builtins/server-detail-before-content.ts +6 -0
  87. package/src/extensions/registries/builtins/server-detail-header-actions.ts +6 -0
  88. package/src/extensions/registries/builtins/settings-after-sections.ts +6 -0
  89. package/src/extensions/registries/builtins/settings-before-sections.ts +6 -0
  90. package/src/extensions/registries/builtins/settings-section-widgets.ts +6 -0
  91. package/src/extensions/registries/builtins/shaderpack-manage-actions.ts +7 -0
  92. package/src/extensions/registries/builtins/shell.ts +5 -0
  93. package/src/extensions/registries/builtins/sidebar-after-content.ts +6 -0
  94. package/src/extensions/registries/builtins/sidebar-before-content.ts +6 -0
  95. package/src/extensions/registries/builtins/sidebar-footer-widgets.ts +6 -0
  96. package/src/extensions/registries/builtins/sidebar-header-widgets.ts +6 -0
  97. package/src/extensions/registries/builtins/sidebar.ts +11 -0
  98. package/src/extensions/registries/builtins/theme.ts +5 -0
  99. package/src/extensions/registries/builtins/user-card-after-meta.ts +6 -0
  100. package/src/extensions/registries/builtins/user-card-before-meta.ts +6 -0
  101. package/src/extensions/registries/builtins/user-menu-actions.ts +6 -0
  102. package/src/extensions/registries/builtins/user-menu-after-actions.ts +6 -0
  103. package/src/extensions/registries/builtins/user-menu-before-actions.ts +6 -0
  104. package/src/extensions/registries/builtins/user-strip.ts +5 -0
  105. package/src/extensions/registries/clear-extension-ui-registries.ts +15 -0
  106. package/src/extensions/registries/define-extension-registry.ts +58 -0
  107. package/src/extensions/registries/extension-host-api.ts +41 -0
  108. package/src/extensions/registries/extension-registry-api.ts +103 -0
  109. package/src/extensions/registries/extension-registry-payload-map.ts +9 -0
  110. package/src/extensions/registries/extension-scope.ts +41 -0
  111. package/src/extensions/registries/get-registry.ts +23 -0
  112. package/src/extensions/registries/index.ts +58 -0
  113. package/src/extensions/registries/manifest-rynt.ts +193 -0
  114. package/src/extensions/registries/registry-slot.ts +40 -0
  115. package/src/extensions/registries/registry-value-map.ts +89 -0
  116. package/src/extensions/registries/store.ts +206 -0
  117. package/src/extensions/resolve-extensions.ts +245 -0
  118. package/src/extensions/router-bridge.ts +103 -0
  119. package/src/extensions/session.ts +6 -0
  120. package/src/extensions/slug.ts +23 -0
  121. package/src/extensions/version.ts +147 -0
  122. package/src/host/extensions-composables.ts +33 -0
  123. package/src/host/extensions-init.ts +194 -0
  124. package/src/host/index.ts +11 -0
  125. package/src/host/launcher-models/index.ts +4 -0
  126. package/src/index.ts +229 -0
  127. package/src/minecraft-loader/base-loader.ts +102 -0
  128. package/src/minecraft-loader/index.ts +11 -0
  129. package/src/minecraft-loader/loader-registry.ts +72 -0
  130. package/src/shared/api/assets.ts +112 -0
  131. package/src/shared/api/auth.ts +283 -0
  132. package/src/shared/api/builds.ts +647 -0
  133. package/src/shared/api/config.ts +19 -0
  134. package/src/shared/api/download-stats.ts +103 -0
  135. package/src/shared/api/downloads.ts +36 -0
  136. package/src/shared/api/entity-authorship.ts +60 -0
  137. package/src/shared/api/events.ts +393 -0
  138. package/src/shared/api/friends.ts +140 -0
  139. package/src/shared/api/graphql.ts +87 -0
  140. package/src/shared/api/index.ts +23 -0
  141. package/src/shared/api/invites.ts +262 -0
  142. package/src/shared/api/library.ts +44 -0
  143. package/src/shared/api/maps.ts +385 -0
  144. package/src/shared/api/notify-websocket.ts +140 -0
  145. package/src/shared/api/posts.ts +357 -0
  146. package/src/shared/api/projectServers.ts +379 -0
  147. package/src/shared/api/serverMembers.ts +173 -0
  148. package/src/shared/api/users.ts +294 -0
  149. package/src/shared/composables/buildEditor/useBuildEditor.ts +66 -0
  150. package/src/shared/composables/buildManifest/buildManifest.ts +447 -0
  151. package/src/shared/composables/filesEditor/filesEditor.ts +346 -0
  152. package/src/shared/composables/index.ts +10 -0
  153. package/src/shared/composables/modsEditor/modsEditor.ts +1678 -0
  154. package/src/shared/composables/registrySlot/registry-slot-utils.ts +25 -0
  155. package/src/shared/composables/registrySlot/useRegistrySlotMissing.ts +35 -0
  156. package/src/shared/composables/resourcePacksEditor/resourcePacksEditor.ts +448 -0
  157. package/src/shared/composables/shaderPacksEditor/shaderPacksEditor.ts +395 -0
  158. package/src/shared/composables/useSkinRender.ts +70 -0
  159. package/src/shared/composables/useZlDeepLink.ts +178 -0
  160. package/src/shared/definitions/defineGraphCache.ts +216 -0
  161. package/src/shared/definitions/defineStore.ts +32 -0
  162. package/src/shared/definitions/index.ts +2 -0
  163. package/src/shared/minecraft-types/build-manifest.ts +611 -0
  164. package/src/shared/minecraft-types/index.ts +3 -0
  165. package/src/shared/minecraft-types/launcher-versions.ts +32 -0
  166. package/src/shared/minecraft-types/minecraft-launcher-types.ts +276 -0
  167. package/src/shared/mocks/index.ts +1 -0
  168. package/src/shared/mocks/navigation.ts +17 -0
  169. package/src/shared/mods/http.ts +45 -0
  170. package/src/shared/mods/index.ts +5 -0
  171. package/src/shared/mods/marketplace-editor-search.ts +266 -0
  172. package/src/shared/mods/marketplace-search-utils.ts +42 -0
  173. package/src/shared/mods/mod-marketplace-registry.ts +66 -0
  174. package/src/shared/mods/mod-marketplace-types.ts +28 -0
  175. package/src/shared/mods/providers/curseforge.ts +464 -0
  176. package/src/shared/mods/providers/index.ts +8 -0
  177. package/src/shared/mods/providers/modrinth.ts +402 -0
  178. package/src/shared/mods/resolve-mods-provider-loader-ids.ts +77 -0
  179. package/src/shared/mods/types.ts +76 -0
  180. package/src/shared/styles/index.css +713 -0
  181. package/src/shared/themes/index.ts +23 -0
  182. package/src/shared/themes/theme-tokens-black.json +126 -0
  183. package/src/shared/themes/theme-tokens-classic.json +126 -0
  184. package/src/shared/themes/theme-tokens-pink.json +126 -0
  185. package/src/shared/themes/theme-tokens.json +126 -0
  186. package/src/shared/themes/types.ts +85 -0
  187. package/src/shared/types/API_DOCUMENTATION.md +422 -0
  188. package/src/shared/types/account.ts +40 -0
  189. package/src/shared/types/build.ts +8 -0
  190. package/src/shared/types/entities.ts +181 -0
  191. package/src/shared/types/index.ts +6 -0
  192. package/src/shared/types/invite-payloads.ts +60 -0
  193. package/src/shared/types/navigation.ts +16 -0
  194. package/src/shared/types/running-build.ts +51 -0
  195. package/src/shared/types/serverMember.ts +17 -0
  196. package/src/shared/types/user.ts +55 -0
  197. package/src/shared/ui/base/Avatar.vue +262 -0
  198. package/src/shared/ui/base/Badge.vue +47 -0
  199. package/src/shared/ui/base/Button.vue +78 -0
  200. package/src/shared/ui/base/Divider.vue +42 -0
  201. package/src/shared/ui/base/Icon.vue +597 -0
  202. package/src/shared/ui/base/StatusIndicator.vue +44 -0
  203. package/src/shared/ui/base/index.ts +7 -0
  204. package/src/shared/ui/cards/InviteCard.vue +47 -0
  205. package/src/shared/ui/cards/index.ts +2 -0
  206. package/src/shared/ui/dialog/Dialog.vue +71 -0
  207. package/src/shared/ui/dialog/DialogContent.vue +31 -0
  208. package/src/shared/ui/dialog/DialogFooter.vue +14 -0
  209. package/src/shared/ui/dialog/DialogHeader.vue +41 -0
  210. package/src/shared/ui/dialog/index.ts +5 -0
  211. package/src/shared/ui/editors/AttachmentImagesEditor.vue +133 -0
  212. package/src/shared/ui/editors/ContentAttachmentsDisplay.vue +76 -0
  213. package/src/shared/ui/editors/MarkdownEditor.vue +956 -0
  214. package/src/shared/ui/editors/MarkdownRenderer.vue +299 -0
  215. package/src/shared/ui/editors/RichContentImageViewer.vue +85 -0
  216. package/src/shared/ui/editors/SocialPostMediaZone.vue +320 -0
  217. package/src/shared/ui/editors/index.ts +6 -0
  218. package/src/shared/ui/editors/markdown-editor-gallery.ts +234 -0
  219. package/src/shared/ui/editors/markdown-editor-image.ts +178 -0
  220. package/src/shared/ui/form/Checkbox.vue +38 -0
  221. package/src/shared/ui/form/FormField.vue +30 -0
  222. package/src/shared/ui/form/FormGrid.vue +38 -0
  223. package/src/shared/ui/form/ImageEditor.vue +598 -0
  224. package/src/shared/ui/form/Input.vue +72 -0
  225. package/src/shared/ui/form/Range.vue +65 -0
  226. package/src/shared/ui/form/Select.vue +76 -0
  227. package/src/shared/ui/form/Switch.vue +38 -0
  228. package/src/shared/ui/form/Textarea.vue +144 -0
  229. package/src/shared/ui/form/index.ts +9 -0
  230. package/src/shared/ui/index.ts +9 -0
  231. package/src/shared/ui/layout/BusyOverlay.vue +31 -0
  232. package/src/shared/ui/layout/Callout.vue +44 -0
  233. package/src/shared/ui/layout/Card.vue +38 -0
  234. package/src/shared/ui/layout/Container.vue +36 -0
  235. package/src/shared/ui/layout/EmptyState.vue +99 -0
  236. package/src/shared/ui/layout/EntityMediaRow.vue +54 -0
  237. package/src/shared/ui/layout/FilterResultsLayout.vue +22 -0
  238. package/src/shared/ui/layout/FloatingPanel.vue +37 -0
  239. package/src/shared/ui/layout/FullscreenDimmer.vue +11 -0
  240. package/src/shared/ui/layout/Grid.vue +40 -0
  241. package/src/shared/ui/layout/Inline.vue +59 -0
  242. package/src/shared/ui/layout/LoadingState.vue +39 -0
  243. package/src/shared/ui/layout/MediaBox.vue +47 -0
  244. package/src/shared/ui/layout/OverlayPanel.vue +28 -0
  245. package/src/shared/ui/layout/OverlayWaitPanel.vue +22 -0
  246. package/src/shared/ui/layout/PageSection.vue +43 -0
  247. package/src/shared/ui/layout/PageToolbar.vue +29 -0
  248. package/src/shared/ui/layout/Panel.vue +39 -0
  249. package/src/shared/ui/layout/ProgressBar.vue +49 -0
  250. package/src/shared/ui/layout/Section.vue +30 -0
  251. package/src/shared/ui/layout/SegmentedControl.vue +43 -0
  252. package/src/shared/ui/layout/SelectableCard.vue +46 -0
  253. package/src/shared/ui/layout/SelectableRow.vue +41 -0
  254. package/src/shared/ui/layout/Skeleton.vue +25 -0
  255. package/src/shared/ui/layout/SkeletonAvatar.vue +30 -0
  256. package/src/shared/ui/layout/SkeletonEntityCard.vue +20 -0
  257. package/src/shared/ui/layout/SkeletonFeedPost.vue +22 -0
  258. package/src/shared/ui/layout/SkeletonGrid.vue +18 -0
  259. package/src/shared/ui/layout/SkeletonListRow.vue +31 -0
  260. package/src/shared/ui/layout/SkeletonText.vue +25 -0
  261. package/src/shared/ui/layout/Stack.vue +42 -0
  262. package/src/shared/ui/layout/StateBlock.vue +44 -0
  263. package/src/shared/ui/layout/TwoPaneLayout.vue +35 -0
  264. package/src/shared/ui/layout/VirtualList.vue +160 -0
  265. package/src/shared/ui/layout/index.ts +35 -0
  266. package/src/shared/ui/layout/skeletonSurfaceStyles.ts +24 -0
  267. package/src/shared/ui/navigation/NavItem.vue +139 -0
  268. package/src/shared/ui/navigation/Tab.vue +61 -0
  269. package/src/shared/ui/navigation/Tabs.vue +37 -0
  270. package/src/shared/ui/navigation/index.ts +4 -0
  271. package/src/shared/ui/primitives/Action.vue +19 -0
  272. package/src/shared/ui/primitives/Block.vue +28 -0
  273. package/src/shared/ui/primitives/CanvasView.vue +19 -0
  274. package/src/shared/ui/primitives/Control.vue +24 -0
  275. package/src/shared/ui/primitives/ControlSelect.vue +19 -0
  276. package/src/shared/ui/primitives/ControlTextarea.vue +17 -0
  277. package/src/shared/ui/primitives/FieldLabel.vue +19 -0
  278. package/src/shared/ui/primitives/Form.vue +19 -0
  279. package/src/shared/ui/primitives/Heading.vue +29 -0
  280. package/src/shared/ui/primitives/Image.vue +17 -0
  281. package/src/shared/ui/primitives/LineBreak.vue +3 -0
  282. package/src/shared/ui/primitives/Link.vue +19 -0
  283. package/src/shared/ui/primitives/List.vue +28 -0
  284. package/src/shared/ui/primitives/ListItem.vue +19 -0
  285. package/src/shared/ui/primitives/OptionItem.vue +19 -0
  286. package/src/shared/ui/primitives/Text.vue +28 -0
  287. package/src/shared/ui/primitives/VideoView.vue +19 -0
  288. package/src/shared/ui/primitives/index.ts +19 -0
  289. package/src/shared/ui/primitives/resolveElement.ts +25 -0
  290. package/src/shared/ui/special/AngularAccent.vue +106 -0
  291. package/src/shared/ui/special/ExtensionRegistrySlotButton.vue +143 -0
  292. package/src/shared/ui/special/InfoRow.vue +39 -0
  293. package/src/shared/ui/special/LogViewer.vue +53 -0
  294. package/src/shared/ui/special/PageHeader.vue +23 -0
  295. package/src/shared/ui/special/RegistrySlotMissingCallout.vue +48 -0
  296. package/src/shared/ui/special/WelcomeCard.vue +32 -0
  297. package/src/shared/ui/special/index.ts +9 -0
  298. package/src/shared/utils/app-paths.ts +50 -0
  299. package/src/shared/utils/attachments.ts +16 -0
  300. package/src/shared/utils/autostart.ts +213 -0
  301. package/src/shared/utils/build-files.ts +439 -0
  302. package/src/shared/utils/build-manifest-init.ts +176 -0
  303. package/src/shared/utils/cloudinary.ts +67 -0
  304. package/src/shared/utils/cn.ts +7 -0
  305. package/src/shared/utils/download-stats-week.ts +165 -0
  306. package/src/shared/utils/entity-api-to-cache.ts +84 -0
  307. package/src/shared/utils/entity-build-from-api.ts +1 -0
  308. package/src/shared/utils/entity-display.ts +27 -0
  309. package/src/shared/utils/entity-map-from-api.ts +1 -0
  310. package/src/shared/utils/file-hash.ts +65 -0
  311. package/src/shared/utils/formatSize.ts +5 -0
  312. package/src/shared/utils/formatTime.ts +157 -0
  313. package/src/shared/utils/getAccountSkinRender.ts +32 -0
  314. package/src/shared/utils/index.ts +34 -0
  315. package/src/shared/utils/local-mods.ts +678 -0
  316. package/src/shared/utils/local-settings.ts +217 -0
  317. package/src/shared/utils/member-join-stats.ts +35 -0
  318. package/src/shared/utils/platform.ts +86 -0
  319. package/src/shared/utils/play-host-slug.ts +92 -0
  320. package/src/shared/utils/rich-content.ts +294 -0
  321. package/src/shared/utils/safeRequest.ts +23 -0
  322. package/src/shared/utils/semver.ts +81 -0
  323. package/src/shared/utils/serverPermissions.ts +155 -0
  324. package/src/shared/utils/skin-render-cache.ts +372 -0
  325. package/src/shared/utils/stripMarkdown.ts +45 -0
  326. package/src/shared/utils/transliterate.ts +74 -0
  327. package/src/shared/utils/updateAccountSkinRender.ts +64 -0
  328. package/src/shared/utils/updater.ts +218 -0
  329. package/src/shared/utils/uploadImage.ts +195 -0
  330. package/src/shared/utils/user-status.ts +9 -0
  331. package/src/tiptap/index.ts +7 -0
  332. package/tsconfig.json +13 -0
@@ -0,0 +1,66 @@
1
+ import { markRaw } from 'vue';
2
+
3
+ import {
4
+ clearRegistryBucket,
5
+ deleteRegistryItem,
6
+ getRegistryEntryMeta,
7
+ getRegistryItem,
8
+ HOST_EXTENSION_ID,
9
+ listRegistryEntries,
10
+ listRegistryValuesSorted,
11
+ } from '../../extensions/registries';
12
+ import { useModProviderRegistry } from '../../extensions/registries/builtins/mod-provider';
13
+
14
+ export type { ModMarketplaceProvider } from './mod-marketplace-types';
15
+
16
+ import type { ModMarketplaceProvider } from './mod-marketplace-types';
17
+
18
+ const RID = 'core.modProvider';
19
+
20
+ /** Подготовить объект провайдера для реестра / `ctx.registerRegistryEntry` (Vue не должен делать функции реактивными). */
21
+ export function markModMarketplaceProvider(
22
+ provider: ModMarketplaceProvider,
23
+ ): ModMarketplaceProvider {
24
+ return {
25
+ ...provider,
26
+ search: markRaw(provider.search),
27
+ install: markRaw(provider.install),
28
+ getProjectDetails: markRaw(provider.getProjectDetails),
29
+ };
30
+ }
31
+
32
+ /**
33
+ * `extensionId` определяется автоматически через scope: в коде расширения — id из `manifest.json`,
34
+ * в коде лаунчера — `rynt`.
35
+ */
36
+ export function registerModMarketplaceProvider(
37
+ provider: ModMarketplaceProvider,
38
+ ): void {
39
+ const row = markModMarketplaceProvider(provider);
40
+ useModProviderRegistry().register(provider.id, row, provider.order);
41
+ }
42
+
43
+ export function unregisterModMarketplaceProvidersForExtension(
44
+ extensionId: string,
45
+ ): void {
46
+ if (extensionId === HOST_EXTENSION_ID) return;
47
+ for (const [key] of listRegistryEntries<ModMarketplaceProvider>(RID)) {
48
+ if (getRegistryEntryMeta(RID, key)?.extensionId === extensionId) {
49
+ deleteRegistryItem(RID, key);
50
+ }
51
+ }
52
+ }
53
+
54
+ export function resetModMarketplaceRegistry(): void {
55
+ clearRegistryBucket(RID);
56
+ }
57
+
58
+ export function listModMarketplaceProviders(): ModMarketplaceProvider[] {
59
+ return listRegistryValuesSorted<ModMarketplaceProvider>(RID);
60
+ }
61
+
62
+ export function getModMarketplaceProvider(
63
+ id: string,
64
+ ): ModMarketplaceProvider | undefined {
65
+ return getRegistryItem<ModMarketplaceProvider>(RID, id);
66
+ }
@@ -0,0 +1,28 @@
1
+ import type { Mod, ResourcePack, ShaderPack } from '../minecraft-types/build-manifest';
2
+ import type {
3
+ InstallContext,
4
+ MarketplaceInstallVersion,
5
+ MarketplaceItem,
6
+ MarketplaceSearchContext,
7
+ MarketplaceSearchResult,
8
+ ModsProviderId,
9
+ ProjectDetails,
10
+ } from './types';
11
+
12
+ /** Один контракт провайдера маркетплейса модов (встроенный или из расширения). `extensionId` — только в метаданных реестра. */
13
+ export type ModMarketplaceProvider = {
14
+ id: ModsProviderId;
15
+ label: string;
16
+ order?: number;
17
+ search: (ctx: MarketplaceSearchContext) => Promise<MarketplaceSearchResult>;
18
+ install: (
19
+ item: MarketplaceItem,
20
+ ctx: InstallContext,
21
+ versionId?: string,
22
+ ) => Promise<Mod | ResourcePack | ShaderPack>;
23
+ getProjectDetails: (projectId: string) => Promise<ProjectDetails>;
24
+ getInstallVersions?: (
25
+ projectId: string,
26
+ ctx: InstallContext,
27
+ ) => Promise<MarketplaceInstallVersion[]>;
28
+ };
@@ -0,0 +1,464 @@
1
+ import type {
2
+ Mod,
3
+ ResourcePack,
4
+ ShaderPack,
5
+ } from '../../minecraft-types/build-manifest';
6
+ import { httpGet } from '../http';
7
+ import type { ModMarketplaceProvider } from '../mod-marketplace-types';
8
+ import { getCurseForgeMarketplaceLoaderId } from '../resolve-mods-provider-loader-ids';
9
+ import type {
10
+ InstallContext,
11
+ MarketplaceInstallVersion,
12
+ MarketplaceItem,
13
+ MarketplaceSearchContext,
14
+ MarketplaceSearchResult,
15
+ ProjectDetails,
16
+ ProjectType,
17
+ } from '../types';
18
+ import { MARKETPLACE_SEARCH_PAGE_SIZE } from '../types';
19
+
20
+ const CURSEFORGE_PROVIDER_ID = 'curseforge';
21
+
22
+ const CURSEFORGE_BASE = 'https://api.curseforge.com';
23
+ const MINECRAFT_GAME_ID = 432;
24
+ const CLASS_ID_MODS = 6;
25
+ const CLASS_ID_RESOURCE_PACKS = 12;
26
+ const CLASS_ID_SHADER_PACKS = 6552;
27
+
28
+ type CfLogo = { url?: string };
29
+
30
+ type CfSearchItem = {
31
+ id: number;
32
+ name: string;
33
+ slug: string;
34
+ summary?: string;
35
+ downloadCount?: number;
36
+ logo?: CfLogo;
37
+ };
38
+
39
+ type CfPagination = {
40
+ index: number;
41
+ pageSize: number;
42
+ totalCount: number;
43
+ };
44
+
45
+ type CfResponse<T> = { data: T; pagination?: CfPagination };
46
+
47
+ type CfFileHash = {
48
+ algo: number; // 1 = sha1
49
+ value: string;
50
+ };
51
+
52
+ type CfFile = {
53
+ id: number;
54
+ fileName: string;
55
+ fileLength: number;
56
+ displayName?: string;
57
+ downloadUrl?: string | null;
58
+ hashes?: CfFileHash[];
59
+ };
60
+
61
+ function getApiKey(): string | null {
62
+ // NOTE: client-side by request (will be bundled into app)
63
+ const key = (import.meta as any).env?.VITE_CURSEFORGE_API_KEY as
64
+ | string
65
+ | undefined;
66
+ return key?.trim() ? key.trim() : null;
67
+ }
68
+
69
+ function loaderToCfModLoaderType(
70
+ loader: string | undefined,
71
+ ): number | undefined {
72
+ // Best-effort mapping (CurseForge ModLoaderType enum)
73
+ // 0 Any, 1 Forge, 4 Fabric, 5 Quilt, 6 NeoForge
74
+ switch ((loader || '').toLowerCase()) {
75
+ case 'forge':
76
+ return 1;
77
+ case 'fabric':
78
+ return 4;
79
+ case 'quilt':
80
+ return 5;
81
+ case 'neoforge':
82
+ return 6;
83
+ default:
84
+ return undefined;
85
+ }
86
+ }
87
+
88
+ function getCfHeaders(): Record<string, string> {
89
+ const apiKey = getApiKey();
90
+ if (!apiKey) {
91
+ throw new Error('VITE_CURSEFORGE_API_KEY is not set');
92
+ }
93
+ return {
94
+ 'x-api-key': apiKey,
95
+ };
96
+ }
97
+
98
+ export async function curseforgeSearch(
99
+ ctx: MarketplaceSearchContext,
100
+ ): Promise<MarketplaceSearchResult> {
101
+ const classId =
102
+ ctx.projectType === 'resourcepack'
103
+ ? CLASS_ID_RESOURCE_PACKS
104
+ : ctx.projectType === 'shaderpack'
105
+ ? CLASS_ID_SHADER_PACKS
106
+ : CLASS_ID_MODS;
107
+
108
+ // Resource packs and shader packs don't depend on mod loader, so don't filter by loader
109
+ const marketplaceLoaderId =
110
+ ctx.projectType === 'resourcepack' || ctx.projectType === 'shaderpack'
111
+ ? undefined
112
+ : getCurseForgeMarketplaceLoaderId(ctx, CURSEFORGE_PROVIDER_ID);
113
+ const modLoaderType = loaderToCfModLoaderType(marketplaceLoaderId);
114
+
115
+ const page = ctx.page ?? 0;
116
+ const pageSize = MARKETPLACE_SEARCH_PAGE_SIZE;
117
+ const index = page * pageSize;
118
+
119
+ const url = `${CURSEFORGE_BASE}/v1/mods/search`;
120
+ const params: Record<string, string | number | undefined> = {
121
+ gameId: MINECRAFT_GAME_ID,
122
+ classId,
123
+ sortField: 12,
124
+ gameVersion: ctx.minecraftVersion || undefined,
125
+ modLoaderType: modLoaderType ?? undefined,
126
+ pageSize,
127
+ index,
128
+ };
129
+ if (ctx.query.trim()) {
130
+ params.searchFilter = ctx.query.trim();
131
+ }
132
+
133
+ const response = await httpGet<CfResponse<CfSearchItem[]>>(url, {
134
+ params,
135
+ headers: getCfHeaders(),
136
+ });
137
+
138
+ const data = response.data ?? [];
139
+ const items = data.map((m) => ({
140
+ provider: 'curseforge' as const,
141
+ projectType: ctx.projectType,
142
+ projectId: String(m.id),
143
+ slug: m.slug || String(m.id),
144
+ name: m.name,
145
+ summary: m.summary,
146
+ iconUrl: m.logo?.url,
147
+ downloads: m.downloadCount,
148
+ }));
149
+
150
+ const pagination = response.pagination;
151
+ const hasMore =
152
+ pagination != null
153
+ ? pagination.index + data.length < pagination.totalCount
154
+ : data.length === pageSize;
155
+
156
+ return { items, hasMore };
157
+ }
158
+
159
+ type CfSortableFile = CfFile & {
160
+ fileDate?: string;
161
+ };
162
+
163
+ async function curseforgeGetCompatibleFiles(
164
+ modId: string,
165
+ ctx: InstallContext,
166
+ ): Promise<CfSortableFile[]> {
167
+ const marketplaceLoaderId =
168
+ ctx.projectType === 'resourcepack' || ctx.projectType === 'shaderpack'
169
+ ? undefined
170
+ : getCurseForgeMarketplaceLoaderId(ctx, CURSEFORGE_PROVIDER_ID);
171
+ const modLoaderType = loaderToCfModLoaderType(marketplaceLoaderId);
172
+ const url = `${CURSEFORGE_BASE}/v1/mods/${encodeURIComponent(modId)}/files`;
173
+ const params = {
174
+ gameVersion: ctx.minecraftVersion || undefined,
175
+ modLoaderType: modLoaderType ?? undefined,
176
+ pageSize: 20,
177
+ };
178
+
179
+ try {
180
+ const response = await httpGet<CfResponse<CfFile[]>>(url, {
181
+ params,
182
+ headers: getCfHeaders(),
183
+ });
184
+
185
+ let files = (response.data ?? []) as CfSortableFile[];
186
+
187
+ if (!files.length && modLoaderType !== undefined) {
188
+ const paramsWithoutLoader = {
189
+ gameVersion: ctx.minecraftVersion || undefined,
190
+ pageSize: 20,
191
+ };
192
+ const retryResponse = await httpGet<CfResponse<CfFile[]>>(url, {
193
+ params: paramsWithoutLoader,
194
+ headers: getCfHeaders(),
195
+ });
196
+ files = (retryResponse.data ?? []) as CfSortableFile[];
197
+ }
198
+
199
+ if (!files.length && ctx.minecraftVersion) {
200
+ const paramsWithoutVersion = {
201
+ modLoaderType: modLoaderType ?? undefined,
202
+ pageSize: 20,
203
+ };
204
+ const retryResponse2 = await httpGet<CfResponse<CfFile[]>>(url, {
205
+ params: paramsWithoutVersion,
206
+ headers: getCfHeaders(),
207
+ });
208
+ files = (retryResponse2.data ?? []) as CfSortableFile[];
209
+ }
210
+
211
+ if (!files.length) {
212
+ const paramsNoFilters = {
213
+ pageSize: 1,
214
+ };
215
+ const retryResponse3 = await httpGet<CfResponse<CfFile[]>>(url, {
216
+ params: paramsNoFilters,
217
+ headers: getCfHeaders(),
218
+ });
219
+ files = (retryResponse3.data ?? []) as CfSortableFile[];
220
+ }
221
+
222
+ if (!files.length) {
223
+ throw new Error('No compatible files found on CurseForge');
224
+ }
225
+ return files;
226
+ } catch (error) {
227
+ throw error;
228
+ }
229
+ }
230
+
231
+ function getSha1FromHashes(hashes: CfFileHash[] | undefined): string | null {
232
+ const sha1 = hashes?.find((h) => h.algo === 1)?.value;
233
+ return sha1 || null;
234
+ }
235
+
236
+ function buildCurseForgeDownloadUrl(fileId: number, fileName: string): string {
237
+ // CurseForge CDN URL format: https://edge.forgecdn.net/files/{first4}/{rest}/{fileName}
238
+ const fileIdStr = String(fileId);
239
+ const firstPart = fileIdStr.slice(0, 4);
240
+ const secondPart = fileIdStr.slice(4);
241
+ return `https://edge.forgecdn.net/files/${firstPart}/${secondPart}/${fileName}`;
242
+ }
243
+
244
+ export async function curseforgeGetInstallVersions(
245
+ modId: string,
246
+ ctx: InstallContext,
247
+ ): Promise<MarketplaceInstallVersion[]> {
248
+ const files = await curseforgeGetCompatibleFiles(modId, ctx);
249
+ return files.map((file, index) => ({
250
+ id: String(file.id),
251
+ label: file.displayName || file.fileName,
252
+ publishedAt: file.fileDate,
253
+ recommended: index === 0,
254
+ }));
255
+ }
256
+
257
+ export async function curseforgeInstallToManifestEntry(
258
+ item: MarketplaceItem,
259
+ ctx: InstallContext,
260
+ selectedVersionId?: string,
261
+ ): Promise<Mod | ResourcePack | ShaderPack> {
262
+ try {
263
+ const files = await curseforgeGetCompatibleFiles(item.projectId, ctx);
264
+ const file = selectedVersionId
265
+ ? files.find((f) => String(f.id) === selectedVersionId)
266
+ : files[0];
267
+ if (!file) {
268
+ throw new Error('Selected CurseForge version not found');
269
+ }
270
+ const sha1 = getSha1FromHashes(file.hashes);
271
+ if (!sha1) {
272
+ throw new Error('CurseForge file does not contain sha1 hash');
273
+ }
274
+ // Build download URL if not provided by API
275
+ const downloadUrl =
276
+ file.downloadUrl || buildCurseForgeDownloadUrl(file.id, file.fileName);
277
+
278
+ const fileEntry = {
279
+ type: 'primary' as const,
280
+ filename: file.fileName,
281
+ path:
282
+ ctx.projectType === 'resourcepack'
283
+ ? `resourcepacks/${file.fileName}`
284
+ : ctx.projectType === 'shaderpack'
285
+ ? `shaderpacks/${file.fileName}`
286
+ : `mods/${file.fileName}`,
287
+ size: file.fileLength,
288
+ hashes: { sha1 },
289
+ urls: [downloadUrl],
290
+ side: 'both' as const,
291
+ };
292
+
293
+ const versionLabel = file.displayName || file.fileName;
294
+
295
+ if (ctx.projectType === 'resourcepack') {
296
+ const rp: ResourcePack = {
297
+ source: 'curseforge',
298
+ id: item.projectId,
299
+ name: item.name,
300
+ projectSlug: item.slug,
301
+ version: versionLabel,
302
+ image: item.iconUrl,
303
+ constraints: {
304
+ minecraft: ctx.minecraftVersion,
305
+ },
306
+ files: [fileEntry],
307
+ };
308
+ return rp;
309
+ }
310
+
311
+ if (ctx.projectType === 'shaderpack') {
312
+ const sp: ShaderPack = {
313
+ source: 'curseforge',
314
+ id: item.projectId,
315
+ name: item.name,
316
+ projectSlug: item.slug,
317
+ version: versionLabel,
318
+ image: item.iconUrl,
319
+ constraints: {
320
+ minecraft: ctx.minecraftVersion,
321
+ },
322
+ files: [fileEntry],
323
+ };
324
+ return sp;
325
+ }
326
+
327
+ const mod: Mod = {
328
+ source: 'curseforge',
329
+ id: item.projectId, // Use projectId (CurseForge modId) for id
330
+ name: item.name,
331
+ projectSlug: item.slug, // Use slug for projectSlug
332
+ image: item.iconUrl,
333
+ version: versionLabel,
334
+ constraints: {
335
+ minecraft: ctx.minecraftVersion,
336
+ loader: ctx.loader,
337
+ },
338
+ files: [fileEntry],
339
+ dependencies: [], // CurseForge API doesn't provide dependencies in file endpoint
340
+ };
341
+ return mod;
342
+ } catch (error) {
343
+ throw error;
344
+ }
345
+ }
346
+
347
+ type CfProject = {
348
+ id: number;
349
+ name: string;
350
+ slug: string;
351
+ summary?: string;
352
+ description?: string;
353
+ downloadCount?: number;
354
+ logo?: CfLogo;
355
+ links?: {
356
+ websiteUrl?: string;
357
+ wikiUrl?: string;
358
+ issuesUrl?: string;
359
+ sourceUrl?: string;
360
+ };
361
+ categories?: Array<{
362
+ id?: number;
363
+ name?: string;
364
+ slug?: string;
365
+ }>;
366
+ authors?: Array<{
367
+ id?: number;
368
+ name?: string;
369
+ url?: string;
370
+ }>;
371
+ dateCreated?: string;
372
+ dateModified?: string;
373
+ dateReleased?: string;
374
+ status?: number;
375
+ };
376
+
377
+ type CfDescriptionResponse = {
378
+ data: string; // HTML description
379
+ };
380
+
381
+ export async function curseforgeGetProjectDetails(
382
+ modId: string,
383
+ ): Promise<ProjectDetails> {
384
+ const [projectResponse, descriptionResponse] = await Promise.allSettled([
385
+ httpGet<CfResponse<CfProject>>(
386
+ `${CURSEFORGE_BASE}/v1/mods/${encodeURIComponent(modId)}`,
387
+ {
388
+ headers: getCfHeaders(),
389
+ },
390
+ ),
391
+ httpGet<CfDescriptionResponse>(
392
+ `${CURSEFORGE_BASE}/v1/mods/${encodeURIComponent(modId)}/description`,
393
+ {
394
+ headers: getCfHeaders(),
395
+ },
396
+ ),
397
+ ]);
398
+
399
+ if (projectResponse.status === 'rejected') {
400
+ throw new Error('Failed to fetch CurseForge project details');
401
+ }
402
+
403
+ const project = projectResponse.value.data;
404
+
405
+ // Get HTML description from separate endpoint if available
406
+ let descriptionHtml: string | undefined = project.description;
407
+ if (descriptionResponse.status === 'fulfilled') {
408
+ descriptionHtml = descriptionResponse.value.data;
409
+ }
410
+
411
+ return {
412
+ provider: 'curseforge',
413
+ projectId: String(project.id),
414
+ slug: project.slug || String(project.id),
415
+ name: project.name,
416
+ summary: project.summary,
417
+ description: descriptionHtml,
418
+ iconUrl: project.logo?.url,
419
+ downloads: project.downloadCount,
420
+ categories: project.categories
421
+ ?.map((c) => c.name || c.slug || '')
422
+ .filter(Boolean),
423
+ authors: project.authors?.map((a) => a.name || '').filter(Boolean),
424
+ websiteUrl: project.links?.websiteUrl,
425
+ sourceUrl: project.links?.sourceUrl,
426
+ issuesUrl: project.links?.issuesUrl,
427
+ wikiUrl: project.links?.wikiUrl,
428
+ };
429
+ }
430
+
431
+ /**
432
+ * Get MarketplaceItem by project ID (for dependency resolution)
433
+ */
434
+ export async function curseforgeGetItemById(
435
+ modId: string,
436
+ projectType: ProjectType,
437
+ ): Promise<MarketplaceItem | null> {
438
+ try {
439
+ const details = await curseforgeGetProjectDetails(modId);
440
+ return {
441
+ provider: 'curseforge',
442
+ projectType,
443
+ projectId: details.projectId,
444
+ slug: details.slug,
445
+ name: details.name,
446
+ summary: details.summary,
447
+ iconUrl: details.iconUrl,
448
+ downloads: details.downloads,
449
+ };
450
+ } catch (e) {
451
+ console.warn(`[curseforge] Failed to get mod ${modId}:`, e);
452
+ return null;
453
+ }
454
+ }
455
+
456
+ export const curseforgeModMarketplaceProvider: ModMarketplaceProvider = {
457
+ id: 'curseforge',
458
+ label: 'CurseForge',
459
+ order: 20,
460
+ search: curseforgeSearch,
461
+ install: curseforgeInstallToManifestEntry,
462
+ getProjectDetails: curseforgeGetProjectDetails,
463
+ getInstallVersions: curseforgeGetInstallVersions,
464
+ };
@@ -0,0 +1,8 @@
1
+ export {
2
+ curseforgeGetItemById,
3
+ curseforgeModMarketplaceProvider,
4
+ } from './curseforge';
5
+ export {
6
+ modrinthGetItemById,
7
+ modrinthModMarketplaceProvider,
8
+ } from './modrinth';