jamdesk 1.0.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 (435) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +323 -0
  3. package/bin/jamdesk.js +76 -0
  4. package/dist/__tests__/integration/deprecated-components.integration.test.d.ts +8 -0
  5. package/dist/__tests__/integration/deprecated-components.integration.test.d.ts.map +1 -0
  6. package/dist/__tests__/integration/deprecated-components.integration.test.js +165 -0
  7. package/dist/__tests__/integration/deprecated-components.integration.test.js.map +1 -0
  8. package/dist/__tests__/integration/migrate.integration.test.d.ts +2 -0
  9. package/dist/__tests__/integration/migrate.integration.test.d.ts.map +1 -0
  10. package/dist/__tests__/integration/migrate.integration.test.js +64 -0
  11. package/dist/__tests__/integration/migrate.integration.test.js.map +1 -0
  12. package/dist/__tests__/integration/prepublish.integration.test.d.ts +2 -0
  13. package/dist/__tests__/integration/prepublish.integration.test.d.ts.map +1 -0
  14. package/dist/__tests__/integration/prepublish.integration.test.js +27 -0
  15. package/dist/__tests__/integration/prepublish.integration.test.js.map +1 -0
  16. package/dist/__tests__/integration/validate.integration.test.d.ts +2 -0
  17. package/dist/__tests__/integration/validate.integration.test.d.ts.map +1 -0
  18. package/dist/__tests__/integration/validate.integration.test.js +56 -0
  19. package/dist/__tests__/integration/validate.integration.test.js.map +1 -0
  20. package/dist/__tests__/unit/deploy-templates.test.d.ts +2 -0
  21. package/dist/__tests__/unit/deploy-templates.test.d.ts.map +1 -0
  22. package/dist/__tests__/unit/deploy-templates.test.js +124 -0
  23. package/dist/__tests__/unit/deploy-templates.test.js.map +1 -0
  24. package/dist/__tests__/unit/deprecated-components-sync.test.d.ts +2 -0
  25. package/dist/__tests__/unit/deprecated-components-sync.test.d.ts.map +1 -0
  26. package/dist/__tests__/unit/deprecated-components-sync.test.js +69 -0
  27. package/dist/__tests__/unit/deprecated-components-sync.test.js.map +1 -0
  28. package/dist/__tests__/unit/deps-sync.test.d.ts +14 -0
  29. package/dist/__tests__/unit/deps-sync.test.d.ts.map +1 -0
  30. package/dist/__tests__/unit/deps-sync.test.js +166 -0
  31. package/dist/__tests__/unit/deps-sync.test.js.map +1 -0
  32. package/dist/__tests__/unit/docs-config.test.d.ts +2 -0
  33. package/dist/__tests__/unit/docs-config.test.d.ts.map +1 -0
  34. package/dist/__tests__/unit/docs-config.test.js +288 -0
  35. package/dist/__tests__/unit/docs-config.test.js.map +1 -0
  36. package/dist/__tests__/unit/errors.test.d.ts +2 -0
  37. package/dist/__tests__/unit/errors.test.d.ts.map +1 -0
  38. package/dist/__tests__/unit/errors.test.js +27 -0
  39. package/dist/__tests__/unit/errors.test.js.map +1 -0
  40. package/dist/__tests__/unit/extract-hooks.test.d.ts +5 -0
  41. package/dist/__tests__/unit/extract-hooks.test.d.ts.map +1 -0
  42. package/dist/__tests__/unit/extract-hooks.test.js +205 -0
  43. package/dist/__tests__/unit/extract-hooks.test.js.map +1 -0
  44. package/dist/__tests__/unit/frontmatter-sync.test.d.ts +8 -0
  45. package/dist/__tests__/unit/frontmatter-sync.test.d.ts.map +1 -0
  46. package/dist/__tests__/unit/frontmatter-sync.test.js +26 -0
  47. package/dist/__tests__/unit/frontmatter-sync.test.js.map +1 -0
  48. package/dist/__tests__/unit/mdx-validator.test.d.ts +2 -0
  49. package/dist/__tests__/unit/mdx-validator.test.d.ts.map +1 -0
  50. package/dist/__tests__/unit/mdx-validator.test.js +264 -0
  51. package/dist/__tests__/unit/mdx-validator.test.js.map +1 -0
  52. package/dist/__tests__/unit/migrate-convert.test.d.ts +2 -0
  53. package/dist/__tests__/unit/migrate-convert.test.d.ts.map +1 -0
  54. package/dist/__tests__/unit/migrate-convert.test.js +297 -0
  55. package/dist/__tests__/unit/migrate-convert.test.js.map +1 -0
  56. package/dist/__tests__/unit/migrate-detect.test.d.ts +2 -0
  57. package/dist/__tests__/unit/migrate-detect.test.d.ts.map +1 -0
  58. package/dist/__tests__/unit/migrate-detect.test.js +35 -0
  59. package/dist/__tests__/unit/migrate-detect.test.js.map +1 -0
  60. package/dist/__tests__/unit/migrate-mdx.test.d.ts +2 -0
  61. package/dist/__tests__/unit/migrate-mdx.test.d.ts.map +1 -0
  62. package/dist/__tests__/unit/migrate-mdx.test.js +158 -0
  63. package/dist/__tests__/unit/migrate-mdx.test.js.map +1 -0
  64. package/dist/__tests__/unit/openapi.test.d.ts +2 -0
  65. package/dist/__tests__/unit/openapi.test.d.ts.map +1 -0
  66. package/dist/__tests__/unit/openapi.test.js +52 -0
  67. package/dist/__tests__/unit/openapi.test.js.map +1 -0
  68. package/dist/__tests__/unit/package-config.test.d.ts +2 -0
  69. package/dist/__tests__/unit/package-config.test.d.ts.map +1 -0
  70. package/dist/__tests__/unit/package-config.test.js +63 -0
  71. package/dist/__tests__/unit/package-config.test.js.map +1 -0
  72. package/dist/__tests__/unit/port.test.d.ts +2 -0
  73. package/dist/__tests__/unit/port.test.d.ts.map +1 -0
  74. package/dist/__tests__/unit/port.test.js +20 -0
  75. package/dist/__tests__/unit/port.test.js.map +1 -0
  76. package/dist/__tests__/unit/vendored-sync.test.d.ts +14 -0
  77. package/dist/__tests__/unit/vendored-sync.test.d.ts.map +1 -0
  78. package/dist/__tests__/unit/vendored-sync.test.js +90 -0
  79. package/dist/__tests__/unit/vendored-sync.test.js.map +1 -0
  80. package/dist/commands/broken-links.d.ts +11 -0
  81. package/dist/commands/broken-links.d.ts.map +1 -0
  82. package/dist/commands/broken-links.js +95 -0
  83. package/dist/commands/broken-links.js.map +1 -0
  84. package/dist/commands/clean.d.ts +7 -0
  85. package/dist/commands/clean.d.ts.map +1 -0
  86. package/dist/commands/clean.js +59 -0
  87. package/dist/commands/clean.js.map +1 -0
  88. package/dist/commands/deploy/cloudflare.d.ts +12 -0
  89. package/dist/commands/deploy/cloudflare.d.ts.map +1 -0
  90. package/dist/commands/deploy/cloudflare.js +409 -0
  91. package/dist/commands/deploy/cloudflare.js.map +1 -0
  92. package/dist/commands/deploy/templates.d.ts +23 -0
  93. package/dist/commands/deploy/templates.d.ts.map +1 -0
  94. package/dist/commands/deploy/templates.js +179 -0
  95. package/dist/commands/deploy/templates.js.map +1 -0
  96. package/dist/commands/deploy/types.d.ts +19 -0
  97. package/dist/commands/deploy/types.d.ts.map +1 -0
  98. package/dist/commands/deploy/types.js +5 -0
  99. package/dist/commands/deploy/types.js.map +1 -0
  100. package/dist/commands/dev.d.ts +14 -0
  101. package/dist/commands/dev.d.ts.map +1 -0
  102. package/dist/commands/dev.js +817 -0
  103. package/dist/commands/dev.js.map +1 -0
  104. package/dist/commands/doctor.d.ts +7 -0
  105. package/dist/commands/doctor.d.ts.map +1 -0
  106. package/dist/commands/doctor.js +159 -0
  107. package/dist/commands/doctor.js.map +1 -0
  108. package/dist/commands/init.d.ts +7 -0
  109. package/dist/commands/init.d.ts.map +1 -0
  110. package/dist/commands/init.js +96 -0
  111. package/dist/commands/init.js.map +1 -0
  112. package/dist/commands/migrate/convert-mdx.d.ts +50 -0
  113. package/dist/commands/migrate/convert-mdx.d.ts.map +1 -0
  114. package/dist/commands/migrate/convert-mdx.js +108 -0
  115. package/dist/commands/migrate/convert-mdx.js.map +1 -0
  116. package/dist/commands/migrate/convert.d.ts +80 -0
  117. package/dist/commands/migrate/convert.d.ts.map +1 -0
  118. package/dist/commands/migrate/convert.js +158 -0
  119. package/dist/commands/migrate/convert.js.map +1 -0
  120. package/dist/commands/migrate/detect.d.ts +31 -0
  121. package/dist/commands/migrate/detect.d.ts.map +1 -0
  122. package/dist/commands/migrate/detect.js +62 -0
  123. package/dist/commands/migrate/detect.js.map +1 -0
  124. package/dist/commands/migrate/extract-hooks.d.ts +71 -0
  125. package/dist/commands/migrate/extract-hooks.d.ts.map +1 -0
  126. package/dist/commands/migrate/extract-hooks.js +473 -0
  127. package/dist/commands/migrate/extract-hooks.js.map +1 -0
  128. package/dist/commands/migrate/index.d.ts +17 -0
  129. package/dist/commands/migrate/index.d.ts.map +1 -0
  130. package/dist/commands/migrate/index.js +282 -0
  131. package/dist/commands/migrate/index.js.map +1 -0
  132. package/dist/commands/migrate/prompts.d.ts +22 -0
  133. package/dist/commands/migrate/prompts.d.ts.map +1 -0
  134. package/dist/commands/migrate/prompts.js +67 -0
  135. package/dist/commands/migrate/prompts.js.map +1 -0
  136. package/dist/commands/migrate/types.d.ts +22 -0
  137. package/dist/commands/migrate/types.d.ts.map +1 -0
  138. package/dist/commands/migrate/types.js +26 -0
  139. package/dist/commands/migrate/types.js.map +1 -0
  140. package/dist/commands/openapi-check.d.ts +11 -0
  141. package/dist/commands/openapi-check.d.ts.map +1 -0
  142. package/dist/commands/openapi-check.js +88 -0
  143. package/dist/commands/openapi-check.js.map +1 -0
  144. package/dist/commands/rename.d.ts +10 -0
  145. package/dist/commands/rename.d.ts.map +1 -0
  146. package/dist/commands/rename.js +125 -0
  147. package/dist/commands/rename.js.map +1 -0
  148. package/dist/commands/update.d.ts +10 -0
  149. package/dist/commands/update.d.ts.map +1 -0
  150. package/dist/commands/update.js +57 -0
  151. package/dist/commands/update.js.map +1 -0
  152. package/dist/commands/validate.d.ts +12 -0
  153. package/dist/commands/validate.d.ts.map +1 -0
  154. package/dist/commands/validate.js +163 -0
  155. package/dist/commands/validate.js.map +1 -0
  156. package/dist/index.d.ts +9 -0
  157. package/dist/index.d.ts.map +1 -0
  158. package/dist/index.js +334 -0
  159. package/dist/index.js.map +1 -0
  160. package/dist/lib/config.d.ts +7 -0
  161. package/dist/lib/config.d.ts.map +1 -0
  162. package/dist/lib/config.js +18 -0
  163. package/dist/lib/config.js.map +1 -0
  164. package/dist/lib/deprecated-components.d.ts +72 -0
  165. package/dist/lib/deprecated-components.d.ts.map +1 -0
  166. package/dist/lib/deprecated-components.js +138 -0
  167. package/dist/lib/deprecated-components.js.map +1 -0
  168. package/dist/lib/deps.d.ts +17 -0
  169. package/dist/lib/deps.d.ts.map +1 -0
  170. package/dist/lib/deps.js +186 -0
  171. package/dist/lib/deps.js.map +1 -0
  172. package/dist/lib/docs-config.d.ts +67 -0
  173. package/dist/lib/docs-config.d.ts.map +1 -0
  174. package/dist/lib/docs-config.js +294 -0
  175. package/dist/lib/docs-config.js.map +1 -0
  176. package/dist/lib/errors.d.ts +23 -0
  177. package/dist/lib/errors.d.ts.map +1 -0
  178. package/dist/lib/errors.js +32 -0
  179. package/dist/lib/errors.js.map +1 -0
  180. package/dist/lib/frontmatter-utils.d.ts +25 -0
  181. package/dist/lib/frontmatter-utils.d.ts.map +1 -0
  182. package/dist/lib/frontmatter-utils.js +64 -0
  183. package/dist/lib/frontmatter-utils.js.map +1 -0
  184. package/dist/lib/mdx-validator.d.ts +27 -0
  185. package/dist/lib/mdx-validator.d.ts.map +1 -0
  186. package/dist/lib/mdx-validator.js +148 -0
  187. package/dist/lib/mdx-validator.js.map +1 -0
  188. package/dist/lib/navigation-validator.d.ts +31 -0
  189. package/dist/lib/navigation-validator.d.ts.map +1 -0
  190. package/dist/lib/navigation-validator.js +75 -0
  191. package/dist/lib/navigation-validator.js.map +1 -0
  192. package/dist/lib/normalize-config.d.ts +57 -0
  193. package/dist/lib/normalize-config.d.ts.map +1 -0
  194. package/dist/lib/normalize-config.js +63 -0
  195. package/dist/lib/normalize-config.js.map +1 -0
  196. package/dist/lib/openapi/cache.d.ts +40 -0
  197. package/dist/lib/openapi/cache.d.ts.map +1 -0
  198. package/dist/lib/openapi/cache.js +76 -0
  199. package/dist/lib/openapi/cache.js.map +1 -0
  200. package/dist/lib/openapi/errors.d.ts +36 -0
  201. package/dist/lib/openapi/errors.d.ts.map +1 -0
  202. package/dist/lib/openapi/errors.js +162 -0
  203. package/dist/lib/openapi/errors.js.map +1 -0
  204. package/dist/lib/openapi/index.d.ts +10 -0
  205. package/dist/lib/openapi/index.d.ts.map +1 -0
  206. package/dist/lib/openapi/index.js +12 -0
  207. package/dist/lib/openapi/index.js.map +1 -0
  208. package/dist/lib/openapi/types.d.ts +198 -0
  209. package/dist/lib/openapi/types.d.ts.map +1 -0
  210. package/dist/lib/openapi/types.js +8 -0
  211. package/dist/lib/openapi/types.js.map +1 -0
  212. package/dist/lib/openapi/validator.d.ts +45 -0
  213. package/dist/lib/openapi/validator.d.ts.map +1 -0
  214. package/dist/lib/openapi/validator.js +128 -0
  215. package/dist/lib/openapi/validator.js.map +1 -0
  216. package/dist/lib/openapi.d.ts +7 -0
  217. package/dist/lib/openapi.d.ts.map +1 -0
  218. package/dist/lib/openapi.js +7 -0
  219. package/dist/lib/openapi.js.map +1 -0
  220. package/dist/lib/output.d.ts +14 -0
  221. package/dist/lib/output.d.ts.map +1 -0
  222. package/dist/lib/output.js +19 -0
  223. package/dist/lib/output.js.map +1 -0
  224. package/dist/lib/path-security.d.ts +23 -0
  225. package/dist/lib/path-security.d.ts.map +1 -0
  226. package/dist/lib/path-security.js +35 -0
  227. package/dist/lib/path-security.js.map +1 -0
  228. package/dist/lib/port.d.ts +18 -0
  229. package/dist/lib/port.d.ts.map +1 -0
  230. package/dist/lib/port.js +65 -0
  231. package/dist/lib/port.js.map +1 -0
  232. package/dist/lib/spinner.d.ts +4 -0
  233. package/dist/lib/spinner.d.ts.map +1 -0
  234. package/dist/lib/spinner.js +16 -0
  235. package/dist/lib/spinner.js.map +1 -0
  236. package/dist/lib/version.d.ts +2 -0
  237. package/dist/lib/version.d.ts.map +1 -0
  238. package/dist/lib/version.js +49 -0
  239. package/dist/lib/version.js.map +1 -0
  240. package/dist/utils/update-checker.d.ts +34 -0
  241. package/dist/utils/update-checker.d.ts.map +1 -0
  242. package/dist/utils/update-checker.js +142 -0
  243. package/dist/utils/update-checker.js.map +1 -0
  244. package/package.json +125 -0
  245. package/templates/docs.json +11 -0
  246. package/templates/introduction.mdx +19 -0
  247. package/templates/quickstart.mdx +20 -0
  248. package/vendored/app/[[...slug]]/error.tsx +103 -0
  249. package/vendored/app/[[...slug]]/page.tsx +690 -0
  250. package/vendored/app/api/assets/[...path]/route.ts +78 -0
  251. package/vendored/app/api/ev/route.ts +61 -0
  252. package/vendored/app/api/isr-health/route.ts +66 -0
  253. package/vendored/app/api/mcp/[project]/route.ts +435 -0
  254. package/vendored/app/api/og/route.tsx +167 -0
  255. package/vendored/app/api/r2/[project]/[...path]/route.ts +214 -0
  256. package/vendored/app/api/revalidate/route.ts +76 -0
  257. package/vendored/app/globals.css +37 -0
  258. package/vendored/app/layout.tsx +571 -0
  259. package/vendored/app/not-found.tsx +47 -0
  260. package/vendored/components/CodeBlockCopyButton.tsx +146 -0
  261. package/vendored/components/HeaderLinkCopy.tsx +135 -0
  262. package/vendored/components/errors/NotFoundContent.tsx +147 -0
  263. package/vendored/components/layout/LayoutWrapper.tsx +128 -0
  264. package/vendored/components/mdx/Accordion.tsx +91 -0
  265. package/vendored/components/mdx/ApiCodePanel.tsx +51 -0
  266. package/vendored/components/mdx/ApiEndpoint.tsx +104 -0
  267. package/vendored/components/mdx/ApiPage.tsx +379 -0
  268. package/vendored/components/mdx/Badge.tsx +169 -0
  269. package/vendored/components/mdx/Callouts.tsx +140 -0
  270. package/vendored/components/mdx/Card.tsx +214 -0
  271. package/vendored/components/mdx/CodeGroup.tsx +136 -0
  272. package/vendored/components/mdx/Color.tsx +244 -0
  273. package/vendored/components/mdx/Columns.tsx +37 -0
  274. package/vendored/components/mdx/Expandable.tsx +37 -0
  275. package/vendored/components/mdx/Frame.tsx +51 -0
  276. package/vendored/components/mdx/Icon.tsx +132 -0
  277. package/vendored/components/mdx/Latex.tsx +75 -0
  278. package/vendored/components/mdx/MDXComponents.tsx +414 -0
  279. package/vendored/components/mdx/Mermaid.tsx +35 -0
  280. package/vendored/components/mdx/MermaidInner.tsx +342 -0
  281. package/vendored/components/mdx/OpenApiEndpoint.tsx +971 -0
  282. package/vendored/components/mdx/Panel.tsx +26 -0
  283. package/vendored/components/mdx/PanelWrapper.tsx +100 -0
  284. package/vendored/components/mdx/ParamField.tsx +75 -0
  285. package/vendored/components/mdx/RequestExample.tsx +91 -0
  286. package/vendored/components/mdx/ResponseExample.tsx +145 -0
  287. package/vendored/components/mdx/ResponseField.tsx +109 -0
  288. package/vendored/components/mdx/Steps.tsx +173 -0
  289. package/vendored/components/mdx/Table.tsx +352 -0
  290. package/vendored/components/mdx/Tabs.tsx +147 -0
  291. package/vendored/components/mdx/Tile.tsx +127 -0
  292. package/vendored/components/mdx/Tooltip.tsx +111 -0
  293. package/vendored/components/mdx/Tree.tsx +484 -0
  294. package/vendored/components/mdx/Update.tsx +90 -0
  295. package/vendored/components/mdx/View.tsx +354 -0
  296. package/vendored/components/mdx/YouTube.tsx +35 -0
  297. package/vendored/components/mdx/ZoomableImage.tsx +83 -0
  298. package/vendored/components/navigation/Breadcrumb.tsx +241 -0
  299. package/vendored/components/navigation/DefaultLogo.tsx +81 -0
  300. package/vendored/components/navigation/Header.tsx +512 -0
  301. package/vendored/components/navigation/LanguageSelector.tsx +249 -0
  302. package/vendored/components/navigation/PageNavigation.tsx +174 -0
  303. package/vendored/components/navigation/Sidebar.tsx +713 -0
  304. package/vendored/components/navigation/SocialFooter.tsx +186 -0
  305. package/vendored/components/navigation/TableOfContents.tsx +435 -0
  306. package/vendored/components/navigation/TabsNav.tsx +182 -0
  307. package/vendored/components/search/LazySearchModal.tsx +19 -0
  308. package/vendored/components/search/SearchModal.tsx +573 -0
  309. package/vendored/components/snippets/ProjectSnippets.tsx +4 -0
  310. package/vendored/components/theme/ThemeProvider.tsx +31 -0
  311. package/vendored/components/theme/ThemeToggle.tsx +134 -0
  312. package/vendored/components/ui/CodePanel.tsx +517 -0
  313. package/vendored/components/ui/CodePanelModal.tsx +342 -0
  314. package/vendored/contexts/TabSyncContext.tsx +30 -0
  315. package/vendored/hooks/useFocusTrap.ts +42 -0
  316. package/vendored/hooks/useHashNavigation.ts +39 -0
  317. package/vendored/hooks/useShikiHighlight.ts +101 -0
  318. package/vendored/lib/analytics-client.ts +77 -0
  319. package/vendored/lib/build/cache.ts +138 -0
  320. package/vendored/lib/build/error-parser.ts +690 -0
  321. package/vendored/lib/build/estimation.ts +113 -0
  322. package/vendored/lib/build/index.ts +17 -0
  323. package/vendored/lib/build/page-file-map.ts +48 -0
  324. package/vendored/lib/build/r2-upload.ts +179 -0
  325. package/vendored/lib/cache-keys.ts +117 -0
  326. package/vendored/lib/code-utils.ts +42 -0
  327. package/vendored/lib/content-loader.ts +176 -0
  328. package/vendored/lib/deprecated-components.ts +185 -0
  329. package/vendored/lib/docs-isr.ts +180 -0
  330. package/vendored/lib/docs-types.ts +874 -0
  331. package/vendored/lib/docs.ts +203 -0
  332. package/vendored/lib/domain-helpers.ts +107 -0
  333. package/vendored/lib/email-notifier.ts +102 -0
  334. package/vendored/lib/email-templates/build-failure.tsx +193 -0
  335. package/vendored/lib/email-templates/components/base-layout.tsx +150 -0
  336. package/vendored/lib/email-templates/components/error-box.tsx +88 -0
  337. package/vendored/lib/email-templates/components/info-row.tsx +63 -0
  338. package/vendored/lib/email-templates/index.ts +13 -0
  339. package/vendored/lib/empty-polyfill.js +3 -0
  340. package/vendored/lib/extract-highlights.ts +124 -0
  341. package/vendored/lib/fonts.ts +227 -0
  342. package/vendored/lib/frontmatter-utils.ts +77 -0
  343. package/vendored/lib/fs-utils.ts +20 -0
  344. package/vendored/lib/git-utils.ts +87 -0
  345. package/vendored/lib/health-checks.ts +224 -0
  346. package/vendored/lib/icon-utils.ts +492 -0
  347. package/vendored/lib/infer-page-type.ts +14 -0
  348. package/vendored/lib/isr-build-executor.ts +185 -0
  349. package/vendored/lib/language-icons.ts +152 -0
  350. package/vendored/lib/language-utils.ts +338 -0
  351. package/vendored/lib/latex-config.ts +64 -0
  352. package/vendored/lib/link-prefix-context.tsx +32 -0
  353. package/vendored/lib/logger.ts +63 -0
  354. package/vendored/lib/mcp-search.ts +255 -0
  355. package/vendored/lib/mdx-inline-components.ts +155 -0
  356. package/vendored/lib/mdx.ts +100 -0
  357. package/vendored/lib/middleware-helpers.ts +519 -0
  358. package/vendored/lib/navigation-resolver.ts +621 -0
  359. package/vendored/lib/navigation-utils.ts +103 -0
  360. package/vendored/lib/normalize-config.ts +94 -0
  361. package/vendored/lib/openapi/cache.ts +92 -0
  362. package/vendored/lib/openapi/code-examples.ts +389 -0
  363. package/vendored/lib/openapi/errors.ts +253 -0
  364. package/vendored/lib/openapi/generator.ts +230 -0
  365. package/vendored/lib/openapi/index.ts +84 -0
  366. package/vendored/lib/openapi/parser.ts +474 -0
  367. package/vendored/lib/openapi/types.ts +232 -0
  368. package/vendored/lib/openapi/validator.ts +156 -0
  369. package/vendored/lib/openapi-isr.ts +121 -0
  370. package/vendored/lib/page-isr-helpers.ts +137 -0
  371. package/vendored/lib/path-safety.ts +130 -0
  372. package/vendored/lib/paths.ts +35 -0
  373. package/vendored/lib/preprocess-mdx.ts +951 -0
  374. package/vendored/lib/process-mdx-with-exports.ts +75 -0
  375. package/vendored/lib/project-resolver.ts +165 -0
  376. package/vendored/lib/r2-content.ts +60 -0
  377. package/vendored/lib/r2-manifest.ts +84 -0
  378. package/vendored/lib/recent-searches.ts +41 -0
  379. package/vendored/lib/recma-compound-components.ts +84 -0
  380. package/vendored/lib/redirect-compiler.ts +160 -0
  381. package/vendored/lib/redirect-matcher.ts +296 -0
  382. package/vendored/lib/redis.ts +23 -0
  383. package/vendored/lib/rehype-class-to-classname.ts +31 -0
  384. package/vendored/lib/rehype-code-meta.ts +275 -0
  385. package/vendored/lib/rehype-nozoom-to-data.ts +45 -0
  386. package/vendored/lib/remark-extract-exports.ts +104 -0
  387. package/vendored/lib/resilience.ts +260 -0
  388. package/vendored/lib/revalidation-helpers.ts +200 -0
  389. package/vendored/lib/revalidation-trigger.ts +150 -0
  390. package/vendored/lib/screenshot-capture.ts +229 -0
  391. package/vendored/lib/search-client.ts +91 -0
  392. package/vendored/lib/search-suggestions.ts +38 -0
  393. package/vendored/lib/search.ts +158 -0
  394. package/vendored/lib/seo.ts +264 -0
  395. package/vendored/lib/shiki-client.ts +131 -0
  396. package/vendored/lib/shiki-config.ts +289 -0
  397. package/vendored/lib/shiki-css-theme.ts +46 -0
  398. package/vendored/lib/shiki-highlighter.ts +62 -0
  399. package/vendored/lib/shiki-transformers.ts +337 -0
  400. package/vendored/lib/slack-notifier.ts +248 -0
  401. package/vendored/lib/snippet-compiler-isr.ts +114 -0
  402. package/vendored/lib/snippet-loader-isr.ts +276 -0
  403. package/vendored/lib/static-artifacts.ts +375 -0
  404. package/vendored/lib/static-file-route.ts +72 -0
  405. package/vendored/lib/tracking-script.ts +19 -0
  406. package/vendored/lib/typography-config.ts +42 -0
  407. package/vendored/lib/validate-config.ts +268 -0
  408. package/vendored/next.config.js +45 -0
  409. package/vendored/postcss.config.js +6 -0
  410. package/vendored/schema/README.md +28 -0
  411. package/vendored/schema/docs-schema.json +4631 -0
  412. package/vendored/scripts/build-project.cjs +174 -0
  413. package/vendored/scripts/build-search-index.cjs +347 -0
  414. package/vendored/scripts/compile-snippets.cjs +488 -0
  415. package/vendored/scripts/copy-files.cjs +295 -0
  416. package/vendored/scripts/dev-project.cjs +534 -0
  417. package/vendored/scripts/enhance-navigation.cjs +354 -0
  418. package/vendored/scripts/validate-links.cjs +423 -0
  419. package/vendored/shared/constants.ts +6 -0
  420. package/vendored/shared/index.ts +19 -0
  421. package/vendored/shared/logger.ts +62 -0
  422. package/vendored/shared/memory-monitor.ts +190 -0
  423. package/vendored/shared/navigation-validator.ts +101 -0
  424. package/vendored/shared/path-security.ts +39 -0
  425. package/vendored/shared/status-reporter.ts +199 -0
  426. package/vendored/shared/timer.ts +51 -0
  427. package/vendored/shared/types.ts +102 -0
  428. package/vendored/tailwind.config.ts +39 -0
  429. package/vendored/themes/base.css +1311 -0
  430. package/vendored/themes/index.ts +119 -0
  431. package/vendored/themes/jam/variables.css +835 -0
  432. package/vendored/themes/nebula/variables.css +282 -0
  433. package/vendored/themes/pulsar/variables.css +1009 -0
  434. package/vendored/themes/types.ts +89 -0
  435. package/vendored/tsconfig.json +48 -0
@@ -0,0 +1,113 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+
4
+ export type BuildEstimationType = 'full' | 'incremental';
5
+
6
+ export interface BuildEstimate {
7
+ minutes: number;
8
+ type: BuildEstimationType;
9
+ fileCount: number;
10
+ changedFiles?: number; // For future incremental builds
11
+ }
12
+
13
+ /**
14
+ * Fixed overhead for all builds (in seconds):
15
+ * - Clone: ~1s
16
+ * - Validate: ~1s
17
+ * - Copy: ~0.5s
18
+ * - R2 upload: ~3-10s (depends on file count)
19
+ * - Cache wait: 30s
20
+ * - Cleanup: ~1s
21
+ * Total: ~45s fixed + variable upload time
22
+ */
23
+ const FIXED_OVERHEAD_SECONDS = 45;
24
+
25
+ export function countFilesRecursive(dirPath: string): number {
26
+ let count = 0;
27
+
28
+ try {
29
+ const items = fs.readdirSync(dirPath, { withFileTypes: true });
30
+
31
+ for (const item of items) {
32
+ if (item.name === 'node_modules' || item.name === '.git') {
33
+ continue; // Skip node_modules and .git
34
+ }
35
+
36
+ const fullPath = path.join(dirPath, item.name);
37
+
38
+ if (item.isFile()) {
39
+ count++;
40
+ } else if (item.isDirectory()) {
41
+ count += countFilesRecursive(fullPath);
42
+ }
43
+ }
44
+ } catch {
45
+ // If we can't read directory, just return current count
46
+ }
47
+
48
+ return count;
49
+ }
50
+
51
+ /**
52
+ * Calculate estimated build time based on build type and file counts
53
+ *
54
+ * This is the FALLBACK formula used when historical data is not available.
55
+ * For projects with build history, Firebase Functions uses actual historical
56
+ * averages instead (see functions/src/index.ts:getEstimatedMinutes).
57
+ *
58
+ * Full builds use a non-linear formula because:
59
+ * - Next.js build time scales worse than linear (dependency resolution, memory pressure)
60
+ * - Observed: acme (466 files) = ~100s, dodo (4277 files) = ~555s
61
+ * - That's 9x files but 5.5x time, showing sub-linear scaling at small sizes
62
+ * but super-linear at larger sizes due to memory/CPU constraints
63
+ *
64
+ * Formula: baseSeconds + linear component + quadratic component + fixed overhead
65
+ * - Base: 30s minimum for Next.js
66
+ * - Linear: 25s per 1000 files
67
+ * - Quadratic: 8s per (1000 files)^2 (captures non-linear scaling)
68
+ * - Fixed: 60s (cache wait, clone, cleanup)
69
+ * - Buffer: +20% conservative estimate
70
+ *
71
+ * @param fileCount Total files in project
72
+ * @param changedFiles Number of changed files (for incremental builds)
73
+ * @param buildType 'full' or 'incremental'
74
+ */
75
+ export function calculateBuildEstimate(
76
+ fileCount: number,
77
+ changedFiles?: number,
78
+ buildType: BuildEstimationType = 'full'
79
+ ): BuildEstimate {
80
+ let minutes: number;
81
+
82
+ if (buildType === 'incremental' && changedFiles !== undefined) {
83
+ // Incremental build: ~1 min per 500 changed files + 1 min overhead
84
+ minutes = Math.max(1, Math.ceil(changedFiles / 500) + 1);
85
+ } else {
86
+ // Non-linear formula for full builds (fallback when no history)
87
+ const filesIn1K = fileCount / 1000;
88
+
89
+ // Next.js build: base + linear + quadratic components
90
+ const nextjsSeconds = 30 + filesIn1K * 25 + filesIn1K * filesIn1K * 8;
91
+
92
+ // R2 upload scales roughly linearly (~0.002s per file)
93
+ const uploadSeconds = Math.max(3, fileCount * 0.002);
94
+
95
+ // Total with fixed overhead
96
+ const totalSeconds = nextjsSeconds + uploadSeconds + FIXED_OVERHEAD_SECONDS;
97
+
98
+ // Add 20% buffer for conservative estimate
99
+ const bufferedSeconds = totalSeconds * 1.2;
100
+
101
+ minutes = Math.ceil(bufferedSeconds / 60);
102
+
103
+ // Minimum 2 minutes for any build
104
+ minutes = Math.max(2, minutes);
105
+ }
106
+
107
+ return {
108
+ minutes,
109
+ type: buildType,
110
+ fileCount,
111
+ changedFiles,
112
+ };
113
+ }
@@ -0,0 +1,17 @@
1
+ export {
2
+ countFilesRecursive,
3
+ calculateBuildEstimate,
4
+ type BuildEstimate,
5
+ type BuildEstimationType,
6
+ } from './estimation.js';
7
+
8
+ export {
9
+ generateErrorRef,
10
+ extractErrorSource,
11
+ formatErrorLocation,
12
+ parseErrorDetails,
13
+ } from './error-parser.js';
14
+
15
+ export { purgeNextJsCache, purgeVercelCache } from './cache.js';
16
+
17
+ export { runR2Upload, type R2UploadOptions, type R2UploadResult } from './r2-upload.js';
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Builds a mapping of URL paths to source MDX files.
3
+ * Used by error parser to show actual file names instead of URL paths.
4
+ */
5
+
6
+ import fs from 'fs';
7
+ import path from 'path';
8
+
9
+ /**
10
+ * Build a mapping of URL paths to MDX file paths.
11
+ *
12
+ * @param contentDir - Path to the content directory
13
+ * @returns Map of URL path -> relative file path
14
+ */
15
+ export function buildPageToFileMap(contentDir: string): Record<string, string> {
16
+ const map: Record<string, string> = {};
17
+
18
+ function traverseDir(dir: string, basePath: string = '') {
19
+ if (!fs.existsSync(dir)) return;
20
+
21
+ const files = fs.readdirSync(dir);
22
+
23
+ for (const file of files) {
24
+ if (file.startsWith('.')) continue;
25
+
26
+ const filePath = path.join(dir, file);
27
+ let stat;
28
+ try {
29
+ stat = fs.statSync(filePath);
30
+ } catch {
31
+ continue;
32
+ }
33
+
34
+ if (stat.isDirectory()) {
35
+ traverseDir(filePath, path.join(basePath, file));
36
+ } else if (file.endsWith('.mdx') || file.endsWith('.md')) {
37
+ const slug = path.join(basePath, file.replace(/\.mdx?$/, ''));
38
+ // Handle index files -> root path
39
+ const urlPath = slug === 'index' ? '/' : `/${slug.replace(/\\/g, '/')}`;
40
+ const relativePath = path.join(basePath, file).replace(/\\/g, '/');
41
+ map[urlPath] = relativePath;
42
+ }
43
+ }
44
+ }
45
+
46
+ traverseDir(contentDir);
47
+ return map;
48
+ }
@@ -0,0 +1,179 @@
1
+ /**
2
+ * R2 upload utilities
3
+ *
4
+ * Functions for uploading build output to Cloudflare R2.
5
+ */
6
+
7
+ import { spawn } from 'child_process';
8
+
9
+ export interface R2UploadOptions {
10
+ slug: string;
11
+ buildId: string;
12
+ commitSha: string;
13
+ fullRebuild: boolean;
14
+ appDir: string;
15
+ }
16
+
17
+ export interface R2UploadResult {
18
+ filesWereUploaded: boolean;
19
+ }
20
+
21
+ /**
22
+ * Upload build output to R2 with progress streaming
23
+ *
24
+ * Runs the upload-r2 script with parallel uploads and manifest-based
25
+ * incremental uploads (unless fullRebuild is true).
26
+ */
27
+ export async function runR2Upload(options: R2UploadOptions): Promise<R2UploadResult> {
28
+ const { slug, buildId, commitSha, fullRebuild, appDir } = options;
29
+
30
+ // Build upload args - add --full flag for full rebuild (ignores manifest)
31
+ const uploadArgs = [
32
+ 'run',
33
+ 'upload-r2',
34
+ slug,
35
+ '--',
36
+ '--parallel',
37
+ '150',
38
+ '--buildId',
39
+ buildId,
40
+ '--commitSha',
41
+ commitSha || 'unknown',
42
+ ];
43
+ if (fullRebuild) {
44
+ uploadArgs.push('--full');
45
+ }
46
+
47
+ // Track whether files were actually uploaded (used to skip cache wait if no changes)
48
+ let filesWereUploaded = true; // Default to true for safety
49
+
50
+ await new Promise<void>((resolve, reject) => {
51
+ const uploadProcess = spawn('npm', uploadArgs, {
52
+ cwd: appDir,
53
+ env: process.env,
54
+ });
55
+
56
+ let lastProgress = '';
57
+ let stdoutBuffer = '';
58
+ let stderrBuffer = '';
59
+
60
+ uploadProcess.stdout.on('data', (data: Buffer) => {
61
+ const output = data.toString();
62
+ stdoutBuffer += output;
63
+
64
+ // Log progress updates (upload counts, manifest operations, diff summary)
65
+ const lines = output.split('\n');
66
+ for (const line of lines) {
67
+ // Capture progress lines AND individual file paths (indented with spaces)
68
+ const isProgressLine =
69
+ line.includes('Uploading...') ||
70
+ line.includes('files to upload') ||
71
+ line.includes('UPLOAD COMPLETE') ||
72
+ line.includes('Deleted') ||
73
+ line.includes('Cleaning') ||
74
+ line.includes('manifest') ||
75
+ line.includes('Fetching') ||
76
+ line.includes('Found') ||
77
+ line.includes('Diff') ||
78
+ line.includes('New files') ||
79
+ line.includes('Changed files') ||
80
+ line.includes('Unchanged') ||
81
+ line.includes('No changes') ||
82
+ line.includes('Full upload') ||
83
+ line.includes('INCREMENTAL') ||
84
+ line.includes('Hashed') ||
85
+ line.includes('Sample') ||
86
+ line.includes('_next/static') ||
87
+ line.includes('HTML files') ||
88
+ line.includes('Files to upload');
89
+ // Also capture indented file paths (lines starting with spaces followed by a path)
90
+ const isFilePath =
91
+ /^\s{4,}\S/.test(line) &&
92
+ (line.includes('.html') ||
93
+ line.includes('.xml') ||
94
+ line.includes('.json') ||
95
+ line.includes('.txt'));
96
+ if (isProgressLine || isFilePath) {
97
+ const trimmed = line.trim();
98
+ if (trimmed && trimmed !== lastProgress) {
99
+ lastProgress = trimmed;
100
+ console.log(
101
+ JSON.stringify({
102
+ severity: 'INFO',
103
+ message: 'R2 upload progress',
104
+ buildId,
105
+ output: trimmed,
106
+ })
107
+ );
108
+ }
109
+ }
110
+ }
111
+ });
112
+
113
+ uploadProcess.stderr.on('data', (data: Buffer) => {
114
+ stderrBuffer += data.toString();
115
+ console.log(
116
+ JSON.stringify({
117
+ severity: 'WARNING',
118
+ message: 'R2 upload stderr',
119
+ buildId,
120
+ output: data.toString().slice(0, 500),
121
+ })
122
+ );
123
+ });
124
+
125
+ // Timeout after 10 minutes (large projects have 35K+ files)
126
+ const timeout = setTimeout(() => {
127
+ uploadProcess.kill('SIGTERM');
128
+ reject(new Error('R2 upload timed out after 10 minutes'));
129
+ }, 600000);
130
+
131
+ uploadProcess.on('close', (code) => {
132
+ clearTimeout(timeout);
133
+ if (code === 0) {
134
+ // Check if files were actually uploaded by parsing the output
135
+ // The upload script outputs "No changes detected, skipping upload" when nothing changed
136
+ if (stdoutBuffer.includes('No changes detected')) {
137
+ filesWereUploaded = false;
138
+ }
139
+ console.log(
140
+ JSON.stringify({
141
+ severity: 'INFO',
142
+ message: 'R2 upload process completed',
143
+ buildId,
144
+ exitCode: code,
145
+ filesWereUploaded,
146
+ })
147
+ );
148
+ resolve();
149
+ } else {
150
+ console.log(
151
+ JSON.stringify({
152
+ severity: 'ERROR',
153
+ message: 'R2 upload failed',
154
+ buildId,
155
+ exitCode: code,
156
+ stdout: stdoutBuffer.slice(-2000),
157
+ stderr: stderrBuffer.slice(-2000),
158
+ })
159
+ );
160
+ reject(new Error(`R2 upload failed with exit code ${code}`));
161
+ }
162
+ });
163
+
164
+ uploadProcess.on('error', (err) => {
165
+ clearTimeout(timeout);
166
+ console.log(
167
+ JSON.stringify({
168
+ severity: 'ERROR',
169
+ message: 'R2 upload process error',
170
+ buildId,
171
+ error: err.message,
172
+ })
173
+ );
174
+ reject(err);
175
+ });
176
+ });
177
+
178
+ return { filesWereUploaded };
179
+ }
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Cache Key Generation for Multi-Tenant ISR
3
+ *
4
+ * Ensures cache keys are properly namespaced by project to prevent
5
+ * cache bleed between tenants. All caches should use these functions
6
+ * for key generation.
7
+ */
8
+
9
+ /**
10
+ * Generate a cache key for project-scoped resources.
11
+ *
12
+ * @param projectSlug - Project identifier
13
+ * @param resourcePath - Resource path within project
14
+ * @returns Namespaced cache key
15
+ */
16
+ export function getCacheKey(projectSlug: string, resourcePath: string): string {
17
+ // Normalize path (remove leading/trailing slashes)
18
+ const normalizedPath = resourcePath.replace(/^\/+|\/+$/g, '');
19
+ return `${projectSlug}:${normalizedPath}`;
20
+ }
21
+
22
+ /**
23
+ * Generate a cache key for config resources.
24
+ *
25
+ * @param projectSlug - Project identifier
26
+ * @returns Namespaced cache key for docs.json
27
+ */
28
+ export function getConfigCacheKey(projectSlug: string): string {
29
+ return `${projectSlug}:config`;
30
+ }
31
+
32
+ /**
33
+ * Generate a cache key for snippet resources.
34
+ *
35
+ * @param projectSlug - Project identifier
36
+ * @param snippetPath - Path to snippet file
37
+ * @returns Namespaced cache key
38
+ */
39
+ export function getSnippetCacheKey(projectSlug: string, snippetPath: string): string {
40
+ return `${projectSlug}:snippet:${snippetPath}`;
41
+ }
42
+
43
+ /**
44
+ * Generate a cache key for OpenAPI specs.
45
+ *
46
+ * @param projectSlug - Project identifier
47
+ * @param specPath - Path or URL to OpenAPI spec
48
+ * @returns Namespaced cache key
49
+ */
50
+ export function getOpenApiCacheKey(projectSlug: string, specPath: string): string {
51
+ // For URLs, include the full URL in the key
52
+ if (specPath.startsWith('http://') || specPath.startsWith('https://')) {
53
+ return `${projectSlug}:openapi:url:${specPath}`;
54
+ }
55
+ return `${projectSlug}:openapi:${specPath}`;
56
+ }
57
+
58
+ /**
59
+ * Generate a cache key for page content.
60
+ *
61
+ * @param projectSlug - Project identifier
62
+ * @param pagePath - Page path
63
+ * @returns Namespaced cache key
64
+ */
65
+ export function getPageCacheKey(projectSlug: string, pagePath: string): string {
66
+ return `${projectSlug}:page:${pagePath}`;
67
+ }
68
+
69
+ /**
70
+ * Generate a Next.js revalidation tag for a project.
71
+ *
72
+ * @param projectSlug - Project identifier
73
+ * @returns Tag for use with revalidateTag()
74
+ */
75
+ export function getProjectTag(projectSlug: string): string {
76
+ return `project:${projectSlug}`;
77
+ }
78
+
79
+ /**
80
+ * Generate a Next.js revalidation tag for a specific page.
81
+ *
82
+ * @param projectSlug - Project identifier
83
+ * @param pagePath - Page path
84
+ * @returns Tag for use with revalidateTag()
85
+ */
86
+ export function getPageTag(projectSlug: string, pagePath: string): string {
87
+ return `page:${projectSlug}:${pagePath}`;
88
+ }
89
+
90
+ /**
91
+ * Parse a cache key back to its components.
92
+ *
93
+ * @param cacheKey - Cache key to parse
94
+ * @returns Project slug and resource path
95
+ */
96
+ export function parseCacheKey(cacheKey: string): { projectSlug: string; resourcePath: string } {
97
+ const colonIndex = cacheKey.indexOf(':');
98
+ if (colonIndex === -1) {
99
+ throw new Error(`Invalid cache key format: ${cacheKey}`);
100
+ }
101
+
102
+ return {
103
+ projectSlug: cacheKey.slice(0, colonIndex),
104
+ resourcePath: cacheKey.slice(colonIndex + 1),
105
+ };
106
+ }
107
+
108
+ /**
109
+ * Check if a cache key belongs to a specific project.
110
+ *
111
+ * @param cacheKey - Cache key to check
112
+ * @param projectSlug - Project to check against
113
+ * @returns true if key belongs to project
114
+ */
115
+ export function isProjectKey(cacheKey: string, projectSlug: string): boolean {
116
+ return cacheKey.startsWith(`${projectSlug}:`);
117
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Shared utilities for code block components
3
+ */
4
+ import { ReactElement } from 'react';
5
+
6
+ /**
7
+ * Language display name mapping
8
+ */
9
+ const LANGUAGE_LABELS: Record<string, string> = {
10
+ bash: 'cURL',
11
+ javascript: 'JavaScript',
12
+ typescript: 'TypeScript',
13
+ python: 'Python',
14
+ php: 'PHP',
15
+ go: 'Go',
16
+ java: 'Java',
17
+ csharp: 'C#',
18
+ rust: 'Rust',
19
+ ruby: 'Ruby',
20
+ json: 'JSON',
21
+ shell: 'Shell',
22
+ html: 'HTML',
23
+ css: 'CSS',
24
+ sql: 'SQL',
25
+ yaml: 'YAML',
26
+ xml: 'XML',
27
+ };
28
+
29
+ /**
30
+ * Get display name for a programming language
31
+ */
32
+ export function formatLanguage(lang: string): string {
33
+ return LANGUAGE_LABELS[lang.toLowerCase()] || lang.charAt(0).toUpperCase() + lang.slice(1);
34
+ }
35
+
36
+ /**
37
+ * Helper for accessing React element props
38
+ * Uses `any` to allow property access without type guards
39
+ */
40
+ export function getElementProps(element: ReactElement): Record<string, any> {
41
+ return (element.props || {}) as Record<string, any>;
42
+ }
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Content Loader
3
+ *
4
+ * Unified interface for loading docs content in both static and ISR modes.
5
+ * Abstracts the difference between filesystem (static) and R2 (ISR) content sources.
6
+ *
7
+ * Usage:
8
+ * const loader = getContentLoader(projectSlug); // projectSlug only used in ISR mode
9
+ * const config = await loader.getConfig();
10
+ * const content = await loader.getContent('api/auth');
11
+ */
12
+
13
+ import fs from 'fs';
14
+ import path from 'path';
15
+ import { parseFrontmatterLenient } from './frontmatter-utils';
16
+ import { getDocsConfig as getStaticDocsConfig, getContentDir } from './docs';
17
+ import {
18
+ getDocsConfig as getIsrDocsConfig,
19
+ getMdxContent,
20
+ getAllDocPaths as getIsrDocPaths,
21
+ type DocsConfig,
22
+ } from './docs-isr';
23
+ import { isIsrMode, ISR_REVALIDATE_SECONDS } from './page-isr-helpers';
24
+
25
+ /**
26
+ * Content loader interface.
27
+ */
28
+ export interface ContentLoader {
29
+ /** Get docs.json configuration */
30
+ getConfig(): Promise<DocsConfig> | DocsConfig;
31
+ /** Get raw MDX content for a page */
32
+ getContent(pagePath: string): Promise<string>;
33
+ /** Get all document paths */
34
+ getAllPaths(): Promise<string[]>;
35
+ /** Check if content exists for a path */
36
+ contentExists(pagePath: string): Promise<boolean>;
37
+ }
38
+
39
+ /**
40
+ * Static mode content loader (filesystem).
41
+ */
42
+ class StaticContentLoader implements ContentLoader {
43
+ private contentDir: string;
44
+
45
+ constructor() {
46
+ this.contentDir = getContentDir();
47
+ }
48
+
49
+ getConfig(): DocsConfig {
50
+ return getStaticDocsConfig();
51
+ }
52
+
53
+ async getContent(pagePath: string): Promise<string> {
54
+ const filePath = path.join(this.contentDir, pagePath) + '.mdx';
55
+ return fs.readFileSync(filePath, 'utf8');
56
+ }
57
+
58
+ async getAllPaths(): Promise<string[]> {
59
+ const paths: string[] = [];
60
+
61
+ const traverseDir = (dir: string, basePath: string = '') => {
62
+ if (!fs.existsSync(dir)) return;
63
+
64
+ const files = fs.readdirSync(dir);
65
+
66
+ for (const file of files) {
67
+ if (file.startsWith('.')) continue;
68
+
69
+ const filePath = path.join(dir, file);
70
+
71
+ let stat;
72
+ try {
73
+ stat = fs.statSync(filePath);
74
+ } catch {
75
+ continue;
76
+ }
77
+
78
+ if (stat.isDirectory()) {
79
+ traverseDir(filePath, path.join(basePath, file));
80
+ } else if (file.endsWith('.mdx')) {
81
+ const slug = path.join(basePath, file.replace(/\.mdx$/, ''));
82
+ paths.push(slug);
83
+ }
84
+ }
85
+ };
86
+
87
+ traverseDir(this.contentDir);
88
+ return paths;
89
+ }
90
+
91
+ async contentExists(pagePath: string): Promise<boolean> {
92
+ const filePath = path.join(this.contentDir, pagePath) + '.mdx';
93
+ return fs.existsSync(filePath);
94
+ }
95
+ }
96
+
97
+ /**
98
+ * ISR mode content loader (R2).
99
+ */
100
+ class IsrContentLoader implements ContentLoader {
101
+ private projectSlug: string;
102
+ private configCache: DocsConfig | null = null;
103
+
104
+ constructor(projectSlug: string) {
105
+ this.projectSlug = projectSlug;
106
+ }
107
+
108
+ async getConfig(): Promise<DocsConfig> {
109
+ if (!this.configCache) {
110
+ this.configCache = await getIsrDocsConfig(this.projectSlug);
111
+ }
112
+ return this.configCache;
113
+ }
114
+
115
+ async getContent(pagePath: string): Promise<string> {
116
+ return getMdxContent(this.projectSlug, pagePath);
117
+ }
118
+
119
+ async getAllPaths(): Promise<string[]> {
120
+ return getIsrDocPaths(this.projectSlug);
121
+ }
122
+
123
+ async contentExists(pagePath: string): Promise<boolean> {
124
+ try {
125
+ await this.getContent(pagePath);
126
+ return true;
127
+ } catch {
128
+ return false;
129
+ }
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Get appropriate content loader based on mode.
135
+ *
136
+ * @param projectSlug - Project identifier (only used in ISR mode)
137
+ * @returns Content loader instance
138
+ */
139
+ export function getContentLoader(projectSlug?: string): ContentLoader {
140
+ if (isIsrMode()) {
141
+ if (!projectSlug) {
142
+ throw new Error('Project slug is required in ISR mode');
143
+ }
144
+ return new IsrContentLoader(projectSlug);
145
+ }
146
+
147
+ return new StaticContentLoader();
148
+ }
149
+
150
+ /**
151
+ * Get Next.js revalidate value based on mode.
152
+ *
153
+ * In static mode, returns false (no revalidation).
154
+ * In ISR mode, returns the revalidation interval in seconds.
155
+ */
156
+ export function getRevalidateValue(): number | false {
157
+ return isIsrMode() ? ISR_REVALIDATE_SECONDS : false;
158
+ }
159
+
160
+ /**
161
+ * Parse frontmatter from raw MDX content.
162
+ * Uses lenient parsing to handle common YAML issues like colons in values.
163
+ */
164
+ export function parseFrontmatter(content: string): {
165
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
166
+ data: { [key: string]: any };
167
+ content: string;
168
+ } {
169
+ return parseFrontmatterLenient(content);
170
+ }
171
+
172
+ // Re-export for convenience
173
+ export { isIsrMode } from './page-isr-helpers';
174
+ export { getProjectFromRequest, getHostAtDocs, normalizeSlugForContent } from './page-isr-helpers';
175
+ export { projectExists } from './docs-isr';
176
+ export type { DocsConfig };