@rocket/js 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (340) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +224 -2
  3. package/dist-types/exports/MainMenu.d.ts +2 -0
  4. package/dist-types/exports/MainMenu.d.ts.map +1 -0
  5. package/dist-types/exports/PageData.d.ts +2 -0
  6. package/dist-types/exports/PageData.d.ts.map +1 -0
  7. package/dist-types/exports/RocketCodeBlock.d.ts +2 -0
  8. package/dist-types/exports/RocketCodeBlock.d.ts.map +1 -0
  9. package/dist-types/exports/RocketIcon.d.ts +2 -0
  10. package/dist-types/exports/RocketIcon.d.ts.map +1 -0
  11. package/dist-types/exports/RocketJsDemo.d.ts +2 -0
  12. package/dist-types/exports/RocketJsDemo.d.ts.map +1 -0
  13. package/dist-types/exports/RocketRequestDemo.d.ts +2 -0
  14. package/dist-types/exports/RocketRequestDemo.d.ts.map +1 -0
  15. package/dist-types/exports/SocialPreviewPlayground.d.ts +2 -0
  16. package/dist-types/exports/SocialPreviewPlayground.d.ts.map +1 -0
  17. package/dist-types/exports/adapters/netlify.d.ts +2 -0
  18. package/dist-types/exports/adapters/netlify.d.ts.map +1 -0
  19. package/dist-types/exports/asyncMessage.d.ts +2 -0
  20. package/dist-types/exports/asyncMessage.d.ts.map +1 -0
  21. package/dist-types/exports/component-hydration.d.ts +2 -0
  22. package/dist-types/exports/component-hydration.d.ts.map +1 -0
  23. package/dist-types/exports/components/web-awesome.d.ts +3 -0
  24. package/dist-types/exports/components/web-awesome.d.ts.map +1 -0
  25. package/dist-types/exports/components.d.ts +2 -0
  26. package/dist-types/exports/components.d.ts.map +1 -0
  27. package/dist-types/exports/config.d.ts +2 -0
  28. package/dist-types/exports/config.d.ts.map +1 -0
  29. package/dist-types/exports/debounce.d.ts +2 -0
  30. package/dist-types/exports/debounce.d.ts.map +1 -0
  31. package/dist-types/exports/define/RocketCodeBlock.d.ts +2 -0
  32. package/dist-types/exports/define/RocketCodeBlock.d.ts.map +1 -0
  33. package/dist-types/exports/define/RocketIcon.d.ts +2 -0
  34. package/dist-types/exports/define/RocketIcon.d.ts.map +1 -0
  35. package/dist-types/exports/define/RocketJsDemo.d.ts +2 -0
  36. package/dist-types/exports/define/RocketJsDemo.d.ts.map +1 -0
  37. package/dist-types/exports/define/RocketRequestDemo.d.ts +2 -0
  38. package/dist-types/exports/define/RocketRequestDemo.d.ts.map +1 -0
  39. package/dist-types/exports/define/menus.d.ts +2 -0
  40. package/dist-types/exports/define/menus.d.ts.map +1 -0
  41. package/dist-types/exports/extractCode.d.ts +2 -0
  42. package/dist-types/exports/extractCode.d.ts.map +1 -0
  43. package/dist-types/exports/globalData.d.ts +2 -0
  44. package/dist-types/exports/globalData.d.ts.map +1 -0
  45. package/dist-types/exports/hydration/hydrationLoader.d.ts +2 -0
  46. package/dist-types/exports/hydration/hydrationLoader.d.ts.map +1 -0
  47. package/dist-types/exports/icons.d.ts +2 -0
  48. package/dist-types/exports/icons.d.ts.map +1 -0
  49. package/dist-types/exports/layout-helper.d.ts +2 -0
  50. package/dist-types/exports/layout-helper.d.ts.map +1 -0
  51. package/dist-types/exports/layout.d.ts +2 -0
  52. package/dist-types/exports/layout.d.ts.map +1 -0
  53. package/dist-types/exports/layouts/atlasDoc.d.ts +2 -0
  54. package/dist-types/exports/layouts/atlasDoc.d.ts.map +1 -0
  55. package/dist-types/exports/layouts/atlasHero.d.ts +2 -0
  56. package/dist-types/exports/layouts/atlasHero.d.ts.map +1 -0
  57. package/dist-types/exports/layouts/atlasNotFound.d.ts +2 -0
  58. package/dist-types/exports/layouts/atlasNotFound.d.ts.map +1 -0
  59. package/dist-types/exports/loaded-page-module.d.ts +2 -0
  60. package/dist-types/exports/loaded-page-module.d.ts.map +1 -0
  61. package/dist-types/exports/markdownHook.d.ts +2 -0
  62. package/dist-types/exports/markdownHook.d.ts.map +1 -0
  63. package/dist-types/exports/menu.d.ts +2 -0
  64. package/dist-types/exports/menu.d.ts.map +1 -0
  65. package/dist-types/exports/menus.d.ts +6 -0
  66. package/dist-types/exports/menus.d.ts.map +1 -0
  67. package/dist-types/exports/page-runtime.d.ts +2 -0
  68. package/dist-types/exports/page-runtime.d.ts.map +1 -0
  69. package/dist-types/exports/pages.d.ts +2 -0
  70. package/dist-types/exports/pages.d.ts.map +1 -0
  71. package/dist-types/exports/resolve.d.ts +2 -0
  72. package/dist-types/exports/resolve.d.ts.map +1 -0
  73. package/dist-types/exports/ssr.d.ts +2 -0
  74. package/dist-types/exports/ssr.d.ts.map +1 -0
  75. package/dist-types/exports/standalone-demo-url.d.ts +2 -0
  76. package/dist-types/exports/standalone-demo-url.d.ts.map +1 -0
  77. package/dist-types/exports/transform.d.ts +2 -0
  78. package/dist-types/exports/transform.d.ts.map +1 -0
  79. package/dist-types/exports/types/hydration.d.ts +23 -0
  80. package/dist-types/exports/types/hydration.d.ts.map +1 -0
  81. package/dist-types/exports/types/rocket.d.ts +504 -0
  82. package/dist-types/exports/types/rocket.d.ts.map +1 -0
  83. package/dist-types/exports/types.d.ts +3 -0
  84. package/dist-types/exports/types.d.ts.map +1 -0
  85. package/dist-types/exports/wds-plugin.d.ts +2 -0
  86. package/dist-types/exports/wds-plugin.d.ts.map +1 -0
  87. package/dist-types/src/PageData.d.ts +82 -0
  88. package/dist-types/src/PageData.d.ts.map +1 -0
  89. package/dist-types/src/RocketCodeBlock.d.ts +64 -0
  90. package/dist-types/src/RocketCodeBlock.d.ts.map +1 -0
  91. package/dist-types/src/RocketIcon.d.ts +35 -0
  92. package/dist-types/src/RocketIcon.d.ts.map +1 -0
  93. package/dist-types/src/RocketJsDemo.d.ts +59 -0
  94. package/dist-types/src/RocketJsDemo.d.ts.map +1 -0
  95. package/dist-types/src/RocketJsDemo.test-browser.d.ts +3 -0
  96. package/dist-types/src/RocketJsDemo.test-browser.d.ts.map +1 -0
  97. package/dist-types/src/RocketRequestDemo.d.ts +57 -0
  98. package/dist-types/src/RocketRequestDemo.d.ts.map +1 -0
  99. package/dist-types/src/RocketRequestDemo.test-browser.d.ts +3 -0
  100. package/dist-types/src/RocketRequestDemo.test-browser.d.ts.map +1 -0
  101. package/dist-types/src/SocialPreviewPlayground.d.ts +102 -0
  102. package/dist-types/src/SocialPreviewPlayground.d.ts.map +1 -0
  103. package/dist-types/src/adapters/netlify.d.ts +54 -0
  104. package/dist-types/src/adapters/netlify.d.ts.map +1 -0
  105. package/dist-types/src/asyncMessage.d.ts +14 -0
  106. package/dist-types/src/asyncMessage.d.ts.map +1 -0
  107. package/dist-types/src/cli/RocketBuild.d.ts +78 -0
  108. package/dist-types/src/cli/RocketBuild.d.ts.map +1 -0
  109. package/dist-types/src/cli/RocketCli.d.ts +17 -0
  110. package/dist-types/src/cli/RocketCli.d.ts.map +1 -0
  111. package/dist-types/src/cli/RocketInit.d.ts +22 -0
  112. package/dist-types/src/cli/RocketInit.d.ts.map +1 -0
  113. package/dist-types/src/cli/RocketStart.d.ts +13 -0
  114. package/dist-types/src/cli/RocketStart.d.ts.map +1 -0
  115. package/dist-types/src/cli/cli.d.ts +3 -0
  116. package/dist-types/src/cli/cli.d.ts.map +1 -0
  117. package/dist-types/src/component-hydration.d.ts +26 -0
  118. package/dist-types/src/component-hydration.d.ts.map +1 -0
  119. package/dist-types/src/components/FeatureList.d.ts +15 -0
  120. package/dist-types/src/components/FeatureList.d.ts.map +1 -0
  121. package/dist-types/src/components/Footer.d.ts +17 -0
  122. package/dist-types/src/components/Footer.d.ts.map +1 -0
  123. package/dist-types/src/components/Header.d.ts +6 -0
  124. package/dist-types/src/components/Header.d.ts.map +1 -0
  125. package/dist-types/src/components/RocketDrawer.d.ts +20 -0
  126. package/dist-types/src/components/RocketDrawer.d.ts.map +1 -0
  127. package/dist-types/src/components/RocketSocialLink.d.ts +30 -0
  128. package/dist-types/src/components/RocketSocialLink.d.ts.map +1 -0
  129. package/dist-types/src/components.d.ts +5 -0
  130. package/dist-types/src/components.d.ts.map +1 -0
  131. package/dist-types/src/config.d.ts +6 -0
  132. package/dist-types/src/config.d.ts.map +1 -0
  133. package/dist-types/src/debounce.d.ts +8 -0
  134. package/dist-types/src/debounce.d.ts.map +1 -0
  135. package/dist-types/src/defaultSocialPreviewTemplate.d.ts +31 -0
  136. package/dist-types/src/defaultSocialPreviewTemplate.d.ts.map +1 -0
  137. package/dist-types/src/development-page-module-loader.d.ts +15 -0
  138. package/dist-types/src/development-page-module-loader.d.ts.map +1 -0
  139. package/dist-types/src/extractCode.d.ts +5 -0
  140. package/dist-types/src/extractCode.d.ts.map +1 -0
  141. package/dist-types/src/hydration/evaluate.d.ts +20 -0
  142. package/dist-types/src/hydration/evaluate.d.ts.map +1 -0
  143. package/dist-types/src/hydration/extractStrategies.d.ts +5 -0
  144. package/dist-types/src/hydration/extractStrategies.d.ts.map +1 -0
  145. package/dist-types/src/hydration/hydrationLoader.d.ts +64 -0
  146. package/dist-types/src/hydration/hydrationLoader.d.ts.map +1 -0
  147. package/dist-types/src/icons.d.ts +170 -0
  148. package/dist-types/src/icons.d.ts.map +1 -0
  149. package/dist-types/src/layouts/atlas/atlasDocLayout.d.ts +45 -0
  150. package/dist-types/src/layouts/atlas/atlasDocLayout.d.ts.map +1 -0
  151. package/dist-types/src/layouts/atlas/atlasHeroLayout.d.ts +7 -0
  152. package/dist-types/src/layouts/atlas/atlasHeroLayout.d.ts.map +1 -0
  153. package/dist-types/src/layouts/atlas/atlasNotFoundLayout.d.ts +5 -0
  154. package/dist-types/src/layouts/atlas/atlasNotFoundLayout.d.ts.map +1 -0
  155. package/dist-types/src/layouts/layout-helper.d.ts +16 -0
  156. package/dist-types/src/layouts/layout-helper.d.ts.map +1 -0
  157. package/dist-types/src/layouts/layout.d.ts +9 -0
  158. package/dist-types/src/layouts/layout.d.ts.map +1 -0
  159. package/dist-types/src/loaded-page-module.d.ts +51 -0
  160. package/dist-types/src/loaded-page-module.d.ts.map +1 -0
  161. package/dist-types/src/main.d.ts +2 -0
  162. package/dist-types/src/main.d.ts.map +1 -0
  163. package/dist-types/src/markdownCompiler.d.ts +22 -0
  164. package/dist-types/src/markdownCompiler.d.ts.map +1 -0
  165. package/dist-types/src/markdownHook.d.ts +6 -0
  166. package/dist-types/src/markdownHook.d.ts.map +1 -0
  167. package/dist-types/src/menu.d.ts +22 -0
  168. package/dist-types/src/menu.d.ts.map +1 -0
  169. package/dist-types/src/menus/MainMenu.d.ts +23 -0
  170. package/dist-types/src/menus/MainMenu.d.ts.map +1 -0
  171. package/dist-types/src/menus/RocketMenu.d.ts +23 -0
  172. package/dist-types/src/menus/RocketMenu.d.ts.map +1 -0
  173. package/dist-types/src/menus/RocketNextPage.d.ts +18 -0
  174. package/dist-types/src/menus/RocketNextPage.d.ts.map +1 -0
  175. package/dist-types/src/menus/RocketPreviousPage.d.ts +18 -0
  176. package/dist-types/src/menus/RocketPreviousPage.d.ts.map +1 -0
  177. package/dist-types/src/menus/RocketToc.d.ts +54 -0
  178. package/dist-types/src/menus/RocketToc.d.ts.map +1 -0
  179. package/dist-types/src/menus/pageNavigation.d.ts +41 -0
  180. package/dist-types/src/menus/pageNavigation.d.ts.map +1 -0
  181. package/dist-types/src/page-pagination.d.ts +69 -0
  182. package/dist-types/src/page-pagination.d.ts.map +1 -0
  183. package/dist-types/src/page-runtime.d.ts +110 -0
  184. package/dist-types/src/page-runtime.d.ts.map +1 -0
  185. package/dist-types/src/pages.d.ts +10 -0
  186. package/dist-types/src/pages.d.ts.map +1 -0
  187. package/dist-types/src/publicAssets.d.ts +70 -0
  188. package/dist-types/src/publicAssets.d.ts.map +1 -0
  189. package/dist-types/src/requestDemoMetadata.d.ts +19 -0
  190. package/dist-types/src/requestDemoMetadata.d.ts.map +1 -0
  191. package/dist-types/src/resolve.d.ts +7 -0
  192. package/dist-types/src/resolve.d.ts.map +1 -0
  193. package/dist-types/src/siteDiscoverability.d.ts +33 -0
  194. package/dist-types/src/siteDiscoverability.d.ts.map +1 -0
  195. package/dist-types/src/siteHeadMetadata.d.ts +20 -0
  196. package/dist-types/src/siteHeadMetadata.d.ts.map +1 -0
  197. package/dist-types/src/socialPreviewImages.d.ts +186 -0
  198. package/dist-types/src/socialPreviewImages.d.ts.map +1 -0
  199. package/dist-types/src/socialPreviewTemplatePreview.d.ts +22 -0
  200. package/dist-types/src/socialPreviewTemplatePreview.d.ts.map +1 -0
  201. package/dist-types/src/ssr.d.ts +6 -0
  202. package/dist-types/src/ssr.d.ts.map +1 -0
  203. package/dist-types/src/standalone-demo-url.d.ts +60 -0
  204. package/dist-types/src/standalone-demo-url.d.ts.map +1 -0
  205. package/dist-types/src/static-page-module-loader.d.ts +15 -0
  206. package/dist-types/src/static-page-module-loader.d.ts.map +1 -0
  207. package/dist-types/src/transform.d.ts +10 -0
  208. package/dist-types/src/transform.d.ts.map +1 -0
  209. package/dist-types/src/urlLifecycle.d.ts +23 -0
  210. package/dist-types/src/urlLifecycle.d.ts.map +1 -0
  211. package/dist-types/src/wds-plugin.d.ts +14 -0
  212. package/dist-types/src/wds-plugin.d.ts.map +1 -0
  213. package/docs/assets/home-background.svg +1 -0
  214. package/docs/assets/prism-one-light.css +368 -0
  215. package/docs/assets/rocket-logo-dark-with-text-below.svg +8 -0
  216. package/docs/assets/rocket-logo-dark-with-text.svg +7 -0
  217. package/docs/assets/rocket-logo-dark.svg +7 -0
  218. package/docs/assets/rocket-logo-light-with-text-below.svg +14 -0
  219. package/docs/assets/rocket-logo-light-with-text.svg +13 -0
  220. package/docs/assets/rocket-logo-light.svg +12 -0
  221. package/docs/assets/rocket-text-no-logo.svg +3 -0
  222. package/exports/MainMenu.js +1 -0
  223. package/exports/PageData.js +1 -0
  224. package/exports/RocketCodeBlock.js +1 -0
  225. package/exports/RocketIcon.js +1 -0
  226. package/exports/RocketJsDemo.js +1 -0
  227. package/exports/RocketRequestDemo.js +1 -0
  228. package/exports/SocialPreviewPlayground.js +1 -0
  229. package/exports/adapters/netlify.js +1 -0
  230. package/exports/asyncMessage.js +1 -0
  231. package/exports/component-hydration.js +1 -0
  232. package/exports/components/web-awesome.js +63 -0
  233. package/exports/components.js +1 -0
  234. package/exports/config.js +1 -0
  235. package/exports/debounce.js +1 -0
  236. package/exports/define/RocketCodeBlock.js +2 -0
  237. package/exports/define/RocketIcon.js +3 -0
  238. package/exports/define/RocketJsDemo.js +5 -0
  239. package/exports/define/RocketRequestDemo.js +5 -0
  240. package/exports/define/menus.js +14 -0
  241. package/exports/extractCode.js +1 -0
  242. package/exports/globalData.js +1 -0
  243. package/exports/hydration/hydrationLoader.js +1 -0
  244. package/exports/icons.js +8 -0
  245. package/exports/layout-helper.js +1 -0
  246. package/exports/layout.js +1 -0
  247. package/exports/layouts/_atlas.css +3 -0
  248. package/exports/layouts/atlasDoc.js +5 -0
  249. package/exports/layouts/atlasHero.js +1 -0
  250. package/exports/layouts/atlasNotFound.js +4 -0
  251. package/exports/loaded-page-module.js +5 -0
  252. package/exports/markdownHook.js +4 -0
  253. package/exports/menu.js +4 -0
  254. package/exports/menus.js +5 -0
  255. package/exports/page-runtime.js +5 -0
  256. package/exports/pages.js +1 -0
  257. package/exports/resolve.js +1 -0
  258. package/exports/ssr.js +1 -0
  259. package/exports/standalone-demo-url.js +10 -0
  260. package/exports/transform.js +1 -0
  261. package/exports/types/hydration.ts +26 -0
  262. package/exports/types/rocket.ts +598 -0
  263. package/exports/types.ts +71 -0
  264. package/exports/wds-plugin.js +1 -0
  265. package/package.json +192 -9
  266. package/src/PageData.js +244 -0
  267. package/src/RocketCodeBlock.js +516 -0
  268. package/src/RocketIcon.js +291 -0
  269. package/src/RocketJsDemo.js +397 -0
  270. package/src/RocketJsDemo.test-browser.js +228 -0
  271. package/src/RocketRequestDemo.js +439 -0
  272. package/src/RocketRequestDemo.test-browser.js +301 -0
  273. package/src/SocialPreviewPlayground.js +573 -0
  274. package/src/adapters/netlify.js +814 -0
  275. package/src/asyncMessage.js +21 -0
  276. package/src/cli/RocketBuild.js +545 -0
  277. package/src/cli/RocketCli.js +47 -0
  278. package/src/cli/RocketInit.js +323 -0
  279. package/src/cli/RocketStart.js +79 -0
  280. package/src/cli/cli.js +7 -0
  281. package/src/component-hydration.js +86 -0
  282. package/src/components/FeatureList.js +114 -0
  283. package/src/components/Footer.js +116 -0
  284. package/src/components/Header.js +122 -0
  285. package/src/components/RocketDrawer.js +193 -0
  286. package/src/components/RocketSocialLink.js +128 -0
  287. package/src/components/assets/discord.svg +7 -0
  288. package/src/components/assets/github.svg +4 -0
  289. package/src/components/assets/gitlab.svg +1 -0
  290. package/src/components/assets/info.txt +1 -0
  291. package/src/components/assets/license.svg +3 -0
  292. package/src/components/assets/npm.svg +5 -0
  293. package/src/components/assets/slack.svg +5 -0
  294. package/src/components/assets/telegram.svg +4 -0
  295. package/src/components/assets/twitter.svg +1 -0
  296. package/src/components.js +15 -0
  297. package/src/config.js +319 -0
  298. package/src/debounce.js +21 -0
  299. package/src/defaultSocialPreviewTemplate.js +118 -0
  300. package/src/development-page-module-loader.js +29 -0
  301. package/src/extractCode.js +41 -0
  302. package/src/hydration/evaluate.js +54 -0
  303. package/src/hydration/extractStrategies.js +91 -0
  304. package/src/hydration/hydrationLoader.js +330 -0
  305. package/src/icons.js +883 -0
  306. package/src/layouts/atlas/atlasDoc.css +877 -0
  307. package/src/layouts/atlas/atlasDocLayout.js +288 -0
  308. package/src/layouts/atlas/atlasHero.css +774 -0
  309. package/src/layouts/atlas/atlasHeroLayout.js +346 -0
  310. package/src/layouts/atlas/atlasNotFound.css +365 -0
  311. package/src/layouts/atlas/atlasNotFoundLayout.js +69 -0
  312. package/src/layouts/layout-helper.js +92 -0
  313. package/src/layouts/layout.js +62 -0
  314. package/src/loaded-page-module.js +97 -0
  315. package/src/main.js +55 -0
  316. package/src/markdownCompiler.js +303 -0
  317. package/src/markdownHook.js +148 -0
  318. package/src/menu.js +210 -0
  319. package/src/menus/MainMenu.js +58 -0
  320. package/src/menus/RocketMenu.js +191 -0
  321. package/src/menus/RocketNextPage.js +25 -0
  322. package/src/menus/RocketPreviousPage.js +29 -0
  323. package/src/menus/RocketToc.js +309 -0
  324. package/src/menus/pageNavigation.js +285 -0
  325. package/src/page-pagination.js +241 -0
  326. package/src/page-runtime.js +481 -0
  327. package/src/pages.js +537 -0
  328. package/src/publicAssets.js +336 -0
  329. package/src/requestDemoMetadata.js +97 -0
  330. package/src/resolve.js +15 -0
  331. package/src/siteDiscoverability.js +184 -0
  332. package/src/siteHeadMetadata.js +69 -0
  333. package/src/socialPreviewImages.js +482 -0
  334. package/src/socialPreviewTemplatePreview.js +352 -0
  335. package/src/ssr.js +14 -0
  336. package/src/standalone-demo-url.js +134 -0
  337. package/src/static-page-module-loader.js +29 -0
  338. package/src/transform.js +633 -0
  339. package/src/urlLifecycle.js +57 -0
  340. package/src/wds-plugin.js +302 -0
@@ -0,0 +1,814 @@
1
+ /** Runs on: server */
2
+ import { createHash } from 'node:crypto';
3
+ import { copyFileSync, cpSync, existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
4
+ import path from 'node:path';
5
+ import { fileURLToPath, pathToFileURL } from 'node:url';
6
+ import { build } from 'vite';
7
+ import { normalizeIconLibrariesConfig, rocketIconRuntimeOutputs } from '../icons.js';
8
+ import { rocketMarkdownPlugin } from '../markdownCompiler.js';
9
+ import { standaloneDemoRoutePatterns } from '../standalone-demo-url.js';
10
+
11
+ const ROCKET_ICON_FUNCTION_PATHS = [
12
+ '/_rocket/icons/:library/:iconFile',
13
+ '/_rocket/rocket-icon.js',
14
+ '/_rocket/RocketIcon.js',
15
+ ];
16
+ const ROCKET_BOOTSTRAP_ICON_INCLUDED_FILES = [
17
+ 'node_modules/bootstrap-icons/package.json',
18
+ 'node_modules/bootstrap-icons/icons/*.svg',
19
+ ];
20
+ const ROCKET_BOOTSTRAP_ICON_LIBRARIES = {
21
+ bootstrap: { type: 'package', packageName: 'bootstrap-icons', files: 'icons/*.svg' },
22
+ };
23
+
24
+ /**
25
+ * @returns {import('@rocket/js/types.js').RocketAdapter}
26
+ */
27
+ export function netlify() {
28
+ return {
29
+ name: 'netlify',
30
+ async build(context) {
31
+ writeNetlifyRedirectOutput(context);
32
+ await buildNetlifyFunction(context);
33
+ },
34
+ };
35
+ }
36
+
37
+ /**
38
+ * @param {import('@rocket/js/types.js').RocketAdapterBuildContext} context
39
+ */
40
+ function writeNetlifyRedirectOutput(context) {
41
+ const redirects = context.config.urlLifecycle?.redirects || [];
42
+ if (!redirects.length) {
43
+ return;
44
+ }
45
+
46
+ mkdirSync(context.outDir, { recursive: true });
47
+ writeFileSync(path.join(context.outDir, '_redirects'), makeNetlifyRedirectsSource(redirects));
48
+ }
49
+
50
+ /**
51
+ * @param {import('@rocket/js/types.js').RedirectConfig[]} redirects
52
+ */
53
+ function makeNetlifyRedirectsSource(redirects) {
54
+ return redirects
55
+ .map(redirect => `${redirect.source} ${redirect.target} ${redirect.status || 308}`)
56
+ .join('\n')
57
+ .concat('\n');
58
+ }
59
+
60
+ /**
61
+ * @param {import('@rocket/js/types.js').RocketAdapterBuildContext} context
62
+ */
63
+ async function buildNetlifyFunction(context) {
64
+ if (context.serverPages.size === 0) {
65
+ return;
66
+ }
67
+
68
+ const tempDir = path.join(context.projectRoot, 'tmp-netlify-rocket');
69
+ const entryFile = path.join(tempDir, 'rocket-ssr-entry.js');
70
+ const componentsEntryFile = path.join(tempDir, 'rocket-live-components.js');
71
+ const functionsDir = path.join(context.projectRoot, '.netlify', 'v1', 'functions');
72
+ const functionFile = path.join(functionsDir, 'rocket-ssr.mjs');
73
+ const liveAssets = new LiveAssets(context);
74
+
75
+ if (existsSync(tempDir)) {
76
+ rmSync(tempDir, { recursive: true });
77
+ }
78
+ mkdirSync(tempDir, { recursive: true });
79
+ mkdirSync(functionsDir, { recursive: true });
80
+ if (existsSync(functionFile)) {
81
+ rmSync(functionFile);
82
+ }
83
+
84
+ try {
85
+ copyServerAssets(context, functionsDir);
86
+ writeFileSync(componentsEntryFile, makeLiveComponentsSource(context, liveAssets));
87
+ writeFileSync(entryFile, makeNetlifyFunctionSource(context));
88
+
89
+ await build({
90
+ configFile: false,
91
+ publicDir: false,
92
+ root: context.projectRoot,
93
+ plugins: [rocketMarkdownPlugin(), liveAssetPlugin(context, liveAssets)],
94
+ resolve: {
95
+ alias: [
96
+ { find: '@rocket/js/components.js', replacement: componentsEntryFile },
97
+ {
98
+ find: path.join(context.projectRoot, 'exports/components.js'),
99
+ replacement: componentsEntryFile,
100
+ },
101
+ {
102
+ find: path.join(context.projectRoot, 'src/components.js'),
103
+ replacement: componentsEntryFile,
104
+ },
105
+ ],
106
+ },
107
+ ssr: {
108
+ noExternal: true,
109
+ },
110
+ build: {
111
+ ssr: entryFile,
112
+ outDir: functionsDir,
113
+ emptyOutDir: false,
114
+ target: 'node22',
115
+ minify: false,
116
+ rollupOptions: {
117
+ output: {
118
+ entryFileNames: 'rocket-ssr.mjs',
119
+ format: 'es',
120
+ },
121
+ },
122
+ },
123
+ });
124
+
125
+ await buildLiveAssets(context, liveAssets);
126
+ } finally {
127
+ if (existsSync(tempDir)) {
128
+ rmSync(tempDir, { recursive: true });
129
+ }
130
+ }
131
+ }
132
+
133
+ /**
134
+ * @param {import('@rocket/js/types.js').RocketAdapterBuildContext} context
135
+ * @param {string} functionsDir
136
+ */
137
+ function copyServerAssets(context, functionsDir) {
138
+ const componentAssets = path.join(context.projectRoot, 'src/components/assets');
139
+ if (existsSync(componentAssets)) {
140
+ cpSync(componentAssets, path.join(functionsDir, 'assets'), { recursive: true });
141
+ }
142
+ }
143
+
144
+ /**
145
+ * @param {import('@rocket/js/types.js').RocketAdapterBuildContext} context
146
+ */
147
+ export function makeNetlifyFunctionSource(context) {
148
+ const allPages = Array.from(context.pages, ([pagePath, page]) => ({
149
+ path: pagePath,
150
+ file: page.file,
151
+ metadata: page.metadata,
152
+ demoNames: page.demoNames,
153
+ config: page.module.config,
154
+ }));
155
+ const serverPages = Array.from(context.serverPages, ([pagePath, page], index) => {
156
+ const type = page.file.endsWith('.rocket.md') ? 'markdown' : 'javascript';
157
+ const demoNames = page.demoNames || [];
158
+ return {
159
+ path: pagePath,
160
+ file: page.file,
161
+ metadata: page.metadata,
162
+ demoNames,
163
+ config: page.module.config,
164
+ moduleName: `pageModule${index}`,
165
+ routePatterns: standaloneDemoRoutePatterns(pagePath, page),
166
+ type,
167
+ standaloneDemos:
168
+ type === 'markdown'
169
+ ? demoNames.map((demoName, demoIndex) => ({
170
+ demoName,
171
+ moduleName: `pageModule${index}StandaloneDemo${demoIndex}`,
172
+ }))
173
+ : [],
174
+ };
175
+ });
176
+
177
+ const imports = serverPages
178
+ .flatMap(page => {
179
+ const specifier = pageModuleSpecifier(context, page.file);
180
+ return [
181
+ `import * as ${page.moduleName} from ${JSON.stringify(specifier)};`,
182
+ ...page.standaloneDemos.map(demo => {
183
+ const demoSpecifier = standaloneDemoModuleSpecifier(context, page.file, demo.demoName);
184
+ return `import * as ${demo.moduleName} from ${JSON.stringify(demoSpecifier)};`;
185
+ }),
186
+ ];
187
+ })
188
+ .join('\n');
189
+
190
+ const configPaths = JSON.stringify([
191
+ ...serverPages.flatMap(page => [page.path, ...page.routePatterns]),
192
+ ...ROCKET_ICON_FUNCTION_PATHS,
193
+ ]);
194
+ const includedFiles = JSON.stringify(netlifyIncludedFiles(context));
195
+ const rocketIconRuntimeOutputEntries = JSON.stringify(rocketIconRuntimeOutputs());
196
+ const urlLifecycle = JSON.stringify(context.config.urlLifecycle);
197
+ const siteOrigin = JSON.stringify(context.config.siteOrigin);
198
+ const siteHeadMetadata = JSON.stringify(context.config.siteHeadMetadata);
199
+ const defaultSocialPreviewImages = JSON.stringify(
200
+ Array.from(context.defaultSocialPreviewImages || []),
201
+ );
202
+ const standaloneDemoModuleEntries = serverPages
203
+ .filter(page => page.standaloneDemos.length)
204
+ .map(
205
+ page =>
206
+ `[${JSON.stringify(page.path)}, new Map([${page.standaloneDemos
207
+ .map(demo => `[${JSON.stringify(demo.demoName)}, ${demo.moduleName}]`)
208
+ .join(',')}])]`,
209
+ )
210
+ .join(',');
211
+ const manifest = serverPages.map(page => ({
212
+ path: page.path,
213
+ file: page.file,
214
+ metadata: page.metadata,
215
+ config: page.config,
216
+ type: page.type,
217
+ }));
218
+
219
+ return `import { normalizeLoadedPageModule } from '@rocket/js/loaded-page-module.js';
220
+ import { PageRuntime, PageRuntimeError } from '@rocket/js/page-runtime.js';
221
+ import { parseComponents } from '@rocket/js/components.js';
222
+ import { createIconAssetStore, resolveRocketIconAsset } from '@rocket/js/icons.js';
223
+ ${imports}
224
+
225
+ const pageModules = [${serverPages.map(page => page.moduleName).join(', ')}];
226
+ const standaloneDemoModules = new Map([${standaloneDemoModuleEntries}]);
227
+ const allPages = ${JSON.stringify(allPages)};
228
+ const serverPages = ${JSON.stringify(manifest)}.map((page, index) => ({
229
+ ...page,
230
+ module: pageModules[index],
231
+ }));
232
+ const pageRegistry = new Map(
233
+ allPages.map(page => [
234
+ page.path,
235
+ {
236
+ file: page.file,
237
+ metadata: page.metadata,
238
+ demoNames: page.demoNames,
239
+ module: { config: page.config },
240
+ },
241
+ ]),
242
+ );
243
+ const serverPageModules = new Map(serverPages.map(page => [page.path, page.module]));
244
+ const urlLifecycle = ${urlLifecycle};
245
+ const siteOrigin = ${siteOrigin};
246
+ const siteHeadMetadata = ${siteHeadMetadata};
247
+ const iconLibraries = ${JSON.stringify(context.config.iconLibraries)};
248
+ const defaultIconLibrary = ${JSON.stringify(context.config.defaultIconLibrary)};
249
+ const rocketBootstrapIconLibraries = ${JSON.stringify(ROCKET_BOOTSTRAP_ICON_LIBRARIES)};
250
+ const defaultSocialPreviewImages = new Map(${defaultSocialPreviewImages});
251
+ const iconAssetStore = createIconAssetStore();
252
+ const rocketIconRuntimeOutputsByPath = new Map(
253
+ ${rocketIconRuntimeOutputEntries}.map(output => [output.path, output]),
254
+ );
255
+ const pageModuleLoader = {
256
+ async load({ page, routePath, variant }) {
257
+ if (page.file.endsWith('.rocket.md')) {
258
+ const module = getMarkdownPageModule(routePath, variant);
259
+ return normalizeLoadedPageModule({ kind: 'markdown', module, parseComponents });
260
+ }
261
+ const module = serverPageModules.get(routePath);
262
+ return normalizeLoadedPageModule({ kind: 'javascript', module, parseComponents });
263
+ },
264
+ };
265
+ const pageRuntime = new PageRuntime({
266
+ pages: pageRegistry,
267
+ pageModuleLoader,
268
+ urlLifecycle,
269
+ siteHeadMetadata,
270
+ siteOrigin,
271
+ iconLibraries,
272
+ defaultIconLibrary,
273
+ iconAssetStore,
274
+ defaultSocialPreviewImages,
275
+ });
276
+
277
+ export const config = {
278
+ path: ${configPaths},
279
+ preferStatic: true,
280
+ generator: '@rocket/js',
281
+ includedFiles: ${includedFiles},
282
+ };
283
+
284
+ export default async function handler(request, context) {
285
+ const url = new URL(request.url);
286
+
287
+ try {
288
+ const rocketIconResponse = await renderRocketIconOutput(url.pathname);
289
+ if (rocketIconResponse) {
290
+ return rocketIconResponse;
291
+ }
292
+ return await pageRuntime.render(request, { adapterContext: context });
293
+ } catch (error) {
294
+ if (!(error instanceof PageRuntimeError)) {
295
+ throw error;
296
+ }
297
+ console.error('Failed to render page: ' + url.pathname, error);
298
+ return new Response('Internal Server Error', { status: 500 });
299
+ }
300
+ }
301
+
302
+ async function renderRocketIconOutput(pathname) {
303
+ const runtimeOutput = rocketIconRuntimeOutputsByPath.get(pathname);
304
+ if (runtimeOutput) {
305
+ return new Response(runtimeOutput.data, {
306
+ headers: { 'content-type': runtimeOutput.type },
307
+ });
308
+ }
309
+
310
+ const iconAsset =
311
+ iconAssetStore.get(pathname) ||
312
+ (await resolveRocketIconAsset(pathname, {
313
+ iconLibraries,
314
+ defaultIconLibrary,
315
+ })) ||
316
+ (await resolveRocketIconAsset(pathname, {
317
+ iconLibraries: rocketBootstrapIconLibraries,
318
+ }));
319
+ if (!iconAsset) {
320
+ return undefined;
321
+ }
322
+ return new Response(iconAsset.svg, {
323
+ headers: { 'content-type': 'image/svg+xml' },
324
+ });
325
+ }
326
+
327
+ function getMarkdownPageModule(routePath, variant) {
328
+ if (typeof variant === 'object' && variant.kind === 'standalone-demo') {
329
+ const module = standaloneDemoModules.get(routePath)?.get(variant.demoName);
330
+ if (module) {
331
+ return module;
332
+ }
333
+ }
334
+ return serverPageModules.get(routePath);
335
+ }
336
+
337
+ `;
338
+ }
339
+
340
+ /**
341
+ * @param {import('@rocket/js/types.js').RocketAdapterBuildContext} context
342
+ * @returns {string[]}
343
+ */
344
+ function netlifyIncludedFiles(context) {
345
+ const includedFiles = new Set(['assets/**', ...ROCKET_BOOTSTRAP_ICON_INCLUDED_FILES]);
346
+ const iconLibraries = normalizeIconLibrariesConfig(
347
+ context.config.iconLibraries,
348
+ 'Icon Library Configuration',
349
+ );
350
+ for (const config of iconLibraries.values()) {
351
+ for (const source of config.sources) {
352
+ if (source.type === 'package') {
353
+ includedFiles.add(
354
+ normalizePath(path.join('node_modules', source.packageName, 'package.json')),
355
+ );
356
+ includedFiles.add(
357
+ normalizePath(path.join('node_modules', source.packageName, source.files)),
358
+ );
359
+ } else {
360
+ includedFiles.add(netlifyIncludedPathSource(source.files, context.projectRoot));
361
+ }
362
+ }
363
+ }
364
+ return [...includedFiles];
365
+ }
366
+
367
+ /**
368
+ * @param {string} files
369
+ * @param {string} projectRoot
370
+ */
371
+ function netlifyIncludedPathSource(files, projectRoot) {
372
+ const resolved = path.resolve(projectRoot, files);
373
+ const relative = path.relative(projectRoot, resolved);
374
+ if (relative && !relative.startsWith(`..${path.sep}`) && relative !== '..') {
375
+ return normalizePath(relative);
376
+ }
377
+ return normalizePath(files);
378
+ }
379
+
380
+ /**
381
+ * @param {import('@rocket/js/types.js').RocketAdapterBuildContext} context
382
+ * @param {string} file
383
+ */
384
+ function pageModuleSpecifier(context, file) {
385
+ return pathToFileURL(path.resolve(context.projectRoot, file)).href;
386
+ }
387
+
388
+ /**
389
+ * @param {import('@rocket/js/types.js').RocketAdapterBuildContext} context
390
+ * @param {string} file
391
+ * @param {string} demoName
392
+ */
393
+ function standaloneDemoModuleSpecifier(context, file, demoName) {
394
+ const specifier = new URL(pageModuleSpecifier(context, file));
395
+ specifier.searchParams.set('rocketSingleDemo', demoName);
396
+ return specifier.href;
397
+ }
398
+
399
+ /**
400
+ * @param {import('@rocket/js/types.js').RocketAdapterBuildContext} context
401
+ * @param {LiveAssets} liveAssets
402
+ */
403
+ export function makeLiveComponentsSource(context, liveAssets) {
404
+ const componentFiles = collectComponentFiles(context);
405
+ const moduleImports = [];
406
+ const moduleEntries = [];
407
+ const publicPathEntries = [];
408
+ let index = 0;
409
+
410
+ for (const [componentFile, { needsClient }] of componentFiles) {
411
+ const moduleName = `componentModule${index++}`;
412
+ const resolvedFile = resolveComponentFile(componentFile, context);
413
+ moduleImports.push(
414
+ `import * as ${moduleName} from ${JSON.stringify(pathToFileURL(resolvedFile).href)};`,
415
+ );
416
+ moduleEntries.push(`[${JSON.stringify(componentFile)}, ${moduleName}]`);
417
+ if (needsClient) {
418
+ publicPathEntries.push(
419
+ `[${JSON.stringify(componentFile)}, ${JSON.stringify(liveAssets.registerEntry(resolvedFile))}]`,
420
+ );
421
+ }
422
+ }
423
+
424
+ const hydrationLoaderPath = liveAssets.registerEntry(
425
+ path.join(context.projectRoot, 'src/hydration/hydrationLoader.js'),
426
+ );
427
+
428
+ return `import { customElements } from '@lit-labs/ssr-dom-shim';
429
+ import { createComponentHydration } from '@rocket/js/component-hydration.js';
430
+ ${moduleImports.join('\n')}
431
+
432
+ customElements.define = (name, ctor) => {
433
+ customElements.__definitions.set(name, {
434
+ ctor,
435
+ observedAttributes: ctor.observedAttributes ?? [],
436
+ });
437
+ };
438
+
439
+ const componentModules = new Map([${moduleEntries.join(', ')}]);
440
+ const componentPublicPaths = new Map([${publicPathEntries.join(', ')}]);
441
+
442
+ export const parseComponents = createComponentHydration({
443
+ customElementsRegistry: customElements,
444
+ loadComponentModule: getComponentModule,
445
+ resolveBrowserImport: getComponentPublicPath,
446
+ hydrationLoaderSpecifier: ${JSON.stringify(hydrationLoaderPath)},
447
+ });
448
+
449
+ async function getComponentModule(file) {
450
+ const module = componentModules.get(file);
451
+ if (module) {
452
+ return module;
453
+ }
454
+ return import(file);
455
+ }
456
+
457
+ function getComponentPublicPath(file) {
458
+ return componentPublicPaths.get(file) || file;
459
+ }
460
+ `;
461
+ }
462
+
463
+ /**
464
+ * @param {import('@rocket/js/types.js').RocketAdapterBuildContext} context
465
+ * @returns {Map<string, {needsClient: boolean}>}
466
+ */
467
+ function collectComponentFiles(context) {
468
+ /** @type {Map<string, {needsClient: boolean}>} */
469
+ const componentFiles = new Map();
470
+ for (const page of context.serverPages.values()) {
471
+ const components = page.module.components;
472
+ if (!components) {
473
+ continue;
474
+ }
475
+ for (const component of Object.values(components)) {
476
+ const existing = componentFiles.get(component.file);
477
+ const needsClient =
478
+ component.loading === 'client' || component.loading.startsWith('hydrate:');
479
+ componentFiles.set(component.file, {
480
+ needsClient: needsClient || existing?.needsClient || false,
481
+ });
482
+ }
483
+ }
484
+ return componentFiles;
485
+ }
486
+
487
+ /**
488
+ * @param {string} file
489
+ * @param {import('@rocket/js/types.js').RocketAdapterBuildContext} context
490
+ * @returns {string}
491
+ */
492
+ function resolveComponentFile(file, context) {
493
+ if (file.startsWith('.')) {
494
+ return path.resolve(context.projectRoot, 'src', file);
495
+ }
496
+ if (path.isAbsolute(file)) {
497
+ return file;
498
+ }
499
+ return fileURLToPath(import.meta.resolve(file));
500
+ }
501
+
502
+ class LiveAssets {
503
+ /**
504
+ * @param {import('@rocket/js/types.js').RocketAdapterBuildContext} context
505
+ */
506
+ constructor(context) {
507
+ this.context = context;
508
+ /** @type {Map<string, {file: string; name: string; publicPath: string; outputPath: string}>} */
509
+ this.entries = new Map();
510
+ /** @type {Map<string, {file: string; publicPath: string; outputPath: string}>} */
511
+ this.assets = new Map();
512
+ }
513
+
514
+ /**
515
+ * @param {string} file
516
+ * @returns {string}
517
+ */
518
+ register(file) {
519
+ const cleanFile = stripQuery(file);
520
+ const ext = path.extname(cleanFile).toLowerCase();
521
+ if (isBundledAsset(ext)) {
522
+ return this.registerEntry(cleanFile);
523
+ }
524
+ return this.registerCopiedAsset(cleanFile);
525
+ }
526
+
527
+ /**
528
+ * @param {string} file
529
+ * @returns {string}
530
+ */
531
+ registerEntry(file) {
532
+ const cleanFile = stripQuery(file);
533
+ const existing = this.entries.get(cleanFile);
534
+ if (existing) {
535
+ return existing.publicPath;
536
+ }
537
+ const ext = path.extname(cleanFile).toLowerCase();
538
+ const name = liveAssetName(cleanFile);
539
+ const publicExt = ext === '.css' ? '.css' : '.js';
540
+ const publicPath = `/assets/rocket-live/${name}${publicExt}`;
541
+ this.entries.set(cleanFile, {
542
+ file: cleanFile,
543
+ name,
544
+ publicPath,
545
+ outputPath: path.join(this.context.outDir, publicPath.slice(1)),
546
+ });
547
+ return publicPath;
548
+ }
549
+
550
+ /**
551
+ * @param {string} file
552
+ * @returns {string}
553
+ */
554
+ registerCopiedAsset(file) {
555
+ const cleanFile = stripQuery(file);
556
+ const existing = this.assets.get(cleanFile);
557
+ if (existing) {
558
+ return existing.publicPath;
559
+ }
560
+ const ext = path.extname(cleanFile);
561
+ const publicPath = `/assets/rocket-live/${liveAssetName(cleanFile)}${ext}`;
562
+ this.assets.set(cleanFile, {
563
+ file: cleanFile,
564
+ publicPath,
565
+ outputPath: path.join(this.context.outDir, publicPath.slice(1)),
566
+ });
567
+ return publicPath;
568
+ }
569
+
570
+ getInput() {
571
+ return Object.fromEntries(Array.from(this.entries.values(), entry => [entry.name, entry.file]));
572
+ }
573
+
574
+ copyAssets() {
575
+ for (const asset of this.assets.values()) {
576
+ mkdirSync(path.dirname(asset.outputPath), { recursive: true });
577
+ copyFileSync(asset.file, asset.outputPath);
578
+ }
579
+ }
580
+ }
581
+
582
+ /**
583
+ * @param {import('@rocket/js/types.js').RocketAdapterBuildContext} context
584
+ * @param {LiveAssets} liveAssets
585
+ */
586
+ async function buildLiveAssets(context, liveAssets) {
587
+ const input = liveAssets.getInput();
588
+ if (Object.keys(input).length) {
589
+ await build({
590
+ configFile: false,
591
+ publicDir: false,
592
+ root: context.projectRoot,
593
+ build: {
594
+ outDir: context.outDir,
595
+ emptyOutDir: false,
596
+ target: 'esnext',
597
+ rollupOptions: {
598
+ preserveEntrySignatures: 'strict',
599
+ input,
600
+ output: {
601
+ entryFileNames: 'assets/rocket-live/[name].js',
602
+ chunkFileNames: 'assets/rocket-live/[name]-[hash].js',
603
+ assetFileNames: 'assets/rocket-live/[name][extname]',
604
+ },
605
+ },
606
+ },
607
+ });
608
+ }
609
+ liveAssets.copyAssets();
610
+ }
611
+
612
+ /**
613
+ * @param {import('@rocket/js/types.js').RocketAdapterBuildContext} context
614
+ * @param {LiveAssets} liveAssets
615
+ * @returns {import('vite').Plugin}
616
+ */
617
+ function liveAssetPlugin(context, liveAssets) {
618
+ const rocketResolveModules = new Set([
619
+ normalizePath(path.join(context.projectRoot, 'src/resolve.js')),
620
+ normalizePath(path.join(context.projectRoot, 'exports/resolve.js')),
621
+ ]);
622
+
623
+ return {
624
+ name: 'rocket-live-assets',
625
+ enforce: 'post',
626
+ async transform(code, id) {
627
+ if (!code.includes('resolve') || !code.includes('import.meta')) {
628
+ return;
629
+ }
630
+
631
+ let ast;
632
+ try {
633
+ ast = this.parse(code);
634
+ } catch {
635
+ return;
636
+ }
637
+
638
+ const resolveNames = await findRocketResolveNames(ast, id, this, rocketResolveModules);
639
+ if (resolveNames.size === 0) {
640
+ return;
641
+ }
642
+
643
+ /** @type {any[]} */
644
+ const callNodes = [];
645
+ walk(ast, node => {
646
+ if (
647
+ node.type === 'CallExpression' &&
648
+ node.callee.type === 'Identifier' &&
649
+ resolveNames.has(node.callee.name) &&
650
+ node.arguments.length >= 2 &&
651
+ node.arguments[0].type === 'Literal' &&
652
+ typeof node.arguments[0].value === 'string' &&
653
+ isImportMeta(node.arguments[1])
654
+ ) {
655
+ callNodes.push(node);
656
+ }
657
+ });
658
+
659
+ if (callNodes.length === 0) {
660
+ return;
661
+ }
662
+
663
+ const replacements = [];
664
+ for (const node of callNodes) {
665
+ const specifier = node.arguments[0].value;
666
+ const resolved = await this.resolve(specifier, id, { skipSelf: true });
667
+ if (!resolved || resolved.external) {
668
+ continue;
669
+ }
670
+ replacements.push({
671
+ start: node.start,
672
+ end: node.end,
673
+ value: JSON.stringify(liveAssets.register(resolved.id)),
674
+ });
675
+ }
676
+
677
+ if (replacements.length === 0) {
678
+ return;
679
+ }
680
+
681
+ return {
682
+ code: applyReplacements(code, replacements),
683
+ map: null,
684
+ };
685
+ },
686
+ };
687
+ }
688
+
689
+ /**
690
+ * @param {any} ast
691
+ * @param {string} id
692
+ * @param {any} pluginContext
693
+ * @param {Set<string>} rocketResolveModules
694
+ * @returns {Promise<Set<string>>}
695
+ */
696
+ async function findRocketResolveNames(ast, id, pluginContext, rocketResolveModules) {
697
+ /** @type {{source: string; localName: string}[]} */
698
+ const imports = [];
699
+ walk(ast, node => {
700
+ if (node.type !== 'ImportDeclaration') {
701
+ return;
702
+ }
703
+ for (const specifier of node.specifiers) {
704
+ if (
705
+ specifier.type === 'ImportSpecifier' &&
706
+ specifier.imported.type === 'Identifier' &&
707
+ specifier.imported.name === 'resolve'
708
+ ) {
709
+ imports.push({
710
+ source: node.source.value,
711
+ localName: specifier.local.name,
712
+ });
713
+ }
714
+ }
715
+ });
716
+
717
+ const resolveNames = new Set();
718
+ for (const importData of imports) {
719
+ const resolved = await pluginContext.resolve(importData.source, id, { skipSelf: true });
720
+ if (!resolved || resolved.external) {
721
+ continue;
722
+ }
723
+ if (rocketResolveModules.has(normalizePath(stripQuery(resolved.id)))) {
724
+ resolveNames.add(importData.localName);
725
+ }
726
+ }
727
+ return resolveNames;
728
+ }
729
+
730
+ /**
731
+ * @param {any} node
732
+ * @param {(node: any) => void} visitor
733
+ */
734
+ function walk(node, visitor) {
735
+ if (!node || typeof node.type !== 'string') {
736
+ return;
737
+ }
738
+ visitor(node);
739
+ for (const value of Object.values(node)) {
740
+ if (Array.isArray(value)) {
741
+ for (const child of value) {
742
+ walk(child, visitor);
743
+ }
744
+ } else if (value && typeof value === 'object' && typeof value.type === 'string') {
745
+ walk(value, visitor);
746
+ }
747
+ }
748
+ }
749
+
750
+ /**
751
+ * @param {any} node
752
+ * @returns {boolean}
753
+ */
754
+ function isImportMeta(node) {
755
+ return (
756
+ node.type === 'MetaProperty' &&
757
+ node.meta.type === 'Identifier' &&
758
+ node.meta.name === 'import' &&
759
+ node.property.type === 'Identifier' &&
760
+ node.property.name === 'meta'
761
+ );
762
+ }
763
+
764
+ /**
765
+ * @param {string} code
766
+ * @param {{start: number; end: number; value: string}[]} replacements
767
+ * @returns {string}
768
+ */
769
+ function applyReplacements(code, replacements) {
770
+ let result = '';
771
+ let lastIndex = 0;
772
+ for (const replacement of replacements.sort((a, b) => a.start - b.start)) {
773
+ result += code.slice(lastIndex, replacement.start);
774
+ result += replacement.value;
775
+ lastIndex = replacement.end;
776
+ }
777
+ result += code.slice(lastIndex);
778
+ return result;
779
+ }
780
+
781
+ /**
782
+ * @param {string} file
783
+ * @returns {string}
784
+ */
785
+ function liveAssetName(file) {
786
+ const ext = path.extname(file);
787
+ const baseName = path.basename(file, ext).replace(/[^a-zA-Z0-9_-]/g, '-') || 'asset';
788
+ const hash = createHash('sha1').update(file).digest('hex').slice(0, 10);
789
+ return `${baseName}-${hash}`;
790
+ }
791
+
792
+ /**
793
+ * @param {string} ext
794
+ * @returns {boolean}
795
+ */
796
+ function isBundledAsset(ext) {
797
+ return ext === '.js' || ext === '.mjs' || ext === '.css';
798
+ }
799
+
800
+ /**
801
+ * @param {string} id
802
+ * @returns {string}
803
+ */
804
+ function stripQuery(id) {
805
+ return id.split('?')[0];
806
+ }
807
+
808
+ /**
809
+ * @param {string} id
810
+ * @returns {string}
811
+ */
812
+ function normalizePath(id) {
813
+ return path.normalize(id).split(path.sep).join('/');
814
+ }