boltdocs 1.10.2 → 2.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 (250) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +21 -0
  3. package/dist/cache-7G6D532T.mjs +1 -0
  4. package/dist/chunk-A4HQPEPU.mjs +1 -0
  5. package/dist/chunk-BA5NH5HU.mjs +1 -0
  6. package/dist/chunk-BQCD3DWG.mjs +1 -0
  7. package/dist/chunk-H63UMKYF.mjs +1 -0
  8. package/dist/chunk-IWHRQHS7.mjs +1 -0
  9. package/dist/chunk-JZXLCA2E.mjs +1 -0
  10. package/dist/chunk-MFU7Q6WF.mjs +1 -0
  11. package/dist/chunk-QYPNX5UN.mjs +1 -0
  12. package/dist/chunk-XEAPSFMB.mjs +1 -0
  13. package/dist/client/components/mdx/index.d.mts +209 -0
  14. package/dist/client/components/mdx/index.d.ts +209 -0
  15. package/dist/client/components/mdx/index.js +1 -0
  16. package/dist/client/components/mdx/index.mjs +1 -0
  17. package/dist/client/hooks/index.d.mts +133 -0
  18. package/dist/client/hooks/index.d.ts +133 -0
  19. package/dist/client/hooks/index.js +1 -0
  20. package/dist/client/hooks/index.mjs +1 -0
  21. package/dist/client/index.d.mts +138 -298
  22. package/dist/client/index.d.ts +138 -298
  23. package/dist/client/index.js +1 -3630
  24. package/dist/client/index.mjs +1 -697
  25. package/dist/client/ssr.d.mts +7 -3
  26. package/dist/client/ssr.d.ts +7 -3
  27. package/dist/client/ssr.js +1 -2928
  28. package/dist/client/ssr.mjs +1 -33
  29. package/dist/{config-BsFQ-ErD.d.ts → config-CX4l-ZNp.d.mts} +42 -35
  30. package/dist/{config-BsFQ-ErD.d.mts → config-CX4l-ZNp.d.ts} +42 -35
  31. package/dist/node/index.d.mts +2 -4
  32. package/dist/node/index.d.ts +2 -4
  33. package/dist/node/index.js +31 -1161
  34. package/dist/node/index.mjs +31 -736
  35. package/dist/search-dialog-EB3N4TYM.mjs +1 -0
  36. package/dist/types-BuZWFT7r.d.ts +159 -0
  37. package/dist/types-CvT-SGbK.d.mts +159 -0
  38. package/dist/use-routes-5bAtAAYX.d.mts +30 -0
  39. package/dist/use-routes-BefRXY3v.d.ts +30 -0
  40. package/package.json +34 -12
  41. package/src/client/app/config-context.tsx +18 -0
  42. package/src/client/app/docs-layout.tsx +14 -0
  43. package/src/client/app/index.tsx +137 -262
  44. package/src/client/app/mdx-component.tsx +52 -0
  45. package/src/client/app/mdx-components-context.tsx +23 -0
  46. package/src/client/app/mdx-page.tsx +20 -0
  47. package/src/client/app/preload.tsx +38 -30
  48. package/src/client/app/router.tsx +30 -0
  49. package/src/client/app/scroll-handler.tsx +40 -0
  50. package/src/client/app/theme-context.tsx +75 -0
  51. package/src/client/components/default-layout.tsx +80 -0
  52. package/src/client/components/docs-layout.tsx +105 -0
  53. package/src/client/components/icons-dev.tsx +74 -0
  54. package/src/client/components/mdx/admonition.tsx +107 -0
  55. package/src/client/components/mdx/badge.tsx +41 -0
  56. package/src/client/components/mdx/button.tsx +35 -0
  57. package/src/client/components/mdx/card.tsx +124 -0
  58. package/src/client/components/mdx/code-block.tsx +119 -0
  59. package/src/client/components/mdx/component-preview.tsx +47 -0
  60. package/src/client/components/mdx/component-props.tsx +83 -0
  61. package/src/client/components/mdx/field.tsx +66 -0
  62. package/src/client/components/mdx/file-tree.tsx +287 -0
  63. package/src/client/components/mdx/hooks/use-code-block.ts +56 -0
  64. package/src/client/components/mdx/hooks/use-component-preview.ts +16 -0
  65. package/src/client/components/mdx/hooks/useTable.ts +74 -0
  66. package/src/client/components/mdx/hooks/useTabs.ts +68 -0
  67. package/src/client/components/mdx/image.tsx +23 -0
  68. package/src/client/components/mdx/index.ts +53 -0
  69. package/src/client/components/mdx/link.tsx +38 -0
  70. package/src/client/components/mdx/list.tsx +192 -0
  71. package/src/client/components/mdx/table.tsx +156 -0
  72. package/src/client/components/mdx/tabs.tsx +135 -0
  73. package/src/client/components/mdx/video.tsx +68 -0
  74. package/src/client/components/primitives/breadcrumbs.tsx +79 -0
  75. package/src/client/components/primitives/button-group.tsx +54 -0
  76. package/src/client/components/primitives/button.tsx +145 -0
  77. package/src/client/components/primitives/helpers/observer.ts +120 -0
  78. package/src/client/components/primitives/index.ts +17 -0
  79. package/src/client/components/primitives/link.tsx +122 -0
  80. package/src/client/components/primitives/menu.tsx +159 -0
  81. package/src/client/components/primitives/navbar.tsx +359 -0
  82. package/src/client/components/primitives/navigation-menu.tsx +116 -0
  83. package/src/client/components/primitives/on-this-page.tsx +461 -0
  84. package/src/client/components/primitives/page-nav.tsx +87 -0
  85. package/src/client/components/primitives/popover.tsx +47 -0
  86. package/src/client/components/primitives/search-dialog.tsx +183 -0
  87. package/src/client/components/primitives/sidebar.tsx +154 -0
  88. package/src/client/components/primitives/tabs.tsx +90 -0
  89. package/src/client/components/primitives/tooltip.tsx +83 -0
  90. package/src/client/components/primitives/types.ts +11 -0
  91. package/src/client/components/ui-base/breadcrumbs.tsx +42 -0
  92. package/src/client/components/ui-base/copy-markdown.tsx +112 -0
  93. package/src/client/components/ui-base/error-boundary.tsx +52 -0
  94. package/src/client/components/ui-base/github-stars.tsx +27 -0
  95. package/src/client/components/ui-base/head.tsx +69 -0
  96. package/src/client/components/ui-base/loading.tsx +87 -0
  97. package/src/client/components/ui-base/navbar.tsx +138 -0
  98. package/src/client/components/ui-base/not-found.tsx +24 -0
  99. package/src/client/components/ui-base/on-this-page.tsx +152 -0
  100. package/src/client/components/ui-base/page-nav.tsx +39 -0
  101. package/src/client/components/ui-base/powered-by.tsx +19 -0
  102. package/src/client/components/ui-base/progress-bar.tsx +67 -0
  103. package/src/client/components/ui-base/search-dialog.tsx +82 -0
  104. package/src/client/components/ui-base/sidebar.tsx +104 -0
  105. package/src/client/components/ui-base/tabs.tsx +65 -0
  106. package/src/client/components/ui-base/theme-toggle.tsx +32 -0
  107. package/src/client/hooks/index.ts +12 -0
  108. package/src/client/hooks/use-breadcrumbs.ts +22 -0
  109. package/src/client/hooks/use-i18n.ts +84 -0
  110. package/src/client/hooks/use-localized-to.ts +95 -0
  111. package/src/client/hooks/use-location.ts +5 -0
  112. package/src/client/hooks/use-navbar.ts +60 -0
  113. package/src/client/hooks/use-onthispage.ts +23 -0
  114. package/src/client/hooks/use-page-nav.ts +22 -0
  115. package/src/client/hooks/use-routes.ts +72 -0
  116. package/src/client/hooks/use-search.ts +71 -0
  117. package/src/client/hooks/use-sidebar.ts +49 -0
  118. package/src/client/hooks/use-tabs.ts +43 -0
  119. package/src/client/hooks/use-version.ts +78 -0
  120. package/src/client/index.ts +55 -17
  121. package/src/client/integrations/codesandbox.ts +179 -0
  122. package/src/client/ssr.tsx +27 -16
  123. package/src/client/theme/neutral.css +360 -0
  124. package/src/client/types.ts +131 -27
  125. package/src/client/utils/cn.ts +6 -0
  126. package/src/client/utils/copy-clipboard.ts +22 -0
  127. package/src/client/utils/get-base-file-path.ts +21 -0
  128. package/src/client/utils/github.ts +121 -0
  129. package/src/client/utils/use-on-change.ts +15 -0
  130. package/src/client/virtual.d.ts +24 -0
  131. package/src/node/cache.ts +156 -156
  132. package/src/node/config.ts +159 -103
  133. package/src/node/index.ts +13 -13
  134. package/src/node/mdx.ts +213 -61
  135. package/src/node/plugin/entry.ts +29 -18
  136. package/src/node/plugin/html.ts +11 -11
  137. package/src/node/plugin/index.ts +161 -84
  138. package/src/node/plugin/types.ts +2 -4
  139. package/src/node/routes/cache.ts +6 -6
  140. package/src/node/routes/index.ts +206 -113
  141. package/src/node/routes/parser.ts +102 -82
  142. package/src/node/routes/sorter.ts +15 -15
  143. package/src/node/routes/types.ts +24 -24
  144. package/src/node/ssg/index.ts +73 -47
  145. package/src/node/ssg/meta.ts +4 -4
  146. package/src/node/ssg/options.ts +5 -5
  147. package/src/node/ssg/sitemap.ts +14 -14
  148. package/src/node/utils.ts +54 -31
  149. package/tsconfig.json +25 -20
  150. package/tsup.config.ts +23 -14
  151. package/dist/PackageManagerTabs-NVT7G625.mjs +0 -99
  152. package/dist/SearchDialog-AGVF6JBO.mjs +0 -194
  153. package/dist/SearchDialog-YPDOM7Q6.css +0 -2847
  154. package/dist/Video-KNTY5BNO.mjs +0 -6
  155. package/dist/cache-KNL5B4EE.mjs +0 -12
  156. package/dist/chunk-7SFUJWTB.mjs +0 -211
  157. package/dist/chunk-FFBNU6IJ.mjs +0 -386
  158. package/dist/chunk-FMTOYQLO.mjs +0 -37
  159. package/dist/chunk-TKLQWU7H.mjs +0 -1920
  160. package/dist/chunk-Z7JHYNAS.mjs +0 -57
  161. package/dist/client/index.css +0 -2847
  162. package/dist/client/ssr.css +0 -2847
  163. package/dist/types-Dj-bfnC3.d.mts +0 -74
  164. package/dist/types-Dj-bfnC3.d.ts +0 -74
  165. package/src/client/theme/components/CodeBlock/CodeBlock.tsx +0 -61
  166. package/src/client/theme/components/CodeBlock/index.ts +0 -1
  167. package/src/client/theme/components/PackageManagerTabs/PackageManagerTabs.tsx +0 -131
  168. package/src/client/theme/components/PackageManagerTabs/index.ts +0 -1
  169. package/src/client/theme/components/PackageManagerTabs/pkg-tabs.css +0 -64
  170. package/src/client/theme/components/Playground/Playground.tsx +0 -180
  171. package/src/client/theme/components/Playground/index.ts +0 -1
  172. package/src/client/theme/components/Playground/playground.css +0 -238
  173. package/src/client/theme/components/Video/Video.tsx +0 -84
  174. package/src/client/theme/components/Video/index.ts +0 -1
  175. package/src/client/theme/components/Video/video.css +0 -41
  176. package/src/client/theme/components/mdx/Admonition.tsx +0 -80
  177. package/src/client/theme/components/mdx/Badge.tsx +0 -31
  178. package/src/client/theme/components/mdx/Button.tsx +0 -50
  179. package/src/client/theme/components/mdx/Card.tsx +0 -80
  180. package/src/client/theme/components/mdx/Field.tsx +0 -60
  181. package/src/client/theme/components/mdx/FileTree.tsx +0 -229
  182. package/src/client/theme/components/mdx/List.tsx +0 -57
  183. package/src/client/theme/components/mdx/Table.tsx +0 -151
  184. package/src/client/theme/components/mdx/Tabs.tsx +0 -123
  185. package/src/client/theme/components/mdx/index.ts +0 -27
  186. package/src/client/theme/components/mdx/mdx-components.css +0 -764
  187. package/src/client/theme/icons/bun.tsx +0 -62
  188. package/src/client/theme/icons/deno.tsx +0 -20
  189. package/src/client/theme/icons/discord.tsx +0 -12
  190. package/src/client/theme/icons/github.tsx +0 -15
  191. package/src/client/theme/icons/npm.tsx +0 -13
  192. package/src/client/theme/icons/pnpm.tsx +0 -72
  193. package/src/client/theme/icons/twitter.tsx +0 -12
  194. package/src/client/theme/styles/markdown.css +0 -394
  195. package/src/client/theme/styles/variables.css +0 -175
  196. package/src/client/theme/styles.css +0 -39
  197. package/src/client/theme/ui/Breadcrumbs/Breadcrumbs.tsx +0 -68
  198. package/src/client/theme/ui/Breadcrumbs/index.ts +0 -1
  199. package/src/client/theme/ui/CopyMarkdown/CopyMarkdown.tsx +0 -82
  200. package/src/client/theme/ui/CopyMarkdown/copy-markdown.css +0 -112
  201. package/src/client/theme/ui/CopyMarkdown/index.ts +0 -1
  202. package/src/client/theme/ui/ErrorBoundary/ErrorBoundary.tsx +0 -50
  203. package/src/client/theme/ui/ErrorBoundary/error-boundary.css +0 -55
  204. package/src/client/theme/ui/ErrorBoundary/index.ts +0 -1
  205. package/src/client/theme/ui/Footer/footer.css +0 -32
  206. package/src/client/theme/ui/Head/Head.tsx +0 -69
  207. package/src/client/theme/ui/Head/index.ts +0 -1
  208. package/src/client/theme/ui/LanguageSwitcher/LanguageSwitcher.tsx +0 -125
  209. package/src/client/theme/ui/LanguageSwitcher/index.ts +0 -1
  210. package/src/client/theme/ui/LanguageSwitcher/language-switcher.css +0 -98
  211. package/src/client/theme/ui/Layout/Layout.tsx +0 -203
  212. package/src/client/theme/ui/Layout/base.css +0 -106
  213. package/src/client/theme/ui/Layout/index.ts +0 -2
  214. package/src/client/theme/ui/Layout/pagination.css +0 -72
  215. package/src/client/theme/ui/Layout/responsive.css +0 -47
  216. package/src/client/theme/ui/Link/Link.tsx +0 -392
  217. package/src/client/theme/ui/Link/LinkPreview.tsx +0 -59
  218. package/src/client/theme/ui/Link/index.ts +0 -2
  219. package/src/client/theme/ui/Link/link-preview.css +0 -48
  220. package/src/client/theme/ui/Loading/Loading.tsx +0 -10
  221. package/src/client/theme/ui/Loading/index.ts +0 -1
  222. package/src/client/theme/ui/Loading/loading.css +0 -30
  223. package/src/client/theme/ui/Navbar/GithubStars.tsx +0 -27
  224. package/src/client/theme/ui/Navbar/Navbar.tsx +0 -193
  225. package/src/client/theme/ui/Navbar/Tabs.tsx +0 -99
  226. package/src/client/theme/ui/Navbar/index.ts +0 -2
  227. package/src/client/theme/ui/Navbar/navbar.css +0 -347
  228. package/src/client/theme/ui/NotFound/NotFound.tsx +0 -19
  229. package/src/client/theme/ui/NotFound/index.ts +0 -1
  230. package/src/client/theme/ui/NotFound/not-found.css +0 -64
  231. package/src/client/theme/ui/OnThisPage/OnThisPage.tsx +0 -244
  232. package/src/client/theme/ui/OnThisPage/index.ts +0 -1
  233. package/src/client/theme/ui/OnThisPage/toc.css +0 -152
  234. package/src/client/theme/ui/PoweredBy/PoweredBy.tsx +0 -18
  235. package/src/client/theme/ui/PoweredBy/index.ts +0 -1
  236. package/src/client/theme/ui/PoweredBy/powered-by.css +0 -76
  237. package/src/client/theme/ui/ProgressBar/ProgressBar.css +0 -17
  238. package/src/client/theme/ui/ProgressBar/ProgressBar.tsx +0 -51
  239. package/src/client/theme/ui/ProgressBar/index.ts +0 -1
  240. package/src/client/theme/ui/SearchDialog/SearchDialog.tsx +0 -209
  241. package/src/client/theme/ui/SearchDialog/index.ts +0 -1
  242. package/src/client/theme/ui/SearchDialog/search.css +0 -152
  243. package/src/client/theme/ui/Sidebar/Sidebar.tsx +0 -244
  244. package/src/client/theme/ui/Sidebar/index.ts +0 -1
  245. package/src/client/theme/ui/Sidebar/sidebar.css +0 -230
  246. package/src/client/theme/ui/ThemeToggle/ThemeToggle.tsx +0 -69
  247. package/src/client/theme/ui/ThemeToggle/index.ts +0 -1
  248. package/src/client/theme/ui/VersionSwitcher/VersionSwitcher.tsx +0 -136
  249. package/src/client/theme/ui/VersionSwitcher/index.ts +0 -1
  250. package/src/client/utils.ts +0 -49
package/src/node/cache.ts CHANGED
@@ -1,65 +1,65 @@
1
- import fs from "fs";
2
- import path from "path";
3
- import crypto from "crypto";
4
- import zlib from "zlib";
5
- import { promisify } from "util";
6
- import { getFileMtime } from "./utils";
7
-
8
- const writeFile = promisify(fs.writeFile);
9
- const readFile = promisify(fs.readFile);
10
- const mkdir = promisify(fs.mkdir);
11
- const rename = promisify(fs.rename);
12
- const unlink = promisify(fs.unlink);
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+ import crypto from 'crypto'
4
+ import zlib from 'zlib'
5
+ import { promisify } from 'util'
6
+ import { getFileMtime } from './utils'
7
+
8
+ const writeFile = promisify(fs.writeFile)
9
+ const readFile = promisify(fs.readFile)
10
+ const mkdir = promisify(fs.mkdir)
11
+ const rename = promisify(fs.rename)
12
+ const unlink = promisify(fs.unlink)
13
13
 
14
14
  /**
15
15
  * Configuration constants for the caching system.
16
16
  */
17
- const CACHE_DIR = process.env.BOLTDOCS_CACHE_DIR || ".boltdocs";
18
- const ASSETS_DIR = "assets";
19
- const SHARDS_DIR = "shards";
17
+ const CACHE_DIR = process.env.BOLTDOCS_CACHE_DIR || '.boltdocs'
18
+ const ASSETS_DIR = 'assets'
19
+ const SHARDS_DIR = 'shards'
20
20
 
21
21
  /**
22
22
  * Default limits for the caching system.
23
23
  */
24
24
  const DEFAULT_LRU_LIMIT = parseInt(
25
- process.env.BOLTDOCS_CACHE_LRU_LIMIT || "2000",
25
+ process.env.BOLTDOCS_CACHE_LRU_LIMIT || '2000',
26
26
  10,
27
- );
28
- const DEFAULT_COMPRESS = process.env.BOLTDOCS_CACHE_COMPRESS !== "0";
27
+ )
28
+ const DEFAULT_COMPRESS = process.env.BOLTDOCS_CACHE_COMPRESS !== '0'
29
29
 
30
30
  /**
31
31
  * Simple LRU cache implementation to prevent memory leaks.
32
32
  */
33
33
  class LRUCache<K, V> {
34
- private cache = new Map<K, V>();
34
+ private cache = new Map<K, V>()
35
35
  constructor(private limit: number) {}
36
36
 
37
37
  get(key: K): V | undefined {
38
- const val = this.cache.get(key);
38
+ const val = this.cache.get(key)
39
39
  if (val !== undefined) {
40
- this.cache.delete(key);
41
- this.cache.set(key, val);
40
+ this.cache.delete(key)
41
+ this.cache.set(key, val)
42
42
  }
43
- return val;
43
+ return val
44
44
  }
45
45
 
46
46
  set(key: K, value: V): void {
47
47
  if (this.cache.has(key)) {
48
- this.cache.delete(key);
48
+ this.cache.delete(key)
49
49
  } else if (this.cache.size >= this.limit) {
50
- const firstKey = this.cache.keys().next().value;
50
+ const firstKey = this.cache.keys().next().value
51
51
  if (firstKey !== undefined) {
52
- this.cache.delete(firstKey);
52
+ this.cache.delete(firstKey)
53
53
  }
54
54
  }
55
- this.cache.set(key, value);
55
+ this.cache.set(key, value)
56
56
  }
57
57
 
58
58
  get size() {
59
- return this.cache.size;
59
+ return this.cache.size
60
60
  }
61
61
  clear() {
62
- this.cache.clear();
62
+ this.cache.clear()
63
63
  }
64
64
  }
65
65
 
@@ -67,44 +67,44 @@ class LRUCache<K, V> {
67
67
  * Simple background task queue to prevent blocking the main thread during IO.
68
68
  */
69
69
  class BackgroundQueue {
70
- private queue: Promise<any> = Promise.resolve();
71
- private pendingCount = 0;
70
+ private queue: Promise<any> = Promise.resolve()
71
+ private pendingCount = 0
72
72
 
73
73
  add(task: () => Promise<any>) {
74
- this.pendingCount++;
74
+ this.pendingCount++
75
75
  this.queue = this.queue.then(task).finally(() => {
76
- this.pendingCount--;
77
- });
76
+ this.pendingCount--
77
+ })
78
78
  }
79
79
 
80
80
  async flush() {
81
- await this.queue;
81
+ await this.queue
82
82
  }
83
83
 
84
84
  get pending() {
85
- return this.pendingCount;
85
+ return this.pendingCount
86
86
  }
87
87
  }
88
88
 
89
- const backgroundQueue = new BackgroundQueue();
89
+ const backgroundQueue = new BackgroundQueue()
90
90
 
91
91
  /**
92
92
  * Generic file-based cache with per-file granularity and asynchronous persistence.
93
93
  */
94
94
  export class FileCache<T> {
95
- private entries = new Map<string, { data: T; mtime: number }>();
96
- private readonly cachePath: string | null = null;
97
- private readonly compress: boolean;
95
+ private entries = new Map<string, { data: T; mtime: number }>()
96
+ private readonly cachePath: string | null = null
97
+ private readonly compress: boolean
98
98
 
99
99
  constructor(
100
100
  options: { name?: string; root?: string; compress?: boolean } = {},
101
101
  ) {
102
102
  this.compress =
103
- options.compress !== undefined ? options.compress : DEFAULT_COMPRESS;
103
+ options.compress !== undefined ? options.compress : DEFAULT_COMPRESS
104
104
  if (options.name) {
105
- const root = options.root || process.cwd();
106
- const ext = this.compress ? "json.gz" : "json";
107
- this.cachePath = path.resolve(root, CACHE_DIR, `${options.name}.${ext}`);
105
+ const root = options.root || process.cwd()
106
+ const ext = this.compress ? 'json.gz' : 'json'
107
+ this.cachePath = path.resolve(root, CACHE_DIR, `${options.name}.${ext}`)
108
108
  }
109
109
  }
110
110
 
@@ -112,16 +112,16 @@ export class FileCache<T> {
112
112
  * Loads the cache. Synchronous for startup simplicity but uses fast I/O.
113
113
  */
114
114
  load(): void {
115
- if (process.env.BOLTDOCS_NO_CACHE === "1") return;
116
- if (!this.cachePath || !fs.existsSync(this.cachePath)) return;
115
+ if (process.env.BOLTDOCS_NO_CACHE === '1') return
116
+ if (!this.cachePath || !fs.existsSync(this.cachePath)) return
117
117
 
118
118
  try {
119
- let raw = fs.readFileSync(this.cachePath);
120
- if (this.cachePath.endsWith(".gz")) {
121
- raw = zlib.gunzipSync(raw);
119
+ let raw = fs.readFileSync(this.cachePath)
120
+ if (this.cachePath.endsWith('.gz')) {
121
+ raw = zlib.gunzipSync(raw)
122
122
  }
123
- const data = JSON.parse(raw.toString("utf-8"));
124
- this.entries = new Map(Object.entries(data));
123
+ const data = JSON.parse(raw.toString('utf-8'))
124
+ this.entries = new Map(Object.entries(data))
125
125
  } catch (e) {
126
126
  // Fallback: ignore cache errors
127
127
  }
@@ -131,72 +131,72 @@ export class FileCache<T> {
131
131
  * Saves the cache in the background.
132
132
  */
133
133
  save(): void {
134
- if (process.env.BOLTDOCS_NO_CACHE === "1") return;
135
- if (!this.cachePath) return;
134
+ if (process.env.BOLTDOCS_NO_CACHE === '1') return
135
+ if (!this.cachePath) return
136
136
 
137
- const data = Object.fromEntries(this.entries);
138
- const content = JSON.stringify(data);
139
- const target = this.cachePath;
140
- const useCompress = this.compress;
137
+ const data = Object.fromEntries(this.entries)
138
+ const content = JSON.stringify(data)
139
+ const target = this.cachePath
140
+ const useCompress = this.compress
141
141
 
142
142
  backgroundQueue.add(async () => {
143
143
  try {
144
- await mkdir(path.dirname(target), { recursive: true });
145
- let buffer = Buffer.from(content);
144
+ await mkdir(path.dirname(target), { recursive: true })
145
+ let buffer = Buffer.from(content)
146
146
  if (useCompress) {
147
- buffer = zlib.gzipSync(buffer);
147
+ buffer = zlib.gzipSync(buffer)
148
148
  }
149
- const tempPath = `${target}.${crypto.randomBytes(4).toString("hex")}.tmp`;
150
- await writeFile(tempPath, buffer);
151
- await rename(tempPath, target);
149
+ const tempPath = `${target}.${crypto.randomBytes(4).toString('hex')}.tmp`
150
+ await writeFile(tempPath, buffer)
151
+ await rename(tempPath, target)
152
152
  } catch (e) {
153
153
  // Fallback: critical error logging skipped for performance
154
154
  }
155
- });
155
+ })
156
156
  }
157
157
 
158
158
  get(filePath: string): T | null {
159
- const entry = this.entries.get(filePath);
160
- if (!entry) return null;
161
- if (getFileMtime(filePath) !== entry.mtime) return null;
162
- return entry.data;
159
+ const entry = this.entries.get(filePath)
160
+ if (!entry) return null
161
+ if (getFileMtime(filePath) !== entry.mtime) return null
162
+ return entry.data
163
163
  }
164
164
 
165
165
  set(filePath: string, data: T): void {
166
166
  this.entries.set(filePath, {
167
167
  data,
168
168
  mtime: getFileMtime(filePath),
169
- });
169
+ })
170
170
  }
171
171
 
172
172
  isValid(filePath: string): boolean {
173
- const entry = this.entries.get(filePath);
174
- if (!entry) return false;
175
- return getFileMtime(filePath) === entry.mtime;
173
+ const entry = this.entries.get(filePath)
174
+ if (!entry) return false
175
+ return getFileMtime(filePath) === entry.mtime
176
176
  }
177
177
 
178
178
  invalidate(filePath: string): void {
179
- this.entries.delete(filePath);
179
+ this.entries.delete(filePath)
180
180
  }
181
181
 
182
182
  invalidateAll(): void {
183
- this.entries.clear();
183
+ this.entries.clear()
184
184
  }
185
185
 
186
186
  pruneStale(currentFiles: Set<string>): void {
187
187
  for (const key of this.entries.keys()) {
188
188
  if (!currentFiles.has(key)) {
189
- this.entries.delete(key);
189
+ this.entries.delete(key)
190
190
  }
191
191
  }
192
192
  }
193
193
 
194
194
  get size(): number {
195
- return this.entries.size;
195
+ return this.entries.size
196
196
  }
197
197
 
198
198
  async flush() {
199
- await backgroundQueue.flush();
199
+ await backgroundQueue.flush()
200
200
  }
201
201
  }
202
202
 
@@ -205,28 +205,28 @@ export class FileCache<T> {
205
205
  * Uses a memory index and individual files for each entry to avoid massive JSON parsing.
206
206
  */
207
207
  export class TransformCache {
208
- private index = new Map<string, string>(); // key -> hash
209
- private memoryCache = new LRUCache<string, string>(DEFAULT_LRU_LIMIT);
210
- private readonly baseDir: string;
211
- private readonly shardsDir: string;
212
- private readonly indexPath: string;
208
+ private index = new Map<string, string>() // key -> hash
209
+ private memoryCache = new LRUCache<string, string>(DEFAULT_LRU_LIMIT)
210
+ private readonly baseDir: string
211
+ private readonly shardsDir: string
212
+ private readonly indexPath: string
213
213
 
214
214
  constructor(name: string, root: string = process.cwd()) {
215
- this.baseDir = path.resolve(root, CACHE_DIR, `transform-${name}`);
216
- this.shardsDir = path.resolve(this.baseDir, SHARDS_DIR);
217
- this.indexPath = path.resolve(this.baseDir, "index.json");
215
+ this.baseDir = path.resolve(root, CACHE_DIR, `transform-${name}`)
216
+ this.shardsDir = path.resolve(this.baseDir, SHARDS_DIR)
217
+ this.indexPath = path.resolve(this.baseDir, 'index.json')
218
218
  }
219
219
 
220
220
  /**
221
221
  * Loads the index into memory.
222
222
  */
223
223
  load(): void {
224
- if (process.env.BOLTDOCS_NO_CACHE === "1") return;
225
- if (!fs.existsSync(this.indexPath)) return;
224
+ if (process.env.BOLTDOCS_NO_CACHE === '1') return
225
+ if (!fs.existsSync(this.indexPath)) return
226
226
 
227
227
  try {
228
- const data = fs.readFileSync(this.indexPath, "utf-8");
229
- this.index = new Map(Object.entries(JSON.parse(data)));
228
+ const data = fs.readFileSync(this.indexPath, 'utf-8')
229
+ this.index = new Map(Object.entries(JSON.parse(data)))
230
230
  } catch (e) {
231
231
  // Index might be corrupt, ignore
232
232
  }
@@ -236,51 +236,51 @@ export class TransformCache {
236
236
  * Persists the index in background.
237
237
  */
238
238
  save(): void {
239
- if (process.env.BOLTDOCS_NO_CACHE === "1") return;
240
- const data = JSON.stringify(Object.fromEntries(this.index));
241
- const target = this.indexPath;
239
+ if (process.env.BOLTDOCS_NO_CACHE === '1') return
240
+ const data = JSON.stringify(Object.fromEntries(this.index))
241
+ const target = this.indexPath
242
242
 
243
243
  backgroundQueue.add(async () => {
244
- await mkdir(path.dirname(target), { recursive: true });
245
- await writeFile(target, data);
246
- });
244
+ await mkdir(path.dirname(target), { recursive: true })
245
+ await writeFile(target, data)
246
+ })
247
247
  }
248
248
 
249
249
  /**
250
250
  * Batch Read: Retrieves multiple transformation results concurrently.
251
251
  */
252
252
  async getMany(keys: string[]): Promise<Map<string, string>> {
253
- const results = new Map<string, string>();
254
- const toLoad: string[] = [];
253
+ const results = new Map<string, string>()
254
+ const toLoad: string[] = []
255
255
 
256
256
  for (const key of keys) {
257
- const mem = this.memoryCache.get(key);
258
- if (mem) results.set(key, mem);
259
- else if (this.index.has(key)) toLoad.push(key);
257
+ const mem = this.memoryCache.get(key)
258
+ if (mem) results.set(key, mem)
259
+ else if (this.index.has(key)) toLoad.push(key)
260
260
  }
261
261
 
262
262
  if (toLoad.length > 0) {
263
263
  const shards = await Promise.all(
264
264
  toLoad.map(async (key) => {
265
- const hash = this.index.get(key)!;
266
- const shardPath = path.resolve(this.shardsDir, `${hash}.gz`);
265
+ const hash = this.index.get(key)!
266
+ const shardPath = path.resolve(this.shardsDir, `${hash}.gz`)
267
267
  try {
268
- const compressed = await readFile(shardPath);
269
- const decompressed = zlib.gunzipSync(compressed).toString("utf-8");
270
- this.memoryCache.set(key, decompressed);
271
- return { key, val: decompressed };
268
+ const compressed = await readFile(shardPath)
269
+ const decompressed = zlib.gunzipSync(compressed).toString('utf-8')
270
+ this.memoryCache.set(key, decompressed)
271
+ return { key, val: decompressed }
272
272
  } catch (e) {
273
- return null;
273
+ return null
274
274
  }
275
275
  }),
276
- );
276
+ )
277
277
 
278
278
  for (const s of shards) {
279
- if (s) results.set(s.key, s.val);
279
+ if (s) results.set(s.key, s.val)
280
280
  }
281
281
  }
282
282
 
283
- return results;
283
+ return results
284
284
  }
285
285
 
286
286
  /**
@@ -288,24 +288,24 @@ export class TransformCache {
288
288
  */
289
289
  get(key: string): string | null {
290
290
  // 1. Check memory first (LRU)
291
- const mem = this.memoryCache.get(key);
292
- if (mem) return mem;
291
+ const mem = this.memoryCache.get(key)
292
+ if (mem) return mem
293
293
 
294
294
  // 2. Check index
295
- const hash = this.index.get(key);
296
- if (!hash) return null;
295
+ const hash = this.index.get(key)
296
+ if (!hash) return null
297
297
 
298
298
  // 3. Load from shard (synchronous read for Vite's transform hook compatibility)
299
- const shardPath = path.resolve(this.shardsDir, `${hash}.gz`);
300
- if (!fs.existsSync(shardPath)) return null;
299
+ const shardPath = path.resolve(this.shardsDir, `${hash}.gz`)
300
+ if (!fs.existsSync(shardPath)) return null
301
301
 
302
302
  try {
303
- const compressed = fs.readFileSync(shardPath);
304
- const decompressed = zlib.gunzipSync(compressed).toString("utf-8");
305
- this.memoryCache.set(key, decompressed);
306
- return decompressed;
303
+ const compressed = fs.readFileSync(shardPath)
304
+ const decompressed = zlib.gunzipSync(compressed).toString('utf-8')
305
+ this.memoryCache.set(key, decompressed)
306
+ return decompressed
307
307
  } catch (e) {
308
- return null;
308
+ return null
309
309
  }
310
310
  }
311
311
 
@@ -313,30 +313,30 @@ export class TransformCache {
313
313
  * Stores a transformation result.
314
314
  */
315
315
  set(key: string, result: string): void {
316
- const hash = crypto.createHash("md5").update(result).digest("hex");
317
- this.index.set(key, hash);
318
- this.memoryCache.set(key, result);
316
+ const hash = crypto.createHash('md5').update(result).digest('hex')
317
+ this.index.set(key, hash)
318
+ this.memoryCache.set(key, result)
319
319
 
320
- const shardPath = path.resolve(this.shardsDir, `${hash}.gz`);
320
+ const shardPath = path.resolve(this.shardsDir, `${hash}.gz`)
321
321
 
322
322
  // Background write shard
323
323
  backgroundQueue.add(async () => {
324
- if (fs.existsSync(shardPath)) return; // Already exists
325
- await mkdir(this.shardsDir, { recursive: true });
324
+ if (fs.existsSync(shardPath)) return // Already exists
325
+ await mkdir(this.shardsDir, { recursive: true })
326
326
 
327
- const compressed = zlib.gzipSync(Buffer.from(result));
328
- const tempPath = `${shardPath}.${crypto.randomBytes(4).toString("hex")}.tmp`;
329
- await writeFile(tempPath, compressed);
330
- await rename(tempPath, shardPath);
331
- });
327
+ const compressed = zlib.gzipSync(Buffer.from(result))
328
+ const tempPath = `${shardPath}.${crypto.randomBytes(4).toString('hex')}.tmp`
329
+ await writeFile(tempPath, compressed)
330
+ await rename(tempPath, shardPath)
331
+ })
332
332
  }
333
333
 
334
334
  get size() {
335
- return this.index.size;
335
+ return this.index.size
336
336
  }
337
337
 
338
338
  async flush() {
339
- await backgroundQueue.flush();
339
+ await backgroundQueue.flush()
340
340
  }
341
341
  }
342
342
 
@@ -344,59 +344,59 @@ export class TransformCache {
344
344
  * Specialized cache for processed assets (e.g., optimized images).
345
345
  */
346
346
  export class AssetCache {
347
- private readonly assetsDir: string;
347
+ private readonly assetsDir: string
348
348
 
349
349
  constructor(root: string = process.cwd()) {
350
- this.assetsDir = path.resolve(root, CACHE_DIR, ASSETS_DIR);
350
+ this.assetsDir = path.resolve(root, CACHE_DIR, ASSETS_DIR)
351
351
  }
352
352
 
353
353
  private getFileHash(filePath: string): string {
354
354
  return crypto
355
- .createHash("md5")
355
+ .createHash('md5')
356
356
  .update(fs.readFileSync(filePath))
357
- .digest("hex");
357
+ .digest('hex')
358
358
  }
359
359
 
360
360
  get(sourcePath: string, cacheKey: string): string | null {
361
- if (!fs.existsSync(sourcePath)) return null;
362
- const sourceHash = this.getFileHash(sourcePath);
361
+ if (!fs.existsSync(sourcePath)) return null
362
+ const sourceHash = this.getFileHash(sourcePath)
363
363
  const cachedPath = this.getCachedPath(
364
364
  sourcePath,
365
365
  `${cacheKey}-${sourceHash}`,
366
- );
367
- return fs.existsSync(cachedPath) ? cachedPath : null;
366
+ )
367
+ return fs.existsSync(cachedPath) ? cachedPath : null
368
368
  }
369
369
 
370
370
  set(sourcePath: string, cacheKey: string, content: Buffer | string): void {
371
- const sourceHash = this.getFileHash(sourcePath);
371
+ const sourceHash = this.getFileHash(sourcePath)
372
372
  const cachedPath = this.getCachedPath(
373
373
  sourcePath,
374
374
  `${cacheKey}-${sourceHash}`,
375
- );
375
+ )
376
376
 
377
377
  backgroundQueue.add(async () => {
378
- await mkdir(this.assetsDir, { recursive: true });
379
- const tempPath = `${cachedPath}.${crypto.randomBytes(4).toString("hex")}.tmp`;
380
- await writeFile(tempPath, content);
381
- await rename(tempPath, cachedPath);
382
- });
378
+ await mkdir(this.assetsDir, { recursive: true })
379
+ const tempPath = `${cachedPath}.${crypto.randomBytes(4).toString('hex')}.tmp`
380
+ await writeFile(tempPath, content)
381
+ await rename(tempPath, cachedPath)
382
+ })
383
383
  }
384
384
 
385
385
  private getCachedPath(sourcePath: string, cacheKey: string): string {
386
- const ext = path.extname(sourcePath);
387
- const name = path.basename(sourcePath, ext);
388
- const safeKey = cacheKey.replace(/[^a-z0-9]/gi, "-").toLowerCase();
389
- return path.join(this.assetsDir, `${name}.${safeKey}${ext}`);
386
+ const ext = path.extname(sourcePath)
387
+ const name = path.basename(sourcePath, ext)
388
+ const safeKey = cacheKey.replace(/[^a-z0-9]/gi, '-').toLowerCase()
389
+ return path.join(this.assetsDir, `${name}.${safeKey}${ext}`)
390
390
  }
391
391
 
392
392
  clear(): void {
393
393
  if (fs.existsSync(this.assetsDir)) {
394
- fs.rmSync(this.assetsDir, { recursive: true, force: true });
394
+ fs.rmSync(this.assetsDir, { recursive: true, force: true })
395
395
  }
396
396
  }
397
397
 
398
398
  async flush() {
399
- await backgroundQueue.flush();
399
+ await backgroundQueue.flush()
400
400
  }
401
401
  }
402
402
 
@@ -404,5 +404,5 @@ export class AssetCache {
404
404
  * Flushes all pending background cache operations.
405
405
  */
406
406
  export async function flushCache() {
407
- await backgroundQueue.flush();
407
+ await backgroundQueue.flush()
408
408
  }