blodemd 0.1.0 → 0.2.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 (289) hide show
  1. package/dist/cli.mjs +50 -174
  2. package/dist/cli.mjs.map +1 -1
  3. package/package.json +3 -36
  4. package/dev-server/app/[[...slug]]/page.tsx +0 -140
  5. package/dev-server/app/blodemd-dev/invalidate/route.ts +0 -12
  6. package/dev-server/app/blodemd-dev/static/[...path]/route.ts +0 -32
  7. package/dev-server/app/blodemd-dev/version/route.ts +0 -14
  8. package/dev-server/app/blodemd-internal/proxy/route.ts +0 -86
  9. package/dev-server/app/error.tsx +0 -24
  10. package/dev-server/app/favicon.ico +0 -0
  11. package/dev-server/app/globals.css +0 -4
  12. package/dev-server/app/layout.tsx +0 -38
  13. package/dev-server/app/not-found.tsx +0 -18
  14. package/dev-server/app/search/route.ts +0 -17
  15. package/dev-server/components/dev-reload-script.tsx +0 -86
  16. package/dev-server/components/providers.tsx +0 -15
  17. package/dev-server/lib/dev-state.ts +0 -8
  18. package/dev-server/lib/local-content-source.ts +0 -103
  19. package/dev-server/lib/local-runtime.tsx +0 -555
  20. package/dev-server/next-env.d.ts +0 -5
  21. package/dev-server/next.config.js +0 -54
  22. package/dev-server/package.json +0 -61
  23. package/dev-server/postcss.config.mjs +0 -7
  24. package/dev-server/public/glide-variable.woff2 +0 -0
  25. package/dev-server/tsconfig.json +0 -50
  26. package/docs/app/globals.css +0 -471
  27. package/docs/components/animate-ui/primitives/buttons/button.tsx +0 -14
  28. package/docs/components/api/api-playground.tsx +0 -467
  29. package/docs/components/api/api-reference.tsx +0 -157
  30. package/docs/components/content/collection-index.tsx +0 -114
  31. package/docs/components/docs/contextual-menu.tsx +0 -495
  32. package/docs/components/docs/copy-page-menu.tsx +0 -364
  33. package/docs/components/docs/doc-header.tsx +0 -223
  34. package/docs/components/docs/doc-shell.tsx +0 -355
  35. package/docs/components/docs/doc-sidebar.tsx +0 -256
  36. package/docs/components/docs/doc-toc.tsx +0 -46
  37. package/docs/components/docs/mobile-nav.tsx +0 -195
  38. package/docs/components/docs/sidebar-active-highlight.tsx +0 -34
  39. package/docs/components/docs/sidebar-scroll-area.tsx +0 -63
  40. package/docs/components/git/repo-picker.tsx +0 -529
  41. package/docs/components/icons/doc-icon.tsx +0 -96
  42. package/docs/components/mdx/accordion.tsx +0 -83
  43. package/docs/components/mdx/agent-instructions.tsx +0 -17
  44. package/docs/components/mdx/badge.tsx +0 -79
  45. package/docs/components/mdx/callout.tsx +0 -88
  46. package/docs/components/mdx/card.tsx +0 -110
  47. package/docs/components/mdx/code-block.tsx +0 -80
  48. package/docs/components/mdx/code-group.tsx +0 -203
  49. package/docs/components/mdx/color.tsx +0 -87
  50. package/docs/components/mdx/columns.tsx +0 -25
  51. package/docs/components/mdx/expandable.tsx +0 -45
  52. package/docs/components/mdx/field-layout.tsx +0 -77
  53. package/docs/components/mdx/frame.tsx +0 -23
  54. package/docs/components/mdx/get-text-content.ts +0 -18
  55. package/docs/components/mdx/icon.tsx +0 -12
  56. package/docs/components/mdx/iframe.tsx +0 -62
  57. package/docs/components/mdx/index.tsx +0 -121
  58. package/docs/components/mdx/installer.tsx +0 -20
  59. package/docs/components/mdx/panel.tsx +0 -11
  60. package/docs/components/mdx/param-field.tsx +0 -56
  61. package/docs/components/mdx/preview.tsx +0 -36
  62. package/docs/components/mdx/prompt.tsx +0 -63
  63. package/docs/components/mdx/request-example.tsx +0 -27
  64. package/docs/components/mdx/response-field.tsx +0 -42
  65. package/docs/components/mdx/steps.tsx +0 -92
  66. package/docs/components/mdx/tabs.tsx +0 -193
  67. package/docs/components/mdx/tile.tsx +0 -43
  68. package/docs/components/mdx/tooltip.tsx +0 -71
  69. package/docs/components/mdx/tree.tsx +0 -120
  70. package/docs/components/mdx/type-table.tsx +0 -71
  71. package/docs/components/mdx/update.tsx +0 -44
  72. package/docs/components/mdx/video.tsx +0 -45
  73. package/docs/components/mdx/view.tsx +0 -66
  74. package/docs/components/posthog-provider.tsx +0 -42
  75. package/docs/components/providers.tsx +0 -15
  76. package/docs/components/tenant-analytics.tsx +0 -49
  77. package/docs/components/third-parties.tsx +0 -32
  78. package/docs/components/ui/badge.tsx +0 -61
  79. package/docs/components/ui/breadcrumb.tsx +0 -112
  80. package/docs/components/ui/button-group.tsx +0 -83
  81. package/docs/components/ui/button.tsx +0 -65
  82. package/docs/components/ui/card.tsx +0 -92
  83. package/docs/components/ui/command.tsx +0 -167
  84. package/docs/components/ui/copy-button.tsx +0 -129
  85. package/docs/components/ui/dialog.tsx +0 -146
  86. package/docs/components/ui/field.tsx +0 -237
  87. package/docs/components/ui/input.tsx +0 -23
  88. package/docs/components/ui/kbd.tsx +0 -98
  89. package/docs/components/ui/label.tsx +0 -22
  90. package/docs/components/ui/morph-icon.tsx +0 -79
  91. package/docs/components/ui/popover.tsx +0 -267
  92. package/docs/components/ui/search-dialog.tsx +0 -431
  93. package/docs/components/ui/search.tsx +0 -101
  94. package/docs/components/ui/separator.tsx +0 -26
  95. package/docs/components/ui/sheet.tsx +0 -133
  96. package/docs/components/ui/sidebar.tsx +0 -758
  97. package/docs/components/ui/skeleton.tsx +0 -11
  98. package/docs/components/ui/switch.tsx +0 -32
  99. package/docs/components/ui/tabs.tsx +0 -138
  100. package/docs/components/ui/theme-toggle.tsx +0 -62
  101. package/docs/components/ui/tooltip.tsx +0 -53
  102. package/docs/components/web-mcp.tsx +0 -115
  103. package/docs/lib/agent-skills.ts +0 -48
  104. package/docs/lib/api-client.ts +0 -72
  105. package/docs/lib/config.ts +0 -6
  106. package/docs/lib/content-root.ts +0 -33
  107. package/docs/lib/content-source.ts +0 -70
  108. package/docs/lib/contextual-options.ts +0 -222
  109. package/docs/lib/dashboard-session.ts +0 -167
  110. package/docs/lib/db.ts +0 -13
  111. package/docs/lib/docs-collection.ts +0 -7
  112. package/docs/lib/docs-runtime.tsx +0 -745
  113. package/docs/lib/edge-config.ts +0 -95
  114. package/docs/lib/env.ts +0 -23
  115. package/docs/lib/etag.ts +0 -22
  116. package/docs/lib/github-install.ts +0 -33
  117. package/docs/lib/llms-full.ts +0 -82
  118. package/docs/lib/marketing-markdown.ts +0 -79
  119. package/docs/lib/marketing-site.ts +0 -31
  120. package/docs/lib/mdx.ts +0 -98
  121. package/docs/lib/navigation.ts +0 -288
  122. package/docs/lib/openapi-proxy.ts +0 -88
  123. package/docs/lib/openapi.ts +0 -158
  124. package/docs/lib/platform-config.ts +0 -6
  125. package/docs/lib/project-authz.ts +0 -46
  126. package/docs/lib/routes.ts +0 -103
  127. package/docs/lib/server-cache.ts +0 -83
  128. package/docs/lib/shiki.ts +0 -44
  129. package/docs/lib/supabase.ts +0 -37
  130. package/docs/lib/tenancy.ts +0 -364
  131. package/docs/lib/tenant-headers.ts +0 -43
  132. package/docs/lib/tenant-static.ts +0 -705
  133. package/docs/lib/tenant-utility-context.ts +0 -62
  134. package/docs/lib/tenants.ts +0 -72
  135. package/docs/lib/theme.ts +0 -29
  136. package/docs/lib/time-ago.ts +0 -24
  137. package/docs/lib/toc.ts +0 -2
  138. package/docs/lib/use-mobile.ts +0 -19
  139. package/docs/lib/use-tab-observer.ts +0 -71
  140. package/docs/lib/utils.ts +0 -5
  141. package/packages/@repo/common/dist/index.d.ts +0 -16
  142. package/packages/@repo/common/dist/index.d.ts.map +0 -1
  143. package/packages/@repo/common/dist/index.js +0 -84
  144. package/packages/@repo/common/package.json +0 -34
  145. package/packages/@repo/common/src/index.ts +0 -101
  146. package/packages/@repo/contracts/dist/analytics.d.ts +0 -21
  147. package/packages/@repo/contracts/dist/analytics.d.ts.map +0 -1
  148. package/packages/@repo/contracts/dist/analytics.js +0 -18
  149. package/packages/@repo/contracts/dist/api-key.d.ts +0 -27
  150. package/packages/@repo/contracts/dist/api-key.d.ts.map +0 -1
  151. package/packages/@repo/contracts/dist/api-key.js +0 -20
  152. package/packages/@repo/contracts/dist/dates.d.ts +0 -4
  153. package/packages/@repo/contracts/dist/dates.d.ts.map +0 -1
  154. package/packages/@repo/contracts/dist/dates.js +0 -2
  155. package/packages/@repo/contracts/dist/deployment.d.ts +0 -71
  156. package/packages/@repo/contracts/dist/deployment.d.ts.map +0 -1
  157. package/packages/@repo/contracts/dist/deployment.js +0 -46
  158. package/packages/@repo/contracts/dist/domain.d.ts +0 -94
  159. package/packages/@repo/contracts/dist/domain.d.ts.map +0 -1
  160. package/packages/@repo/contracts/dist/domain.js +0 -36
  161. package/packages/@repo/contracts/dist/git.d.ts +0 -28
  162. package/packages/@repo/contracts/dist/git.d.ts.map +0 -1
  163. package/packages/@repo/contracts/dist/git.js +0 -24
  164. package/packages/@repo/contracts/dist/ids.d.ts +0 -14
  165. package/packages/@repo/contracts/dist/ids.d.ts.map +0 -1
  166. package/packages/@repo/contracts/dist/ids.js +0 -11
  167. package/packages/@repo/contracts/dist/index.d.ts +0 -12
  168. package/packages/@repo/contracts/dist/index.d.ts.map +0 -1
  169. package/packages/@repo/contracts/dist/index.js +0 -13
  170. package/packages/@repo/contracts/dist/pagination.d.ts +0 -23
  171. package/packages/@repo/contracts/dist/pagination.d.ts.map +0 -1
  172. package/packages/@repo/contracts/dist/pagination.js +0 -15
  173. package/packages/@repo/contracts/dist/project.d.ts +0 -42
  174. package/packages/@repo/contracts/dist/project.d.ts.map +0 -1
  175. package/packages/@repo/contracts/dist/project.js +0 -25
  176. package/packages/@repo/contracts/dist/tenant.d.ts +0 -147
  177. package/packages/@repo/contracts/dist/tenant.d.ts.map +0 -1
  178. package/packages/@repo/contracts/dist/tenant.js +0 -58
  179. package/packages/@repo/contracts/dist/user.d.ts +0 -9
  180. package/packages/@repo/contracts/dist/user.d.ts.map +0 -1
  181. package/packages/@repo/contracts/dist/user.js +0 -9
  182. package/packages/@repo/contracts/package.json +0 -37
  183. package/packages/@repo/contracts/src/analytics.ts +0 -33
  184. package/packages/@repo/contracts/src/api-key.ts +0 -27
  185. package/packages/@repo/contracts/src/dates.ts +0 -4
  186. package/packages/@repo/contracts/src/deployment.ts +0 -73
  187. package/packages/@repo/contracts/src/domain.ts +0 -51
  188. package/packages/@repo/contracts/src/git.ts +0 -31
  189. package/packages/@repo/contracts/src/ids.ts +0 -23
  190. package/packages/@repo/contracts/src/index.ts +0 -13
  191. package/packages/@repo/contracts/src/pagination.ts +0 -21
  192. package/packages/@repo/contracts/src/project.ts +0 -32
  193. package/packages/@repo/contracts/src/tenant.ts +0 -94
  194. package/packages/@repo/contracts/src/user.ts +0 -12
  195. package/packages/@repo/models/dist/docs-config.d.ts +0 -961
  196. package/packages/@repo/models/dist/docs-config.d.ts.map +0 -1
  197. package/packages/@repo/models/dist/docs-config.js +0 -531
  198. package/packages/@repo/models/dist/index.d.ts +0 -3
  199. package/packages/@repo/models/dist/index.d.ts.map +0 -1
  200. package/packages/@repo/models/dist/index.js +0 -3
  201. package/packages/@repo/models/dist/tenant.d.ts +0 -37
  202. package/packages/@repo/models/dist/tenant.d.ts.map +0 -1
  203. package/packages/@repo/models/dist/tenant.js +0 -1
  204. package/packages/@repo/models/package.json +0 -37
  205. package/packages/@repo/models/src/docs-config.ts +0 -629
  206. package/packages/@repo/models/src/index.ts +0 -3
  207. package/packages/@repo/models/src/tenant.ts +0 -44
  208. package/packages/@repo/prebuild/dist/index.d.ts +0 -2
  209. package/packages/@repo/prebuild/dist/index.d.ts.map +0 -1
  210. package/packages/@repo/prebuild/dist/index.js +0 -2
  211. package/packages/@repo/prebuild/dist/openapi.d.ts +0 -43
  212. package/packages/@repo/prebuild/dist/openapi.d.ts.map +0 -1
  213. package/packages/@repo/prebuild/dist/openapi.js +0 -86
  214. package/packages/@repo/prebuild/package.json +0 -39
  215. package/packages/@repo/prebuild/src/index.ts +0 -2
  216. package/packages/@repo/prebuild/src/openapi.ts +0 -154
  217. package/packages/@repo/previewing/dist/blob-source.d.ts +0 -16
  218. package/packages/@repo/previewing/dist/blob-source.d.ts.map +0 -1
  219. package/packages/@repo/previewing/dist/blob-source.js +0 -128
  220. package/packages/@repo/previewing/dist/config-loader.d.ts +0 -134
  221. package/packages/@repo/previewing/dist/config-loader.d.ts.map +0 -1
  222. package/packages/@repo/previewing/dist/config-loader.js +0 -231
  223. package/packages/@repo/previewing/dist/constants.d.ts +0 -15
  224. package/packages/@repo/previewing/dist/constants.d.ts.map +0 -1
  225. package/packages/@repo/previewing/dist/constants.js +0 -14
  226. package/packages/@repo/previewing/dist/content-index.d.ts +0 -7
  227. package/packages/@repo/previewing/dist/content-index.d.ts.map +0 -1
  228. package/packages/@repo/previewing/dist/content-index.js +0 -291
  229. package/packages/@repo/previewing/dist/content-source.d.ts +0 -12
  230. package/packages/@repo/previewing/dist/content-source.d.ts.map +0 -1
  231. package/packages/@repo/previewing/dist/content-source.js +0 -1
  232. package/packages/@repo/previewing/dist/fs-source.d.ts +0 -11
  233. package/packages/@repo/previewing/dist/fs-source.d.ts.map +0 -1
  234. package/packages/@repo/previewing/dist/fs-source.js +0 -71
  235. package/packages/@repo/previewing/dist/index.d.ts +0 -16
  236. package/packages/@repo/previewing/dist/index.d.ts.map +0 -1
  237. package/packages/@repo/previewing/dist/index.js +0 -13
  238. package/packages/@repo/previewing/dist/markdown/agent-markdown.d.ts +0 -3
  239. package/packages/@repo/previewing/dist/markdown/agent-markdown.d.ts.map +0 -1
  240. package/packages/@repo/previewing/dist/markdown/agent-markdown.js +0 -176
  241. package/packages/@repo/previewing/dist/markdown/format.d.ts +0 -8
  242. package/packages/@repo/previewing/dist/markdown/format.d.ts.map +0 -1
  243. package/packages/@repo/previewing/dist/markdown/format.js +0 -43
  244. package/packages/@repo/previewing/dist/markdown/links.d.ts +0 -3
  245. package/packages/@repo/previewing/dist/markdown/links.d.ts.map +0 -1
  246. package/packages/@repo/previewing/dist/markdown/links.js +0 -31
  247. package/packages/@repo/previewing/dist/openapi-pages.d.ts +0 -7
  248. package/packages/@repo/previewing/dist/openapi-pages.d.ts.map +0 -1
  249. package/packages/@repo/previewing/dist/openapi-pages.js +0 -200
  250. package/packages/@repo/previewing/dist/search-index.d.ts +0 -4
  251. package/packages/@repo/previewing/dist/search-index.d.ts.map +0 -1
  252. package/packages/@repo/previewing/dist/search-index.js +0 -23
  253. package/packages/@repo/previewing/dist/serialization.d.ts +0 -13
  254. package/packages/@repo/previewing/dist/serialization.d.ts.map +0 -1
  255. package/packages/@repo/previewing/dist/serialization.js +0 -108
  256. package/packages/@repo/previewing/dist/toc-index.d.ts +0 -5
  257. package/packages/@repo/previewing/dist/toc-index.d.ts.map +0 -1
  258. package/packages/@repo/previewing/dist/toc-index.js +0 -53
  259. package/packages/@repo/previewing/dist/types.d.ts +0 -92
  260. package/packages/@repo/previewing/dist/types.d.ts.map +0 -1
  261. package/packages/@repo/previewing/dist/types.js +0 -1
  262. package/packages/@repo/previewing/dist/utility-index.d.ts +0 -7
  263. package/packages/@repo/previewing/dist/utility-index.d.ts.map +0 -1
  264. package/packages/@repo/previewing/dist/utility-index.js +0 -201
  265. package/packages/@repo/previewing/package.json +0 -41
  266. package/packages/@repo/previewing/src/blob-source.ts +0 -185
  267. package/packages/@repo/previewing/src/config-loader.ts +0 -316
  268. package/packages/@repo/previewing/src/constants.ts +0 -16
  269. package/packages/@repo/previewing/src/content-index.ts +0 -384
  270. package/packages/@repo/previewing/src/content-source.ts +0 -12
  271. package/packages/@repo/previewing/src/fs-source.ts +0 -103
  272. package/packages/@repo/previewing/src/index.ts +0 -71
  273. package/packages/@repo/previewing/src/markdown/agent-markdown.ts +0 -254
  274. package/packages/@repo/previewing/src/markdown/format.ts +0 -63
  275. package/packages/@repo/previewing/src/markdown/links.ts +0 -46
  276. package/packages/@repo/previewing/src/openapi-pages.ts +0 -319
  277. package/packages/@repo/previewing/src/search-index.ts +0 -38
  278. package/packages/@repo/previewing/src/serialization.ts +0 -191
  279. package/packages/@repo/previewing/src/toc-index.ts +0 -72
  280. package/packages/@repo/previewing/src/types.ts +0 -105
  281. package/packages/@repo/previewing/src/utility-index.ts +0 -304
  282. package/packages/@repo/validation/dist/index.d.ts +0 -12
  283. package/packages/@repo/validation/dist/index.d.ts.map +0 -1
  284. package/packages/@repo/validation/dist/index.js +0 -30
  285. package/packages/@repo/validation/package.json +0 -38
  286. package/packages/@repo/validation/src/blodemd-docs-schema.json +0 -3575
  287. package/packages/@repo/validation/src/index.ts +0 -59
  288. package/scripts/prepare-package.mjs +0 -53
  289. package/scripts/repo-packages.mjs +0 -8
@@ -1,705 +0,0 @@
1
- import { slugify } from "@repo/common";
2
- import type { TenantResolution } from "@repo/contracts";
3
- import type { Tenant } from "@repo/models";
4
- import type { UtilityIndex } from "@repo/previewing";
5
- import {
6
- absolutiseInternalLinks,
7
- buildContentIndex,
8
- buildPageMetadataMap,
9
- formatMarkdownPage,
10
- formatMarkdownPageSection,
11
- formatOpenApiPageContent,
12
- getPrebuiltUtilityLlmPagePath,
13
- loadPrebuiltContentIndex,
14
- loadPrebuiltUtilityIndex,
15
- loadSiteConfig,
16
- PREBUILT_UTILITY_LLMS_FULL_PATH,
17
- PREBUILT_UTILITY_LLMS_PATH,
18
- PREBUILT_UTILITY_LLMS_SEGMENT_PREFIX,
19
- PREBUILT_UTILITY_SITEMAP_PATH,
20
- prepareLlmsFullContent,
21
- sanitizePlaceholderUrls,
22
- stripFrontmatter,
23
- toAgentMarkdown,
24
- UTILITY_DOCS_ROOT_TOKEN,
25
- } from "@repo/previewing";
26
-
27
- import {
28
- getTenantContentSource,
29
- resolveSiteConfigAssets,
30
- } from "@/lib/content-source";
31
- import {
32
- getDocsCollection,
33
- getDocsCollectionWithNavigation,
34
- getDocsNavigation,
35
- } from "@/lib/docs-collection";
36
- import { capLlmsFullContent } from "@/lib/llms-full";
37
- import {
38
- buildNavigation,
39
- enrichNavWithMetadata,
40
- flattenNav,
41
- getVisibleNavigation,
42
- } from "@/lib/navigation";
43
- import type { NavGroup } from "@/lib/navigation";
44
- import type { OpenApiEntry } from "@/lib/openapi";
45
- import { loadOpenApiRegistry } from "@/lib/openapi";
46
- import { toDocHref, toMarkdownDocHref } from "@/lib/routes";
47
- import { createTimedPromiseCache } from "@/lib/server-cache";
48
- import { getRequestProtocol } from "@/lib/tenancy";
49
- import type { TenantRequestContext } from "@/lib/tenant-utility-context";
50
-
51
- // Re-exported so tenant-static.unit.test.ts continues to guard the shared
52
- // implementation now living in @repo/previewing.
53
- export { absolutiseInternalLinks, sanitizePlaceholderUrls };
54
-
55
- const TENANT_STATIC_CACHE_TTL_MS = 30 * 60 * 1000;
56
-
57
- const getTenantStaticCacheKey = (tenant: Tenant) =>
58
- [
59
- tenant.id,
60
- tenant.slug,
61
- tenant.activeDeploymentId ?? "",
62
- tenant.activeDeploymentManifestUrl ?? "",
63
- tenant.docsPath ?? "",
64
- tenant.pathPrefix ?? "",
65
- tenant.primaryDomain,
66
- ].join(":");
67
-
68
- const tenantUrlDataCache = createTimedPromiseCache<
69
- string,
70
- Awaited<ReturnType<typeof buildTenantUrlData>>
71
- >({
72
- maxEntries: 512,
73
- ttlMs: TENANT_STATIC_CACHE_TTL_MS,
74
- });
75
-
76
- const tenantUtilityIndexCache = createTimedPromiseCache<string, UtilityIndex>({
77
- maxEntries: 512,
78
- ttlMs: TENANT_STATIC_CACHE_TTL_MS,
79
- });
80
-
81
- const isMissingContentFileError = (error: unknown) => {
82
- if (
83
- typeof error === "object" &&
84
- error !== null &&
85
- "code" in error &&
86
- (error as { code?: string }).code === "ENOENT"
87
- ) {
88
- return true;
89
- }
90
-
91
- return error instanceof Error && error.message.includes("not found");
92
- };
93
-
94
- const getCanonicalHost = (
95
- tenant: Tenant,
96
- requestedHost?: string,
97
- strategy?: TenantResolution["strategy"] | null
98
- ) =>
99
- (strategy === "custom-domain" || strategy === "path") && requestedHost
100
- ? requestedHost
101
- : tenant.primaryDomain;
102
-
103
- const getCanonicalBasePath = (
104
- tenant: Tenant,
105
- basePath?: string,
106
- strategy?: TenantResolution["strategy"] | null
107
- ) => {
108
- if (strategy === "path") {
109
- return basePath || `/${tenant.slug}`;
110
- }
111
- if (strategy === "custom-domain") {
112
- return basePath ?? tenant.pathPrefix ?? "";
113
- }
114
- return basePath ?? "";
115
- };
116
-
117
- export const getTenantRequestContextFromHeaders = (
118
- tenant: Tenant,
119
- headerStore: Pick<Headers, "get">
120
- ): TenantRequestContext => ({
121
- basePath: headerStore.get("x-tenant-base-path") ?? tenant.pathPrefix ?? "",
122
- protocol: getRequestProtocol(headerStore),
123
- requestedHost: headerStore.get("x-tenant-domain") ?? undefined,
124
- strategy: (headerStore.get("x-tenant-strategy") ?? null) as
125
- | TenantResolution["strategy"]
126
- | null,
127
- });
128
-
129
- export const getStaticTenantRequestContext = (
130
- tenant: Tenant
131
- ): TenantRequestContext => ({
132
- basePath: tenant.pathPrefix ?? "",
133
- protocol: "https",
134
- requestedHost: tenant.primaryDomain,
135
- strategy: tenant.customDomains.length > 0 ? "custom-domain" : null,
136
- });
137
-
138
- export const getCanonicalOrigin = (
139
- tenant: Tenant,
140
- context: TenantRequestContext = {}
141
- ) =>
142
- `${context.protocol ?? "https"}://${getCanonicalHost(
143
- tenant,
144
- context.requestedHost,
145
- context.strategy
146
- )}`;
147
-
148
- export const getCanonicalDocBasePath = (
149
- tenant: Tenant,
150
- context: TenantRequestContext = {}
151
- ) => getCanonicalBasePath(tenant, context.basePath, context.strategy);
152
-
153
- const renderUtilityTemplate = (
154
- source: string,
155
- tenant: Tenant,
156
- context: TenantRequestContext = {}
157
- ) =>
158
- source.replaceAll(
159
- UTILITY_DOCS_ROOT_TOKEN,
160
- `${getCanonicalOrigin(tenant, context)}${getCanonicalDocBasePath(
161
- tenant,
162
- context
163
- )}`
164
- );
165
-
166
- const buildTenantUrlData = async (tenant: Tenant) => {
167
- const contentSource = getTenantContentSource(tenant);
168
- const configResult = await loadSiteConfig(contentSource);
169
- if (!configResult.ok) {
170
- throw new Error("Invalid config");
171
- }
172
-
173
- const config = await resolveSiteConfigAssets(
174
- configResult.config,
175
- contentSource
176
- );
177
- const contentIndex =
178
- (await loadPrebuiltContentIndex(contentSource)) ??
179
- (await buildContentIndex(contentSource, config));
180
- if (contentIndex.errors.length) {
181
- throw new Error("Invalid content");
182
- }
183
-
184
- const docsCollection = getDocsCollection(config);
185
- const docsNavigation = getDocsNavigation(config);
186
- const docsCollectionWithNavigation = getDocsCollectionWithNavigation(config);
187
- const registry = await loadOpenApiRegistry(
188
- docsCollectionWithNavigation,
189
- contentSource
190
- );
191
- const metadataMap = buildPageMetadataMap(contentIndex);
192
- const rawNav = docsNavigation
193
- ? buildNavigation(
194
- docsNavigation,
195
- registry,
196
- docsCollection?.slugPrefix ?? ""
197
- )
198
- : [];
199
- const nav = enrichNavWithMetadata(rawNav, metadataMap);
200
- const visibleNav = getVisibleNavigation(nav);
201
- const hiddenSlugs = new Set<string>();
202
- for (const [slug, meta] of metadataMap) {
203
- if (meta.hidden || meta.noindex) {
204
- hiddenSlugs.add(slug);
205
- }
206
- }
207
-
208
- const navPages = flattenNav(visibleNav).map((page) => page.path);
209
- const contentPages = contentIndex.entries
210
- .filter(
211
- (entry) =>
212
- !(entry.kind === "entry" && entry.hidden) &&
213
- !hiddenSlugs.has(entry.slug)
214
- )
215
- .map((entry) => entry.slug);
216
-
217
- return {
218
- config,
219
- contentIndex,
220
- contentSource,
221
- hiddenSlugs,
222
- pages: [...new Set([...navPages, ...contentPages])],
223
- registry,
224
- visibleNav,
225
- };
226
- };
227
-
228
- const loadTenantUrlData = async (tenant: Tenant) =>
229
- await tenantUrlDataCache.getOrCreate(
230
- getTenantStaticCacheKey(tenant),
231
- async () => await buildTenantUrlData(tenant)
232
- );
233
-
234
- const resolveLlmPages = (
235
- data: Awaited<ReturnType<typeof loadTenantUrlData>>
236
- ): (
237
- | {
238
- kind: "content";
239
- relativePath: string;
240
- slug: string;
241
- title: string;
242
- description?: string;
243
- }
244
- | {
245
- kind: "openapi";
246
- entry: OpenApiEntry;
247
- slug: string;
248
- title: string;
249
- description?: string;
250
- }
251
- )[] =>
252
- data.pages
253
- .map((slug) => {
254
- const contentEntry = data.contentIndex.bySlug.get(slug);
255
- if (
256
- contentEntry &&
257
- contentEntry.kind === "entry" &&
258
- !contentEntry.hidden &&
259
- !data.hiddenSlugs.has(contentEntry.slug)
260
- ) {
261
- return {
262
- description: contentEntry.description,
263
- kind: "content" as const,
264
- relativePath: contentEntry.relativePath,
265
- slug: contentEntry.slug,
266
- title: contentEntry.title,
267
- };
268
- }
269
-
270
- const openApiEntry = data.registry.bySlug.get(slug);
271
- if (!openApiEntry) {
272
- return null;
273
- }
274
-
275
- return {
276
- description: openApiEntry.operation.description,
277
- entry: openApiEntry,
278
- kind: "openapi" as const,
279
- slug,
280
- title: openApiEntry.operation.summary ?? openApiEntry.identifier,
281
- };
282
- })
283
- .filter((page) => page !== null);
284
-
285
- const buildRuntimeUtilityIndex = async (
286
- tenant: Tenant
287
- ): Promise<UtilityIndex> => {
288
- const data = await loadTenantUrlData(tenant);
289
- const pages = await Promise.all(
290
- resolveLlmPages(data).map(async (page) => {
291
- if (page.kind === "openapi") {
292
- return {
293
- content: formatOpenApiPageContent(page.entry.operation),
294
- description: page.description,
295
- slug: page.slug,
296
- title: page.title,
297
- };
298
- }
299
-
300
- const raw = await data.contentSource.readFile(page.relativePath);
301
- return {
302
- content: toAgentMarkdown(stripFrontmatter(raw)),
303
- description: page.description,
304
- slug: page.slug,
305
- title: page.title,
306
- };
307
- })
308
- );
309
-
310
- return {
311
- description: data.config.description,
312
- name: data.config.name,
313
- pages,
314
- };
315
- };
316
-
317
- export const loadTenantUtilityIndex = async (tenant: Tenant) =>
318
- await tenantUtilityIndexCache.getOrCreate(
319
- getTenantStaticCacheKey(tenant),
320
- async () => {
321
- const prebuilt = await loadPrebuiltUtilityIndex(
322
- getTenantContentSource(tenant)
323
- );
324
- if (prebuilt) {
325
- return prebuilt;
326
- }
327
-
328
- return await buildRuntimeUtilityIndex(tenant);
329
- }
330
- );
331
-
332
- const loadTenantUtilityTemplate = async (tenant: Tenant, path: string) => {
333
- const contentSource = getTenantContentSource(tenant);
334
- try {
335
- return await contentSource.readFile(path);
336
- } catch (error) {
337
- if (isMissingContentFileError(error)) {
338
- return null;
339
- }
340
-
341
- throw error;
342
- }
343
- };
344
-
345
- export const clearTenantStaticCaches = () => {
346
- tenantUrlDataCache.clear();
347
- tenantUtilityIndexCache.clear();
348
- };
349
-
350
- export const clearTenantStaticCachesForTenant = (tenantId: string) => {
351
- tenantUrlDataCache.deleteByPrefix(tenantId);
352
- tenantUtilityIndexCache.deleteByPrefix(tenantId);
353
- };
354
-
355
- export const buildTenantSitemapXml = async (
356
- tenant: Tenant,
357
- context: TenantRequestContext = {}
358
- ) => {
359
- const prebuilt = await loadTenantUtilityTemplate(
360
- tenant,
361
- PREBUILT_UTILITY_SITEMAP_PATH
362
- );
363
- if (prebuilt) {
364
- return renderUtilityTemplate(prebuilt, tenant, context);
365
- }
366
-
367
- const { pages } = await loadTenantUtilityIndex(tenant);
368
- const origin = getCanonicalOrigin(tenant, context);
369
- const basePath = getCanonicalDocBasePath(tenant, context);
370
- const urls = pages.map(
371
- (page) => `${origin}${toDocHref(page.slug, basePath)}`
372
- );
373
-
374
- return `<?xml version="1.0" encoding="UTF-8"?>
375
- <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
376
- ${urls.map((url) => ` <url><loc>${url}</loc></url>`).join("\n")}
377
- </urlset>`;
378
- };
379
-
380
- export const buildTenantRobotsTxt = (
381
- tenant: Tenant,
382
- context: TenantRequestContext = {}
383
- ) => {
384
- const origin = getCanonicalOrigin(tenant, context);
385
- const basePath = getCanonicalDocBasePath(tenant, context);
386
- return `User-agent: *
387
- Allow: /
388
- Content-Signal: ai-train=no, search=yes, ai-input=yes
389
-
390
- # LLM-friendly content
391
- # Append .md to any page URL for raw markdown
392
- # ${origin}${toDocHref("llms-full.txt", basePath)} - Full documentation content
393
- # ${origin}${toDocHref("llms.txt", basePath)} - Index of all documentation pages
394
-
395
- Sitemap: ${origin}${toDocHref("sitemap.xml", basePath)}
396
-
397
- # Agent Skills
398
- # ${origin}${toDocHref(".well-known/skills/index.json", basePath)} - Discover installable agent skills`;
399
- };
400
-
401
- const getNavGroupSegments = (
402
- data: Awaited<ReturnType<typeof loadTenantUrlData>>
403
- ): Map<string, Set<string>> => {
404
- const segments = new Map<string, Set<string>>();
405
- for (const entry of data.visibleNav) {
406
- if (entry.type !== "group") {
407
- continue;
408
- }
409
- const group = entry as NavGroup;
410
- const segmentSlug = slugify(group.title);
411
- const pageSlugs = new Set(flattenNav([group]).map((page) => page.path));
412
- if (pageSlugs.size > 0) {
413
- segments.set(segmentSlug, pageSlugs);
414
- }
415
- }
416
- return segments;
417
- };
418
-
419
- export const buildTenantLlmsTxt = async (
420
- tenant: Tenant,
421
- context: TenantRequestContext = {}
422
- ) => {
423
- const prebuilt = await loadTenantUtilityTemplate(
424
- tenant,
425
- PREBUILT_UTILITY_LLMS_PATH
426
- );
427
- if (prebuilt) {
428
- return renderUtilityTemplate(prebuilt, tenant, context);
429
- }
430
-
431
- const urlData = await loadTenantUrlData(tenant);
432
- const data = await loadTenantUtilityIndex(tenant);
433
- const origin = getCanonicalOrigin(tenant, context);
434
- const basePath = getCanonicalDocBasePath(tenant, context);
435
-
436
- const segments = getNavGroupSegments(urlData);
437
- const segmentLines =
438
- segments.size > 0
439
- ? [
440
- "",
441
- "## Segments",
442
- ...[...segments.keys()].map(
443
- (seg) =>
444
- `- [${seg}](${origin}${toDocHref(`llms/${seg}.txt`, basePath)})`
445
- ),
446
- ]
447
- : [];
448
-
449
- const lines = [
450
- `# ${data.name}`,
451
- data.description ? `> ${data.description}` : null,
452
- "",
453
- `Sitemap: ${origin}${toDocHref("sitemap.xml", basePath)}`,
454
- `Full content: ${origin}${toDocHref("llms-full.txt", basePath)}`,
455
- `Skills: ${origin}${toDocHref(".well-known/skills/index.json", basePath)}`,
456
- ...segmentLines,
457
- "",
458
- "## Docs",
459
- ...data.pages.map((page) => {
460
- const url = `${origin}${toMarkdownDocHref(page.slug, basePath)}`;
461
- const desc = page.description ? `: ${page.description}` : "";
462
- return `- [${page.title}](${url})${desc}`;
463
- }),
464
- ];
465
-
466
- return lines.filter((line) => line !== null).join("\n");
467
- };
468
-
469
- export const buildTenantLlmsFullTxt = async (
470
- tenant: Tenant,
471
- context: TenantRequestContext = {}
472
- ) => {
473
- const origin = getCanonicalOrigin(tenant, context);
474
- const basePath = getCanonicalDocBasePath(tenant, context);
475
- const indexUrl = `${origin}${toDocHref("llms.txt", basePath)}`;
476
-
477
- const prebuilt = await loadTenantUtilityTemplate(
478
- tenant,
479
- PREBUILT_UTILITY_LLMS_FULL_PATH
480
- );
481
- if (prebuilt) {
482
- const rendered = renderUtilityTemplate(prebuilt, tenant, context);
483
- return capLlmsFullContent(
484
- prepareLlmsFullContent(rendered, origin, basePath),
485
- indexUrl
486
- );
487
- }
488
-
489
- const data = await loadTenantUtilityIndex(tenant);
490
- const parts = data.pages.map((page) => {
491
- const url = `${origin}${toDocHref(page.slug, basePath)}`;
492
- const content = prepareLlmsFullContent(page.content, origin, basePath);
493
- return formatMarkdownPageSection(
494
- page.title,
495
- url,
496
- content,
497
- page.description
498
- );
499
- });
500
-
501
- return capLlmsFullContent(parts.join("\n\n"), indexUrl);
502
- };
503
-
504
- export const getLlmPageText = async (
505
- tenant: Tenant,
506
- slug: string,
507
- _context: TenantRequestContext = {}
508
- ) => {
509
- const prebuilt = await loadTenantUtilityTemplate(
510
- tenant,
511
- getPrebuiltUtilityLlmPagePath(slug)
512
- );
513
- if (prebuilt) {
514
- return prebuilt;
515
- }
516
-
517
- const data = await loadTenantUtilityIndex(tenant);
518
- const page = data.pages.find(
519
- (item) => item.slug === slug || (slug === "index" && item.slug === "")
520
- );
521
- if (!page) {
522
- return null;
523
- }
524
- return formatMarkdownPage(
525
- page.title,
526
- toAgentMarkdown(page.content),
527
- page.description
528
- );
529
- };
530
-
531
- export const buildTenantSkillsIndex = async (
532
- tenant: Tenant,
533
- _context: TenantRequestContext = {}
534
- ) => {
535
- const data = await loadTenantUrlData(tenant);
536
- const slug = data.config.slug ?? tenant.slug;
537
- const description = data.config.description ?? "";
538
-
539
- const skills = [
540
- {
541
- description: `${data.config.name} documentation. ${description}`.trim(),
542
- files: ["SKILL.md"],
543
- name: slug,
544
- },
545
- ];
546
-
547
- return JSON.stringify({ skills }, null, 2);
548
- };
549
-
550
- export const buildTenantSkillMd = async (
551
- tenant: Tenant,
552
- skillName: string,
553
- context: TenantRequestContext = {}
554
- ) => {
555
- const data = await loadTenantUrlData(tenant);
556
- const slug = data.config.slug ?? tenant.slug;
557
-
558
- if (skillName !== slug) {
559
- return null;
560
- }
561
-
562
- const origin = getCanonicalOrigin(tenant, context);
563
- const basePath = getCanonicalDocBasePath(tenant, context);
564
- const description = data.config.description ?? "";
565
-
566
- const lines = [
567
- "---",
568
- `name: ${slug}`,
569
- `description: ${data.config.name} documentation. ${description} Use when working with ${data.config.name}, answering questions about its features, or helping users follow its guides.`.trim(),
570
- "---",
571
- "",
572
- `# ${data.config.name}`,
573
- "",
574
- description ? `${description}\n` : "",
575
- "## Documentation",
576
- "",
577
- `- Full docs index: ${origin}${toDocHref("llms.txt", basePath)}`,
578
- `- Complete docs content: ${origin}${toDocHref("llms-full.txt", basePath)}`,
579
- `- Append \`.md\` to any page URL for raw markdown`,
580
- "",
581
- "## Key Pages",
582
- "",
583
- ...resolveLlmPages(data)
584
- .slice(0, 20)
585
- .map((page) => {
586
- const url = `${origin}${toMarkdownDocHref(page.slug, basePath)}`;
587
- const desc = page.description ? ` - ${page.description}` : "";
588
- return `- [${page.title}](${url})${desc}`;
589
- }),
590
- ];
591
-
592
- return lines.filter((line) => line !== null).join("\n");
593
- };
594
-
595
- export const buildTenantLlmsSegment = async (
596
- tenant: Tenant,
597
- segmentName: string,
598
- context: TenantRequestContext = {}
599
- ): Promise<string | null> => {
600
- const prebuilt = await loadTenantUtilityTemplate(
601
- tenant,
602
- `${PREBUILT_UTILITY_LLMS_SEGMENT_PREFIX}${segmentName}.txt`
603
- );
604
- if (prebuilt) {
605
- return renderUtilityTemplate(prebuilt, tenant, context);
606
- }
607
-
608
- const data = await loadTenantUrlData(tenant);
609
- const segments = getNavGroupSegments(data);
610
- const segmentSlugs = segments.get(segmentName);
611
- if (!segmentSlugs) {
612
- return null;
613
- }
614
-
615
- const origin = getCanonicalOrigin(tenant, context);
616
- const basePath = getCanonicalDocBasePath(tenant, context);
617
- const utilityIndex = await loadTenantUtilityIndex(tenant);
618
-
619
- const segmentPages = utilityIndex.pages.filter((page) =>
620
- segmentSlugs.has(page.slug)
621
- );
622
-
623
- if (segmentPages.length === 0) {
624
- return null;
625
- }
626
-
627
- const groupTitle =
628
- [...data.visibleNav].find(
629
- (entry) => entry.type === "group" && slugify(entry.title) === segmentName
630
- )?.title ?? segmentName;
631
-
632
- const parts = segmentPages.map((page) => {
633
- const url = `${origin}${toDocHref(page.slug, basePath)}`;
634
- const content = prepareLlmsFullContent(page.content, origin, basePath);
635
- return formatMarkdownPageSection(
636
- page.title,
637
- url,
638
- content,
639
- page.description
640
- );
641
- });
642
-
643
- return [
644
- `# ${data.config.name} - ${groupTitle}`,
645
- `> Segment of ${origin}${toDocHref("llms-full.txt", basePath)}`,
646
- "",
647
- ...parts,
648
- ].join("\n\n");
649
- };
650
-
651
- export const listTenantLlmsSegments = async (
652
- tenant: Tenant
653
- ): Promise<string[]> => {
654
- const data = await loadTenantUrlData(tenant);
655
- return [...getNavGroupSegments(data).keys()];
656
- };
657
-
658
- export const getPageJson = async (
659
- tenant: Tenant,
660
- slug: string,
661
- context: TenantRequestContext = {}
662
- ): Promise<Record<string, unknown> | null> => {
663
- const data = await loadTenantUrlData(tenant);
664
- const contentEntry = data.contentIndex.bySlug.get(slug);
665
- if (!contentEntry || contentEntry.kind !== "entry") {
666
- return null;
667
- }
668
-
669
- const origin = getCanonicalOrigin(tenant, context);
670
- const basePath = getCanonicalDocBasePath(tenant, context);
671
- const url = `${origin}${toDocHref(slug, basePath)}`;
672
- const markdownUrl = `${origin}${toMarkdownDocHref(slug, basePath)}`;
673
-
674
- const result: Record<string, unknown> = {
675
- "@context": "https://schema.org",
676
- "@type": "TechArticle",
677
- description: contentEntry.description,
678
- name: contentEntry.title,
679
- url,
680
- };
681
-
682
- if (contentEntry.frontmatter) {
683
- const fm = contentEntry.frontmatter as Record<string, unknown>;
684
- if (fm.price !== undefined && fm.currency !== undefined) {
685
- result["@type"] = "Product";
686
- result.offers = {
687
- "@type": "Offer",
688
- availability: "https://schema.org/InStock",
689
- price: fm.price,
690
- priceCurrency: fm.currency,
691
- };
692
- if (fm.sku) {
693
- result.sku = fm.sku;
694
- }
695
- }
696
- }
697
-
698
- result.encoding = {
699
- "@type": "MediaObject",
700
- contentUrl: markdownUrl,
701
- encodingFormat: "text/markdown",
702
- };
703
-
704
- return result;
705
- };