@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.
- package/README.md +137 -0
- package/bin/cli.js +408 -0
- package/dist/index.cjs +20 -0
- package/dist/index.d.cts +475 -0
- package/dist/index.d.ts +475 -0
- package/dist/index.js +20 -0
- package/docs/_dir.yml +2 -0
- package/docs/config.md +75 -0
- package/docs/data-sources.md +88 -0
- package/docs/deploy.md +38 -0
- package/docs/features.md +51 -0
- package/docs/getting-started.md +42 -0
- package/docs/index.md +34 -0
- package/docs/markdown.md +154 -0
- package/docs/theming.md +53 -0
- package/package.json +142 -0
- package/scripts/generate-docs-index.ts +111 -0
- package/scripts/github-pull.ts +124 -0
- package/src/adapters/config/index.ts +1 -0
- package/src/adapters/config/node-config-loader.ts +36 -0
- package/src/adapters/fs/fs-docs-loader.ts +31 -0
- package/src/adapters/fs/index.ts +12 -0
- package/src/adapters/fs/memory-fs.ts +60 -0
- package/src/adapters/fs/node-fs.ts +116 -0
- package/src/adapters/git/index.ts +164 -0
- package/src/adapters/github/github-pull.ts +340 -0
- package/src/adapters/index.ts +6 -0
- package/src/adapters/velite.ts +112 -0
- package/src/adapters/vite/docs-watcher.ts +36 -0
- package/src/adapters/vite/index.ts +2 -0
- package/src/adapters/vite/polling-watcher.ts +89 -0
- package/src/code-block-enhancements/index.ts +3 -0
- package/src/config/index.ts +15 -0
- package/src/content/index.ts +11 -0
- package/src/content-validation/index.ts +5 -0
- package/src/index.ts +174 -0
- package/src/live-editor/index.ts +7 -0
- package/src/modules/analytics/application/plausible-adapter.ts +103 -0
- package/src/modules/analytics/application/umami-adapter.ts +109 -0
- package/src/modules/analytics/domain/events/index.ts +37 -0
- package/src/modules/analytics/domain/models/index.ts +35 -0
- package/src/modules/analytics/domain/operations/analytics-operations.ts +67 -0
- package/src/modules/analytics/domain/validators/index.ts +50 -0
- package/src/modules/analytics/index.ts +9 -0
- package/src/modules/analytics/ports/analytics-port.ts +17 -0
- package/src/modules/analytics/types/analytics.ts +16 -0
- package/src/modules/api-docs/application/type-docs-adapter.ts +34 -0
- package/src/modules/api-docs/domain/events/index.ts +42 -0
- package/src/modules/api-docs/domain/models/index.ts +40 -0
- package/src/modules/api-docs/domain/operations/api-docs-operations.ts +59 -0
- package/src/modules/api-docs/domain/validators/index.ts +56 -0
- package/src/modules/api-docs/index.ts +8 -0
- package/src/modules/api-docs/ports/api-docs-port.ts +21 -0
- package/src/modules/api-docs/types/api-docs.ts +15 -0
- package/src/modules/api-reference/openapi.ts +166 -0
- package/src/modules/api-reference/orpc.ts +94 -0
- package/src/modules/code-block-enhancements/application/usecases/index.ts +39 -0
- package/src/modules/code-block-enhancements/domain/code-operations.ts +72 -0
- package/src/modules/code-block-enhancements/domain/events/index.ts +58 -0
- package/src/modules/code-block-enhancements/domain/index.ts +11 -0
- package/src/modules/code-block-enhancements/domain/models/index.ts +36 -0
- package/src/modules/code-block-enhancements/domain/validators/index.ts +50 -0
- package/src/modules/code-block-enhancements/index.ts +10 -0
- package/src/modules/code-block-enhancements/ports/index.ts +18 -0
- package/src/modules/code-block-enhancements/types/index.ts +37 -0
- package/src/modules/code-execution/application/sandbox-adapter.ts +44 -0
- package/src/modules/code-execution/domain/events/index.ts +58 -0
- package/src/modules/code-execution/domain/models/index.ts +33 -0
- package/src/modules/code-execution/domain/operations/execution-operations.ts +60 -0
- package/src/modules/code-execution/domain/validators/index.ts +50 -0
- package/src/modules/code-execution/index.ts +8 -0
- package/src/modules/code-execution/ports/execution-port.ts +15 -0
- package/src/modules/code-execution/types/execution.ts +15 -0
- package/src/modules/comments/application/giscus-adapter.ts +55 -0
- package/src/modules/comments/domain/events/index.ts +55 -0
- package/src/modules/comments/domain/models/index.ts +30 -0
- package/src/modules/comments/domain/operations/comment-operations.ts +46 -0
- package/src/modules/comments/domain/validators/index.ts +50 -0
- package/src/modules/comments/index.ts +8 -0
- package/src/modules/comments/ports/comment-port.ts +18 -0
- package/src/modules/comments/types/comments.ts +19 -0
- package/src/modules/config/application/usecases/index.ts +1 -0
- package/src/modules/config/application/usecases/loadConfig.ts +38 -0
- package/src/modules/config/application/workflows/index.ts +1 -0
- package/src/modules/config/application/workflows/validateConfig.ts +14 -0
- package/src/modules/config/domain/events/index.ts +50 -0
- package/src/modules/config/domain/models/index.ts +9 -0
- package/src/modules/config/domain/operations/defaults.ts +74 -0
- package/src/modules/config/domain/operations/index.ts +2 -0
- package/src/modules/config/domain/operations/resolve.ts +40 -0
- package/src/modules/config/domain/validators/index.ts +152 -0
- package/src/modules/config/index.ts +23 -0
- package/src/modules/config/ports/index.ts +15 -0
- package/src/modules/config/types/index.ts +113 -0
- package/src/modules/config/types/public.ts +19 -0
- package/src/modules/content/application/cache/index.ts +6 -0
- package/src/modules/content/application/cache/parse-cache.ts +6 -0
- package/src/modules/content/application/cache/parseCache.ts +56 -0
- package/src/modules/content/application/usecases/index.ts +2 -0
- package/src/modules/content/application/usecases/load-doc-page.ts +1 -0
- package/src/modules/content/application/usecases/loadDocPage.ts +111 -0
- package/src/modules/content/application/usecases/scanDocsDir.ts +105 -0
- package/src/modules/content/application/workflows/index.ts +1 -0
- package/src/modules/content/application/workflows/processDocs.ts +51 -0
- package/src/modules/content/domain/events/index.ts +61 -0
- package/src/modules/content/domain/models/index.ts +13 -0
- package/src/modules/content/domain/operations/build-page.ts +146 -0
- package/src/modules/content/domain/operations/buildPage.ts +93 -0
- package/src/modules/content/domain/operations/index.ts +17 -0
- package/src/modules/content/domain/operations/parse.ts +241 -0
- package/src/modules/content/domain/validators/frontmatter.ts +82 -0
- package/src/modules/content/domain/validators/index.ts +6 -0
- package/src/modules/content/index.ts +27 -0
- package/src/modules/content/ports/index.ts +45 -0
- package/src/modules/content/ports/velite.ts +134 -0
- package/src/modules/content/types/index.ts +76 -0
- package/src/modules/content/types/public.ts +1 -0
- package/src/modules/content-linting/application/builtin-linting-adapter.ts +82 -0
- package/src/modules/content-linting/domain/events/index.ts +58 -0
- package/src/modules/content-linting/domain/models/index.ts +46 -0
- package/src/modules/content-linting/domain/operations/linting-operations.ts +82 -0
- package/src/modules/content-linting/domain/validators/index.ts +50 -0
- package/src/modules/content-linting/index.ts +8 -0
- package/src/modules/content-linting/ports/linting-port.ts +21 -0
- package/src/modules/content-linting/types/linting.ts +18 -0
- package/src/modules/content-validation/application/usecases/index.ts +18 -0
- package/src/modules/content-validation/domain/events/index.ts +7 -0
- package/src/modules/content-validation/domain/index.ts +16 -0
- package/src/modules/content-validation/domain/models/index.ts +33 -0
- package/src/modules/content-validation/domain/operations/index.ts +157 -0
- package/src/modules/content-validation/domain/types/index.ts +17 -0
- package/src/modules/content-validation/domain/validators/index.ts +8 -0
- package/src/modules/content-validation/index.ts +9 -0
- package/src/modules/content-validation/ports/index.ts +15 -0
- package/src/modules/content-validation/types/index.ts +5 -0
- package/src/modules/export/application/puppeteer-export-adapter.ts +63 -0
- package/src/modules/export/domain/events/index.ts +55 -0
- package/src/modules/export/domain/models/index.ts +38 -0
- package/src/modules/export/domain/operations/export-operations.ts +56 -0
- package/src/modules/export/domain/validators/index.ts +52 -0
- package/src/modules/export/index.ts +8 -0
- package/src/modules/export/ports/export-port.ts +15 -0
- package/src/modules/export/types/export.ts +15 -0
- package/src/modules/external-search/application/algolia-adapter.ts +182 -0
- package/src/modules/external-search/application/meilisearch-adapter.ts +161 -0
- package/src/modules/external-search/domain/events/index.ts +42 -0
- package/src/modules/external-search/domain/models/index.ts +42 -0
- package/src/modules/external-search/domain/operations/search-operations.ts +53 -0
- package/src/modules/external-search/domain/validators/index.ts +55 -0
- package/src/modules/external-search/index.ts +9 -0
- package/src/modules/external-search/ports/external-search-port.ts +23 -0
- package/src/modules/external-search/types/search.ts +19 -0
- package/src/modules/git-history/application/simple-git-adapter.ts +46 -0
- package/src/modules/git-history/domain/events/index.ts +34 -0
- package/src/modules/git-history/domain/models/index.ts +25 -0
- package/src/modules/git-history/domain/operations/git-history-operations.ts +56 -0
- package/src/modules/git-history/domain/validators/index.ts +52 -0
- package/src/modules/git-history/index.ts +8 -0
- package/src/modules/git-history/ports/git-history-port.ts +21 -0
- package/src/modules/git-history/types/git-history.ts +15 -0
- package/src/modules/i18n/application/fs-locale-loader.ts +39 -0
- package/src/modules/i18n/domain/events/index.ts +34 -0
- package/src/modules/i18n/domain/models/index.ts +34 -0
- package/src/modules/i18n/domain/operations/locale-operations.ts +74 -0
- package/src/modules/i18n/domain/validators/index.ts +52 -0
- package/src/modules/i18n/index.ts +8 -0
- package/src/modules/i18n/ports/locale-loader-port.ts +18 -0
- package/src/modules/i18n/types/locale.ts +17 -0
- package/src/modules/image-optimization/application/sharp-adapter.ts +58 -0
- package/src/modules/image-optimization/domain/events/index.ts +39 -0
- package/src/modules/image-optimization/domain/models/index.ts +27 -0
- package/src/modules/image-optimization/domain/operations/image-operations.ts +65 -0
- package/src/modules/image-optimization/domain/validators/index.ts +52 -0
- package/src/modules/image-optimization/index.ts +8 -0
- package/src/modules/image-optimization/ports/image-optimizer-port.ts +15 -0
- package/src/modules/image-optimization/types/image.ts +17 -0
- package/src/modules/live-editor/application/usecases/index.ts +60 -0
- package/src/modules/live-editor/domain/events/index.ts +37 -0
- package/src/modules/live-editor/domain/gitOperations.ts +110 -0
- package/src/modules/live-editor/domain/index.ts +15 -0
- package/src/modules/live-editor/domain/models/index.ts +21 -0
- package/src/modules/live-editor/domain/validators/index.ts +55 -0
- package/src/modules/live-editor/index.ts +14 -0
- package/src/modules/live-editor/ports/index.ts +49 -0
- package/src/modules/live-editor/types/index.ts +80 -0
- package/src/modules/live-preview/application/vite-preview-adapter.ts +20 -0
- package/src/modules/live-preview/domain/operations/preview-operations.ts +56 -0
- package/src/modules/live-preview/index.ts +8 -0
- package/src/modules/live-preview/ports/preview-port.ts +20 -0
- package/src/modules/live-preview/types/preview.ts +16 -0
- package/src/modules/mdx/application/mdx-js-adapter.ts +38 -0
- package/src/modules/mdx/domain/operations/parse-mdx.ts +43 -0
- package/src/modules/mdx/index.ts +8 -0
- package/src/modules/mdx/ports/mdx-parser-port.ts +15 -0
- package/src/modules/mdx/types/mdx.ts +14 -0
- package/src/modules/navigation/application/usecases/buildNav.ts +15 -0
- package/src/modules/navigation/application/usecases/buildSidebar.ts +45 -0
- package/src/modules/navigation/application/usecases/index.ts +2 -0
- package/src/modules/navigation/domain/events/index.ts +30 -0
- package/src/modules/navigation/domain/models/index.ts +7 -0
- package/src/modules/navigation/domain/operations/group.ts +79 -0
- package/src/modules/navigation/domain/operations/index.ts +10 -0
- package/src/modules/navigation/domain/operations/sort.ts +27 -0
- package/src/modules/navigation/domain/shared/utils/array.ts +39 -0
- package/src/modules/navigation/domain/validators/index.ts +88 -0
- package/src/modules/navigation/index.ts +15 -0
- package/src/modules/navigation/ports/index.ts +9 -0
- package/src/modules/navigation/types/index.ts +38 -0
- package/src/modules/navigation/types/public.ts +9 -0
- package/src/modules/openapi/application/swagger-parser-adapter.ts +178 -0
- package/src/modules/openapi/domain/operations/parse-openapi.ts +46 -0
- package/src/modules/openapi/index.ts +8 -0
- package/src/modules/openapi/ports/openapi-parser-port.ts +15 -0
- package/src/modules/openapi/types/openapi.ts +37 -0
- package/src/modules/plugin/application/usecases/build-virtual-modules.ts +53 -0
- package/src/modules/plugin/application/usecases/index.ts +1 -0
- package/src/modules/plugin/application/workflows/build-docs.ts +79 -0
- package/src/modules/plugin/application/workflows/index.ts +1 -0
- package/src/modules/plugin/domain/events/index.ts +62 -0
- package/src/modules/plugin/domain/models/index.ts +1 -0
- package/src/modules/plugin/domain/operations/build-virtual.ts +76 -0
- package/src/modules/plugin/domain/operations/index.ts +11 -0
- package/src/modules/plugin/domain/validators/index.ts +30 -0
- package/src/modules/plugin/index.ts +14 -0
- package/src/modules/plugin/ports/index.ts +21 -0
- package/src/modules/plugin/types/index.ts +27 -0
- package/src/modules/plugin/types/public.ts +1 -0
- package/src/modules/search/application/usecases/index.ts +1 -0
- package/src/modules/search/application/usecases/indexPages.ts +15 -0
- package/src/modules/search/domain/events/index.ts +32 -0
- package/src/modules/search/domain/models/index.ts +1 -0
- package/src/modules/search/domain/operations/build-index.ts +6 -0
- package/src/modules/search/domain/operations/buildIndex.ts +70 -0
- package/src/modules/search/domain/operations/index.ts +7 -0
- package/src/modules/search/domain/operations/query.ts +186 -0
- package/src/modules/search/domain/validators/index.ts +32 -0
- package/src/modules/search/index.ts +9 -0
- package/src/modules/search/types/index.ts +22 -0
- package/src/modules/search/types/public.ts +1 -0
- package/src/modules/search-analytics/application/local-storage-adapter.ts +68 -0
- package/src/modules/search-analytics/domain/operations/search-analytics-operations.ts +74 -0
- package/src/modules/search-analytics/index.ts +8 -0
- package/src/modules/search-analytics/ports/search-analytics-port.ts +20 -0
- package/src/modules/search-analytics/types/search-analytics.ts +16 -0
- package/src/modules/search-highlighting/application/dom-highlighting-adapter.ts +36 -0
- package/src/modules/search-highlighting/domain/operations/highlighting-operations.ts +72 -0
- package/src/modules/search-highlighting/index.ts +8 -0
- package/src/modules/search-highlighting/ports/highlighting-port.ts +14 -0
- package/src/modules/search-highlighting/types/highlighting.ts +15 -0
- package/src/modules/seo-optimization/application/usecases/index.ts +18 -0
- package/src/modules/seo-optimization/domain/index.ts +12 -0
- package/src/modules/seo-optimization/domain/seoOperations.ts +92 -0
- package/src/modules/seo-optimization/index.ts +8 -0
- package/src/modules/seo-optimization/ports/index.ts +18 -0
- package/src/modules/seo-optimization/types/index.ts +41 -0
- package/src/modules/theme/application/css-theme-adapter.ts +50 -0
- package/src/modules/theme/domain/operations/theme-operations.ts +68 -0
- package/src/modules/theme/index.ts +8 -0
- package/src/modules/theme/ports/theme-port.ts +8 -0
- package/src/modules/theme/types/theme.ts +12 -0
- package/src/modules/toc/application/markdown-toc-adapter.ts +106 -0
- package/src/modules/toc/domain/operations/toc-operations.ts +92 -0
- package/src/modules/toc/index.ts +8 -0
- package/src/modules/toc/ports/toc-port.ts +21 -0
- package/src/modules/toc/types/toc.ts +17 -0
- package/src/modules/toc-generator/application/usecases/index.ts +30 -0
- package/src/modules/toc-generator/domain/index.ts +12 -0
- package/src/modules/toc-generator/domain/tocOperations.ts +104 -0
- package/src/modules/toc-generator/index.ts +9 -0
- package/src/modules/toc-generator/ports/index.ts +20 -0
- package/src/modules/toc-generator/types/index.ts +50 -0
- package/src/modules/version-control/domain/events/index.ts +39 -0
- package/src/modules/version-control/domain/models/index.ts +25 -0
- package/src/modules/version-control/domain/validators/index.ts +50 -0
- package/src/modules/versioning/application/fs-version-loader.ts +44 -0
- package/src/modules/versioning/domain/operations/versioning-operations.ts +80 -0
- package/src/modules/versioning/index.ts +8 -0
- package/src/modules/versioning/ports/version-loader-port.ts +18 -0
- package/src/modules/versioning/types/versioning.ts +17 -0
- package/src/modules/workflow/domain/events/index.ts +55 -0
- package/src/modules/workflow/domain/models/index.ts +40 -0
- package/src/modules/workflow/domain/validators/index.ts +50 -0
- package/src/modules/yaml-parser/application/js-yaml-adapter.ts +34 -0
- package/src/modules/yaml-parser/domain/operations/parse-yaml.ts +58 -0
- package/src/modules/yaml-parser/index.ts +7 -0
- package/src/modules/yaml-parser/ports/yaml-parser-port.ts +18 -0
- package/src/navigation/index.ts +9 -0
- package/src/plugin/index.ts +4 -0
- package/src/presentation/index.ts +1 -0
- package/src/presentation/live-editor/index.ts +22 -0
- package/src/presentation/live-editor/live-editor-component.ts +219 -0
- package/src/presentation/live-editor/virtual-module.ts +16 -0
- package/src/presentation/solid/CodeBlock.tsx +120 -0
- package/src/presentation/solid/Toc.tsx +58 -0
- package/src/presentation/solid/index.ts +11 -0
- package/src/presentation/vite-plugin/docs-plugin.ts +212 -0
- package/src/presentation/vite-plugin/index.ts +9 -0
- package/src/presentation/vite-plugin/transform-markdown.ts +26 -0
- package/src/runtime/analytics.ts +59 -0
- package/src/runtime/api-diff.ts +115 -0
- package/src/runtime/app.tsx +32 -0
- package/src/runtime/components/AccentPicker.tsx +114 -0
- package/src/runtime/components/ApiPlayground.tsx +332 -0
- package/src/runtime/components/AskAiDialog.tsx +127 -0
- package/src/runtime/components/BackToTop.tsx +38 -0
- package/src/runtime/components/Banner.tsx +75 -0
- package/src/runtime/components/Breadcrumbs.tsx +42 -0
- package/src/runtime/components/CollectionDropdown.tsx +85 -0
- package/src/runtime/components/CustomizeDrawer.tsx +195 -0
- package/src/runtime/components/DocMarkdown.tsx +579 -0
- package/src/runtime/components/DocPrevNext.tsx +54 -0
- package/src/runtime/components/DocToc.tsx +147 -0
- package/src/runtime/components/DocsDropdown.tsx +184 -0
- package/src/runtime/components/Footer.tsx +52 -0
- package/src/runtime/components/GitHubAuth.tsx +82 -0
- package/src/runtime/components/GitHubStats.tsx +73 -0
- package/src/runtime/components/Head.tsx +225 -0
- package/src/runtime/components/LocaleDropdown.tsx +75 -0
- package/src/runtime/components/MobileBottomNav.tsx +111 -0
- package/src/runtime/components/NotFound.tsx +139 -0
- package/src/runtime/components/PageActions.tsx +144 -0
- package/src/runtime/components/RelatedDocs.tsx +50 -0
- package/src/runtime/components/ScrollProgress.tsx +32 -0
- package/src/runtime/components/SearchPalette.tsx +333 -0
- package/src/runtime/components/ShowcaseCard.tsx +87 -0
- package/src/runtime/components/SidebarNav.tsx +237 -0
- package/src/runtime/components/Skeleton.tsx +39 -0
- package/src/runtime/components/ThemeToggle.tsx +26 -0
- package/src/runtime/components/TopNav.tsx +270 -0
- package/src/runtime/components/VersionDropdown.tsx +189 -0
- package/src/runtime/components/markdown/components.ts +280 -0
- package/src/runtime/config.ts +225 -0
- package/src/runtime/content.ts +451 -0
- package/src/runtime/context.tsx +30 -0
- package/src/runtime/data.ts +93 -0
- package/src/runtime/github.ts +226 -0
- package/src/runtime/icons.ts +32 -0
- package/src/runtime/index.ts +153 -0
- package/src/runtime/layouts/DocsLayout.tsx +144 -0
- package/src/runtime/markdown-content.css +996 -0
- package/src/runtime/pages/AbTestPage.tsx +88 -0
- package/src/runtime/pages/AnalyticsPage.tsx +90 -0
- package/src/runtime/pages/ApiDiffPage.tsx +86 -0
- package/src/runtime/pages/ApiEndpointPage.tsx +248 -0
- package/src/runtime/pages/BuilderPage.tsx +150 -0
- package/src/runtime/pages/ChangelogPage.tsx +210 -0
- package/src/runtime/pages/CollectionPage.tsx +140 -0
- package/src/runtime/pages/CommunityPage.tsx +384 -0
- package/src/runtime/pages/CreatePage.tsx +448 -0
- package/src/runtime/pages/DocPage.tsx +193 -0
- package/src/runtime/pages/EditPage.tsx +201 -0
- package/src/runtime/pages/HomePage.tsx +187 -0
- package/src/runtime/pages/IssuesPage.tsx +140 -0
- package/src/runtime/pages/OAuthCallbackPage.tsx +80 -0
- package/src/runtime/pages/PluginsPage.tsx +249 -0
- package/src/runtime/pages/ShowcasePage.tsx +202 -0
- package/src/runtime/pwa.ts +39 -0
- package/src/runtime/router.tsx +192 -0
- package/src/runtime/seo.ts +192 -0
- package/src/runtime/theme.css +175 -0
- package/src/runtime/theme.ts +224 -0
- package/src/runtime/types.ts +217 -0
- package/src/search/index.ts +6 -0
- package/src/seo-optimization/index.ts +4 -0
- package/src/shared/constants/index.ts +26 -0
- package/src/shared/errors/index.ts +195 -0
- package/src/shared/index.ts +27 -0
- package/src/shared/types/brand.ts +14 -0
- package/src/shared/types/client.d.ts +45 -0
- package/src/shared/types/either.ts +38 -0
- package/src/shared/types/index.ts +42 -0
- package/src/shared/types/option.ts +52 -0
- package/src/shared/types/result.ts +81 -0
- package/src/shared/utils/array.ts +97 -0
- package/src/shared/utils/index.ts +46 -0
- package/src/shared/utils/object.ts +47 -0
- package/src/shared/utils/string.ts +74 -0
- package/src/toc-generator/index.ts +1 -0
- package/src/types/js-yaml.d.ts +42 -0
- package/src/worker.ts +462 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain events for export
|
|
3
|
+
*/
|
|
4
|
+
export interface ExportStartedEvent {
|
|
5
|
+
readonly type: "EXPORT_STARTED";
|
|
6
|
+
readonly timestamp: number;
|
|
7
|
+
readonly format: string;
|
|
8
|
+
readonly filename: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ExportCompletedEvent {
|
|
12
|
+
readonly type: "EXPORT_COMPLETED";
|
|
13
|
+
readonly timestamp: number;
|
|
14
|
+
readonly filePath: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ExportFailedEvent {
|
|
18
|
+
readonly type: "EXPORT_FAILED";
|
|
19
|
+
readonly timestamp: number;
|
|
20
|
+
readonly error: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type ExportDomainEvent =
|
|
24
|
+
| ExportStartedEvent
|
|
25
|
+
| ExportCompletedEvent
|
|
26
|
+
| ExportFailedEvent;
|
|
27
|
+
|
|
28
|
+
export const createExportStartedEvent = (
|
|
29
|
+
format: string,
|
|
30
|
+
filename: string,
|
|
31
|
+
now: number = Date.now(),
|
|
32
|
+
): ExportStartedEvent => ({
|
|
33
|
+
type: "EXPORT_STARTED",
|
|
34
|
+
timestamp: now,
|
|
35
|
+
format,
|
|
36
|
+
filename,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export const createExportCompletedEvent = (
|
|
40
|
+
filePath: string,
|
|
41
|
+
now: number = Date.now(),
|
|
42
|
+
): ExportCompletedEvent => ({
|
|
43
|
+
type: "EXPORT_COMPLETED",
|
|
44
|
+
timestamp: now,
|
|
45
|
+
filePath,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export const createExportFailedEvent = (
|
|
49
|
+
error: string,
|
|
50
|
+
now: number = Date.now(),
|
|
51
|
+
): ExportFailedEvent => ({
|
|
52
|
+
type: "EXPORT_FAILED",
|
|
53
|
+
timestamp: now,
|
|
54
|
+
error,
|
|
55
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain models for export
|
|
3
|
+
*/
|
|
4
|
+
export interface ExportConfig {
|
|
5
|
+
readonly format: "pdf" | "html" | "markdown" | "json";
|
|
6
|
+
readonly includeImages: boolean;
|
|
7
|
+
readonly includeCodeBlocks: boolean;
|
|
8
|
+
readonly filename: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ExportResult {
|
|
12
|
+
readonly success: boolean;
|
|
13
|
+
readonly filePath?: string;
|
|
14
|
+
readonly error?: string;
|
|
15
|
+
readonly timestamp: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const createExportConfig = (
|
|
19
|
+
format: ExportConfig["format"],
|
|
20
|
+
filename: string,
|
|
21
|
+
options?: { includeImages?: boolean; includeCodeBlocks?: boolean },
|
|
22
|
+
): ExportConfig => ({
|
|
23
|
+
format,
|
|
24
|
+
filename,
|
|
25
|
+
includeImages: options?.includeImages ?? true,
|
|
26
|
+
includeCodeBlocks: options?.includeCodeBlocks ?? true,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export const createExportResult = (
|
|
30
|
+
success: boolean,
|
|
31
|
+
options?: { filePath?: string; error?: string; timestamp?: number },
|
|
32
|
+
now: number = Date.now(),
|
|
33
|
+
): ExportResult => ({
|
|
34
|
+
success,
|
|
35
|
+
filePath: options?.filePath,
|
|
36
|
+
error: options?.error,
|
|
37
|
+
timestamp: options?.timestamp ?? now,
|
|
38
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure export operations.
|
|
3
|
+
* No I/O. No exceptions thrown. Returns Result types.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { Result } from "@create-docs/shared/types";
|
|
7
|
+
import { err, ok } from "@create-docs/shared/types";
|
|
8
|
+
import type { ExportConfig, ExportResult } from "../../types/export";
|
|
9
|
+
|
|
10
|
+
export type ExportError = {
|
|
11
|
+
readonly kind: "export-error";
|
|
12
|
+
readonly message: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Validate export config.
|
|
17
|
+
*/
|
|
18
|
+
export const validateExportConfig = (config: ExportConfig): boolean => {
|
|
19
|
+
if (!config.format) return false;
|
|
20
|
+
if (!config.outputDir) return false;
|
|
21
|
+
return true;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Generate export filename.
|
|
26
|
+
*/
|
|
27
|
+
export const generateExportFilename = (
|
|
28
|
+
slug: string,
|
|
29
|
+
format: "pdf" | "epub",
|
|
30
|
+
now: number = Date.now(),
|
|
31
|
+
): string => {
|
|
32
|
+
const timestamp = new Date(now).toISOString().split("T")[0];
|
|
33
|
+
return `${slug}-${timestamp}.${format}`;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Process export result.
|
|
38
|
+
*/
|
|
39
|
+
export const processExportResult = (
|
|
40
|
+
success: boolean,
|
|
41
|
+
outputPath: string,
|
|
42
|
+
error: string | null,
|
|
43
|
+
): Result<ExportResult, ExportError> => {
|
|
44
|
+
try {
|
|
45
|
+
return ok({
|
|
46
|
+
success,
|
|
47
|
+
outputPath,
|
|
48
|
+
error,
|
|
49
|
+
});
|
|
50
|
+
} catch (error) {
|
|
51
|
+
return err({
|
|
52
|
+
kind: "export-error",
|
|
53
|
+
message: error instanceof Error ? error.message : "Unknown error",
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Export Domain Schemas - Arktype validation schemas
|
|
2
|
+
// Following /follow-arktype workflow for type-safe runtime validation
|
|
3
|
+
|
|
4
|
+
import { type Type, type } from "arktype";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Export Format Schema
|
|
8
|
+
*/
|
|
9
|
+
export const exportFormatSchema: Type = type(
|
|
10
|
+
"'pdf' | 'html' | 'markdown' | 'json'",
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
export type ExportFormat = typeof exportFormatSchema.infer;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Filename Schema
|
|
17
|
+
*/
|
|
18
|
+
export const filenameSchema: Type = type("string >= 1");
|
|
19
|
+
|
|
20
|
+
export type Filename = typeof filenameSchema.infer;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Validation errors
|
|
24
|
+
*/
|
|
25
|
+
export class ValidationError extends Error {
|
|
26
|
+
constructor(message: string) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = "ValidationError";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Validate export format using Arktype
|
|
34
|
+
*/
|
|
35
|
+
export const validateExportFormat = (format: unknown): ExportFormat => {
|
|
36
|
+
const result = exportFormatSchema(format);
|
|
37
|
+
if (result instanceof type.errors) {
|
|
38
|
+
throw new ValidationError("Invalid export format");
|
|
39
|
+
}
|
|
40
|
+
return result as ExportFormat;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Validate filename using Arktype
|
|
45
|
+
*/
|
|
46
|
+
export const validateFilename = (filename: unknown): Filename => {
|
|
47
|
+
const result = filenameSchema(filename);
|
|
48
|
+
if (result instanceof type.errors) {
|
|
49
|
+
throw new ValidationError("Filename must be a non-empty string");
|
|
50
|
+
}
|
|
51
|
+
return result as Filename;
|
|
52
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public API for the export module.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export { createPuppeteerExportAdapter } from "./application/puppeteer-export-adapter";
|
|
6
|
+
export * from "./domain/operations/export-operations";
|
|
7
|
+
export * from "./ports/export-port";
|
|
8
|
+
export * from "./types/export";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Port for export operations.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type ExportPort = {
|
|
6
|
+
/**
|
|
7
|
+
* Export documentation to PDF.
|
|
8
|
+
*/
|
|
9
|
+
readonly exportToPdf: (content: string, config: unknown) => Promise<unknown>;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Export documentation to EPUB.
|
|
13
|
+
*/
|
|
14
|
+
readonly exportToEpub: (content: string, config: unknown) => Promise<unknown>;
|
|
15
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Export types for PDF/EPUB export functionality.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type ExportConfig = {
|
|
6
|
+
readonly format: "pdf" | "epub";
|
|
7
|
+
readonly outputDir: string;
|
|
8
|
+
readonly includeImages: boolean;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type ExportResult = {
|
|
12
|
+
readonly success: boolean;
|
|
13
|
+
readonly outputPath: string;
|
|
14
|
+
readonly error: string | null;
|
|
15
|
+
};
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Algolia adapter implementation.
|
|
3
|
+
* Provides Algolia search integration via the REST API.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { configError, pluginError } from "@create-docs/shared/errors";
|
|
7
|
+
import type { ExternalSearchPort } from "../ports/external-search-port";
|
|
8
|
+
import type {
|
|
9
|
+
ExternalSearchConfig,
|
|
10
|
+
ExternalSearchResult,
|
|
11
|
+
} from "../types/search";
|
|
12
|
+
|
|
13
|
+
export const createAlgoliaAdapter = (
|
|
14
|
+
appId: string,
|
|
15
|
+
_apiKey: string,
|
|
16
|
+
): ExternalSearchPort => ({
|
|
17
|
+
search: async (query: string, config?: unknown) => {
|
|
18
|
+
const cfg = config as Partial<ExternalSearchConfig> | undefined;
|
|
19
|
+
const indexName = cfg?.indexName;
|
|
20
|
+
const apiKey = cfg?.apiKey ?? _apiKey;
|
|
21
|
+
|
|
22
|
+
if (!appId) {
|
|
23
|
+
throw configError("Algolia appId is required", {
|
|
24
|
+
context: { query, config },
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!indexName) {
|
|
29
|
+
throw configError("Algolia indexName is required", {
|
|
30
|
+
context: { appId, query },
|
|
31
|
+
hint: "Set indexName in the search config.",
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!apiKey) {
|
|
36
|
+
throw configError("Algolia API key is required", {
|
|
37
|
+
context: { appId, indexName, query },
|
|
38
|
+
hint: "Pass the API key to createAlgoliaAdapter or set apiKey in config.",
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const searchHost = `https://${appId}-dsn.algolia.net`;
|
|
43
|
+
const url = `${searchHost}/1/indexes/${encodeURIComponent(indexName)}/query`;
|
|
44
|
+
const headers = {
|
|
45
|
+
"X-Algolia-Application-Id": appId,
|
|
46
|
+
"X-Algolia-API-Key": apiKey,
|
|
47
|
+
"Content-Type": "application/json",
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
const response = await fetch(url, {
|
|
52
|
+
method: "POST",
|
|
53
|
+
headers,
|
|
54
|
+
body: JSON.stringify({
|
|
55
|
+
params: `query=${encodeURIComponent(query)}&hitsPerPage=20`,
|
|
56
|
+
}),
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
if (!response.ok) {
|
|
60
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const data = (await response.json()) as {
|
|
64
|
+
hits?: readonly ExternalSearchResult[];
|
|
65
|
+
};
|
|
66
|
+
return data.hits ?? [];
|
|
67
|
+
} catch (error) {
|
|
68
|
+
throw pluginError("Algolia search failed", {
|
|
69
|
+
context: { query, config, error: String(error) },
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
index: async (docs: readonly unknown[], config?: unknown) => {
|
|
75
|
+
const cfg = config as Partial<ExternalSearchConfig> | undefined;
|
|
76
|
+
const indexName = cfg?.indexName;
|
|
77
|
+
const apiKey = cfg?.apiKey ?? _apiKey;
|
|
78
|
+
|
|
79
|
+
if (!appId) {
|
|
80
|
+
throw configError("Algolia appId is required", {
|
|
81
|
+
context: { config },
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!indexName) {
|
|
86
|
+
throw configError("Algolia indexName is required", {
|
|
87
|
+
context: { appId },
|
|
88
|
+
hint: "Set indexName in the search config.",
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (!apiKey) {
|
|
93
|
+
throw configError("Algolia API key is required", {
|
|
94
|
+
context: { appId, indexName },
|
|
95
|
+
hint: "Pass the API key to createAlgoliaAdapter or set apiKey in config.",
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const writeHost = `https://${appId}.algolia.net`;
|
|
100
|
+
const url = `${writeHost}/1/indexes/${encodeURIComponent(indexName)}/batch`;
|
|
101
|
+
const headers = {
|
|
102
|
+
"X-Algolia-Application-Id": appId,
|
|
103
|
+
"X-Algolia-API-Key": apiKey,
|
|
104
|
+
"Content-Type": "application/json",
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const requests = docs.map((doc) => ({
|
|
108
|
+
action: "addObject" as const,
|
|
109
|
+
body: doc,
|
|
110
|
+
}));
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
const response = await fetch(url, {
|
|
114
|
+
method: "POST",
|
|
115
|
+
headers,
|
|
116
|
+
body: JSON.stringify({ requests }),
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
if (!response.ok) {
|
|
120
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
121
|
+
}
|
|
122
|
+
} catch (error) {
|
|
123
|
+
throw pluginError("Algolia indexing failed", {
|
|
124
|
+
context: {
|
|
125
|
+
docCount: docs.length,
|
|
126
|
+
config,
|
|
127
|
+
error: String(error),
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
clear: async (config?: unknown) => {
|
|
134
|
+
const cfg = config as Partial<ExternalSearchConfig> | undefined;
|
|
135
|
+
const indexName = cfg?.indexName;
|
|
136
|
+
const apiKey = cfg?.apiKey ?? _apiKey;
|
|
137
|
+
|
|
138
|
+
if (!appId) {
|
|
139
|
+
throw configError("Algolia appId is required", {
|
|
140
|
+
context: { config },
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (!indexName) {
|
|
145
|
+
throw configError("Algolia indexName is required", {
|
|
146
|
+
context: { appId },
|
|
147
|
+
hint: "Set indexName in the search config.",
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (!apiKey) {
|
|
152
|
+
throw configError("Algolia API key is required", {
|
|
153
|
+
context: { appId, indexName },
|
|
154
|
+
hint: "Pass the API key to createAlgoliaAdapter or set apiKey in config.",
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const writeHost = `https://${appId}.algolia.net`;
|
|
159
|
+
const url = `${writeHost}/1/indexes/${encodeURIComponent(indexName)}/clear`;
|
|
160
|
+
const headers = {
|
|
161
|
+
"X-Algolia-Application-Id": appId,
|
|
162
|
+
"X-Algolia-API-Key": apiKey,
|
|
163
|
+
"Content-Type": "application/json",
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
try {
|
|
167
|
+
const response = await fetch(url, {
|
|
168
|
+
method: "POST",
|
|
169
|
+
headers,
|
|
170
|
+
body: "{}",
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
if (!response.ok) {
|
|
174
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
175
|
+
}
|
|
176
|
+
} catch (error) {
|
|
177
|
+
throw pluginError("Algolia clear failed", {
|
|
178
|
+
context: { config, error: String(error) },
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
});
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MeiliSearch adapter implementation.
|
|
3
|
+
* Provides MeiliSearch search integration via the REST API.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { configError, pluginError } from "@create-docs/shared/errors";
|
|
7
|
+
import type { ExternalSearchPort } from "../ports/external-search-port";
|
|
8
|
+
import type {
|
|
9
|
+
ExternalSearchConfig,
|
|
10
|
+
ExternalSearchResult,
|
|
11
|
+
} from "../types/search";
|
|
12
|
+
|
|
13
|
+
export const createMeilisearchAdapter = (
|
|
14
|
+
host: string,
|
|
15
|
+
_apiKey: string,
|
|
16
|
+
): ExternalSearchPort => ({
|
|
17
|
+
search: async (query: string, config?: unknown) => {
|
|
18
|
+
const cfg = config as Partial<ExternalSearchConfig> | undefined;
|
|
19
|
+
const resolvedHost = (cfg?.host ?? host).replace(/\/+$/, "");
|
|
20
|
+
const indexName = cfg?.indexName;
|
|
21
|
+
const apiKey = cfg?.apiKey ?? _apiKey;
|
|
22
|
+
|
|
23
|
+
if (!resolvedHost) {
|
|
24
|
+
throw configError("MeiliSearch host is required", {
|
|
25
|
+
context: { query, config },
|
|
26
|
+
hint: "Pass host to createMeilisearchAdapter or set host in config.",
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (!indexName) {
|
|
31
|
+
throw configError("MeiliSearch indexName is required", {
|
|
32
|
+
context: { host: resolvedHost, query },
|
|
33
|
+
hint: "Set indexName in the search config.",
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const url = `${resolvedHost}/indexes/${encodeURIComponent(indexName)}/search`;
|
|
38
|
+
const headers: Record<string, string> = {
|
|
39
|
+
"Content-Type": "application/json",
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
if (apiKey) {
|
|
43
|
+
headers.Authorization = `Bearer ${apiKey}`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const response = await fetch(url, {
|
|
48
|
+
method: "POST",
|
|
49
|
+
headers,
|
|
50
|
+
body: JSON.stringify({ q: query, limit: 20 }),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
if (!response.ok) {
|
|
54
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const data = (await response.json()) as {
|
|
58
|
+
hits?: readonly ExternalSearchResult[];
|
|
59
|
+
};
|
|
60
|
+
return data.hits ?? [];
|
|
61
|
+
} catch (error) {
|
|
62
|
+
throw pluginError("MeiliSearch search failed", {
|
|
63
|
+
context: { query, config, host: resolvedHost, error: String(error) },
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
index: async (docs: readonly unknown[], config?: unknown) => {
|
|
69
|
+
const cfg = config as Partial<ExternalSearchConfig> | undefined;
|
|
70
|
+
const resolvedHost = (cfg?.host ?? host).replace(/\/+$/, "");
|
|
71
|
+
const indexName = cfg?.indexName;
|
|
72
|
+
const apiKey = cfg?.apiKey ?? _apiKey;
|
|
73
|
+
|
|
74
|
+
if (!resolvedHost) {
|
|
75
|
+
throw configError("MeiliSearch host is required", {
|
|
76
|
+
context: { config },
|
|
77
|
+
hint: "Pass host to createMeilisearchAdapter or set host in config.",
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!indexName) {
|
|
82
|
+
throw configError("MeiliSearch indexName is required", {
|
|
83
|
+
context: { host: resolvedHost },
|
|
84
|
+
hint: "Set indexName in the search config.",
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const url = `${resolvedHost}/indexes/${encodeURIComponent(indexName)}/documents`;
|
|
89
|
+
const headers: Record<string, string> = {
|
|
90
|
+
"Content-Type": "application/json",
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
if (apiKey) {
|
|
94
|
+
headers.Authorization = `Bearer ${apiKey}`;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
const response = await fetch(url, {
|
|
99
|
+
method: "POST",
|
|
100
|
+
headers,
|
|
101
|
+
body: JSON.stringify(docs),
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
if (!response.ok) {
|
|
105
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
106
|
+
}
|
|
107
|
+
} catch (error) {
|
|
108
|
+
throw pluginError("MeiliSearch indexing failed", {
|
|
109
|
+
context: {
|
|
110
|
+
docCount: docs.length,
|
|
111
|
+
config,
|
|
112
|
+
host: resolvedHost,
|
|
113
|
+
error: String(error),
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
clear: async (config?: unknown) => {
|
|
120
|
+
const cfg = config as Partial<ExternalSearchConfig> | undefined;
|
|
121
|
+
const resolvedHost = (cfg?.host ?? host).replace(/\/+$/, "");
|
|
122
|
+
const indexName = cfg?.indexName;
|
|
123
|
+
const apiKey = cfg?.apiKey ?? _apiKey;
|
|
124
|
+
|
|
125
|
+
if (!resolvedHost) {
|
|
126
|
+
throw configError("MeiliSearch host is required", {
|
|
127
|
+
context: { config },
|
|
128
|
+
hint: "Pass host to createMeilisearchAdapter or set host in config.",
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (!indexName) {
|
|
133
|
+
throw configError("MeiliSearch indexName is required", {
|
|
134
|
+
context: { host: resolvedHost },
|
|
135
|
+
hint: "Set indexName in the search config.",
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const url = `${resolvedHost}/indexes/${encodeURIComponent(indexName)}/documents`;
|
|
140
|
+
const headers: Record<string, string> = {};
|
|
141
|
+
|
|
142
|
+
if (apiKey) {
|
|
143
|
+
headers.Authorization = `Bearer ${apiKey}`;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
const response = await fetch(url, {
|
|
148
|
+
method: "DELETE",
|
|
149
|
+
headers,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
if (!response.ok) {
|
|
153
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
154
|
+
}
|
|
155
|
+
} catch (error) {
|
|
156
|
+
throw pluginError("MeiliSearch clear failed", {
|
|
157
|
+
context: { config, host: resolvedHost, error: String(error) },
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain events for external search
|
|
3
|
+
*/
|
|
4
|
+
export interface SearchRequestedEvent {
|
|
5
|
+
readonly type: "SEARCH_REQUESTED";
|
|
6
|
+
readonly timestamp: number;
|
|
7
|
+
readonly query: string;
|
|
8
|
+
readonly providerId: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface SearchCompletedEvent {
|
|
12
|
+
readonly type: "SEARCH_COMPLETED";
|
|
13
|
+
readonly timestamp: number;
|
|
14
|
+
readonly query: string;
|
|
15
|
+
readonly resultCount: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type ExternalSearchDomainEvent =
|
|
19
|
+
| SearchRequestedEvent
|
|
20
|
+
| SearchCompletedEvent;
|
|
21
|
+
|
|
22
|
+
export const createSearchRequestedEvent = (
|
|
23
|
+
query: string,
|
|
24
|
+
providerId: string,
|
|
25
|
+
now: number = Date.now(),
|
|
26
|
+
): SearchRequestedEvent => ({
|
|
27
|
+
type: "SEARCH_REQUESTED",
|
|
28
|
+
timestamp: now,
|
|
29
|
+
query,
|
|
30
|
+
providerId,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export const createSearchCompletedEvent = (
|
|
34
|
+
query: string,
|
|
35
|
+
resultCount: number,
|
|
36
|
+
now: number = Date.now(),
|
|
37
|
+
): SearchCompletedEvent => ({
|
|
38
|
+
type: "SEARCH_COMPLETED",
|
|
39
|
+
timestamp: now,
|
|
40
|
+
query,
|
|
41
|
+
resultCount,
|
|
42
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain models for external search
|
|
3
|
+
*/
|
|
4
|
+
export interface SearchProvider {
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly name: string;
|
|
7
|
+
readonly endpoint: string;
|
|
8
|
+
readonly enabled: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface SearchResult {
|
|
12
|
+
readonly providerId: string;
|
|
13
|
+
readonly title: string;
|
|
14
|
+
readonly url: string;
|
|
15
|
+
readonly snippet?: string;
|
|
16
|
+
readonly relevance: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const createSearchProvider = (
|
|
20
|
+
id: string,
|
|
21
|
+
name: string,
|
|
22
|
+
endpoint: string,
|
|
23
|
+
enabled: boolean = true,
|
|
24
|
+
): SearchProvider => ({
|
|
25
|
+
id,
|
|
26
|
+
name,
|
|
27
|
+
endpoint,
|
|
28
|
+
enabled,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export const createSearchResult = (
|
|
32
|
+
providerId: string,
|
|
33
|
+
title: string,
|
|
34
|
+
url: string,
|
|
35
|
+
options?: { snippet?: string; relevance?: number },
|
|
36
|
+
): SearchResult => ({
|
|
37
|
+
providerId,
|
|
38
|
+
title,
|
|
39
|
+
url,
|
|
40
|
+
snippet: options?.snippet,
|
|
41
|
+
relevance: options?.relevance ?? 0,
|
|
42
|
+
});
|