@wrikka/create-docs 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (380) hide show
  1. package/README.md +137 -0
  2. package/bin/cli.js +408 -0
  3. package/dist/index.cjs +20 -0
  4. package/dist/index.d.cts +475 -0
  5. package/dist/index.d.ts +475 -0
  6. package/dist/index.js +20 -0
  7. package/docs/_dir.yml +2 -0
  8. package/docs/config.md +75 -0
  9. package/docs/data-sources.md +88 -0
  10. package/docs/deploy.md +38 -0
  11. package/docs/features.md +51 -0
  12. package/docs/getting-started.md +42 -0
  13. package/docs/index.md +34 -0
  14. package/docs/markdown.md +154 -0
  15. package/docs/theming.md +53 -0
  16. package/package.json +142 -0
  17. package/scripts/generate-docs-index.ts +111 -0
  18. package/scripts/github-pull.ts +124 -0
  19. package/src/adapters/config/index.ts +1 -0
  20. package/src/adapters/config/node-config-loader.ts +36 -0
  21. package/src/adapters/fs/fs-docs-loader.ts +31 -0
  22. package/src/adapters/fs/index.ts +12 -0
  23. package/src/adapters/fs/memory-fs.ts +60 -0
  24. package/src/adapters/fs/node-fs.ts +116 -0
  25. package/src/adapters/git/index.ts +164 -0
  26. package/src/adapters/github/github-pull.ts +340 -0
  27. package/src/adapters/index.ts +6 -0
  28. package/src/adapters/velite.ts +112 -0
  29. package/src/adapters/vite/docs-watcher.ts +36 -0
  30. package/src/adapters/vite/index.ts +2 -0
  31. package/src/adapters/vite/polling-watcher.ts +89 -0
  32. package/src/code-block-enhancements/index.ts +3 -0
  33. package/src/config/index.ts +15 -0
  34. package/src/content/index.ts +11 -0
  35. package/src/content-validation/index.ts +5 -0
  36. package/src/index.ts +174 -0
  37. package/src/live-editor/index.ts +7 -0
  38. package/src/modules/analytics/application/plausible-adapter.ts +103 -0
  39. package/src/modules/analytics/application/umami-adapter.ts +109 -0
  40. package/src/modules/analytics/domain/events/index.ts +37 -0
  41. package/src/modules/analytics/domain/models/index.ts +35 -0
  42. package/src/modules/analytics/domain/operations/analytics-operations.ts +67 -0
  43. package/src/modules/analytics/domain/validators/index.ts +50 -0
  44. package/src/modules/analytics/index.ts +9 -0
  45. package/src/modules/analytics/ports/analytics-port.ts +17 -0
  46. package/src/modules/analytics/types/analytics.ts +16 -0
  47. package/src/modules/api-docs/application/type-docs-adapter.ts +34 -0
  48. package/src/modules/api-docs/domain/events/index.ts +42 -0
  49. package/src/modules/api-docs/domain/models/index.ts +40 -0
  50. package/src/modules/api-docs/domain/operations/api-docs-operations.ts +59 -0
  51. package/src/modules/api-docs/domain/validators/index.ts +56 -0
  52. package/src/modules/api-docs/index.ts +8 -0
  53. package/src/modules/api-docs/ports/api-docs-port.ts +21 -0
  54. package/src/modules/api-docs/types/api-docs.ts +15 -0
  55. package/src/modules/api-reference/openapi.ts +166 -0
  56. package/src/modules/api-reference/orpc.ts +94 -0
  57. package/src/modules/code-block-enhancements/application/usecases/index.ts +39 -0
  58. package/src/modules/code-block-enhancements/domain/code-operations.ts +72 -0
  59. package/src/modules/code-block-enhancements/domain/events/index.ts +58 -0
  60. package/src/modules/code-block-enhancements/domain/index.ts +11 -0
  61. package/src/modules/code-block-enhancements/domain/models/index.ts +36 -0
  62. package/src/modules/code-block-enhancements/domain/validators/index.ts +50 -0
  63. package/src/modules/code-block-enhancements/index.ts +10 -0
  64. package/src/modules/code-block-enhancements/ports/index.ts +18 -0
  65. package/src/modules/code-block-enhancements/types/index.ts +37 -0
  66. package/src/modules/code-execution/application/sandbox-adapter.ts +44 -0
  67. package/src/modules/code-execution/domain/events/index.ts +58 -0
  68. package/src/modules/code-execution/domain/models/index.ts +33 -0
  69. package/src/modules/code-execution/domain/operations/execution-operations.ts +60 -0
  70. package/src/modules/code-execution/domain/validators/index.ts +50 -0
  71. package/src/modules/code-execution/index.ts +8 -0
  72. package/src/modules/code-execution/ports/execution-port.ts +15 -0
  73. package/src/modules/code-execution/types/execution.ts +15 -0
  74. package/src/modules/comments/application/giscus-adapter.ts +55 -0
  75. package/src/modules/comments/domain/events/index.ts +55 -0
  76. package/src/modules/comments/domain/models/index.ts +30 -0
  77. package/src/modules/comments/domain/operations/comment-operations.ts +46 -0
  78. package/src/modules/comments/domain/validators/index.ts +50 -0
  79. package/src/modules/comments/index.ts +8 -0
  80. package/src/modules/comments/ports/comment-port.ts +18 -0
  81. package/src/modules/comments/types/comments.ts +19 -0
  82. package/src/modules/config/application/usecases/index.ts +1 -0
  83. package/src/modules/config/application/usecases/loadConfig.ts +38 -0
  84. package/src/modules/config/application/workflows/index.ts +1 -0
  85. package/src/modules/config/application/workflows/validateConfig.ts +14 -0
  86. package/src/modules/config/domain/events/index.ts +50 -0
  87. package/src/modules/config/domain/models/index.ts +9 -0
  88. package/src/modules/config/domain/operations/defaults.ts +74 -0
  89. package/src/modules/config/domain/operations/index.ts +2 -0
  90. package/src/modules/config/domain/operations/resolve.ts +40 -0
  91. package/src/modules/config/domain/validators/index.ts +152 -0
  92. package/src/modules/config/index.ts +23 -0
  93. package/src/modules/config/ports/index.ts +15 -0
  94. package/src/modules/config/types/index.ts +113 -0
  95. package/src/modules/config/types/public.ts +19 -0
  96. package/src/modules/content/application/cache/index.ts +6 -0
  97. package/src/modules/content/application/cache/parse-cache.ts +6 -0
  98. package/src/modules/content/application/cache/parseCache.ts +56 -0
  99. package/src/modules/content/application/usecases/index.ts +2 -0
  100. package/src/modules/content/application/usecases/load-doc-page.ts +1 -0
  101. package/src/modules/content/application/usecases/loadDocPage.ts +111 -0
  102. package/src/modules/content/application/usecases/scanDocsDir.ts +105 -0
  103. package/src/modules/content/application/workflows/index.ts +1 -0
  104. package/src/modules/content/application/workflows/processDocs.ts +51 -0
  105. package/src/modules/content/domain/events/index.ts +61 -0
  106. package/src/modules/content/domain/models/index.ts +13 -0
  107. package/src/modules/content/domain/operations/build-page.ts +146 -0
  108. package/src/modules/content/domain/operations/buildPage.ts +93 -0
  109. package/src/modules/content/domain/operations/index.ts +17 -0
  110. package/src/modules/content/domain/operations/parse.ts +241 -0
  111. package/src/modules/content/domain/validators/frontmatter.ts +82 -0
  112. package/src/modules/content/domain/validators/index.ts +6 -0
  113. package/src/modules/content/index.ts +27 -0
  114. package/src/modules/content/ports/index.ts +45 -0
  115. package/src/modules/content/ports/velite.ts +134 -0
  116. package/src/modules/content/types/index.ts +76 -0
  117. package/src/modules/content/types/public.ts +1 -0
  118. package/src/modules/content-linting/application/builtin-linting-adapter.ts +82 -0
  119. package/src/modules/content-linting/domain/events/index.ts +58 -0
  120. package/src/modules/content-linting/domain/models/index.ts +46 -0
  121. package/src/modules/content-linting/domain/operations/linting-operations.ts +82 -0
  122. package/src/modules/content-linting/domain/validators/index.ts +50 -0
  123. package/src/modules/content-linting/index.ts +8 -0
  124. package/src/modules/content-linting/ports/linting-port.ts +21 -0
  125. package/src/modules/content-linting/types/linting.ts +18 -0
  126. package/src/modules/content-validation/application/usecases/index.ts +18 -0
  127. package/src/modules/content-validation/domain/events/index.ts +7 -0
  128. package/src/modules/content-validation/domain/index.ts +16 -0
  129. package/src/modules/content-validation/domain/models/index.ts +33 -0
  130. package/src/modules/content-validation/domain/operations/index.ts +157 -0
  131. package/src/modules/content-validation/domain/types/index.ts +17 -0
  132. package/src/modules/content-validation/domain/validators/index.ts +8 -0
  133. package/src/modules/content-validation/index.ts +9 -0
  134. package/src/modules/content-validation/ports/index.ts +15 -0
  135. package/src/modules/content-validation/types/index.ts +5 -0
  136. package/src/modules/export/application/puppeteer-export-adapter.ts +63 -0
  137. package/src/modules/export/domain/events/index.ts +55 -0
  138. package/src/modules/export/domain/models/index.ts +38 -0
  139. package/src/modules/export/domain/operations/export-operations.ts +56 -0
  140. package/src/modules/export/domain/validators/index.ts +52 -0
  141. package/src/modules/export/index.ts +8 -0
  142. package/src/modules/export/ports/export-port.ts +15 -0
  143. package/src/modules/export/types/export.ts +15 -0
  144. package/src/modules/external-search/application/algolia-adapter.ts +182 -0
  145. package/src/modules/external-search/application/meilisearch-adapter.ts +161 -0
  146. package/src/modules/external-search/domain/events/index.ts +42 -0
  147. package/src/modules/external-search/domain/models/index.ts +42 -0
  148. package/src/modules/external-search/domain/operations/search-operations.ts +53 -0
  149. package/src/modules/external-search/domain/validators/index.ts +55 -0
  150. package/src/modules/external-search/index.ts +9 -0
  151. package/src/modules/external-search/ports/external-search-port.ts +23 -0
  152. package/src/modules/external-search/types/search.ts +19 -0
  153. package/src/modules/git-history/application/simple-git-adapter.ts +46 -0
  154. package/src/modules/git-history/domain/events/index.ts +34 -0
  155. package/src/modules/git-history/domain/models/index.ts +25 -0
  156. package/src/modules/git-history/domain/operations/git-history-operations.ts +56 -0
  157. package/src/modules/git-history/domain/validators/index.ts +52 -0
  158. package/src/modules/git-history/index.ts +8 -0
  159. package/src/modules/git-history/ports/git-history-port.ts +21 -0
  160. package/src/modules/git-history/types/git-history.ts +15 -0
  161. package/src/modules/i18n/application/fs-locale-loader.ts +39 -0
  162. package/src/modules/i18n/domain/events/index.ts +34 -0
  163. package/src/modules/i18n/domain/models/index.ts +34 -0
  164. package/src/modules/i18n/domain/operations/locale-operations.ts +74 -0
  165. package/src/modules/i18n/domain/validators/index.ts +52 -0
  166. package/src/modules/i18n/index.ts +8 -0
  167. package/src/modules/i18n/ports/locale-loader-port.ts +18 -0
  168. package/src/modules/i18n/types/locale.ts +17 -0
  169. package/src/modules/image-optimization/application/sharp-adapter.ts +58 -0
  170. package/src/modules/image-optimization/domain/events/index.ts +39 -0
  171. package/src/modules/image-optimization/domain/models/index.ts +27 -0
  172. package/src/modules/image-optimization/domain/operations/image-operations.ts +65 -0
  173. package/src/modules/image-optimization/domain/validators/index.ts +52 -0
  174. package/src/modules/image-optimization/index.ts +8 -0
  175. package/src/modules/image-optimization/ports/image-optimizer-port.ts +15 -0
  176. package/src/modules/image-optimization/types/image.ts +17 -0
  177. package/src/modules/live-editor/application/usecases/index.ts +60 -0
  178. package/src/modules/live-editor/domain/events/index.ts +37 -0
  179. package/src/modules/live-editor/domain/gitOperations.ts +110 -0
  180. package/src/modules/live-editor/domain/index.ts +15 -0
  181. package/src/modules/live-editor/domain/models/index.ts +21 -0
  182. package/src/modules/live-editor/domain/validators/index.ts +55 -0
  183. package/src/modules/live-editor/index.ts +14 -0
  184. package/src/modules/live-editor/ports/index.ts +49 -0
  185. package/src/modules/live-editor/types/index.ts +80 -0
  186. package/src/modules/live-preview/application/vite-preview-adapter.ts +20 -0
  187. package/src/modules/live-preview/domain/operations/preview-operations.ts +56 -0
  188. package/src/modules/live-preview/index.ts +8 -0
  189. package/src/modules/live-preview/ports/preview-port.ts +20 -0
  190. package/src/modules/live-preview/types/preview.ts +16 -0
  191. package/src/modules/mdx/application/mdx-js-adapter.ts +38 -0
  192. package/src/modules/mdx/domain/operations/parse-mdx.ts +43 -0
  193. package/src/modules/mdx/index.ts +8 -0
  194. package/src/modules/mdx/ports/mdx-parser-port.ts +15 -0
  195. package/src/modules/mdx/types/mdx.ts +14 -0
  196. package/src/modules/navigation/application/usecases/buildNav.ts +15 -0
  197. package/src/modules/navigation/application/usecases/buildSidebar.ts +45 -0
  198. package/src/modules/navigation/application/usecases/index.ts +2 -0
  199. package/src/modules/navigation/domain/events/index.ts +30 -0
  200. package/src/modules/navigation/domain/models/index.ts +7 -0
  201. package/src/modules/navigation/domain/operations/group.ts +79 -0
  202. package/src/modules/navigation/domain/operations/index.ts +10 -0
  203. package/src/modules/navigation/domain/operations/sort.ts +27 -0
  204. package/src/modules/navigation/domain/shared/utils/array.ts +39 -0
  205. package/src/modules/navigation/domain/validators/index.ts +88 -0
  206. package/src/modules/navigation/index.ts +15 -0
  207. package/src/modules/navigation/ports/index.ts +9 -0
  208. package/src/modules/navigation/types/index.ts +38 -0
  209. package/src/modules/navigation/types/public.ts +9 -0
  210. package/src/modules/openapi/application/swagger-parser-adapter.ts +178 -0
  211. package/src/modules/openapi/domain/operations/parse-openapi.ts +46 -0
  212. package/src/modules/openapi/index.ts +8 -0
  213. package/src/modules/openapi/ports/openapi-parser-port.ts +15 -0
  214. package/src/modules/openapi/types/openapi.ts +37 -0
  215. package/src/modules/plugin/application/usecases/build-virtual-modules.ts +53 -0
  216. package/src/modules/plugin/application/usecases/index.ts +1 -0
  217. package/src/modules/plugin/application/workflows/build-docs.ts +79 -0
  218. package/src/modules/plugin/application/workflows/index.ts +1 -0
  219. package/src/modules/plugin/domain/events/index.ts +62 -0
  220. package/src/modules/plugin/domain/models/index.ts +1 -0
  221. package/src/modules/plugin/domain/operations/build-virtual.ts +76 -0
  222. package/src/modules/plugin/domain/operations/index.ts +11 -0
  223. package/src/modules/plugin/domain/validators/index.ts +30 -0
  224. package/src/modules/plugin/index.ts +14 -0
  225. package/src/modules/plugin/ports/index.ts +21 -0
  226. package/src/modules/plugin/types/index.ts +27 -0
  227. package/src/modules/plugin/types/public.ts +1 -0
  228. package/src/modules/search/application/usecases/index.ts +1 -0
  229. package/src/modules/search/application/usecases/indexPages.ts +15 -0
  230. package/src/modules/search/domain/events/index.ts +32 -0
  231. package/src/modules/search/domain/models/index.ts +1 -0
  232. package/src/modules/search/domain/operations/build-index.ts +6 -0
  233. package/src/modules/search/domain/operations/buildIndex.ts +70 -0
  234. package/src/modules/search/domain/operations/index.ts +7 -0
  235. package/src/modules/search/domain/operations/query.ts +186 -0
  236. package/src/modules/search/domain/validators/index.ts +32 -0
  237. package/src/modules/search/index.ts +9 -0
  238. package/src/modules/search/types/index.ts +22 -0
  239. package/src/modules/search/types/public.ts +1 -0
  240. package/src/modules/search-analytics/application/local-storage-adapter.ts +68 -0
  241. package/src/modules/search-analytics/domain/operations/search-analytics-operations.ts +74 -0
  242. package/src/modules/search-analytics/index.ts +8 -0
  243. package/src/modules/search-analytics/ports/search-analytics-port.ts +20 -0
  244. package/src/modules/search-analytics/types/search-analytics.ts +16 -0
  245. package/src/modules/search-highlighting/application/dom-highlighting-adapter.ts +36 -0
  246. package/src/modules/search-highlighting/domain/operations/highlighting-operations.ts +72 -0
  247. package/src/modules/search-highlighting/index.ts +8 -0
  248. package/src/modules/search-highlighting/ports/highlighting-port.ts +14 -0
  249. package/src/modules/search-highlighting/types/highlighting.ts +15 -0
  250. package/src/modules/seo-optimization/application/usecases/index.ts +18 -0
  251. package/src/modules/seo-optimization/domain/index.ts +12 -0
  252. package/src/modules/seo-optimization/domain/seoOperations.ts +92 -0
  253. package/src/modules/seo-optimization/index.ts +8 -0
  254. package/src/modules/seo-optimization/ports/index.ts +18 -0
  255. package/src/modules/seo-optimization/types/index.ts +41 -0
  256. package/src/modules/theme/application/css-theme-adapter.ts +50 -0
  257. package/src/modules/theme/domain/operations/theme-operations.ts +68 -0
  258. package/src/modules/theme/index.ts +8 -0
  259. package/src/modules/theme/ports/theme-port.ts +8 -0
  260. package/src/modules/theme/types/theme.ts +12 -0
  261. package/src/modules/toc/application/markdown-toc-adapter.ts +106 -0
  262. package/src/modules/toc/domain/operations/toc-operations.ts +92 -0
  263. package/src/modules/toc/index.ts +8 -0
  264. package/src/modules/toc/ports/toc-port.ts +21 -0
  265. package/src/modules/toc/types/toc.ts +17 -0
  266. package/src/modules/toc-generator/application/usecases/index.ts +30 -0
  267. package/src/modules/toc-generator/domain/index.ts +12 -0
  268. package/src/modules/toc-generator/domain/tocOperations.ts +104 -0
  269. package/src/modules/toc-generator/index.ts +9 -0
  270. package/src/modules/toc-generator/ports/index.ts +20 -0
  271. package/src/modules/toc-generator/types/index.ts +50 -0
  272. package/src/modules/version-control/domain/events/index.ts +39 -0
  273. package/src/modules/version-control/domain/models/index.ts +25 -0
  274. package/src/modules/version-control/domain/validators/index.ts +50 -0
  275. package/src/modules/versioning/application/fs-version-loader.ts +44 -0
  276. package/src/modules/versioning/domain/operations/versioning-operations.ts +80 -0
  277. package/src/modules/versioning/index.ts +8 -0
  278. package/src/modules/versioning/ports/version-loader-port.ts +18 -0
  279. package/src/modules/versioning/types/versioning.ts +17 -0
  280. package/src/modules/workflow/domain/events/index.ts +55 -0
  281. package/src/modules/workflow/domain/models/index.ts +40 -0
  282. package/src/modules/workflow/domain/validators/index.ts +50 -0
  283. package/src/modules/yaml-parser/application/js-yaml-adapter.ts +34 -0
  284. package/src/modules/yaml-parser/domain/operations/parse-yaml.ts +58 -0
  285. package/src/modules/yaml-parser/index.ts +7 -0
  286. package/src/modules/yaml-parser/ports/yaml-parser-port.ts +18 -0
  287. package/src/navigation/index.ts +9 -0
  288. package/src/plugin/index.ts +4 -0
  289. package/src/presentation/index.ts +1 -0
  290. package/src/presentation/live-editor/index.ts +22 -0
  291. package/src/presentation/live-editor/live-editor-component.ts +219 -0
  292. package/src/presentation/live-editor/virtual-module.ts +16 -0
  293. package/src/presentation/solid/CodeBlock.tsx +120 -0
  294. package/src/presentation/solid/Toc.tsx +58 -0
  295. package/src/presentation/solid/index.ts +11 -0
  296. package/src/presentation/vite-plugin/docs-plugin.ts +212 -0
  297. package/src/presentation/vite-plugin/index.ts +9 -0
  298. package/src/presentation/vite-plugin/transform-markdown.ts +26 -0
  299. package/src/runtime/analytics.ts +59 -0
  300. package/src/runtime/api-diff.ts +115 -0
  301. package/src/runtime/app.tsx +32 -0
  302. package/src/runtime/components/AccentPicker.tsx +114 -0
  303. package/src/runtime/components/ApiPlayground.tsx +332 -0
  304. package/src/runtime/components/AskAiDialog.tsx +127 -0
  305. package/src/runtime/components/BackToTop.tsx +38 -0
  306. package/src/runtime/components/Banner.tsx +75 -0
  307. package/src/runtime/components/Breadcrumbs.tsx +42 -0
  308. package/src/runtime/components/CollectionDropdown.tsx +85 -0
  309. package/src/runtime/components/CustomizeDrawer.tsx +195 -0
  310. package/src/runtime/components/DocMarkdown.tsx +579 -0
  311. package/src/runtime/components/DocPrevNext.tsx +54 -0
  312. package/src/runtime/components/DocToc.tsx +147 -0
  313. package/src/runtime/components/DocsDropdown.tsx +184 -0
  314. package/src/runtime/components/Footer.tsx +52 -0
  315. package/src/runtime/components/GitHubAuth.tsx +82 -0
  316. package/src/runtime/components/GitHubStats.tsx +73 -0
  317. package/src/runtime/components/Head.tsx +225 -0
  318. package/src/runtime/components/LocaleDropdown.tsx +75 -0
  319. package/src/runtime/components/MobileBottomNav.tsx +111 -0
  320. package/src/runtime/components/NotFound.tsx +139 -0
  321. package/src/runtime/components/PageActions.tsx +144 -0
  322. package/src/runtime/components/RelatedDocs.tsx +50 -0
  323. package/src/runtime/components/ScrollProgress.tsx +32 -0
  324. package/src/runtime/components/SearchPalette.tsx +333 -0
  325. package/src/runtime/components/ShowcaseCard.tsx +87 -0
  326. package/src/runtime/components/SidebarNav.tsx +237 -0
  327. package/src/runtime/components/Skeleton.tsx +39 -0
  328. package/src/runtime/components/ThemeToggle.tsx +26 -0
  329. package/src/runtime/components/TopNav.tsx +270 -0
  330. package/src/runtime/components/VersionDropdown.tsx +189 -0
  331. package/src/runtime/components/markdown/components.ts +280 -0
  332. package/src/runtime/config.ts +225 -0
  333. package/src/runtime/content.ts +451 -0
  334. package/src/runtime/context.tsx +30 -0
  335. package/src/runtime/data.ts +93 -0
  336. package/src/runtime/github.ts +226 -0
  337. package/src/runtime/icons.ts +32 -0
  338. package/src/runtime/index.ts +153 -0
  339. package/src/runtime/layouts/DocsLayout.tsx +144 -0
  340. package/src/runtime/markdown-content.css +996 -0
  341. package/src/runtime/pages/AbTestPage.tsx +88 -0
  342. package/src/runtime/pages/AnalyticsPage.tsx +90 -0
  343. package/src/runtime/pages/ApiDiffPage.tsx +86 -0
  344. package/src/runtime/pages/ApiEndpointPage.tsx +248 -0
  345. package/src/runtime/pages/BuilderPage.tsx +150 -0
  346. package/src/runtime/pages/ChangelogPage.tsx +210 -0
  347. package/src/runtime/pages/CollectionPage.tsx +140 -0
  348. package/src/runtime/pages/CommunityPage.tsx +384 -0
  349. package/src/runtime/pages/CreatePage.tsx +448 -0
  350. package/src/runtime/pages/DocPage.tsx +193 -0
  351. package/src/runtime/pages/EditPage.tsx +201 -0
  352. package/src/runtime/pages/HomePage.tsx +187 -0
  353. package/src/runtime/pages/IssuesPage.tsx +140 -0
  354. package/src/runtime/pages/OAuthCallbackPage.tsx +80 -0
  355. package/src/runtime/pages/PluginsPage.tsx +249 -0
  356. package/src/runtime/pages/ShowcasePage.tsx +202 -0
  357. package/src/runtime/pwa.ts +39 -0
  358. package/src/runtime/router.tsx +192 -0
  359. package/src/runtime/seo.ts +192 -0
  360. package/src/runtime/theme.css +175 -0
  361. package/src/runtime/theme.ts +224 -0
  362. package/src/runtime/types.ts +217 -0
  363. package/src/search/index.ts +6 -0
  364. package/src/seo-optimization/index.ts +4 -0
  365. package/src/shared/constants/index.ts +26 -0
  366. package/src/shared/errors/index.ts +195 -0
  367. package/src/shared/index.ts +27 -0
  368. package/src/shared/types/brand.ts +14 -0
  369. package/src/shared/types/client.d.ts +45 -0
  370. package/src/shared/types/either.ts +38 -0
  371. package/src/shared/types/index.ts +42 -0
  372. package/src/shared/types/option.ts +52 -0
  373. package/src/shared/types/result.ts +81 -0
  374. package/src/shared/utils/array.ts +97 -0
  375. package/src/shared/utils/index.ts +46 -0
  376. package/src/shared/utils/object.ts +47 -0
  377. package/src/shared/utils/string.ts +74 -0
  378. package/src/toc-generator/index.ts +1 -0
  379. package/src/types/js-yaml.d.ts +42 -0
  380. package/src/worker.ts +462 -0
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Runtime types for the create-docs Solid app shell.
3
+ *
4
+ * A consumer injects a {@link DocsDataSource} so the UI stays
5
+ * source-agnostic: oRPC, static manifest, CMS, anything.
6
+ */
7
+
8
+ export interface CollectionMeta {
9
+ id: string;
10
+ label: string;
11
+ icon?: string;
12
+ description?: string;
13
+ /** Optional repository URL used by "Edit on GitHub" etc. */
14
+ repoUrl?: string;
15
+ /** "docs" renders markdown pages, "api" renders the API reference layout, "showcase" renders cards. */
16
+ type?: "docs" | "api" | "showcase";
17
+ /** Sidebar sections (from `_dir.yml` or manual config) — ordered nav groups. */
18
+ sections?: {
19
+ id: string;
20
+ label: string;
21
+ icon?: string;
22
+ order?: number;
23
+ collapsed?: boolean;
24
+ }[];
25
+ }
26
+
27
+ export interface DocSeo {
28
+ title?: string;
29
+ description?: string;
30
+ image?: string;
31
+ ogType?: "article" | "website";
32
+ noIndex?: boolean;
33
+ }
34
+
35
+ /** Frontmatter parsed from a markdown document. */
36
+ export interface DocFrontmatter {
37
+ title?: string;
38
+ description?: string;
39
+ /** Sort order within the sidebar/category. */
40
+ order?: number;
41
+ /** Sidebar category override. */
42
+ category?: string;
43
+ /** Hide from lists, search, sitemap and feeds (still renderable in dev). */
44
+ draft?: boolean;
45
+ /** ISO date — doc is hidden until this time (scheduled publishing). */
46
+ publishedAt?: string;
47
+ /** ISO date — shown as "last updated". */
48
+ lastUpdated?: string;
49
+ tags?: string[];
50
+ /** Small badge shown next to the sidebar label. */
51
+ badge?: string;
52
+ /** Iconify icon class for the sidebar entry. */
53
+ icon?: string;
54
+ /** Page-level overrides. */
55
+ toc?: boolean;
56
+ aside?: boolean;
57
+ editLink?: boolean;
58
+ layout?: "doc" | "page" | "home";
59
+ /** Per-page SEO overrides. */
60
+ seo?: DocSeo;
61
+ [key: string]: unknown;
62
+ }
63
+
64
+ /** One Markdown document. */
65
+ export interface DocContent {
66
+ id: string;
67
+ label: string;
68
+ /** Body may be omitted in lightweight entries. */
69
+ content?: string;
70
+ category?: string;
71
+ order?: number;
72
+ icon?: string;
73
+ /** Optional badge shown in sidebar and search. */
74
+ badge?: string;
75
+ description?: string;
76
+ path?: string;
77
+ /** Optional tags for grouping/filtering. */
78
+ tags?: string[];
79
+ /** ISO date if available. */
80
+ date?: string;
81
+ /** Last-updated ISO timestamp. */
82
+ lastUpdated?: string;
83
+ /** Frontmatter values parsed from the file. */
84
+ frontmatter?: DocFrontmatter;
85
+ }
86
+
87
+ export interface DocEntry extends DocContent {
88
+ /** Sidebar category (required for grouping). */
89
+ category: string;
90
+ /** Short description. */
91
+ description: string;
92
+ /** Original file path / route path. */
93
+ path: string;
94
+ /** Support nested sidebar submenus. */
95
+ children?: DocEntry[];
96
+ /** Excluded from listings when the source filters drafts. */
97
+ draft?: boolean;
98
+ /** Original publication timestamp (ISO). */
99
+ publishedAt?: string;
100
+ /** Per-page SEO overrides. */
101
+ seo?: DocSeo;
102
+ /** Entry render type. */
103
+ type?: "doc" | "api" | "showcase" | "rust" | "npm" | "md";
104
+ /** Nav entries may omit the full body content. */
105
+ content?: string;
106
+ }
107
+
108
+ /** Nuxt Content-style query over a data source. */
109
+ export interface DocQuery {
110
+ collection?: string;
111
+ /** Filters — all provided fields must match. */
112
+ where?: {
113
+ category?: string;
114
+ tag?: string;
115
+ draft?: boolean;
116
+ };
117
+ sort?: "title" | "order" | "lastUpdated" | "id";
118
+ order?: "asc" | "desc";
119
+ limit?: number;
120
+ }
121
+
122
+ /** Search result returned from buildSearchIndex(). */
123
+ export interface SearchResult {
124
+ collection: string;
125
+ id: string;
126
+ title: string;
127
+ snippet: string;
128
+ score: number;
129
+ }
130
+
131
+ export interface AskInput {
132
+ collection: string;
133
+ id: string;
134
+ question: string;
135
+ }
136
+
137
+ export interface AskResult {
138
+ answer: string;
139
+ cost?: { tokens?: number; ms?: number };
140
+ }
141
+
142
+ /** Port — the app shell only talks to this interface. */
143
+ export interface DocsDataSource {
144
+ /** Available collections. */
145
+ collections(): Promise<CollectionMeta[]> | CollectionMeta[];
146
+ /** List all documents in a collection. */
147
+ list(collection: string): Promise<DocEntry[]> | DocEntry[];
148
+ /** Fetch a single document. */
149
+ get(collection: string, id: string): Promise<DocContent> | DocContent;
150
+ /** Optional full-text search across collections. */
151
+ search?(
152
+ q: string,
153
+ collection?: string,
154
+ ): Promise<SearchResult[]> | SearchResult[];
155
+ /** Optional — enables the Ask AI button when present. */
156
+ ask?(input: AskInput): Promise<AskResult> | AskResult;
157
+ /** Optional — Nuxt Content-style filtered/sorted document listing. */
158
+ query?(q: DocQuery): Promise<DocEntry[]> | DocEntry[];
159
+ }
160
+
161
+ export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
162
+
163
+ export interface ApiParameter {
164
+ name: string;
165
+ in: "query" | "path" | "header" | "cookie";
166
+ required: boolean;
167
+ description?: string;
168
+ schema?: unknown;
169
+ example?: unknown;
170
+ }
171
+
172
+ export interface GraphQlEndpoint {
173
+ /** GraphQL operation name. */
174
+ operation?: string;
175
+ /** GraphQL query or mutation. */
176
+ query: string;
177
+ /** Example / schema for variables. */
178
+ variables?: Record<string, unknown>;
179
+ }
180
+
181
+ export interface CliArg {
182
+ name: string;
183
+ required: boolean;
184
+ description?: string;
185
+ example?: string;
186
+ }
187
+
188
+ export interface CliEndpoint {
189
+ /** Base command, e.g. "wrikka". */
190
+ command: string;
191
+ /** Subcommand, e.g. "create". */
192
+ subcommand?: string;
193
+ args?: CliArg[];
194
+ }
195
+
196
+ export interface ApiEndpoint {
197
+ id: string;
198
+ method: HttpMethod;
199
+ path: string;
200
+ summary?: string;
201
+ description?: string;
202
+ tag?: string;
203
+ parameters: ApiParameter[];
204
+ requestBody?: {
205
+ description?: string;
206
+ required: boolean;
207
+ example?: unknown;
208
+ contentType?: string;
209
+ };
210
+ responses: Record<string, { description: string; example?: unknown }>;
211
+ /** Absolute base URL used by the playground. Defaults to origin. */
212
+ server?: string;
213
+ /** GraphQL-specific payload. */
214
+ graphql?: GraphQlEndpoint;
215
+ /** CLI-specific payload. */
216
+ cli?: CliEndpoint;
217
+ }
@@ -0,0 +1,6 @@
1
+ export type SearchEntry = unknown;
2
+ export type SearchIndex = unknown;
3
+ export const buildSearchIndex = () => null;
4
+ export const indexPages = () => null;
5
+ export const pageToSearchEntry = () => null;
6
+ export const search = () => null;
@@ -0,0 +1,4 @@
1
+ export type MetaTagGenerator = unknown;
2
+ export type MetaTags = unknown;
3
+ export type SeoOptions = unknown;
4
+ export const optimizeSeo = () => null;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Compile-time static constants. These are the only safe values
3
+ * to import in the domain layer (where I/O is forbidden).
4
+ */
5
+
6
+ export const DEFAULT_DOCS_DIR = "docs" as const;
7
+ export const DEFAULT_BASE_ROUTE = "/docs" as const;
8
+ export const DEFAULT_PORT = 5173 as const;
9
+ export const VIRTUAL_PREFIX = "virtual:docs/" as const;
10
+ export const PLUGIN_NAME = "vite-plugin-docs" as const;
11
+
12
+ export const SUPPORTED_EXTENSIONS = [".md", ".mdoc"] as const;
13
+ export const FRONTMATTER_DELIMITER = "---" as const;
14
+
15
+ export const SEARCH_CONTENT_LIMIT = 500 as const;
16
+ export const SIDEBAR_DEFAULT_GROUP_TITLE = "Documentation" as const;
17
+ export const SIDEBAR_DEFAULT_ORDER = 999 as const;
18
+
19
+ export const BADGE_VARIANTS = [
20
+ "default",
21
+ "success",
22
+ "warning",
23
+ "danger",
24
+ ] as const;
25
+ export const API_AUTH_TYPES = ["bearer", "apiKey", "oauth2"] as const;
26
+ export const HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"] as const;
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Domain error types — tagged unions for typed failures.
3
+ *
4
+ * Each module can extend this with its own error variants, but
5
+ * all errors should flow through these base types at boundaries.
6
+ */
7
+
8
+ export type AppErrorKind =
9
+ | "file_not_found"
10
+ | "parse_error"
11
+ | "validation_error"
12
+ | "config_error"
13
+ | "io_error"
14
+ | "plugin_error";
15
+
16
+ export interface AppError {
17
+ readonly kind: AppErrorKind;
18
+ readonly message: string;
19
+ readonly cause?: unknown;
20
+ readonly context?: Readonly<Record<string, unknown>>;
21
+ /** JSON-pointer-like path to the offending field (e.g. "site.title"). */
22
+ readonly path?: string;
23
+ /** Actionable hint shown to the user (e.g. allowed values). */
24
+ readonly hint?: string;
25
+ /** Documentation URL related to this error. */
26
+ readonly docsUrl?: string;
27
+ /** Allowed values, for inline suggestions. */
28
+ readonly suggestions?: readonly string[];
29
+ }
30
+
31
+ const DOCS_BASE = "https://create-docs.dev/errors";
32
+
33
+ export const makeError = (
34
+ kind: AppErrorKind,
35
+ message: string,
36
+ options?: {
37
+ cause?: unknown;
38
+ context?: Record<string, unknown>;
39
+ path?: string;
40
+ hint?: string;
41
+ suggestions?: readonly string[];
42
+ },
43
+ ): AppError => {
44
+ const base: {
45
+ kind: AppErrorKind;
46
+ message: string;
47
+ cause?: unknown;
48
+ context?: Readonly<Record<string, unknown>>;
49
+ path?: string;
50
+ hint?: string;
51
+ suggestions?: readonly string[];
52
+ docsUrl: string;
53
+ } = {
54
+ kind,
55
+ message,
56
+ docsUrl: `${DOCS_BASE}/${kind.replace(/_/g, "-")}`,
57
+ };
58
+ if (options?.cause !== undefined) base.cause = options.cause;
59
+ if (options?.context !== undefined) base.context = options.context;
60
+ if (options?.path !== undefined) base.path = options.path;
61
+ if (options?.hint !== undefined) base.hint = options.hint;
62
+ if (options?.suggestions !== undefined)
63
+ base.suggestions = options.suggestions;
64
+ return base;
65
+ };
66
+
67
+ export const fileNotFound = (path: string, cause?: unknown): AppError =>
68
+ makeError("file_not_found", `File not found: ${path}`, {
69
+ cause,
70
+ context: { path },
71
+ hint: "Check that the docsDir option points to an existing directory.",
72
+ });
73
+
74
+ export const parseError = (
75
+ path: string,
76
+ message: string,
77
+ cause?: unknown,
78
+ ): AppError =>
79
+ makeError("parse_error", message, {
80
+ cause,
81
+ context: { path },
82
+ hint: "Verify the frontmatter is delimited by '---' on its own line.",
83
+ });
84
+
85
+ export const validationError = (
86
+ message: string,
87
+ options?: {
88
+ path?: string;
89
+ suggestions?: readonly string[];
90
+ context?: Record<string, unknown>;
91
+ },
92
+ ): AppError => {
93
+ const ctx = options?.context ?? {};
94
+ if (options?.path !== undefined) ctx.path = options.path;
95
+ return makeError("validation_error", message, {
96
+ context: ctx,
97
+ path: options?.path,
98
+ suggestions: options?.suggestions,
99
+ hint: options?.suggestions?.length
100
+ ? `Did you mean one of: ${options.suggestions.join(", ")}?`
101
+ : undefined,
102
+ });
103
+ };
104
+
105
+ export const configError = (
106
+ message: string,
107
+ options?: {
108
+ path?: string;
109
+ suggestions?: readonly string[];
110
+ context?: Record<string, unknown>;
111
+ hint?: string;
112
+ cause?: unknown;
113
+ },
114
+ ): AppError => {
115
+ const ctx = options?.context ?? {};
116
+ if (options?.path !== undefined) ctx.path = options.path;
117
+ return makeError("config_error", message, {
118
+ context: ctx,
119
+ path: options?.path,
120
+ suggestions: options?.suggestions,
121
+ hint:
122
+ options?.hint ??
123
+ (options?.suggestions?.length
124
+ ? `Allowed: ${options.suggestions.join(", ")}.`
125
+ : "See https://create-docs.dev/docs/configuration for the full schema."),
126
+ cause: options?.cause,
127
+ });
128
+ };
129
+
130
+ export const ioError = (
131
+ path: string,
132
+ message: string,
133
+ cause?: unknown,
134
+ ): AppError => makeError("io_error", message, { cause, context: { path } });
135
+
136
+ export const pluginError = (
137
+ message: string,
138
+ options?: {
139
+ path?: string;
140
+ hint?: string;
141
+ context?: Record<string, unknown>;
142
+ cause?: unknown;
143
+ },
144
+ ): AppError => {
145
+ const ctx = options?.context ?? {};
146
+ if (options?.path !== undefined) ctx.path = options.path;
147
+ return makeError("plugin_error", message, {
148
+ context: ctx,
149
+ path: options?.path,
150
+ hint: options?.hint,
151
+ cause: options?.cause,
152
+ });
153
+ };
154
+
155
+ const RED = "\u001B[31m";
156
+ const YELLOW = "\u001B[33m";
157
+ const CYAN = "\u001B[36m";
158
+ const DIM = "\u001B[2m";
159
+ const RESET = "\u001B[0m";
160
+ const BOLD = "\u001B[1m";
161
+
162
+ const isColorSupported = (): boolean => {
163
+ if (typeof process === "undefined") return false;
164
+ const env = process.env;
165
+ if (env?.NO_COLOR && env.NO_COLOR.length > 0) return false;
166
+ if (env?.FORCE_COLOR && env.FORCE_COLOR.length > 0) return true;
167
+ return Boolean(process.stdout?.isTTY);
168
+ };
169
+
170
+ /** Format an AppError as a multi-line, ANSI-coloured, actionable message. */
171
+ export const formatError = (
172
+ e: AppError,
173
+ color: boolean = isColorSupported(),
174
+ ): string => {
175
+ const c = (code: string, s: string): string =>
176
+ color ? `${code}${s}${RESET}` : s;
177
+ const lines: string[] = [];
178
+ lines.push(`${c(BOLD + RED, "✖")} ${c(BOLD, e.message)}`);
179
+ lines.push(` ${c(DIM, "kind:")} ${e.kind}`);
180
+ if (e.path) lines.push(` ${c(DIM, "path:")} ${e.path}`);
181
+ if (e.suggestions && e.suggestions.length > 0) {
182
+ lines.push(
183
+ ` ${c(DIM, "allowed:")} ${e.suggestions.map((s) => c(CYAN, s)).join(", ")}`,
184
+ );
185
+ }
186
+ if (e.hint) lines.push(` ${c(YELLOW, "hint:")} ${e.hint}`);
187
+ if (e.docsUrl) lines.push(` ${c(DIM, "docs:")} ${c(CYAN, e.docsUrl)}`);
188
+ if (e.context && Object.keys(e.context).length > 0) {
189
+ lines.push(` ${c(DIM, "context:")} ${JSON.stringify(e.context)}`);
190
+ }
191
+ if (e.cause !== undefined) {
192
+ lines.push(` ${c(DIM, "cause:")} ${String(e.cause)}`);
193
+ }
194
+ return lines.join("\n");
195
+ };
@@ -0,0 +1,27 @@
1
+ export {
2
+ API_AUTH_TYPES,
3
+ BADGE_VARIANTS,
4
+ DEFAULT_BASE_ROUTE,
5
+ DEFAULT_DOCS_DIR,
6
+ DEFAULT_PORT,
7
+ FRONTMATTER_DELIMITER,
8
+ HTTP_METHODS,
9
+ PLUGIN_NAME,
10
+ SEARCH_CONTENT_LIMIT,
11
+ SIDEBAR_DEFAULT_GROUP_TITLE,
12
+ SIDEBAR_DEFAULT_ORDER,
13
+ SUPPORTED_EXTENSIONS,
14
+ VIRTUAL_PREFIX,
15
+ } from "./constants";
16
+ export {
17
+ configError,
18
+ fileNotFound,
19
+ formatError,
20
+ ioError,
21
+ makeError,
22
+ parseError,
23
+ pluginError,
24
+ validationError,
25
+ } from "./errors";
26
+ export * from "./types";
27
+ export * from "./utils";
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Brand<T, B> — A nominal type for primitives (preventing ID mixups at compile time).
3
+ *
4
+ * @example
5
+ * type UserId = Brand<string, 'UserId'>;
6
+ * type PostId = Brand<string, 'PostId'>;
7
+ * const get = (id: UserId) => ...;
8
+ * get('abc' as UserId); // OK
9
+ * get('abc' as PostId); // compile error
10
+ */
11
+ export type Brand<T, B extends string> = T & { readonly __brand: B };
12
+
13
+ export const brand = <T, B extends string>(value: T): Brand<T, B> =>
14
+ value as Brand<T, B>;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Ambient type declarations for the `virtual:docs/*` modules.
3
+ * Import this from your tsconfig (or include it in your project's types)
4
+ * to get full autocomplete on the virtual module imports.
5
+ */
6
+ declare module "virtual:docs/data" {
7
+ import type { DocPage } from "@create-docs/modules/content";
8
+ export const docsData: ReadonlyArray<{
9
+ id: string;
10
+ slug: string;
11
+ title: string;
12
+ description?: string;
13
+ frontmatter: DocPage["frontmatter"];
14
+ rawContent: string;
15
+ content: string;
16
+ filePath: string;
17
+ }>;
18
+ }
19
+
20
+ declare module "virtual:docs/sidebar" {
21
+ import type { SidebarGroup } from "@create-docs/modules/navigation";
22
+ export const sidebar: readonly SidebarGroup[];
23
+ }
24
+
25
+ declare module "virtual:docs/nav" {
26
+ import type { NavSection } from "@create-docs/modules/navigation";
27
+ export const nav: readonly NavSection[];
28
+ }
29
+
30
+ declare module "virtual:docs/search-index" {
31
+ import type { SearchEntry } from "@create-docs/modules/search";
32
+ export const searchIndex: readonly SearchEntry[];
33
+ }
34
+
35
+ declare module "virtual:docs/config" {
36
+ import type { ResolvedDocsConfig } from "@create-docs/modules/config";
37
+ export const docsConfig: ResolvedDocsConfig;
38
+ export const site: ResolvedDocsConfig["site"];
39
+ export const nav: ResolvedDocsConfig["nav"];
40
+ export const sidebar: ResolvedDocsConfig["sidebar"];
41
+ export const api: ResolvedDocsConfig["api"];
42
+ export const search: ResolvedDocsConfig["search"];
43
+ export const editLink: ResolvedDocsConfig["editLink"];
44
+ export const lastUpdated: ResolvedDocsConfig["lastUpdated"];
45
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Either<L, R> — A pure algebraic data type for a value that can be one of two types.
3
+ *
4
+ * Convention: L = "left" (often an error/short-circuit), R = "right" (success/continuation).
5
+ *
6
+ * Use this when you need to model two valid outcomes (e.g., a value OR a reason it isn't applicable)
7
+ * without committing to Result's "err" semantics.
8
+ */
9
+ export type Either<L, R> =
10
+ | { readonly tag: "left"; readonly left: L }
11
+ | { readonly tag: "right"; readonly right: R };
12
+
13
+ export const left = <L>(value: L): Either<L, never> => ({
14
+ tag: "left",
15
+ left: value,
16
+ });
17
+
18
+ export const right = <R>(value: R): Either<never, R> => ({
19
+ tag: "right",
20
+ right: value,
21
+ });
22
+
23
+ export const isLeft = <L, R>(e: Either<L, R>): e is { tag: "left"; left: L } =>
24
+ e.tag === "left";
25
+
26
+ export const isRight = <L, R>(
27
+ e: Either<L, R>,
28
+ ): e is { tag: "right"; right: R } => e.tag === "right";
29
+
30
+ export const map = <L, R, R2>(
31
+ e: Either<L, R>,
32
+ fn: (right: R) => R2,
33
+ ): Either<L, R2> => (e.tag === "right" ? right(fn(e.right)) : e);
34
+
35
+ export const mapLeft = <L, L2, R>(
36
+ e: Either<L, R>,
37
+ fn: (left: L) => L2,
38
+ ): Either<L2, R> => (e.tag === "left" ? left(fn(e.left)) : e);
@@ -0,0 +1,42 @@
1
+ export type { Brand } from "./brand";
2
+ export { brand } from "./brand";
3
+ export type { Either } from "./either";
4
+ export {
5
+ isLeft,
6
+ isRight,
7
+ left,
8
+ map as mapEither,
9
+ mapLeft,
10
+ right,
11
+ } from "./either";
12
+ export type { Option } from "./option";
13
+
14
+ export {
15
+ filter,
16
+ flatMap as flatMapOption,
17
+ fromNullable,
18
+ fromPredicate,
19
+ getOrElse,
20
+ isNone,
21
+ isSome,
22
+ map as mapOption,
23
+ none,
24
+ orElse,
25
+ some,
26
+ toNullable,
27
+ } from "./option";
28
+ export type { Result } from "./result";
29
+ export {
30
+ all,
31
+ err,
32
+ flatMap as flatMapResult,
33
+ fromThrowable,
34
+ isErr,
35
+ isOk,
36
+ map as mapResult,
37
+ mapErr,
38
+ ok,
39
+ partition,
40
+ unwrap,
41
+ unwrapOr,
42
+ } from "./result";
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Option<T> — A pure algebraic data type for values that may be absent.
3
+ *
4
+ * Use this to model nullable values without `null | undefined` leakage.
5
+ *
6
+ * @example
7
+ * const findUser = (id: string): Option<User> =>
8
+ * users.has(id) ? some(users.get(id)!) : none;
9
+ */
10
+ export type Option<T> =
11
+ | { readonly kind: "some"; readonly value: T }
12
+ | { readonly kind: "none" };
13
+
14
+ export const some = <T>(value: T): Option<T> => ({ kind: "some", value });
15
+
16
+ export const none = <T = never>(): Option<T> => ({ kind: "none" });
17
+
18
+ export const isSome = <T>(o: Option<T>): o is { kind: "some"; value: T } =>
19
+ o.kind === "some";
20
+
21
+ export const isNone = <T>(o: Option<T>): o is { kind: "none" } =>
22
+ o.kind === "none";
23
+
24
+ export const map = <T, U>(o: Option<T>, fn: (value: T) => U): Option<U> =>
25
+ o.kind === "some" ? some(fn(o.value)) : o;
26
+
27
+ export const flatMap = <T, U>(
28
+ o: Option<T>,
29
+ fn: (value: T) => Option<U>,
30
+ ): Option<U> => (o.kind === "some" ? fn(o.value) : o);
31
+
32
+ export const filter = <T>(
33
+ o: Option<T>,
34
+ pred: (value: T) => boolean,
35
+ ): Option<T> => (o.kind === "some" && pred(o.value) ? o : none());
36
+
37
+ export const orElse = <T>(o: Option<T>, fallback: Option<T>): Option<T> =>
38
+ o.kind === "some" ? o : fallback;
39
+
40
+ export const getOrElse = <T>(o: Option<T>, fallback: T): T =>
41
+ o.kind === "some" ? o.value : fallback;
42
+
43
+ export const toNullable = <T>(o: Option<T>): T | null =>
44
+ o.kind === "some" ? o.value : null;
45
+
46
+ export const fromNullable = <T>(value: T | null | undefined): Option<T> =>
47
+ value === null || value === undefined ? none() : some(value);
48
+
49
+ export const fromPredicate = <T>(
50
+ value: T,
51
+ pred: (v: T) => boolean,
52
+ ): Option<T> => (pred(value) ? some(value) : none());