vocs 2.0.17 → 2.1.2

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 (306) hide show
  1. package/dist/config.d.ts +1 -0
  2. package/dist/config.d.ts.map +1 -1
  3. package/dist/config.js +1 -0
  4. package/dist/config.js.map +1 -1
  5. package/dist/globals.d.ts +16 -0
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +1 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/internal/config.d.ts +28 -0
  11. package/dist/internal/config.d.ts.map +1 -1
  12. package/dist/internal/config.js +10 -2
  13. package/dist/internal/config.js.map +1 -1
  14. package/dist/internal/llms.d.ts +21 -2
  15. package/dist/internal/llms.d.ts.map +1 -1
  16. package/dist/internal/llms.js +41 -1
  17. package/dist/internal/llms.js.map +1 -1
  18. package/dist/internal/markdown-negotiation.d.ts +36 -0
  19. package/dist/internal/markdown-negotiation.d.ts.map +1 -0
  20. package/dist/internal/markdown-negotiation.js +81 -0
  21. package/dist/internal/markdown-negotiation.js.map +1 -0
  22. package/dist/internal/markdown.d.ts.map +1 -1
  23. package/dist/internal/markdown.js +5 -0
  24. package/dist/internal/markdown.js.map +1 -1
  25. package/dist/internal/openapi/anchors.d.ts +25 -0
  26. package/dist/internal/openapi/anchors.d.ts.map +1 -0
  27. package/dist/internal/openapi/anchors.js +37 -0
  28. package/dist/internal/openapi/anchors.js.map +1 -0
  29. package/dist/internal/openapi/app.d.ts +89 -0
  30. package/dist/internal/openapi/app.d.ts.map +1 -0
  31. package/dist/internal/openapi/app.js +62 -0
  32. package/dist/internal/openapi/app.js.map +1 -0
  33. package/dist/internal/openapi/index.d.ts +8 -0
  34. package/dist/internal/openapi/index.d.ts.map +1 -0
  35. package/dist/internal/openapi/index.js +5 -0
  36. package/dist/internal/openapi/index.js.map +1 -0
  37. package/dist/internal/openapi/markdown.d.ts +42 -0
  38. package/dist/internal/openapi/markdown.d.ts.map +1 -0
  39. package/dist/internal/openapi/markdown.js +235 -0
  40. package/dist/internal/openapi/markdown.js.map +1 -0
  41. package/dist/internal/openapi/openapi.d.ts +187 -0
  42. package/dist/internal/openapi/openapi.d.ts.map +1 -0
  43. package/dist/internal/openapi/openapi.js +44 -0
  44. package/dist/internal/openapi/openapi.js.map +1 -0
  45. package/dist/internal/openapi/openrpc.d.ts +90 -0
  46. package/dist/internal/openapi/openrpc.d.ts.map +1 -0
  47. package/dist/internal/openapi/openrpc.js +213 -0
  48. package/dist/internal/openapi/openrpc.js.map +1 -0
  49. package/dist/internal/openapi/parser.d.ts +181 -0
  50. package/dist/internal/openapi/parser.d.ts.map +1 -0
  51. package/dist/internal/openapi/parser.js +329 -0
  52. package/dist/internal/openapi/parser.js.map +1 -0
  53. package/dist/internal/openapi/registry.d.ts +36 -0
  54. package/dist/internal/openapi/registry.d.ts.map +1 -0
  55. package/dist/internal/openapi/registry.js +79 -0
  56. package/dist/internal/openapi/registry.js.map +1 -0
  57. package/dist/internal/openapi/sample.d.ts +115 -0
  58. package/dist/internal/openapi/sample.d.ts.map +1 -0
  59. package/dist/internal/openapi/sample.js +434 -0
  60. package/dist/internal/openapi/sample.js.map +1 -0
  61. package/dist/internal/openapi/search.d.ts +19 -0
  62. package/dist/internal/openapi/search.d.ts.map +1 -0
  63. package/dist/internal/openapi/search.js +98 -0
  64. package/dist/internal/openapi/search.js.map +1 -0
  65. package/dist/internal/openapi/sidebar.d.ts +30 -0
  66. package/dist/internal/openapi/sidebar.d.ts.map +1 -0
  67. package/dist/internal/openapi/sidebar.js +67 -0
  68. package/dist/internal/openapi/sidebar.js.map +1 -0
  69. package/dist/internal/openapi/union.d.ts +36 -0
  70. package/dist/internal/openapi/union.d.ts.map +1 -0
  71. package/dist/internal/openapi/union.js +69 -0
  72. package/dist/internal/openapi/union.js.map +1 -0
  73. package/dist/internal/search.d.ts.map +1 -1
  74. package/dist/internal/search.js +20 -0
  75. package/dist/internal/search.js.map +1 -1
  76. package/dist/internal/vite-plugins.d.ts +12 -0
  77. package/dist/internal/vite-plugins.d.ts.map +1 -1
  78. package/dist/internal/vite-plugins.js +102 -11
  79. package/dist/internal/vite-plugins.js.map +1 -1
  80. package/dist/react/Badge.d.ts +2 -3
  81. package/dist/react/Badge.d.ts.map +1 -1
  82. package/dist/react/Layout.client.d.ts.map +1 -1
  83. package/dist/react/Layout.client.js +2 -2
  84. package/dist/react/Layout.client.js.map +1 -1
  85. package/dist/react/OpenApi.d.ts +6 -0
  86. package/dist/react/OpenApi.d.ts.map +1 -0
  87. package/dist/react/OpenApi.js +6 -0
  88. package/dist/react/OpenApi.js.map +1 -0
  89. package/dist/react/internal/CodeToHtml.client.d.ts +53 -2
  90. package/dist/react/internal/CodeToHtml.client.d.ts.map +1 -1
  91. package/dist/react/internal/CodeToHtml.client.js +154 -21
  92. package/dist/react/internal/CodeToHtml.client.js.map +1 -1
  93. package/dist/react/internal/Sidebar.d.ts.map +1 -1
  94. package/dist/react/internal/Sidebar.js +99 -2
  95. package/dist/react/internal/Sidebar.js.map +1 -1
  96. package/dist/react/internal/openapi/CodeSample.client.d.ts +21 -0
  97. package/dist/react/internal/openapi/CodeSample.client.d.ts.map +1 -0
  98. package/dist/react/internal/openapi/CodeSample.client.js +134 -0
  99. package/dist/react/internal/openapi/CodeSample.client.js.map +1 -0
  100. package/dist/react/internal/openapi/CollapsibleChildren.client.d.ts +17 -0
  101. package/dist/react/internal/openapi/CollapsibleChildren.client.d.ts.map +1 -0
  102. package/dist/react/internal/openapi/CollapsibleChildren.client.js +18 -0
  103. package/dist/react/internal/openapi/CollapsibleChildren.client.js.map +1 -0
  104. package/dist/react/internal/openapi/Disclosure.client.d.ts +28 -0
  105. package/dist/react/internal/openapi/Disclosure.client.d.ts.map +1 -0
  106. package/dist/react/internal/openapi/Disclosure.client.js +38 -0
  107. package/dist/react/internal/openapi/Disclosure.client.js.map +1 -0
  108. package/dist/react/internal/openapi/Endpoints.d.ts +26 -0
  109. package/dist/react/internal/openapi/Endpoints.d.ts.map +1 -0
  110. package/dist/react/internal/openapi/Endpoints.js +33 -0
  111. package/dist/react/internal/openapi/Endpoints.js.map +1 -0
  112. package/dist/react/internal/openapi/EndpointsView.d.ts +24 -0
  113. package/dist/react/internal/openapi/EndpointsView.d.ts.map +1 -0
  114. package/dist/react/internal/openapi/EndpointsView.js +26 -0
  115. package/dist/react/internal/openapi/EndpointsView.js.map +1 -0
  116. package/dist/react/internal/openapi/EnumValues.client.d.ts +14 -0
  117. package/dist/react/internal/openapi/EnumValues.client.d.ts.map +1 -0
  118. package/dist/react/internal/openapi/EnumValues.client.js +20 -0
  119. package/dist/react/internal/openapi/EnumValues.client.js.map +1 -0
  120. package/dist/react/internal/openapi/HeadingAnchor.d.ts +15 -0
  121. package/dist/react/internal/openapi/HeadingAnchor.d.ts.map +1 -0
  122. package/dist/react/internal/openapi/HeadingAnchor.js +12 -0
  123. package/dist/react/internal/openapi/HeadingAnchor.js.map +1 -0
  124. package/dist/react/internal/openapi/OpenApiPage.d.ts +79 -0
  125. package/dist/react/internal/openapi/OpenApiPage.d.ts.map +1 -0
  126. package/dist/react/internal/openapi/OpenApiPage.js +72 -0
  127. package/dist/react/internal/openapi/OpenApiPage.js.map +1 -0
  128. package/dist/react/internal/openapi/Operation.d.ts +25 -0
  129. package/dist/react/internal/openapi/Operation.d.ts.map +1 -0
  130. package/dist/react/internal/openapi/Operation.js +101 -0
  131. package/dist/react/internal/openapi/Operation.js.map +1 -0
  132. package/dist/react/internal/openapi/Playground.client.d.ts +33 -0
  133. package/dist/react/internal/openapi/Playground.client.d.ts.map +1 -0
  134. package/dist/react/internal/openapi/Playground.client.js +170 -0
  135. package/dist/react/internal/openapi/Playground.client.js.map +1 -0
  136. package/dist/react/internal/openapi/PropertyExample.client.d.ts +17 -0
  137. package/dist/react/internal/openapi/PropertyExample.client.d.ts.map +1 -0
  138. package/dist/react/internal/openapi/PropertyExample.client.js +21 -0
  139. package/dist/react/internal/openapi/PropertyExample.client.js.map +1 -0
  140. package/dist/react/internal/openapi/Reference.d.ts +55 -0
  141. package/dist/react/internal/openapi/Reference.d.ts.map +1 -0
  142. package/dist/react/internal/openapi/Reference.js +42 -0
  143. package/dist/react/internal/openapi/Reference.js.map +1 -0
  144. package/dist/react/internal/openapi/Schema.d.ts +110 -0
  145. package/dist/react/internal/openapi/Schema.d.ts.map +1 -0
  146. package/dist/react/internal/openapi/Schema.js +239 -0
  147. package/dist/react/internal/openapi/Schema.js.map +1 -0
  148. package/dist/react/internal/openapi/SchemaUnion.client.d.ts +25 -0
  149. package/dist/react/internal/openapi/SchemaUnion.client.d.ts.map +1 -0
  150. package/dist/react/internal/openapi/SchemaUnion.client.js +48 -0
  151. package/dist/react/internal/openapi/SchemaUnion.client.js.map +1 -0
  152. package/dist/react/internal/openapi/anchor-navigation.client.d.ts +47 -0
  153. package/dist/react/internal/openapi/anchor-navigation.client.d.ts.map +1 -0
  154. package/dist/react/internal/openapi/anchor-navigation.client.js +120 -0
  155. package/dist/react/internal/openapi/anchor-navigation.client.js.map +1 -0
  156. package/dist/react/internal/openapi/auth.d.ts +28 -0
  157. package/dist/react/internal/openapi/auth.d.ts.map +1 -0
  158. package/dist/react/internal/openapi/auth.js +75 -0
  159. package/dist/react/internal/openapi/auth.js.map +1 -0
  160. package/dist/react/useLayout.d.ts +2 -0
  161. package/dist/react/useLayout.d.ts.map +1 -1
  162. package/dist/react/useLayout.js +2 -0
  163. package/dist/react/useLayout.js.map +1 -1
  164. package/dist/server/handlers.d.ts +1 -1
  165. package/dist/server/handlers.d.ts.map +1 -1
  166. package/dist/server/handlers.js +26 -5
  167. package/dist/server/handlers.js.map +1 -1
  168. package/dist/server/og-assets.d.ts +5 -0
  169. package/dist/server/og-assets.d.ts.map +1 -0
  170. package/dist/server/og-assets.js +11 -0
  171. package/dist/server/og-assets.js.map +1 -0
  172. package/dist/server/openapi/assets.d.ts +33 -0
  173. package/dist/server/openapi/assets.d.ts.map +1 -0
  174. package/dist/server/openapi/assets.generated.d.ts +9 -0
  175. package/dist/server/openapi/assets.generated.d.ts.map +1 -0
  176. package/dist/server/openapi/assets.generated.js +1091 -0
  177. package/dist/server/openapi/assets.generated.js.map +1 -0
  178. package/dist/server/openapi/assets.js +32 -0
  179. package/dist/server/openapi/assets.js.map +1 -0
  180. package/dist/server/openapi/handler.d.ts +103 -0
  181. package/dist/server/openapi/handler.d.ts.map +1 -0
  182. package/dist/server/openapi/handler.js +198 -0
  183. package/dist/server/openapi/handler.js.map +1 -0
  184. package/dist/server/openapi/handler.test.d.ts +2 -0
  185. package/dist/server/openapi/handler.test.d.ts.map +1 -0
  186. package/dist/server/openapi/handler.test.js +203 -0
  187. package/dist/server/openapi/handler.test.js.map +1 -0
  188. package/dist/server/openapi/html.d.ts +16 -0
  189. package/dist/server/openapi/html.d.ts.map +1 -0
  190. package/dist/server/openapi/html.js +75 -0
  191. package/dist/server/openapi/html.js.map +1 -0
  192. package/dist/server/openapi/pages.d.ts +33 -0
  193. package/dist/server/openapi/pages.d.ts.map +1 -0
  194. package/dist/server/openapi/pages.js +130 -0
  195. package/dist/server/openapi/pages.js.map +1 -0
  196. package/dist/server/openapi/pages.test.d.ts +2 -0
  197. package/dist/server/openapi/pages.test.d.ts.map +1 -0
  198. package/dist/server/openapi/pages.test.js +94 -0
  199. package/dist/server/openapi/pages.test.js.map +1 -0
  200. package/dist/server/openapi/state.d.ts +42 -0
  201. package/dist/server/openapi/state.d.ts.map +1 -0
  202. package/dist/server/openapi/state.js +101 -0
  203. package/dist/server/openapi/state.js.map +1 -0
  204. package/dist/styles/index.css +16 -0
  205. package/dist/styles/markdown.css +9 -7
  206. package/dist/styles/openapi-playground.css +80 -0
  207. package/dist/styles/openapi.css +660 -0
  208. package/dist/vite.d.ts.map +1 -1
  209. package/dist/vite.js +1 -0
  210. package/dist/vite.js.map +1 -1
  211. package/dist/waku/internal/middleware/md-router.d.ts +0 -4
  212. package/dist/waku/internal/middleware/md-router.d.ts.map +1 -1
  213. package/dist/waku/internal/middleware/md-router.js +3 -48
  214. package/dist/waku/internal/middleware/md-router.js.map +1 -1
  215. package/dist/waku/internal/patches/adapters/vercel-build-enhancer.js +1 -1
  216. package/dist/waku/internal/patches/adapters/vercel-build-enhancer.js.map +1 -1
  217. package/dist/waku/internal/patches/router.d.ts.map +1 -1
  218. package/dist/waku/internal/patches/router.js +114 -1
  219. package/dist/waku/internal/patches/router.js.map +1 -1
  220. package/package.json +5 -1
  221. package/src/config.ts +1 -0
  222. package/src/globals.d.ts +16 -0
  223. package/src/index.ts +1 -0
  224. package/src/internal/config.ts +40 -1
  225. package/src/internal/llms.ts +51 -1
  226. package/src/internal/markdown-negotiation.test.ts +42 -0
  227. package/src/internal/markdown-negotiation.ts +95 -0
  228. package/src/internal/markdown.ts +5 -0
  229. package/src/internal/openapi/anchors.ts +44 -0
  230. package/src/internal/openapi/app.ts +127 -0
  231. package/src/internal/openapi/index.ts +24 -0
  232. package/src/internal/openapi/markdown.test.ts +115 -0
  233. package/src/internal/openapi/markdown.ts +275 -0
  234. package/src/internal/openapi/openapi.ts +212 -0
  235. package/src/internal/openapi/openrpc.test.ts +239 -0
  236. package/src/internal/openapi/openrpc.ts +295 -0
  237. package/src/internal/openapi/parser.test.ts +203 -0
  238. package/src/internal/openapi/parser.ts +613 -0
  239. package/src/internal/openapi/registry.test.ts +89 -0
  240. package/src/internal/openapi/registry.ts +89 -0
  241. package/src/internal/openapi/sample.test.ts +283 -0
  242. package/src/internal/openapi/sample.ts +562 -0
  243. package/src/internal/openapi/search.test.ts +62 -0
  244. package/src/internal/openapi/search.ts +108 -0
  245. package/src/internal/openapi/sidebar.test.ts +131 -0
  246. package/src/internal/openapi/sidebar.ts +94 -0
  247. package/src/internal/openapi/union.test.ts +51 -0
  248. package/src/internal/openapi/union.ts +74 -0
  249. package/src/internal/search.ts +20 -0
  250. package/src/internal/test/virtual-config.stub.ts +14 -0
  251. package/src/internal/vite-plugins.ts +106 -11
  252. package/src/openapi-app/App.tsx +64 -0
  253. package/src/openapi-app/blocks.tsx +33 -0
  254. package/src/openapi-app/client.tsx +25 -0
  255. package/src/openapi-app/links.test.ts +84 -0
  256. package/src/openapi-app/links.ts +66 -0
  257. package/src/openapi-app/payload.ts +20 -0
  258. package/src/openapi-app/virtual/config.ts +7 -0
  259. package/src/openapi-app/virtual/group-icons.ts +2 -0
  260. package/src/openapi-app/virtual/langs.ts +6 -0
  261. package/src/openapi-app/virtual/openapi.ts +10 -0
  262. package/src/openapi-app/virtual/search-index.ts +21 -0
  263. package/src/openapi-app/virtual/slots.ts +4 -0
  264. package/src/openapi-app/virtual/user-styles.ts +2 -0
  265. package/src/openapi-app/waku.tsx +154 -0
  266. package/src/react/Badge.tsx +2 -3
  267. package/src/react/Layout.client.tsx +17 -4
  268. package/src/react/OpenApi.tsx +5 -0
  269. package/src/react/internal/CodeToHtml.client.tsx +283 -22
  270. package/src/react/internal/Sidebar.tsx +126 -22
  271. package/src/react/internal/openapi/CodeSample.client.tsx +294 -0
  272. package/src/react/internal/openapi/CollapsibleChildren.client.tsx +41 -0
  273. package/src/react/internal/openapi/Disclosure.client.tsx +67 -0
  274. package/src/react/internal/openapi/Endpoints.tsx +58 -0
  275. package/src/react/internal/openapi/EndpointsView.tsx +76 -0
  276. package/src/react/internal/openapi/EnumValues.client.tsx +49 -0
  277. package/src/react/internal/openapi/HeadingAnchor.tsx +28 -0
  278. package/src/react/internal/openapi/OpenApiPage.tsx +173 -0
  279. package/src/react/internal/openapi/Operation.test.tsx +101 -0
  280. package/src/react/internal/openapi/Operation.tsx +335 -0
  281. package/src/react/internal/openapi/Playground.client.tsx +234 -0
  282. package/src/react/internal/openapi/PropertyExample.client.tsx +55 -0
  283. package/src/react/internal/openapi/Reference.tsx +120 -0
  284. package/src/react/internal/openapi/Schema.tsx +467 -0
  285. package/src/react/internal/openapi/SchemaUnion.client.tsx +123 -0
  286. package/src/react/internal/openapi/anchor-navigation.client.ts +154 -0
  287. package/src/react/internal/openapi/auth.ts +69 -0
  288. package/src/react/useLayout.ts +4 -0
  289. package/src/server/handlers.ts +31 -6
  290. package/src/server/og-assets.ts +14 -0
  291. package/src/server/openapi/assets.generated.ts +1093 -0
  292. package/src/server/openapi/assets.ts +57 -0
  293. package/src/server/openapi/handler.test.ts +244 -0
  294. package/src/server/openapi/handler.ts +277 -0
  295. package/src/server/openapi/html.ts +84 -0
  296. package/src/server/openapi/pages.test.ts +111 -0
  297. package/src/server/openapi/pages.ts +153 -0
  298. package/src/server/openapi/state.ts +136 -0
  299. package/src/styles/index.css +16 -0
  300. package/src/styles/markdown.css +9 -7
  301. package/src/styles/openapi-playground.css +80 -0
  302. package/src/styles/openapi.css +660 -0
  303. package/src/vite.ts +1 -0
  304. package/src/waku/internal/middleware/md-router.ts +8 -52
  305. package/src/waku/internal/patches/adapters/vercel-build-enhancer.ts +1 -1
  306. package/src/waku/internal/patches/router.ts +131 -1
@@ -1,55 +1,10 @@
1
1
  import type { MiddlewareHandler } from 'hono'
2
-
3
- export const aiUserAgents = [
4
- 'GPTBot',
5
- 'OAI-SearchBot',
6
- 'ChatGPT-User',
7
- 'ChatGPT-User/2.0',
8
- 'anthropic-ai',
9
- 'ClaudeBot',
10
- 'claude-web',
11
- 'PerplexityBot',
12
- 'Perplexity-User',
13
- 'Google-Extended',
14
- 'FacebookBot',
15
- 'meta-externalagent',
16
- 'Bytespider',
17
- 'cohere-ai',
18
- 'AI2Bot',
19
- 'CCBot',
20
- 'Diffbot',
21
- 'omgili',
22
- 'Timpibot',
23
- 'MistralAI-User',
24
- 'GoogleAgent-Mariner',
25
- ]
26
-
27
- export const searchEngineUserAgents = [
28
- 'Googlebot',
29
- 'Bingbot',
30
- 'Amazonbot',
31
- 'Applebot',
32
- 'Applebot-Extended',
33
- 'DuckAssistBot',
34
- 'YouBot',
35
- ]
36
-
37
- export const terminalUserAgents = ['curl/', 'Wget/', 'HTTPie/', 'httpie-go/', 'xh/']
38
-
39
- export const ogBotUserAgents = [
40
- 'Discordbot',
41
- 'Embedly',
42
- 'Facebot',
43
- 'Iframely',
44
- 'LinkedInBot',
45
- 'Pinterestbot',
46
- 'Slackbot',
47
- 'Slurp',
48
- 'TelegramBot',
49
- 'Twitterbot',
50
- 'WhatsApp',
51
- 'facebookexternalhit',
52
- ]
2
+ import {
3
+ aiUserAgents,
4
+ ogBotUserAgents,
5
+ searchEngineUserAgents,
6
+ terminalUserAgents,
7
+ } from '../../../internal/markdown-negotiation.js'
53
8
 
54
9
  const isDev = process.env['NODE_ENV'] !== 'production'
55
10
 
@@ -63,8 +18,9 @@ async function resolveContent() {
63
18
  const { rehypePlugins, remarkPlugins } = Mdx.getCompileOptions('txt', config)
64
19
  const pagesDir = path.resolve(config.rootDir, config.srcDir, config.pagesDir)
65
20
  const pages = await Llms.getPagesFromDir(pagesDir)
21
+ const openapiPages = await Llms.getOpenApiPages(config)
66
22
  return Llms.buildLlmsContent({
67
- pages,
23
+ pages: [...openapiPages, ...pages],
68
24
  title: config.title,
69
25
  description: config.description,
70
26
  rehypePlugins,
@@ -1,6 +1,6 @@
1
1
  import { cpSync, existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'
2
2
  import path from 'node:path'
3
- import { aiUserAgents, terminalUserAgents } from '../../middleware/md-router.js'
3
+ import { aiUserAgents, terminalUserAgents } from '../../../../internal/markdown-negotiation.js'
4
4
 
5
5
  export type BuildOptions = {
6
6
  assetsDir: string
@@ -1,4 +1,4 @@
1
- import { type FunctionComponent, lazy, type ReactNode } from 'react'
1
+ import { createElement, type FunctionComponent, lazy, type ReactNode } from 'react'
2
2
  import { createPages } from 'waku/router/server'
3
3
  import * as DedupeHead from '../dedupe-head.js'
4
4
  import {
@@ -105,9 +105,30 @@ export function router(
105
105
  )
106
106
 
107
107
  const consumerPaths = new Set<string>()
108
+ // Consumer page modules keyed by their final route path (e.g.
109
+ // `/api/activities`). Used to compose OpenAPI "override" pages: a consumer
110
+ // page mounted at an OpenAPI route supplies the intro content while the
111
+ // generated reference body still renders below it.
112
+ const consumerModules = new Map<string, () => Promise<unknown>>()
108
113
  for (const file in modules) {
109
114
  const srcPath = toSrcPath(file)
110
115
  consumerPaths.add(srcPath.slice(pagesDirPrefix.length).replace(/\.\w+$/, ''))
116
+ const importFn = modules[file]
117
+ if (importFn) {
118
+ const items = srcPath
119
+ .slice(pagesDirPrefix.length)
120
+ .replace(/\.\w+$/, '')
121
+ .split('/')
122
+ .filter(Boolean)
123
+ const last = items.at(-1)
124
+ const route =
125
+ '/' +
126
+ (last && (['_layout', 'index', '_root'].includes(last) || last.startsWith('_part'))
127
+ ? items.slice(0, -1)
128
+ : items
129
+ ).join('/')
130
+ consumerModules.set(route, importFn)
131
+ }
111
132
  }
112
133
 
113
134
  const allModules = { ...defaultPages, ...modules }
@@ -115,6 +136,27 @@ export function router(
115
136
  return wrapPages(
116
137
  createPages(
117
138
  async ({ createPage, createLayout, createRoot, createApi, createSlice }) => {
139
+ // OpenAPI config/specs (data-only virtual modules, safe to import
140
+ // eagerly). The set of OpenAPI route paths lets the page loop below skip
141
+ // creating a standalone page for any consumer override mounted at one of
142
+ // them — the OpenAPI loop owns that route and renders the override as the
143
+ // page intro.
144
+ const { config } = await import('virtual:vocs/config')
145
+ const { specs } = await import('virtual:vocs/openapi')
146
+ const openapiRoutePaths = new Set<string>()
147
+ for (const entry of config.openapi ?? []) {
148
+ openapiRoutePaths.add(entry.path)
149
+ for (const group of specs[entry.path]?.groups ?? [])
150
+ openapiRoutePaths.add(`${entry.path}/${group.id}`)
151
+ }
152
+
153
+ // A consumer page mounted under a section path (e.g. `/api/auth`) that
154
+ // isn't a generated route — a "guide" page rendered with the section
155
+ // layout (see the OpenAPI loop below).
156
+ const isOpenApiGuidePath = (path: string) =>
157
+ !openapiRoutePaths.has(path) &&
158
+ (config.openapi ?? []).some((entry) => path.startsWith(`${entry.path}/`))
159
+
118
160
  for (const file in allModules) {
119
161
  const importFn = allModules[file]
120
162
  if (!importFn) continue
@@ -142,6 +184,18 @@ export function router(
142
184
  ? pathItems.slice(0, -1)
143
185
  : pathItems
144
186
  ).join('/')
187
+
188
+ // A consumer page mounted at an OpenAPI route is an "override": skip
189
+ // creating a standalone page here so the OpenAPI loop can mount it
190
+ // with the generated reference body (it reads the same module as the
191
+ // page intro).
192
+ if (openapiRoutePaths.has(path)) continue
193
+
194
+ // A consumer page mounted *under* an OpenAPI section path (e.g.
195
+ // `/api/auth`) but not at a generated route is a "guide" page. Skip it
196
+ // here so the OpenAPI loop can mount it with the section layout.
197
+ if (isOpenApiGuidePath(path)) continue
198
+
145
199
  const sourceFile = isBuiltIn ? undefined : srcPath
146
200
  const sourceFileProperty = sourceFile ? { unstable_sourceFile: sourceFile } : {}
147
201
 
@@ -250,6 +304,82 @@ export function router(
250
304
  } as never) // FIXME avoid as never
251
305
  }
252
306
  }
307
+
308
+ // Mount OpenAPI sections programmatically from config (no source files).
309
+ // `OpenApiPage` is imported lazily inside this RSC-only callback so the
310
+ // client-component chain (Layout) is never pulled into the shared/SSR
311
+ // module graph.
312
+ if (config.openapi?.length) {
313
+ const { OpenApiGuide, OpenApiPage } = await import(
314
+ '../../../react/internal/openapi/OpenApiPage.js'
315
+ )
316
+
317
+ // Resolves a consumer "override" page mounted at `routePath` into the
318
+ // props (`intro` content + frontmatter `title`) layered onto the
319
+ // generated `OpenApiPage`. Returns empty props when there is no
320
+ // override. Uses the MDX `default` export (raw content) — not `Page` —
321
+ // so the override is not wrapped in its own Layout.
322
+ const overrideProps = async (routePath: string) => {
323
+ const importFn = consumerModules.get(routePath)
324
+ if (!importFn) return {}
325
+ const mod = (await importFn()) as {
326
+ default?: FunctionComponent
327
+ frontmatter?: { title?: string }
328
+ }
329
+ if (!mod.default) return {}
330
+ const Content = mod.default
331
+ return { intro: createElement(Content), title: mod.frontmatter?.title }
332
+ }
333
+
334
+ for (const entry of config.openapi) {
335
+ // Section root: overview listing every category.
336
+ const rootProps = await overrideProps(entry.path)
337
+ createPage({
338
+ path: entry.path,
339
+ component: () =>
340
+ createElement(OpenApiPage, {
341
+ mount: entry.path,
342
+ endpoints: !rootProps.intro,
343
+ ...rootProps,
344
+ }),
345
+ render: 'static',
346
+ } as never)
347
+
348
+ // Mount one page per category at `${path}/${group}`.
349
+ const ir = specs[entry.path]
350
+ for (const group of ir?.groups ?? []) {
351
+ const groupRoute = `${entry.path}/${group.id}`
352
+ const groupProps = await overrideProps(groupRoute)
353
+ createPage({
354
+ path: groupRoute,
355
+ component: () =>
356
+ createElement(OpenApiPage, { mount: entry.path, group: group.id, ...groupProps }),
357
+ render: 'static',
358
+ } as never)
359
+ }
360
+
361
+ // Mount consumer "guide" pages under the section (e.g. `/api/auth`)
362
+ // with the section layout: a normal MDX page rendered full-bleed,
363
+ // content-width, and without the right gutter/TOC.
364
+ for (const [routePath, importFn] of consumerModules) {
365
+ if (!routePath.startsWith(`${entry.path}/`)) continue
366
+ if (openapiRoutePaths.has(routePath)) continue
367
+ const mod = (await importFn()) as {
368
+ default?: FunctionComponent
369
+ frontmatter?: { title?: string }
370
+ }
371
+ if (!mod.default) continue
372
+ const Content = mod.default
373
+ const title = mod.frontmatter?.title
374
+ createPage({
375
+ path: routePath,
376
+ component: () => createElement(OpenApiGuide, { title }, createElement(Content)),
377
+ render: 'static',
378
+ } as never)
379
+ }
380
+ }
381
+ }
382
+
253
383
  // HACK: to satisfy the return type, unused at runtime
254
384
  return null as never
255
385
  },